There are two different situations here. One is running untrusted machine code on a CPU. The other is running untrusted byte code or scripts in a JIT compiler, such as Javascript.
edit: I changed some things due to my misunderstanding of the code that Spectre uses to work properly. It uses existing code with higher privileges with conditional branches where the CPU is deliberately made to execute the wrong path in the branch with malicious data given to it, which results in memory reads which are cached and then thrown out. Except for proof of concept code, the exploit uses code already on the system, not its own code like I said previously.
Meltdown is related to running untrusted machine code on an Intel CPU in a restricted environment, such as a limited user account. The code can use Meltdown to access read protected memory such as kernel memory that is supposed to be off limits. It is not related to JIT compilers.
Spectre is related to: 1) Like Meltdown, running untrusted machine code in a restricted environment and accessing restricted memory such as kernel memory. What can be accessed depends on what is mapped in to the virtual address space when the Spectre vulnerable code is run. 2) JIT compiers such as Javascript. Javascript and other JIT compiled restricted environments that are running untrusted code can be exploited by Spectre to gain access the address space of the Javascript JIT compiler, the browser, and likely more than that.
Code that is running in a JIT compiler or interpreter has the advantage of just needing patches to the JIT compiler or interpreter to fix the problem. Making it so that the attacking script can't probe the cache can defeat Spectre. I believe patching against Spectre for native code is where it gets harder.
The page table isolation patch that is used to fix Meltdown does not fix Spectre*. Spectre vulnerable code is conditional code that is already on the system. To make use of Spectre, this code is runs with different privileges than the attacking program so that it has access to data that the attacking program does not have access to. After the attacking program prepares the caches and mistrains the branch predictor, the Spectre vulnerable code is called by the attacking program with arguments that cause its speculatively executed instructions to read from memory that it normally protects against. These read instructions are never fully executed by the CPU because it dumps them once it finds out that the branch prediction was wrong. But the read operations affected the caches, and now the attacking program analyzes the caches to find the data.
So yes it is possible to make software patches. Once found to be vulnerable, individual conditionals can be modified such that they are useless to Spectre. A more generic approach of adding machine code after all branch instructions can be done to cause the CPU to not speculatively execute anything. That will cause a noticeable performance impact, since a modern CPU can speculatively execute over 100 instructions while waiting to verify a branch prediction! Maybe some sort of compiler modification can be done to have it disable speculative execution after conditionals which access data based on the value of the variable used for the conditional, or memory accesses based on outside data, or it could require that variables used in conditionals be stored in a register to have speculative execution guaranteed to be enabled.
*What I have said here involves memory accesses to areas that are readable by the Spectre vulnerable code. What I don't know yet is if speculatively executed instructions can access read-protected data like Meltdown does. Maybe this is possible on Intel CPUs and not AMD? I suspect that there is not much discussion about this because most CPUs are Intel and anything Intel that's vulnerable to Spectre is also vulnerable to Meltdown. But could matter for untrusted code that's running in a JIT compiler, since such code would then have access to the read-protected part of the JIT compiler's address space (the kernel and physical memory) while using Spectre vulnerable code that's running with the privileges of the JIT compiler. The page table isolation patches would fix this, but users may think that since they aren't running native code that they don't need it.