6502 is a very restrictive architecture. This wasn't too bad, when problems were usually trivial enough that 8 bit operations or at best 16 bit operations were needed the bulk of the time. But for any non-trivial problem these days, that's just not the case. And the limitation of a single general purpose register, a 256 byte zero page, a 256 byte stack and almost no addressing modes is just way too restrictive, if you want to start writing your programs in a high-level language; if you write tiny trivial hand-optimized assembly programs, that might not be obvious.
On top of that, the tiny address space made it impossible to write anything but the most trivial applications (by today's standards).
For simple programs written during that time period, the code was reasonably dense, but certainly not ground breakingly so. If you tried to write any modern programs, you'd be wasting a lot of space emulating 32 bit (or wider) operations, switching memory banks, and figuring out how to work around the lack of an FPU; let alone a MMU. The code would be horribly verbose.
x86 is actually not horribly bad by modern standards. It is almost the most compact encoding that anybody has managed to come up with, and that's a good thing. These days, memory bandwidth is a serious bottle neck and as a first approximation, the more compactly the compiler can encode your program, the faster it'll run. Code density is one of the driving forcing in going from asm.js to WebAssembly. asm.js is intrinsically verbose, but relies on compression to fix this issue.