+static int offsetOfStackRegion(StackMaps::RecordMap& recordMap, uint32_t stackmapID)
+{
+ if (stackmapID == UINT_MAX)
+ return 0;
+
+ StackMaps::RecordMap::iterator iter = recordMap.find(stackmapID);
+ RELEASE_ASSERT(iter != recordMap.end());
+ RELEASE_ASSERT(iter->value.size() == 1);
+ RELEASE_ASSERT(iter->value[0].locations.size() == 1);
+ Location capturedLocation =
+ Location::forStackmaps(nullptr, iter->value[0].locations[0]);
+ RELEASE_ASSERT(capturedLocation.kind() == Location::Register);
+ RELEASE_ASSERT(capturedLocation.gpr() == GPRInfo::callFrameRegister);
+ RELEASE_ASSERT(!(capturedLocation.addend() % sizeof(Register)));
+ return capturedLocation.addend() / sizeof(Register);
+}
+
+static void generateInlineIfPossibleOutOfLineIfNot(State& state, VM& vm, CodeBlock* codeBlock, CCallHelpers& code, char* startOfInlineCode, size_t sizeOfInlineCode, const char* codeDescription, const std::function<void(LinkBuffer&, CCallHelpers&, bool wasCompiledInline)>& callback)
+{
+ std::unique_ptr<LinkBuffer> codeLinkBuffer;
+ size_t actualCodeSize = code.m_assembler.buffer().codeSize();
+
+ if (actualCodeSize <= sizeOfInlineCode) {
+ LinkBuffer codeLinkBuffer(vm, code, startOfInlineCode, sizeOfInlineCode);
+
+ // Fill the remainder of the inline space with nops to avoid confusing the disassembler.
+ MacroAssembler::AssemblerType_T::fillNops(bitwise_cast<char*>(startOfInlineCode) + actualCodeSize, sizeOfInlineCode - actualCodeSize);
+
+ callback(codeLinkBuffer, code, true);
+
+ return;
+ }
+
+ // If there isn't enough space in the provided inline code area, allocate out of line
+ // executable memory to link the provided code. Place a jump at the beginning of the
+ // inline area and jump to the out of line code. Similarly return by appending a jump
+ // to the provided code that goes to the instruction after the inline code.
+ // Fill the middle with nop's.
+ MacroAssembler::Jump returnToMainline = code.jump();
+
+ // Allocate out of line executable memory and link the provided code there.
+ codeLinkBuffer = std::make_unique<LinkBuffer>(vm, code, codeBlock, JITCompilationMustSucceed);
+
+ // Plant a jmp in the inline buffer to the out of line code.
+ MacroAssembler callToOutOfLineCode;
+ MacroAssembler::Jump jumpToOutOfLine = callToOutOfLineCode.jump();
+ LinkBuffer inlineBuffer(vm, callToOutOfLineCode, startOfInlineCode, sizeOfInlineCode);
+ inlineBuffer.link(jumpToOutOfLine, codeLinkBuffer->entrypoint());
+
+ // Fill the remainder of the inline space with nops to avoid confusing the disassembler.
+ MacroAssembler::AssemblerType_T::fillNops(bitwise_cast<char*>(startOfInlineCode) + inlineBuffer.size(), sizeOfInlineCode - inlineBuffer.size());
+
+ // Link the end of the out of line code to right after the inline area.
+ codeLinkBuffer->link(returnToMainline, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(startOfInlineCode)).labelAtOffset(sizeOfInlineCode));
+
+ callback(*codeLinkBuffer.get(), code, false);
+
+ state.finalizer->outOfLineCodeInfos.append(OutOfLineCodeInfo(WTF::move(codeLinkBuffer), codeDescription));
+}
+