My hypothesis is that a common DSL framework would be just an ordinary programming language (e.g. an extended version of Haskell or Rust) that allows library writers to subset its AST and substitute a code generator for its preferred subset. That way, a DSL writer doesn't have to re implement expression parsing, type checking, error messages, ... but instead just has to do the code generation. Moreover, it would limit fragmentation since the DSLs are, by requirement, the same syntax as the host language, so users would have a more consistent experience between different languages instead of working across arbitrarily different syntaxes.
Whether these restricted languages are doable as embedded DSLs in general-purpose language remains to be seen. There have been attempts that work pretty well (Accelerate for Haskell is the one I know best), but they are limited in expressibility, and the ergonomics (type errors and conceptual clarity) are not great. Also, even with all the work that has gone into Accelerate, the end result is only useful to Haskell programmers, which is a shame. Perhaps this can be solved with a sufficient amount of shared infrastructure. Access to the real AST, instead of the lifted operations used by Accelerate, would be a good start.
I'd argue that the Racket language (or language platform, depending on your view of things) shows it's possible with its #lang mechanism and macro system. For example, though Racket proper is untyped, Typed Racket is implemented as a #lang with macros and includes an optimizing compiler that removes runtime checks on programs that typecheck successfully.
Ziggurat[0] was an attempt at a general-purpose system to communicate static properties of DSLs past the more general host language (where they don't necessarily apply). It probably falls under the "ergonomics are not great" category though.
0: http://www.ccs.neu.edu/home/shivers/papers/ziggurat-jfp.pdf
https://github.com/pcpratts/rootbeer1
http://openjdk.java.net/projects/sumatra/
There has been work done on automatically identifying and running ordinary JVM hotspots on the GPU.
That said, I agree that automatic parallelisation is a hard problem. I don't think it's the only interesting area of language innovation: most of the innovations making programmers lives easier in recent years have nothing to do with it.
Intel/AMD processors have complex branch predictors and instruction decoders and SIMD, ARM has conditional execution and some sort of quasi-SIMD, and GPUs have a weird hybrid of SIMD and multi-threaded-single-whatever (execution??) with sorta-kinda shared memory. Not only do these architectures implement memory access differently, the way basic control flow operations (conditionals and loops) work is physically different.
That's not even including architectures like SPARC or specialized DSPs. Or FPGAs, which are a whole different universe.
Imperative languages are probably hopeless, but declarative languages may work. Functional languages in its current popular incarnations is about as hard to compile intelligently as imperative code, but I think that functional array programming (where bulk operations are primitives) show promise. Consider computing the average of every row of an n*m matrix 'a' (a 2D array). In Haskell-ish syntax, we would write this as:
map (map (/m)) (map sum a)
Now the compiler really only has to figure out two high-level things: how to apply a function (division by 'm') to every element of an array, and how to sum equally-sized segments of an array. Summing is again an instance of a more primitive bulk operation, reduction, which is parallel in theory, and has known efficient parallel implementations on most hardware. It's also possible to do some fusion for this small example, but my point is that we will need a programming model where the individual statement or expression works at a much higher level, and has much stronger properties, than in most current languages. You still need to teach the compiler about each specific hardware platform you want to target, of course (possibly by automatic learning or autotuning, as in http://www.lift-project.org/ ).And it's true that the hard part is still transforming a representation close to the problem domain into a VM-executable one, as they are worlds apart. Then there is also an ecosystem problem, which forces us into the meta world and generating specific code in a specific format instead of doing anything with a VM. I didn't really see the appeal last time we discussed it and I don't see it now.
More relevant is power. The more wasted cycles the shorter your battery life. The hotter that device implanted in you becomes. The worse the cooling problem in the datacenter.
It's naive to think that "computers are fast enough".
There are a lot of computational tasks that can not run on a smartphone today. It'd be great to run an IDE, a few baclground classification tasks, and a high quality augmented reality VR headset app on a device with an 8 hour battery under that load and fits in my pocket.
That's not happening without lots of hardware customization.
You can't solve that with JITs. From what I have seen, JITs are very useful for taking away the overhead of indirect calls and similar dynamic behaviour, but I don't think that's going to be the primary language design challenge of the future. No compiler can (usefully) extract significant amounts of parallelism from an algorithm which has none, and current programming models are not particularly convenient for expressing parallel algorithms. While current languages allow you to express parallelism by using low-level features, the resulting program will invariably be non-portable. High-level parallel languages (or maybe libraries) are the only solution I can see.