The other issue with dynamically-typed languages is that the language sometimes "helpfully" fixes the types for you. I came across one JS project that said this:
for (var i = 1; i != Math.pow(2, 16); i <<= 1)
Replacing Math.pow(2, 16) with 1 << 16 effected a 30× speedup--and this was in SpiderMonkey, which tends to be a little less finicky about optimizing mixed types than V8.
(It's been a while since I coded PHP, but my recollection is that PHP tries to pull a strings-are-integer tricks a few times).
This doesn't look to me like a dynamic typing problem. All the types are Javascript numbers. The issue probably stems from Math.pow's flexibility; it can even accept fractional exponents. The more general algorithm is probably slower.
(It's been a while since I coded PHP, but my recollection is that PHP tries to pull a strings-are-integer tricks a few times).