Unless it was a tail call...
Really, throw and return are quite similar, both invoke an externally provided continuation and abandon the current one.
In a pure CPS setting, the caller's "only" responsibility is to give the right arguments (in scare quotes because getting a continuation right is usually trickier than the "plain" values usually given to functions).
In languages with functions, the caller is also responsible for handling/ignoring any return value and carrying out any subsequent computations, if the procedure returns.
In languages with exceptions, the caller is also responsible for handling/passing-on any exceptions.
Out of these three sorts of language, my current preference is for the second. It's probably fair to say that most procedures in a codebase will return a value (i.e. they're not continuations) and will not throw an exception (they're exceptional, after all). Hence it seems empirically desirable to allow `return`: it alters the semantics from a pure CPS scenario to one where we must always be vigilant that a procedure may return; but since most procedures (in such languages) return, that's not an edge case (in fact it's continuations, procedures without `return`, that are rare!); hence the benefits seem worth the cost.
When `throw` is introduced, we again must be vigilant when we're calling procedures. However, since most procedures don't `throw`, the benefit of having this ability is less than that of `return`. Also, since there may be many occurrences of `throw`, with different exception types, the cost of looking out for and handling these is greater than for `return`.
Hence my (current) opinion that `return` is very much a "good GOTO", whilst `throw` is a "bad GOTO" :)
Then we get `call-cc`... ;)
'call-cc', the control operator from hell that puts 'spaghetti' goto to shame.