MacroAssemblerCodePtr StructureStubInfo::addAccessCase( CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase) { VM& vm = *codeBlock->vm(); if (!accessCase) return MacroAssemblerCodePtr(); if (cacheType == CacheType::Stub) return u.stub->regenerateWithCase(vm, codeBlock, *this, ident, WTFMove(accessCase)); std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>(); Vector<std::unique_ptr<AccessCase>> accessCases; std::unique_ptr<AccessCase> previousCase = AccessCase::fromStructureStubInfo(vm, codeBlock, *this); if (previousCase) accessCases.append(WTFMove(previousCase)); accessCases.append(WTFMove(accessCase)); MacroAssemblerCodePtr result = access->regenerateWithCases(vm, codeBlock, *this, ident, WTFMove(accessCases)); if (!result) return MacroAssemblerCodePtr(); initStub(codeBlock, WTFMove(access)); return result; }
AccessGenerationResult StructureStubInfo::addAccessCase( CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase) { VM& vm = *codeBlock->vm(); if (verbose) dataLog("Adding access case: ", accessCase, "\n"); if (!accessCase) return AccessGenerationResult::GaveUp; AccessGenerationResult result; if (cacheType == CacheType::Stub) { result = u.stub->addCase(vm, codeBlock, *this, ident, WTFMove(accessCase)); if (verbose) dataLog("Had stub, result: ", result, "\n"); if (!result.buffered()) { bufferedStructures.clear(); return result; } } else { std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>(); Vector<std::unique_ptr<AccessCase>, 2> accessCases; std::unique_ptr<AccessCase> previousCase = AccessCase::fromStructureStubInfo(vm, codeBlock, *this); if (previousCase) accessCases.append(WTFMove(previousCase)); accessCases.append(WTFMove(accessCase)); result = access->addCases(vm, codeBlock, *this, ident, WTFMove(accessCases)); if (verbose) dataLog("Created stub, result: ", result, "\n"); if (!result.buffered()) { bufferedStructures.clear(); return result; } initStub(codeBlock, WTFMove(access)); } RELEASE_ASSERT(!result.generatedSomeCode()); // If we didn't buffer any cases then bail. If this made no changes then we'll just try again // subject to cool-down. if (!result.buffered()) { if (verbose) dataLog("Didn't buffer anything, bailing.\n"); bufferedStructures.clear(); return result; } // The buffering countdown tells us if we should be repatching now. if (bufferingCountdown) { if (verbose) dataLog("Countdown is too high: ", bufferingCountdown, ".\n"); return result; } // Forget the buffered structures so that all future attempts to cache get fully handled by the // PolymorphicAccess. bufferedStructures.clear(); result = u.stub->regenerate(vm, codeBlock, *this, ident); if (verbose) dataLog("Regeneration result: ", result, "\n"); RELEASE_ASSERT(!result.buffered()); if (!result.generatedSomeCode()) return result; // If we generated some code then we don't want to attempt to repatch in the future until we // gather enough cases. bufferingCountdown = Options::repatchBufferingCountdown(); return result; }