mustang 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (560) hide show
  1. data/.rspec +1 -0
  2. data/Isolate +9 -0
  3. data/README.md +6 -12
  4. data/Rakefile +30 -4
  5. data/TODO.md +9 -0
  6. data/ext/v8/extconf.rb +56 -0
  7. data/ext/v8/v8.cpp +37 -0
  8. data/ext/v8/v8_array.cpp +161 -0
  9. data/ext/v8/v8_array.h +17 -0
  10. data/ext/v8/v8_base.cpp +147 -0
  11. data/ext/v8/v8_base.h +23 -0
  12. data/ext/v8/v8_cast.cpp +151 -0
  13. data/ext/v8/v8_cast.h +64 -0
  14. data/ext/v8/v8_context.cpp +174 -0
  15. data/ext/v8/v8_context.h +12 -0
  16. data/ext/v8/v8_date.cpp +61 -0
  17. data/ext/v8/v8_date.h +16 -0
  18. data/ext/v8/v8_errors.cpp +147 -0
  19. data/ext/v8/v8_errors.h +19 -0
  20. data/ext/v8/v8_external.cpp +66 -0
  21. data/ext/v8/v8_external.h +16 -0
  22. data/ext/v8/v8_function.cpp +182 -0
  23. data/ext/v8/v8_function.h +14 -0
  24. data/ext/v8/v8_integer.cpp +70 -0
  25. data/ext/v8/v8_integer.h +16 -0
  26. data/ext/v8/v8_macros.h +30 -0
  27. data/ext/v8/v8_main.cpp +53 -0
  28. data/ext/v8/v8_main.h +13 -0
  29. data/ext/v8/v8_number.cpp +62 -0
  30. data/ext/v8/v8_number.h +16 -0
  31. data/ext/v8/v8_object.cpp +172 -0
  32. data/ext/v8/v8_object.h +17 -0
  33. data/ext/v8/v8_ref.cpp +72 -0
  34. data/ext/v8/v8_ref.h +43 -0
  35. data/ext/v8/v8_regexp.cpp +148 -0
  36. data/ext/v8/v8_regexp.h +16 -0
  37. data/ext/v8/v8_string.cpp +78 -0
  38. data/ext/v8/v8_string.h +16 -0
  39. data/ext/v8/v8_value.cpp +370 -0
  40. data/ext/v8/v8_value.h +19 -0
  41. data/gemspec.yml +2 -1
  42. data/lib/core_ext/class.rb +14 -0
  43. data/lib/core_ext/object.rb +12 -0
  44. data/lib/core_ext/symbol.rb +23 -0
  45. data/lib/mustang.rb +44 -0
  46. data/lib/mustang/context.rb +69 -0
  47. data/lib/mustang/errors.rb +36 -0
  48. data/lib/support/delegated.rb +25 -0
  49. data/lib/v8/array.rb +21 -0
  50. data/lib/v8/context.rb +13 -0
  51. data/lib/v8/date.rb +20 -0
  52. data/lib/v8/error.rb +15 -0
  53. data/lib/v8/external.rb +16 -0
  54. data/lib/v8/function.rb +11 -0
  55. data/lib/v8/integer.rb +16 -0
  56. data/lib/v8/number.rb +16 -0
  57. data/lib/v8/object.rb +66 -0
  58. data/lib/v8/regexp.rb +23 -0
  59. data/lib/v8/string.rb +27 -0
  60. data/mustang.gemspec +3 -0
  61. data/spec/core_ext/class_spec.rb +19 -0
  62. data/spec/core_ext/object_spec.rb +19 -0
  63. data/spec/core_ext/symbol_spec.rb +27 -0
  64. data/spec/fixtures/test1.js +2 -0
  65. data/spec/fixtures/test2.js +2 -0
  66. data/spec/spec_helper.rb +20 -0
  67. data/spec/v8/array_spec.rb +88 -0
  68. data/spec/v8/cast_spec.rb +151 -0
  69. data/spec/v8/context_spec.rb +78 -0
  70. data/spec/v8/data_spec.rb +39 -0
  71. data/spec/v8/date_spec.rb +45 -0
  72. data/spec/v8/empty_spec.rb +27 -0
  73. data/spec/v8/errors_spec.rb +142 -0
  74. data/spec/v8/external_spec.rb +44 -0
  75. data/spec/v8/function_spec.rb +170 -0
  76. data/spec/v8/integer_spec.rb +41 -0
  77. data/spec/v8/main_spec.rb +18 -0
  78. data/spec/v8/null_spec.rb +27 -0
  79. data/spec/v8/number_spec.rb +40 -0
  80. data/spec/v8/object_spec.rb +79 -0
  81. data/spec/v8/primitive_spec.rb +9 -0
  82. data/spec/v8/regexp_spec.rb +65 -0
  83. data/spec/v8/string_spec.rb +48 -0
  84. data/spec/v8/undefined_spec.rb +27 -0
  85. data/spec/v8/value_spec.rb +215 -0
  86. data/vendor/v8/.gitignore +2 -0
  87. data/vendor/v8/AUTHORS +3 -1
  88. data/vendor/v8/ChangeLog +117 -0
  89. data/vendor/v8/SConstruct +334 -53
  90. data/vendor/v8/include/v8-debug.h +21 -11
  91. data/vendor/v8/include/v8-preparser.h +1 -1
  92. data/vendor/v8/include/v8-profiler.h +122 -43
  93. data/vendor/v8/include/v8-testing.h +5 -0
  94. data/vendor/v8/include/v8.h +171 -17
  95. data/vendor/v8/preparser/SConscript +38 -0
  96. data/vendor/v8/preparser/preparser-process.cc +77 -114
  97. data/vendor/v8/samples/shell.cc +232 -46
  98. data/vendor/v8/src/SConscript +29 -5
  99. data/vendor/v8/src/accessors.cc +70 -211
  100. data/vendor/v8/{test/cctest/test-mips.cc → src/allocation-inl.h} +15 -18
  101. data/vendor/v8/src/allocation.cc +0 -82
  102. data/vendor/v8/src/allocation.h +9 -42
  103. data/vendor/v8/src/api.cc +1645 -1156
  104. data/vendor/v8/src/api.h +76 -12
  105. data/vendor/v8/src/apiutils.h +0 -7
  106. data/vendor/v8/src/arguments.h +15 -4
  107. data/vendor/v8/src/arm/assembler-arm-inl.h +10 -9
  108. data/vendor/v8/src/arm/assembler-arm.cc +62 -23
  109. data/vendor/v8/src/arm/assembler-arm.h +76 -11
  110. data/vendor/v8/src/arm/builtins-arm.cc +39 -33
  111. data/vendor/v8/src/arm/code-stubs-arm.cc +1182 -402
  112. data/vendor/v8/src/arm/code-stubs-arm.h +20 -54
  113. data/vendor/v8/src/arm/codegen-arm.cc +159 -106
  114. data/vendor/v8/src/arm/codegen-arm.h +6 -6
  115. data/vendor/v8/src/arm/constants-arm.h +16 -1
  116. data/vendor/v8/src/arm/cpu-arm.cc +7 -5
  117. data/vendor/v8/src/arm/debug-arm.cc +6 -4
  118. data/vendor/v8/src/arm/deoptimizer-arm.cc +51 -14
  119. data/vendor/v8/src/arm/disasm-arm.cc +47 -15
  120. data/vendor/v8/src/arm/frames-arm.h +1 -1
  121. data/vendor/v8/src/arm/full-codegen-arm.cc +724 -408
  122. data/vendor/v8/src/arm/ic-arm.cc +90 -85
  123. data/vendor/v8/src/arm/lithium-arm.cc +140 -69
  124. data/vendor/v8/src/arm/lithium-arm.h +161 -46
  125. data/vendor/v8/src/arm/lithium-codegen-arm.cc +567 -297
  126. data/vendor/v8/src/arm/lithium-codegen-arm.h +21 -9
  127. data/vendor/v8/src/arm/lithium-gap-resolver-arm.cc +2 -0
  128. data/vendor/v8/src/arm/macro-assembler-arm.cc +457 -96
  129. data/vendor/v8/src/arm/macro-assembler-arm.h +115 -18
  130. data/vendor/v8/src/arm/regexp-macro-assembler-arm.cc +20 -13
  131. data/vendor/v8/src/arm/regexp-macro-assembler-arm.h +1 -0
  132. data/vendor/v8/src/arm/simulator-arm.cc +184 -101
  133. data/vendor/v8/src/arm/simulator-arm.h +26 -21
  134. data/vendor/v8/src/arm/stub-cache-arm.cc +450 -467
  135. data/vendor/v8/src/arm/virtual-frame-arm.cc +14 -12
  136. data/vendor/v8/src/arm/virtual-frame-arm.h +11 -8
  137. data/vendor/v8/src/array.js +35 -18
  138. data/vendor/v8/src/assembler.cc +186 -92
  139. data/vendor/v8/src/assembler.h +106 -69
  140. data/vendor/v8/src/ast-inl.h +5 -0
  141. data/vendor/v8/src/ast.cc +46 -35
  142. data/vendor/v8/src/ast.h +107 -50
  143. data/vendor/v8/src/atomicops.h +2 -0
  144. data/vendor/v8/src/atomicops_internals_mips_gcc.h +169 -0
  145. data/vendor/v8/src/bootstrapper.cc +649 -399
  146. data/vendor/v8/src/bootstrapper.h +94 -27
  147. data/vendor/v8/src/builtins.cc +359 -227
  148. data/vendor/v8/src/builtins.h +157 -123
  149. data/vendor/v8/src/checks.cc +2 -2
  150. data/vendor/v8/src/checks.h +4 -0
  151. data/vendor/v8/src/code-stubs.cc +27 -17
  152. data/vendor/v8/src/code-stubs.h +38 -17
  153. data/vendor/v8/src/codegen-inl.h +5 -1
  154. data/vendor/v8/src/codegen.cc +27 -17
  155. data/vendor/v8/src/codegen.h +9 -9
  156. data/vendor/v8/src/compilation-cache.cc +92 -206
  157. data/vendor/v8/src/compilation-cache.h +205 -30
  158. data/vendor/v8/src/compiler.cc +107 -120
  159. data/vendor/v8/src/compiler.h +17 -2
  160. data/vendor/v8/src/contexts.cc +22 -15
  161. data/vendor/v8/src/contexts.h +14 -8
  162. data/vendor/v8/src/conversions.cc +86 -30
  163. data/vendor/v8/src/counters.cc +19 -4
  164. data/vendor/v8/src/counters.h +28 -16
  165. data/vendor/v8/src/cpu-profiler-inl.h +4 -3
  166. data/vendor/v8/src/cpu-profiler.cc +123 -72
  167. data/vendor/v8/src/cpu-profiler.h +33 -19
  168. data/vendor/v8/src/cpu.h +2 -0
  169. data/vendor/v8/src/d8-debug.cc +3 -3
  170. data/vendor/v8/src/d8-debug.h +7 -6
  171. data/vendor/v8/src/d8-posix.cc +2 -0
  172. data/vendor/v8/src/d8.cc +22 -12
  173. data/vendor/v8/src/d8.gyp +3 -0
  174. data/vendor/v8/src/d8.js +618 -0
  175. data/vendor/v8/src/data-flow.h +3 -3
  176. data/vendor/v8/src/dateparser.h +4 -2
  177. data/vendor/v8/src/debug-agent.cc +10 -9
  178. data/vendor/v8/src/debug-agent.h +9 -11
  179. data/vendor/v8/src/debug-debugger.js +121 -0
  180. data/vendor/v8/src/debug.cc +331 -227
  181. data/vendor/v8/src/debug.h +248 -219
  182. data/vendor/v8/src/deoptimizer.cc +173 -62
  183. data/vendor/v8/src/deoptimizer.h +119 -19
  184. data/vendor/v8/src/disasm.h +3 -0
  185. data/vendor/v8/src/disassembler.cc +10 -9
  186. data/vendor/v8/src/execution.cc +185 -129
  187. data/vendor/v8/src/execution.h +47 -78
  188. data/vendor/v8/src/extensions/experimental/break-iterator.cc +250 -0
  189. data/vendor/v8/src/extensions/experimental/break-iterator.h +89 -0
  190. data/vendor/v8/src/extensions/experimental/experimental.gyp +2 -0
  191. data/vendor/v8/src/extensions/experimental/i18n-extension.cc +22 -2
  192. data/vendor/v8/src/extensions/externalize-string-extension.cc +2 -2
  193. data/vendor/v8/src/extensions/gc-extension.cc +1 -1
  194. data/vendor/v8/src/factory.cc +261 -154
  195. data/vendor/v8/src/factory.h +162 -158
  196. data/vendor/v8/src/flag-definitions.h +17 -11
  197. data/vendor/v8/src/frame-element.cc +0 -5
  198. data/vendor/v8/src/frame-element.h +9 -13
  199. data/vendor/v8/src/frames-inl.h +7 -0
  200. data/vendor/v8/src/frames.cc +56 -46
  201. data/vendor/v8/src/frames.h +36 -25
  202. data/vendor/v8/src/full-codegen.cc +15 -24
  203. data/vendor/v8/src/full-codegen.h +13 -41
  204. data/vendor/v8/src/func-name-inferrer.cc +7 -6
  205. data/vendor/v8/src/func-name-inferrer.h +1 -1
  206. data/vendor/v8/src/gdb-jit.cc +1 -0
  207. data/vendor/v8/src/global-handles.cc +118 -56
  208. data/vendor/v8/src/global-handles.h +98 -40
  209. data/vendor/v8/src/globals.h +2 -2
  210. data/vendor/v8/src/handles-inl.h +106 -9
  211. data/vendor/v8/src/handles.cc +220 -157
  212. data/vendor/v8/src/handles.h +38 -59
  213. data/vendor/v8/src/hashmap.h +3 -3
  214. data/vendor/v8/src/heap-inl.h +141 -25
  215. data/vendor/v8/src/heap-profiler.cc +117 -63
  216. data/vendor/v8/src/heap-profiler.h +38 -21
  217. data/vendor/v8/src/heap.cc +805 -564
  218. data/vendor/v8/src/heap.h +640 -594
  219. data/vendor/v8/src/hydrogen-instructions.cc +216 -73
  220. data/vendor/v8/src/hydrogen-instructions.h +259 -124
  221. data/vendor/v8/src/hydrogen.cc +996 -1171
  222. data/vendor/v8/src/hydrogen.h +163 -144
  223. data/vendor/v8/src/ia32/assembler-ia32-inl.h +12 -11
  224. data/vendor/v8/src/ia32/assembler-ia32.cc +85 -39
  225. data/vendor/v8/src/ia32/assembler-ia32.h +82 -16
  226. data/vendor/v8/src/ia32/builtins-ia32.cc +64 -58
  227. data/vendor/v8/src/ia32/code-stubs-ia32.cc +248 -324
  228. data/vendor/v8/src/ia32/code-stubs-ia32.h +3 -44
  229. data/vendor/v8/src/ia32/codegen-ia32.cc +217 -165
  230. data/vendor/v8/src/ia32/codegen-ia32.h +3 -0
  231. data/vendor/v8/src/ia32/cpu-ia32.cc +6 -5
  232. data/vendor/v8/src/ia32/debug-ia32.cc +8 -5
  233. data/vendor/v8/src/ia32/deoptimizer-ia32.cc +124 -14
  234. data/vendor/v8/src/ia32/disasm-ia32.cc +85 -62
  235. data/vendor/v8/src/ia32/frames-ia32.h +1 -1
  236. data/vendor/v8/src/ia32/full-codegen-ia32.cc +348 -435
  237. data/vendor/v8/src/ia32/ic-ia32.cc +91 -91
  238. data/vendor/v8/src/ia32/lithium-codegen-ia32.cc +500 -255
  239. data/vendor/v8/src/ia32/lithium-codegen-ia32.h +13 -4
  240. data/vendor/v8/src/ia32/lithium-gap-resolver-ia32.cc +6 -0
  241. data/vendor/v8/src/ia32/lithium-ia32.cc +122 -45
  242. data/vendor/v8/src/ia32/lithium-ia32.h +128 -41
  243. data/vendor/v8/src/ia32/macro-assembler-ia32.cc +109 -84
  244. data/vendor/v8/src/ia32/macro-assembler-ia32.h +18 -9
  245. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.cc +26 -15
  246. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.h +1 -0
  247. data/vendor/v8/src/ia32/register-allocator-ia32.cc +30 -30
  248. data/vendor/v8/src/ia32/simulator-ia32.h +4 -4
  249. data/vendor/v8/src/ia32/stub-cache-ia32.cc +383 -400
  250. data/vendor/v8/src/ia32/virtual-frame-ia32.cc +36 -13
  251. data/vendor/v8/src/ia32/virtual-frame-ia32.h +11 -5
  252. data/vendor/v8/src/ic-inl.h +12 -2
  253. data/vendor/v8/src/ic.cc +304 -221
  254. data/vendor/v8/src/ic.h +115 -58
  255. data/vendor/v8/src/interpreter-irregexp.cc +25 -21
  256. data/vendor/v8/src/interpreter-irregexp.h +2 -1
  257. data/vendor/v8/src/isolate.cc +883 -0
  258. data/vendor/v8/src/isolate.h +1304 -0
  259. data/vendor/v8/src/json.js +10 -10
  260. data/vendor/v8/src/jsregexp.cc +111 -80
  261. data/vendor/v8/src/jsregexp.h +6 -7
  262. data/vendor/v8/src/jump-target-heavy.cc +5 -8
  263. data/vendor/v8/src/jump-target-heavy.h +0 -6
  264. data/vendor/v8/src/jump-target-inl.h +1 -1
  265. data/vendor/v8/src/jump-target-light.cc +3 -3
  266. data/vendor/v8/src/lithium-allocator-inl.h +2 -0
  267. data/vendor/v8/src/lithium-allocator.cc +42 -30
  268. data/vendor/v8/src/lithium-allocator.h +8 -22
  269. data/vendor/v8/src/lithium.cc +1 -0
  270. data/vendor/v8/src/liveedit.cc +141 -99
  271. data/vendor/v8/src/liveedit.h +7 -2
  272. data/vendor/v8/src/liveobjectlist-inl.h +90 -0
  273. data/vendor/v8/src/liveobjectlist.cc +2537 -1
  274. data/vendor/v8/src/liveobjectlist.h +245 -35
  275. data/vendor/v8/src/log-utils.cc +122 -35
  276. data/vendor/v8/src/log-utils.h +33 -36
  277. data/vendor/v8/src/log.cc +299 -241
  278. data/vendor/v8/src/log.h +177 -110
  279. data/vendor/v8/src/mark-compact.cc +612 -470
  280. data/vendor/v8/src/mark-compact.h +153 -80
  281. data/vendor/v8/src/messages.cc +16 -14
  282. data/vendor/v8/src/messages.js +30 -7
  283. data/vendor/v8/src/mips/assembler-mips-inl.h +155 -35
  284. data/vendor/v8/src/mips/assembler-mips.cc +1093 -219
  285. data/vendor/v8/src/mips/assembler-mips.h +552 -153
  286. data/vendor/v8/src/mips/builtins-mips.cc +43 -100
  287. data/vendor/v8/src/mips/code-stubs-mips.cc +752 -0
  288. data/vendor/v8/src/mips/code-stubs-mips.h +511 -0
  289. data/vendor/v8/src/mips/codegen-mips-inl.h +8 -14
  290. data/vendor/v8/src/mips/codegen-mips.cc +672 -896
  291. data/vendor/v8/src/mips/codegen-mips.h +271 -69
  292. data/vendor/v8/src/mips/constants-mips.cc +44 -20
  293. data/vendor/v8/src/mips/constants-mips.h +238 -40
  294. data/vendor/v8/src/mips/cpu-mips.cc +20 -3
  295. data/vendor/v8/src/mips/debug-mips.cc +35 -7
  296. data/vendor/v8/src/mips/deoptimizer-mips.cc +91 -0
  297. data/vendor/v8/src/mips/disasm-mips.cc +329 -93
  298. data/vendor/v8/src/mips/frames-mips.cc +2 -50
  299. data/vendor/v8/src/mips/frames-mips.h +24 -9
  300. data/vendor/v8/src/mips/full-codegen-mips.cc +473 -23
  301. data/vendor/v8/src/mips/ic-mips.cc +81 -45
  302. data/vendor/v8/src/mips/jump-target-mips.cc +11 -106
  303. data/vendor/v8/src/mips/lithium-codegen-mips.h +65 -0
  304. data/vendor/v8/src/mips/lithium-mips.h +304 -0
  305. data/vendor/v8/src/mips/macro-assembler-mips.cc +2391 -390
  306. data/vendor/v8/src/mips/macro-assembler-mips.h +718 -121
  307. data/vendor/v8/src/mips/regexp-macro-assembler-mips.cc +478 -0
  308. data/vendor/v8/src/mips/regexp-macro-assembler-mips.h +250 -0
  309. data/vendor/v8/src/mips/register-allocator-mips-inl.h +0 -3
  310. data/vendor/v8/src/mips/register-allocator-mips.h +3 -2
  311. data/vendor/v8/src/mips/simulator-mips.cc +1009 -221
  312. data/vendor/v8/src/mips/simulator-mips.h +119 -36
  313. data/vendor/v8/src/mips/stub-cache-mips.cc +331 -148
  314. data/vendor/v8/src/mips/{fast-codegen-mips.cc → virtual-frame-mips-inl.h} +11 -30
  315. data/vendor/v8/src/mips/virtual-frame-mips.cc +137 -149
  316. data/vendor/v8/src/mips/virtual-frame-mips.h +294 -312
  317. data/vendor/v8/src/mirror-debugger.js +9 -8
  318. data/vendor/v8/src/mksnapshot.cc +2 -2
  319. data/vendor/v8/src/objects-debug.cc +16 -16
  320. data/vendor/v8/src/objects-inl.h +421 -195
  321. data/vendor/v8/src/objects-printer.cc +7 -7
  322. data/vendor/v8/src/objects-visiting.cc +1 -1
  323. data/vendor/v8/src/objects-visiting.h +33 -12
  324. data/vendor/v8/src/objects.cc +935 -658
  325. data/vendor/v8/src/objects.h +234 -139
  326. data/vendor/v8/src/parser.cc +484 -439
  327. data/vendor/v8/src/parser.h +35 -14
  328. data/vendor/v8/src/platform-cygwin.cc +173 -107
  329. data/vendor/v8/src/platform-freebsd.cc +224 -72
  330. data/vendor/v8/src/platform-linux.cc +234 -95
  331. data/vendor/v8/src/platform-macos.cc +215 -82
  332. data/vendor/v8/src/platform-nullos.cc +9 -3
  333. data/vendor/v8/src/platform-openbsd.cc +22 -7
  334. data/vendor/v8/src/platform-posix.cc +30 -5
  335. data/vendor/v8/src/platform-solaris.cc +120 -38
  336. data/vendor/v8/src/platform-tls-mac.h +62 -0
  337. data/vendor/v8/src/platform-tls-win32.h +62 -0
  338. data/vendor/v8/src/platform-tls.h +50 -0
  339. data/vendor/v8/src/platform-win32.cc +195 -97
  340. data/vendor/v8/src/platform.h +72 -15
  341. data/vendor/v8/src/preparse-data.cc +2 -0
  342. data/vendor/v8/src/preparser-api.cc +8 -2
  343. data/vendor/v8/src/preparser.cc +1 -1
  344. data/vendor/v8/src/prettyprinter.cc +43 -52
  345. data/vendor/v8/src/prettyprinter.h +1 -1
  346. data/vendor/v8/src/profile-generator-inl.h +0 -28
  347. data/vendor/v8/src/profile-generator.cc +942 -685
  348. data/vendor/v8/src/profile-generator.h +210 -176
  349. data/vendor/v8/src/property.cc +6 -0
  350. data/vendor/v8/src/property.h +14 -3
  351. data/vendor/v8/src/regexp-macro-assembler-irregexp.cc +1 -1
  352. data/vendor/v8/src/regexp-macro-assembler.cc +28 -19
  353. data/vendor/v8/src/regexp-macro-assembler.h +11 -6
  354. data/vendor/v8/src/regexp-stack.cc +18 -10
  355. data/vendor/v8/src/regexp-stack.h +45 -21
  356. data/vendor/v8/src/regexp.js +3 -3
  357. data/vendor/v8/src/register-allocator-inl.h +3 -3
  358. data/vendor/v8/src/register-allocator.cc +1 -7
  359. data/vendor/v8/src/register-allocator.h +5 -15
  360. data/vendor/v8/src/rewriter.cc +2 -1
  361. data/vendor/v8/src/runtime-profiler.cc +158 -128
  362. data/vendor/v8/src/runtime-profiler.h +131 -15
  363. data/vendor/v8/src/runtime.cc +2409 -1692
  364. data/vendor/v8/src/runtime.h +93 -17
  365. data/vendor/v8/src/safepoint-table.cc +3 -0
  366. data/vendor/v8/src/safepoint-table.h +9 -3
  367. data/vendor/v8/src/scanner-base.cc +21 -28
  368. data/vendor/v8/src/scanner-base.h +22 -11
  369. data/vendor/v8/src/scanner.cc +3 -5
  370. data/vendor/v8/src/scanner.h +4 -2
  371. data/vendor/v8/src/scopeinfo.cc +11 -16
  372. data/vendor/v8/src/scopeinfo.h +26 -15
  373. data/vendor/v8/src/scopes.cc +67 -37
  374. data/vendor/v8/src/scopes.h +26 -12
  375. data/vendor/v8/src/serialize.cc +193 -154
  376. data/vendor/v8/src/serialize.h +41 -36
  377. data/vendor/v8/src/small-pointer-list.h +163 -0
  378. data/vendor/v8/src/snapshot-common.cc +1 -1
  379. data/vendor/v8/src/snapshot.h +3 -1
  380. data/vendor/v8/src/spaces-inl.h +30 -25
  381. data/vendor/v8/src/spaces.cc +263 -370
  382. data/vendor/v8/src/spaces.h +178 -166
  383. data/vendor/v8/src/string-search.cc +4 -3
  384. data/vendor/v8/src/string-search.h +21 -20
  385. data/vendor/v8/src/string-stream.cc +32 -24
  386. data/vendor/v8/src/string.js +7 -7
  387. data/vendor/v8/src/stub-cache.cc +324 -248
  388. data/vendor/v8/src/stub-cache.h +181 -155
  389. data/vendor/v8/src/token.cc +3 -3
  390. data/vendor/v8/src/token.h +3 -3
  391. data/vendor/v8/src/top.cc +218 -390
  392. data/vendor/v8/src/type-info.cc +98 -32
  393. data/vendor/v8/src/type-info.h +10 -3
  394. data/vendor/v8/src/unicode.cc +1 -1
  395. data/vendor/v8/src/unicode.h +1 -1
  396. data/vendor/v8/src/utils.h +3 -0
  397. data/vendor/v8/src/v8-counters.cc +18 -11
  398. data/vendor/v8/src/v8-counters.h +34 -13
  399. data/vendor/v8/src/v8.cc +66 -121
  400. data/vendor/v8/src/v8.h +7 -4
  401. data/vendor/v8/src/v8globals.h +18 -12
  402. data/vendor/v8/src/{memory.h → v8memory.h} +0 -0
  403. data/vendor/v8/src/v8natives.js +59 -18
  404. data/vendor/v8/src/v8threads.cc +127 -114
  405. data/vendor/v8/src/v8threads.h +42 -35
  406. data/vendor/v8/src/v8utils.h +2 -39
  407. data/vendor/v8/src/variables.h +1 -1
  408. data/vendor/v8/src/version.cc +26 -5
  409. data/vendor/v8/src/version.h +4 -0
  410. data/vendor/v8/src/virtual-frame-heavy-inl.h +2 -4
  411. data/vendor/v8/src/virtual-frame-light-inl.h +5 -4
  412. data/vendor/v8/src/vm-state-inl.h +21 -17
  413. data/vendor/v8/src/vm-state.h +7 -5
  414. data/vendor/v8/src/win32-headers.h +1 -0
  415. data/vendor/v8/src/x64/assembler-x64-inl.h +12 -11
  416. data/vendor/v8/src/x64/assembler-x64.cc +80 -40
  417. data/vendor/v8/src/x64/assembler-x64.h +67 -17
  418. data/vendor/v8/src/x64/builtins-x64.cc +34 -33
  419. data/vendor/v8/src/x64/code-stubs-x64.cc +636 -377
  420. data/vendor/v8/src/x64/code-stubs-x64.h +14 -48
  421. data/vendor/v8/src/x64/codegen-x64-inl.h +1 -1
  422. data/vendor/v8/src/x64/codegen-x64.cc +158 -136
  423. data/vendor/v8/src/x64/codegen-x64.h +4 -1
  424. data/vendor/v8/src/x64/cpu-x64.cc +7 -5
  425. data/vendor/v8/src/x64/debug-x64.cc +8 -6
  426. data/vendor/v8/src/x64/deoptimizer-x64.cc +195 -20
  427. data/vendor/v8/src/x64/disasm-x64.cc +42 -23
  428. data/vendor/v8/src/x64/frames-x64.cc +1 -1
  429. data/vendor/v8/src/x64/frames-x64.h +2 -2
  430. data/vendor/v8/src/x64/full-codegen-x64.cc +780 -218
  431. data/vendor/v8/src/x64/ic-x64.cc +77 -79
  432. data/vendor/v8/src/x64/jump-target-x64.cc +1 -1
  433. data/vendor/v8/src/x64/lithium-codegen-x64.cc +698 -181
  434. data/vendor/v8/src/x64/lithium-codegen-x64.h +31 -6
  435. data/vendor/v8/src/x64/lithium-x64.cc +136 -54
  436. data/vendor/v8/src/x64/lithium-x64.h +142 -51
  437. data/vendor/v8/src/x64/macro-assembler-x64.cc +456 -187
  438. data/vendor/v8/src/x64/macro-assembler-x64.h +166 -34
  439. data/vendor/v8/src/x64/regexp-macro-assembler-x64.cc +44 -28
  440. data/vendor/v8/src/x64/regexp-macro-assembler-x64.h +8 -4
  441. data/vendor/v8/src/x64/register-allocator-x64-inl.h +3 -3
  442. data/vendor/v8/src/x64/register-allocator-x64.cc +12 -8
  443. data/vendor/v8/src/x64/simulator-x64.h +5 -5
  444. data/vendor/v8/src/x64/stub-cache-x64.cc +299 -344
  445. data/vendor/v8/src/x64/virtual-frame-x64.cc +37 -13
  446. data/vendor/v8/src/x64/virtual-frame-x64.h +13 -7
  447. data/vendor/v8/src/zone-inl.h +49 -3
  448. data/vendor/v8/src/zone.cc +42 -41
  449. data/vendor/v8/src/zone.h +37 -34
  450. data/vendor/v8/test/benchmarks/testcfg.py +100 -0
  451. data/vendor/v8/test/cctest/SConscript +5 -4
  452. data/vendor/v8/test/cctest/cctest.h +3 -2
  453. data/vendor/v8/test/cctest/cctest.status +6 -11
  454. data/vendor/v8/test/cctest/test-accessors.cc +3 -3
  455. data/vendor/v8/test/cctest/test-alloc.cc +39 -33
  456. data/vendor/v8/test/cctest/test-api.cc +1092 -205
  457. data/vendor/v8/test/cctest/test-assembler-arm.cc +39 -25
  458. data/vendor/v8/test/cctest/test-assembler-ia32.cc +36 -37
  459. data/vendor/v8/test/cctest/test-assembler-mips.cc +1098 -40
  460. data/vendor/v8/test/cctest/test-assembler-x64.cc +32 -25
  461. data/vendor/v8/test/cctest/test-ast.cc +1 -0
  462. data/vendor/v8/test/cctest/test-circular-queue.cc +8 -5
  463. data/vendor/v8/test/cctest/test-compiler.cc +24 -24
  464. data/vendor/v8/test/cctest/test-cpu-profiler.cc +140 -5
  465. data/vendor/v8/test/cctest/test-dataflow.cc +1 -0
  466. data/vendor/v8/test/cctest/test-debug.cc +136 -77
  467. data/vendor/v8/test/cctest/test-decls.cc +1 -1
  468. data/vendor/v8/test/cctest/test-deoptimization.cc +25 -24
  469. data/vendor/v8/test/cctest/test-disasm-arm.cc +9 -4
  470. data/vendor/v8/test/cctest/test-disasm-ia32.cc +10 -8
  471. data/vendor/v8/test/cctest/test-func-name-inference.cc +10 -4
  472. data/vendor/v8/test/cctest/test-heap-profiler.cc +226 -164
  473. data/vendor/v8/test/cctest/test-heap.cc +240 -217
  474. data/vendor/v8/test/cctest/test-liveedit.cc +1 -0
  475. data/vendor/v8/test/cctest/test-log-stack-tracer.cc +18 -20
  476. data/vendor/v8/test/cctest/test-log.cc +114 -108
  477. data/vendor/v8/test/cctest/test-macro-assembler-x64.cc +247 -177
  478. data/vendor/v8/test/cctest/test-mark-compact.cc +129 -90
  479. data/vendor/v8/test/cctest/test-parsing.cc +15 -14
  480. data/vendor/v8/test/cctest/test-platform-linux.cc +1 -0
  481. data/vendor/v8/test/cctest/test-platform-tls.cc +66 -0
  482. data/vendor/v8/test/cctest/test-platform-win32.cc +1 -0
  483. data/vendor/v8/test/cctest/test-profile-generator.cc +1 -1
  484. data/vendor/v8/test/cctest/test-regexp.cc +53 -41
  485. data/vendor/v8/test/cctest/test-reloc-info.cc +18 -11
  486. data/vendor/v8/test/cctest/test-serialize.cc +44 -43
  487. data/vendor/v8/test/cctest/test-sockets.cc +8 -3
  488. data/vendor/v8/test/cctest/test-spaces.cc +47 -29
  489. data/vendor/v8/test/cctest/test-strings.cc +20 -20
  490. data/vendor/v8/test/cctest/test-thread-termination.cc +8 -3
  491. data/vendor/v8/test/cctest/test-threads.cc +5 -3
  492. data/vendor/v8/test/cctest/test-utils.cc +5 -4
  493. data/vendor/v8/test/cctest/testcfg.py +7 -3
  494. data/vendor/v8/test/es5conform/es5conform.status +2 -77
  495. data/vendor/v8/test/es5conform/testcfg.py +1 -1
  496. data/vendor/v8/test/message/testcfg.py +1 -1
  497. data/vendor/v8/test/mjsunit/accessors-on-global-object.js +3 -3
  498. data/vendor/v8/test/mjsunit/array-concat.js +43 -1
  499. data/vendor/v8/test/mjsunit/array-join.js +25 -0
  500. data/vendor/v8/test/mjsunit/bitops-info.js +7 -1
  501. data/vendor/v8/test/mjsunit/compiler/array-length.js +2 -2
  502. data/vendor/v8/test/mjsunit/compiler/global-accessors.js +47 -0
  503. data/vendor/v8/test/mjsunit/compiler/pic.js +1 -1
  504. data/vendor/v8/test/mjsunit/compiler/regress-loadfield.js +65 -0
  505. data/vendor/v8/test/mjsunit/math-sqrt.js +5 -1
  506. data/vendor/v8/test/mjsunit/mjsunit.js +59 -8
  507. data/vendor/v8/test/mjsunit/mjsunit.status +0 -12
  508. data/vendor/v8/test/mjsunit/mul-exhaustive.js +129 -11
  509. data/vendor/v8/test/mjsunit/negate-zero.js +1 -1
  510. data/vendor/v8/test/mjsunit/object-freeze.js +5 -13
  511. data/vendor/v8/test/mjsunit/object-prevent-extensions.js +9 -50
  512. data/vendor/v8/test/mjsunit/object-seal.js +4 -13
  513. data/vendor/v8/test/mjsunit/override-eval-with-non-function.js +36 -0
  514. data/vendor/v8/test/mjsunit/regress/regress-1145.js +54 -0
  515. data/vendor/v8/test/mjsunit/regress/regress-1172-bis.js +37 -0
  516. data/vendor/v8/test/mjsunit/regress/regress-1181.js +54 -0
  517. data/vendor/v8/test/mjsunit/regress/regress-1207.js +35 -0
  518. data/vendor/v8/test/mjsunit/regress/regress-1209.js +34 -0
  519. data/vendor/v8/test/mjsunit/regress/regress-1210.js +48 -0
  520. data/vendor/v8/test/mjsunit/regress/regress-1213.js +43 -0
  521. data/vendor/v8/test/mjsunit/regress/regress-1218.js +29 -0
  522. data/vendor/v8/test/mjsunit/regress/regress-1229.js +79 -0
  523. data/vendor/v8/test/mjsunit/regress/regress-1233.js +47 -0
  524. data/vendor/v8/test/mjsunit/regress/regress-1236.js +34 -0
  525. data/vendor/v8/test/mjsunit/regress/regress-1237.js +36 -0
  526. data/vendor/v8/test/mjsunit/regress/regress-1240.js +39 -0
  527. data/vendor/v8/test/mjsunit/regress/regress-1257.js +58 -0
  528. data/vendor/v8/test/mjsunit/regress/regress-1278.js +69 -0
  529. data/vendor/v8/test/mjsunit/regress/regress-create-exception.js +1 -0
  530. data/vendor/v8/test/mjsunit/regress/regress-lazy-deopt-reloc.js +52 -0
  531. data/vendor/v8/test/mjsunit/sin-cos.js +15 -10
  532. data/vendor/v8/test/mjsunit/smi-negative-zero.js +2 -2
  533. data/vendor/v8/test/mjsunit/str-to-num.js +1 -1
  534. data/vendor/v8/test/mjsunit/strict-mode.js +435 -0
  535. data/vendor/v8/test/mjsunit/testcfg.py +23 -6
  536. data/vendor/v8/test/mozilla/mozilla.status +0 -2
  537. data/vendor/v8/test/mozilla/testcfg.py +1 -1
  538. data/vendor/v8/test/preparser/empty.js +28 -0
  539. data/vendor/v8/test/preparser/functions-only.js +38 -0
  540. data/vendor/v8/test/preparser/non-alphanum.js +34 -0
  541. data/vendor/v8/test/preparser/symbols-only.js +49 -0
  542. data/vendor/v8/test/preparser/testcfg.py +90 -0
  543. data/vendor/v8/test/sputnik/testcfg.py +1 -1
  544. data/vendor/v8/test/test262/README +16 -0
  545. data/vendor/v8/test/test262/harness-adapt.js +80 -0
  546. data/vendor/v8/test/test262/test262.status +1506 -0
  547. data/vendor/v8/test/test262/testcfg.py +123 -0
  548. data/vendor/v8/tools/freebsd-tick-processor +10 -0
  549. data/vendor/v8/tools/gyp/v8.gyp +8 -33
  550. data/vendor/v8/tools/linux-tick-processor +5 -3
  551. data/vendor/v8/tools/test.py +37 -14
  552. data/vendor/v8/tools/tickprocessor.js +22 -8
  553. data/vendor/v8/tools/visual_studio/v8_base.vcproj +13 -1
  554. data/vendor/v8/tools/visual_studio/v8_base_arm.vcproj +5 -1
  555. data/vendor/v8/tools/visual_studio/v8_base_x64.vcproj +5 -1
  556. data/vendor/v8/tools/visual_studio/x64.vsprops +1 -0
  557. metadata +1495 -1341
  558. data/ext/extconf.rb +0 -22
  559. data/ext/mustang.cpp +0 -58
  560. data/vendor/v8/src/top.h +0 -608
@@ -25,6 +25,7 @@
25
25
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
26
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
 
28
+ #include "v8.h"
28
29
  #include "hydrogen.h"
29
30
 
30
31
  #include "codegen.h"
@@ -42,6 +43,8 @@
42
43
  #include "x64/lithium-codegen-x64.h"
43
44
  #elif V8_TARGET_ARCH_ARM
44
45
  #include "arm/lithium-codegen-arm.h"
46
+ #elif V8_TARGET_ARCH_MIPS
47
+ #include "mips/lithium-codegen-mips.h"
45
48
  #else
46
49
  #error Unsupported target architecture.
47
50
  #endif
@@ -92,7 +95,7 @@ void HBasicBlock::AddPhi(HPhi* phi) {
92
95
  void HBasicBlock::RemovePhi(HPhi* phi) {
93
96
  ASSERT(phi->block() == this);
94
97
  ASSERT(phis_.Contains(phi));
95
- ASSERT(phi->HasNoUses());
98
+ ASSERT(phi->HasNoUses() || !phi->is_live());
96
99
  phi->ClearOperands();
97
100
  phis_.RemoveElement(phi);
98
101
  phi->SetBlock(NULL);
@@ -113,6 +116,21 @@ void HBasicBlock::AddInstruction(HInstruction* instr) {
113
116
  }
114
117
 
115
118
 
119
+ HDeoptimize* HBasicBlock::CreateDeoptimize() {
120
+ ASSERT(HasEnvironment());
121
+ HEnvironment* environment = last_environment();
122
+
123
+ HDeoptimize* instr = new HDeoptimize(environment->length());
124
+
125
+ for (int i = 0; i < environment->length(); i++) {
126
+ HValue* val = environment->values()->at(i);
127
+ instr->AddEnvironmentValue(val);
128
+ }
129
+
130
+ return instr;
131
+ }
132
+
133
+
116
134
  HSimulate* HBasicBlock::CreateSimulate(int id) {
117
135
  ASSERT(HasEnvironment());
118
136
  HEnvironment* environment = last_environment();
@@ -150,6 +168,10 @@ void HBasicBlock::Finish(HControlInstruction* end) {
150
168
 
151
169
 
152
170
  void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
171
+ if (block->IsInlineReturnTarget()) {
172
+ AddInstruction(new HLeaveInlined);
173
+ last_environment_ = last_environment()->outer();
174
+ }
153
175
  AddSimulate(AstNode::kNoNumber);
154
176
  HGoto* instr = new HGoto(block);
155
177
  instr->set_include_stack_check(include_stack_check);
@@ -157,6 +179,18 @@ void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) {
157
179
  }
158
180
 
159
181
 
182
+ void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
183
+ ASSERT(target->IsInlineReturnTarget());
184
+ ASSERT(return_value != NULL);
185
+ AddInstruction(new HLeaveInlined);
186
+ last_environment_ = last_environment()->outer();
187
+ last_environment()->Push(return_value);
188
+ AddSimulate(AstNode::kNoNumber);
189
+ HGoto* instr = new HGoto(target);
190
+ Finish(instr);
191
+ }
192
+
193
+
160
194
  void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
161
195
  ASSERT(!HasEnvironment());
162
196
  ASSERT(first() == NULL);
@@ -286,6 +320,13 @@ void HBasicBlock::Verify() {
286
320
  // Check that every block is finished.
287
321
  ASSERT(IsFinished());
288
322
  ASSERT(block_id() >= 0);
323
+
324
+ // Check that the incoming edges are in edge split form.
325
+ if (predecessors_.length() > 1) {
326
+ for (int i = 0; i < predecessors_.length(); ++i) {
327
+ ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL);
328
+ }
329
+ }
289
330
  }
290
331
  #endif
291
332
 
@@ -473,158 +514,81 @@ HConstant* HGraph::GetConstantMinus1() {
473
514
 
474
515
 
475
516
  HConstant* HGraph::GetConstantTrue() {
476
- return GetConstant(&constant_true_, Heap::true_value());
517
+ return GetConstant(&constant_true_, isolate()->heap()->true_value());
477
518
  }
478
519
 
479
520
 
480
521
  HConstant* HGraph::GetConstantFalse() {
481
- return GetConstant(&constant_false_, Heap::false_value());
522
+ return GetConstant(&constant_false_, isolate()->heap()->false_value());
482
523
  }
483
524
 
484
525
 
485
- void HSubgraph::AppendJoin(HBasicBlock* first,
486
- HBasicBlock* second,
487
- int join_id) {
526
+ HBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
527
+ HBasicBlock* second,
528
+ int join_id) {
488
529
  if (first == NULL) {
489
- exit_block_ = second;
530
+ return second;
490
531
  } else if (second == NULL) {
491
- exit_block_ = first;
532
+ return first;
492
533
  } else {
493
534
  HBasicBlock* join_block = graph_->CreateBasicBlock();
494
535
  first->Goto(join_block);
495
536
  second->Goto(join_block);
496
537
  join_block->SetJoinId(join_id);
497
- exit_block_ = join_block;
538
+ return join_block;
498
539
  }
499
540
  }
500
541
 
501
542
 
502
- void HSubgraph::ResolveContinue(IterationStatement* statement,
503
- HBasicBlock* continue_block) {
543
+ HBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
544
+ HBasicBlock* exit_block,
545
+ HBasicBlock* continue_block) {
504
546
  if (continue_block != NULL) {
547
+ if (exit_block != NULL) exit_block->Goto(continue_block);
505
548
  continue_block->SetJoinId(statement->ContinueId());
549
+ return continue_block;
506
550
  }
507
- exit_block_ =
508
- JoinBlocks(exit_block(), continue_block, statement->ContinueId());
551
+ return exit_block;
509
552
  }
510
553
 
511
554
 
512
- HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) {
513
- if (a == NULL) return b;
514
- if (b == NULL) return a;
515
- HBasicBlock* target = graph_->CreateBasicBlock();
516
- a->Goto(target);
517
- b->Goto(target);
518
- target->SetJoinId(id);
519
- return target;
520
- }
521
-
522
-
523
- void HSubgraph::AppendEndless(IterationStatement* statement,
524
- HBasicBlock* body_entry,
525
- HBasicBlock* body_exit,
526
- HBasicBlock* break_block) {
527
- if (exit_block() != NULL) {
528
- exit_block()->Goto(body_entry, false);
529
- }
530
- if (body_exit != NULL) {
531
- body_exit->Goto(body_entry, true);
555
+ HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
556
+ HBasicBlock* loop_entry,
557
+ HBasicBlock* body_exit,
558
+ HBasicBlock* loop_successor,
559
+ HBasicBlock* break_block) {
560
+ if (body_exit != NULL) body_exit->Goto(loop_entry, true);
561
+ loop_entry->PostProcessLoopHeader(statement);
562
+ if (break_block != NULL) {
563
+ if (loop_successor != NULL) loop_successor->Goto(break_block);
564
+ break_block->SetJoinId(statement->ExitId());
565
+ return break_block;
532
566
  }
533
- if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
534
- exit_block_ = break_block;
535
- body_entry->PostProcessLoopHeader(statement);
567
+ return loop_successor;
536
568
  }
537
569
 
538
570
 
539
- void HSubgraph::AppendDoWhile(IterationStatement* statement,
540
- HBasicBlock* body_entry,
541
- HBasicBlock* go_back,
542
- HBasicBlock* exit_block,
543
- HBasicBlock* break_block) {
544
- if (this->exit_block() != NULL) {
545
- this->exit_block()->Goto(body_entry, false);
546
- }
547
- if (go_back != NULL) {
548
- go_back->Goto(body_entry, true);
549
- }
550
- if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
551
- exit_block_ =
552
- JoinBlocks(exit_block, break_block, statement->ExitId());
553
- body_entry->PostProcessLoopHeader(statement);
554
- }
555
-
556
-
557
- void HSubgraph::AppendWhile(IterationStatement* statement,
558
- HBasicBlock* condition_entry,
559
- HBasicBlock* exit_block,
560
- HBasicBlock* body_exit,
561
- HBasicBlock* break_block,
562
- HBasicBlock* loop_entry,
563
- HBasicBlock* loop_exit) {
564
- if (this->exit_block() != NULL) {
565
- this->exit_block()->Goto(condition_entry, false);
566
- }
567
-
568
- if (break_block != NULL) break_block->SetJoinId(statement->ExitId());
569
- exit_block_ =
570
- JoinBlocks(exit_block, break_block, statement->ExitId());
571
-
572
- if (loop_entry != NULL) {
573
- if (body_exit != NULL) {
574
- body_exit->Goto(loop_entry, true);
575
- }
576
- loop_entry->SetJoinId(statement->EntryId());
577
- exit_block_ = JoinBlocks(exit_block_, loop_exit, statement->ExitId());
578
- } else {
579
- if (body_exit != NULL) {
580
- body_exit->Goto(condition_entry, true);
581
- }
582
- }
583
- condition_entry->PostProcessLoopHeader(statement);
584
- }
585
-
586
-
587
- void HSubgraph::Append(BreakableStatement* stmt,
588
- HBasicBlock* entry_block,
589
- HBasicBlock* exit_block,
590
- HBasicBlock* break_block) {
591
- exit_block_->Goto(entry_block);
592
- exit_block_ = exit_block;
593
-
594
- if (stmt != NULL) {
595
- entry_block->SetJoinId(stmt->EntryId());
596
- if (break_block != NULL) break_block->SetJoinId(stmt->EntryId());
597
- exit_block_ = JoinBlocks(exit_block, break_block, stmt->ExitId());
598
- }
599
- }
600
-
601
-
602
- void HSubgraph::FinishExit(HControlInstruction* instruction) {
603
- ASSERT(exit_block() != NULL);
604
- exit_block_->Finish(instruction);
605
- exit_block_->ClearEnvironment();
606
- exit_block_ = NULL;
571
+ void HBasicBlock::FinishExit(HControlInstruction* instruction) {
572
+ Finish(instruction);
573
+ ClearEnvironment();
607
574
  }
608
575
 
609
576
 
610
577
  HGraph::HGraph(CompilationInfo* info)
611
- : HSubgraph(this),
578
+ : isolate_(info->isolate()),
612
579
  next_block_id_(0),
613
- info_(info),
580
+ entry_block_(NULL),
614
581
  blocks_(8),
615
582
  values_(16),
616
583
  phi_list_(NULL) {
617
584
  start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
618
585
  start_environment_->set_ast_id(info->function()->id());
586
+ entry_block_ = CreateBasicBlock();
587
+ entry_block_->SetInitialEnvironment(start_environment_);
619
588
  }
620
589
 
621
590
 
622
- bool HGraph::AllowCodeMotion() const {
623
- return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
624
- }
625
-
626
-
627
- Handle<Code> HGraph::Compile() {
591
+ Handle<Code> HGraph::Compile(CompilationInfo* info) {
628
592
  int values = GetMaximumValueID();
629
593
  if (values > LAllocator::max_initial_value_ids()) {
630
594
  if (FLAG_trace_bailout) PrintF("Function is too big\n");
@@ -632,7 +596,7 @@ Handle<Code> HGraph::Compile() {
632
596
  }
633
597
 
634
598
  LAllocator allocator(values, this);
635
- LChunkBuilder builder(this, &allocator);
599
+ LChunkBuilder builder(info, this, &allocator);
636
600
  LChunk* chunk = builder.Build();
637
601
  if (chunk == NULL) return Handle<Code>::null();
638
602
 
@@ -642,8 +606,8 @@ Handle<Code> HGraph::Compile() {
642
606
 
643
607
  if (!FLAG_use_lithium) return Handle<Code>::null();
644
608
 
645
- MacroAssembler assembler(NULL, 0);
646
- LCodeGen generator(chunk, &assembler, info());
609
+ MacroAssembler assembler(info->isolate(), NULL, 0);
610
+ LCodeGen generator(chunk, &assembler, info);
647
611
 
648
612
  if (FLAG_eliminate_empty_blocks) {
649
613
  chunk->MarkEmptyBlocks();
@@ -653,13 +617,13 @@ Handle<Code> HGraph::Compile() {
653
617
  if (FLAG_trace_codegen) {
654
618
  PrintF("Crankshaft Compiler - ");
655
619
  }
656
- CodeGenerator::MakeCodePrologue(info());
620
+ CodeGenerator::MakeCodePrologue(info);
657
621
  Code::Flags flags =
658
622
  Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP);
659
623
  Handle<Code> code =
660
- CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
624
+ CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
661
625
  generator.FinishCode(code);
662
- CodeGenerator::PrintCode(code, info());
626
+ CodeGenerator::PrintCode(code, info);
663
627
  return code;
664
628
  }
665
629
  return Handle<Code>::null();
@@ -674,20 +638,14 @@ HBasicBlock* HGraph::CreateBasicBlock() {
674
638
 
675
639
 
676
640
  void HGraph::Canonicalize() {
641
+ if (!FLAG_use_canonicalizing) return;
677
642
  HPhase phase("Canonicalize", this);
678
- if (FLAG_use_canonicalizing) {
679
- for (int i = 0; i < blocks()->length(); ++i) {
680
- HBasicBlock* b = blocks()->at(i);
681
- for (HInstruction* insn = b->first(); insn != NULL; insn = insn->next()) {
682
- HValue* value = insn->Canonicalize();
683
- if (value != insn) {
684
- if (value != NULL) {
685
- insn->ReplaceAndDelete(value);
686
- } else {
687
- insn->Delete();
688
- }
689
- }
690
- }
643
+ for (int i = 0; i < blocks()->length(); ++i) {
644
+ HInstruction* instr = blocks()->at(i)->first();
645
+ while (instr != NULL) {
646
+ HValue* value = instr->Canonicalize();
647
+ if (value != instr) instr->ReplaceAndDelete(value);
648
+ instr = instr->next();
691
649
  }
692
650
  }
693
651
  }
@@ -701,7 +659,7 @@ void HGraph::OrderBlocks() {
701
659
  HBasicBlock* start = blocks_[0];
702
660
  Postorder(start, &visited, &reverse_result, NULL);
703
661
 
704
- blocks_.Clear();
662
+ blocks_.Rewind(0);
705
663
  int index = 0;
706
664
  for (int i = reverse_result.length() - 1; i >= 0; --i) {
707
665
  HBasicBlock* b = reverse_result[i];
@@ -766,8 +724,7 @@ void HGraph::AssignDominators() {
766
724
 
767
725
 
768
726
  void HGraph::EliminateRedundantPhis() {
769
- HPhase phase("Phi elimination", this);
770
- ZoneList<HValue*> uses_to_replace(2);
727
+ HPhase phase("Redundant phi elimination", this);
771
728
 
772
729
  // Worklist of phis that can potentially be eliminated. Initialized
773
730
  // with all phi nodes. When elimination of a phi node modifies
@@ -790,26 +747,57 @@ void HGraph::EliminateRedundantPhis() {
790
747
  if (value != NULL) {
791
748
  // Iterate through uses finding the ones that should be
792
749
  // replaced.
793
- const ZoneList<HValue*>* uses = phi->uses();
794
- for (int i = 0; i < uses->length(); ++i) {
795
- HValue* use = uses->at(i);
796
- if (!use->block()->IsStartBlock()) {
797
- uses_to_replace.Add(use);
750
+ SmallPointerList<HValue>* uses = phi->uses();
751
+ while (!uses->is_empty()) {
752
+ HValue* use = uses->RemoveLast();
753
+ if (use != NULL) {
754
+ phi->ReplaceAtUse(use, value);
755
+ if (use->IsPhi()) worklist.Add(HPhi::cast(use));
798
756
  }
799
757
  }
800
- // Replace the uses and add phis modified to the work list.
801
- for (int i = 0; i < uses_to_replace.length(); ++i) {
802
- HValue* use = uses_to_replace[i];
803
- phi->ReplaceAtUse(use, value);
804
- if (use->IsPhi()) worklist.Add(HPhi::cast(use));
805
- }
806
- uses_to_replace.Rewind(0);
807
758
  block->RemovePhi(phi);
808
- } else if (FLAG_eliminate_dead_phis && phi->HasNoUses() &&
809
- !phi->IsReceiver()) {
759
+ }
760
+ }
761
+ }
762
+
763
+
764
+ void HGraph::EliminateUnreachablePhis() {
765
+ HPhase phase("Unreachable phi elimination", this);
766
+
767
+ // Initialize worklist.
768
+ ZoneList<HPhi*> phi_list(blocks_.length());
769
+ ZoneList<HPhi*> worklist(blocks_.length());
770
+ for (int i = 0; i < blocks_.length(); ++i) {
771
+ for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
772
+ HPhi* phi = blocks_[i]->phis()->at(j);
773
+ phi_list.Add(phi);
810
774
  // We can't eliminate phis in the receiver position in the environment
811
775
  // because in case of throwing an error we need this value to
812
776
  // construct a stack trace.
777
+ if (phi->HasRealUses() || phi->IsReceiver()) {
778
+ phi->set_is_live(true);
779
+ worklist.Add(phi);
780
+ }
781
+ }
782
+ }
783
+
784
+ // Iteratively mark live phis.
785
+ while (!worklist.is_empty()) {
786
+ HPhi* phi = worklist.RemoveLast();
787
+ for (int i = 0; i < phi->OperandCount(); i++) {
788
+ HValue* operand = phi->OperandAt(i);
789
+ if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) {
790
+ HPhi::cast(operand)->set_is_live(true);
791
+ worklist.Add(HPhi::cast(operand));
792
+ }
793
+ }
794
+ }
795
+
796
+ // Remove unreachable phis.
797
+ for (int i = 0; i < phi_list.length(); i++) {
798
+ HPhi* phi = phi_list[i];
799
+ if (!phi->is_live()) {
800
+ HBasicBlock* block = phi->block();
813
801
  block->RemovePhi(phi);
814
802
  block->RecordDeletedPhi(phi->merged_index());
815
803
  }
@@ -818,11 +806,11 @@ void HGraph::EliminateRedundantPhis() {
818
806
 
819
807
 
820
808
  bool HGraph::CollectPhis() {
821
- const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
822
- phi_list_ = new ZoneList<HPhi*>(blocks->length());
823
- for (int i = 0; i < blocks->length(); ++i) {
824
- for (int j = 0; j < blocks->at(i)->phis()->length(); j++) {
825
- HPhi* phi = blocks->at(i)->phis()->at(j);
809
+ int block_count = blocks_.length();
810
+ phi_list_ = new ZoneList<HPhi*>(block_count);
811
+ for (int i = 0; i < block_count; ++i) {
812
+ for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
813
+ HPhi* phi = blocks_[i]->phis()->at(j);
826
814
  phi_list_->Add(phi);
827
815
  // We don't support phi uses of arguments for now.
828
816
  if (phi->CheckFlag(HValue::kIsArguments)) return false;
@@ -931,13 +919,15 @@ void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
931
919
  ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
932
920
  if (test->value()->IsCompare()) {
933
921
  HCompare* compare = HCompare::cast(test->value());
934
- Token::Value op = compare->token();
935
- if (test->SecondSuccessor() == dest) {
936
- op = Token::NegateCompareOp(op);
922
+ if (compare->GetInputRepresentation().IsInteger32()) {
923
+ Token::Value op = compare->token();
924
+ if (test->SecondSuccessor() == dest) {
925
+ op = Token::NegateCompareOp(op);
926
+ }
927
+ Token::Value inverted_op = Token::InvertCompareOp(op);
928
+ InferControlFlowRange(op, compare->left(), compare->right());
929
+ InferControlFlowRange(inverted_op, compare->right(), compare->left());
937
930
  }
938
- Token::Value inverted_op = Token::InvertCompareOp(op);
939
- InferControlFlowRange(op, compare->left(), compare->right());
940
- InferControlFlowRange(inverted_op, compare->right(), compare->left());
941
931
  }
942
932
  }
943
933
 
@@ -947,8 +937,8 @@ void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
947
937
  void HRangeAnalysis::InferControlFlowRange(Token::Value op,
948
938
  HValue* value,
949
939
  HValue* other) {
950
- Range* range = other->range();
951
- if (range == NULL) range = new Range();
940
+ Range temp_range;
941
+ Range* range = other->range() != NULL ? other->range() : &temp_range;
952
942
  Range* new_range = NULL;
953
943
 
954
944
  TraceRange("Control flow range infer %d %s %d\n",
@@ -1040,8 +1030,8 @@ HValueMap::HValueMap(const HValueMap* other)
1040
1030
  lists_size_(other->lists_size_),
1041
1031
  count_(other->count_),
1042
1032
  present_flags_(other->present_flags_),
1043
- array_(Zone::NewArray<HValueMapListElement>(other->array_size_)),
1044
- lists_(Zone::NewArray<HValueMapListElement>(other->lists_size_)),
1033
+ array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)),
1034
+ lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)),
1045
1035
  free_list_head_(other->free_list_head_) {
1046
1036
  memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
1047
1037
  memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
@@ -1120,7 +1110,7 @@ void HValueMap::Resize(int new_size) {
1120
1110
  }
1121
1111
 
1122
1112
  HValueMapListElement* new_array =
1123
- Zone::NewArray<HValueMapListElement>(new_size);
1113
+ ZONE->NewArray<HValueMapListElement>(new_size);
1124
1114
  memset(new_array, 0, sizeof(HValueMapListElement) * new_size);
1125
1115
 
1126
1116
  HValueMapListElement* old_array = array_;
@@ -1158,7 +1148,7 @@ void HValueMap::ResizeLists(int new_size) {
1158
1148
  ASSERT(new_size > lists_size_);
1159
1149
 
1160
1150
  HValueMapListElement* new_lists =
1161
- Zone::NewArray<HValueMapListElement>(new_size);
1151
+ ZONE->NewArray<HValueMapListElement>(new_size);
1162
1152
  memset(new_lists, 0, sizeof(HValueMapListElement) * new_size);
1163
1153
 
1164
1154
  HValueMapListElement* old_lists = lists_;
@@ -1256,16 +1246,17 @@ void HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) {
1256
1246
 
1257
1247
  class HGlobalValueNumberer BASE_EMBEDDED {
1258
1248
  public:
1259
- explicit HGlobalValueNumberer(HGraph* graph)
1249
+ explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1260
1250
  : graph_(graph),
1251
+ info_(info),
1261
1252
  block_side_effects_(graph_->blocks()->length()),
1262
1253
  loop_side_effects_(graph_->blocks()->length()) {
1263
- ASSERT(Heap::allow_allocation(false));
1254
+ ASSERT(info->isolate()->heap()->allow_allocation(false));
1264
1255
  block_side_effects_.AddBlock(0, graph_->blocks()->length());
1265
1256
  loop_side_effects_.AddBlock(0, graph_->blocks()->length());
1266
1257
  }
1267
1258
  ~HGlobalValueNumberer() {
1268
- ASSERT(!Heap::allow_allocation(true));
1259
+ ASSERT(!info_->isolate()->heap()->allow_allocation(true));
1269
1260
  }
1270
1261
 
1271
1262
  void Analyze();
@@ -1277,9 +1268,14 @@ class HGlobalValueNumberer BASE_EMBEDDED {
1277
1268
  void ProcessLoopBlock(HBasicBlock* block,
1278
1269
  HBasicBlock* before_loop,
1279
1270
  int loop_kills);
1271
+ bool AllowCodeMotion();
1280
1272
  bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1281
1273
 
1274
+ HGraph* graph() { return graph_; }
1275
+ CompilationInfo* info() { return info_; }
1276
+
1282
1277
  HGraph* graph_;
1278
+ CompilationInfo* info_;
1283
1279
 
1284
1280
  // A map of block IDs to their side effects.
1285
1281
  ZoneList<int> block_side_effects_;
@@ -1380,10 +1376,15 @@ void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
1380
1376
  }
1381
1377
 
1382
1378
 
1379
+ bool HGlobalValueNumberer::AllowCodeMotion() {
1380
+ return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1381
+ }
1382
+
1383
+
1383
1384
  bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1384
1385
  HBasicBlock* loop_header) {
1385
1386
  // If we've disabled code motion, don't move any instructions.
1386
- if (!graph_->AllowCodeMotion()) return false;
1387
+ if (!AllowCodeMotion()) return false;
1387
1388
 
1388
1389
  // If --aggressive-loop-invariant-motion, move everything except change
1389
1390
  // instructions.
@@ -1443,8 +1444,7 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1443
1444
  instr->Mnemonic(),
1444
1445
  other->id(),
1445
1446
  other->Mnemonic());
1446
- instr->ReplaceValue(other);
1447
- instr->Delete();
1447
+ instr->ReplaceAndDelete(other);
1448
1448
  } else {
1449
1449
  map->Add(instr);
1450
1450
  }
@@ -1744,8 +1744,7 @@ void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
1744
1744
 
1745
1745
  void HGraph::InsertRepresentationChangeForUse(HValue* value,
1746
1746
  HValue* use,
1747
- Representation to,
1748
- bool is_truncating) {
1747
+ Representation to) {
1749
1748
  // Insert the representation change right before its use. For phi-uses we
1750
1749
  // insert at the end of the corresponding predecessor.
1751
1750
  HInstruction* next = NULL;
@@ -1762,6 +1761,7 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
1762
1761
  // information we treat constants like normal instructions and insert the
1763
1762
  // change instructions for them.
1764
1763
  HInstruction* new_value = NULL;
1764
+ bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
1765
1765
  if (value->IsConstant()) {
1766
1766
  HConstant* constant = HConstant::cast(value);
1767
1767
  // Try to create a new copy of the constant with the new representation.
@@ -1771,7 +1771,7 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
1771
1771
  }
1772
1772
 
1773
1773
  if (new_value == NULL) {
1774
- new_value = new HChange(value, value->representation(), to);
1774
+ new_value = new HChange(value, value->representation(), to, is_truncating);
1775
1775
  }
1776
1776
 
1777
1777
  new_value->InsertBefore(next);
@@ -1798,15 +1798,18 @@ int CompareConversionUses(HValue* a,
1798
1798
  }
1799
1799
 
1800
1800
 
1801
- void HGraph::InsertRepresentationChanges(HValue* current) {
1801
+ void HGraph::InsertRepresentationChangesForValue(
1802
+ HValue* current,
1803
+ ZoneList<HValue*>* to_convert,
1804
+ ZoneList<Representation>* to_convert_reps) {
1802
1805
  Representation r = current->representation();
1803
1806
  if (r.IsNone()) return;
1804
1807
  if (current->uses()->length() == 0) return;
1805
1808
 
1806
1809
  // Collect the representation changes in a sorted list. This allows
1807
1810
  // us to avoid duplicate changes without searching the list.
1808
- ZoneList<HValue*> to_convert(2);
1809
- ZoneList<Representation> to_convert_reps(2);
1811
+ ASSERT(to_convert->is_empty());
1812
+ ASSERT(to_convert_reps->is_empty());
1810
1813
  for (int i = 0; i < current->uses()->length(); ++i) {
1811
1814
  HValue* use = current->uses()->at(i);
1812
1815
  // The occurrences index means the index within the operand array of "use"
@@ -1826,10 +1829,10 @@ void HGraph::InsertRepresentationChanges(HValue* current) {
1826
1829
  Representation req = use->RequiredInputRepresentation(operand_index);
1827
1830
  if (req.IsNone() || req.Equals(r)) continue;
1828
1831
  int index = 0;
1829
- while (to_convert.length() > index &&
1830
- CompareConversionUses(to_convert[index],
1832
+ while (index < to_convert->length() &&
1833
+ CompareConversionUses(to_convert->at(index),
1831
1834
  use,
1832
- to_convert_reps[index],
1835
+ to_convert_reps->at(index),
1833
1836
  req) < 0) {
1834
1837
  ++index;
1835
1838
  }
@@ -1839,21 +1842,22 @@ void HGraph::InsertRepresentationChanges(HValue* current) {
1839
1842
  current->id(),
1840
1843
  use->id());
1841
1844
  }
1842
- to_convert.InsertAt(index, use);
1843
- to_convert_reps.InsertAt(index, req);
1845
+ to_convert->InsertAt(index, use);
1846
+ to_convert_reps->InsertAt(index, req);
1844
1847
  }
1845
1848
 
1846
- for (int i = 0; i < to_convert.length(); ++i) {
1847
- HValue* use = to_convert[i];
1848
- Representation r_to = to_convert_reps[i];
1849
- bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32);
1850
- InsertRepresentationChangeForUse(current, use, r_to, is_truncating);
1849
+ for (int i = 0; i < to_convert->length(); ++i) {
1850
+ HValue* use = to_convert->at(i);
1851
+ Representation r_to = to_convert_reps->at(i);
1852
+ InsertRepresentationChangeForUse(current, use, r_to);
1851
1853
  }
1852
1854
 
1853
1855
  if (current->uses()->is_empty()) {
1854
1856
  ASSERT(current->IsConstant());
1855
1857
  current->Delete();
1856
1858
  }
1859
+ to_convert->Rewind(0);
1860
+ to_convert_reps->Rewind(0);
1857
1861
  }
1858
1862
 
1859
1863
 
@@ -1889,17 +1893,19 @@ void HGraph::InsertRepresentationChanges() {
1889
1893
  }
1890
1894
  }
1891
1895
 
1896
+ ZoneList<HValue*> value_list(4);
1897
+ ZoneList<Representation> rep_list(4);
1892
1898
  for (int i = 0; i < blocks_.length(); ++i) {
1893
1899
  // Process phi instructions first.
1894
1900
  for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
1895
1901
  HPhi* phi = blocks_[i]->phis()->at(j);
1896
- InsertRepresentationChanges(phi);
1902
+ InsertRepresentationChangesForValue(phi, &value_list, &rep_list);
1897
1903
  }
1898
1904
 
1899
1905
  // Process normal instructions.
1900
1906
  HInstruction* current = blocks_[i]->first();
1901
1907
  while (current != NULL) {
1902
- InsertRepresentationChanges(current);
1908
+ InsertRepresentationChangesForValue(current, &value_list, &rep_list);
1903
1909
  current = current->next();
1904
1910
  }
1905
1911
  }
@@ -1930,10 +1936,54 @@ void HGraph::ComputeMinusZeroChecks() {
1930
1936
  }
1931
1937
 
1932
1938
 
1939
+ // Implementation of utility class to encapsulate the translation state for
1940
+ // a (possibly inlined) function.
1941
+ FunctionState::FunctionState(HGraphBuilder* owner,
1942
+ CompilationInfo* info,
1943
+ TypeFeedbackOracle* oracle)
1944
+ : owner_(owner),
1945
+ compilation_info_(info),
1946
+ oracle_(oracle),
1947
+ call_context_(NULL),
1948
+ function_return_(NULL),
1949
+ test_context_(NULL),
1950
+ outer_(owner->function_state()) {
1951
+ if (outer_ != NULL) {
1952
+ // State for an inline function.
1953
+ if (owner->ast_context()->IsTest()) {
1954
+ HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
1955
+ HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
1956
+ if_true->MarkAsInlineReturnTarget();
1957
+ if_false->MarkAsInlineReturnTarget();
1958
+ // The AstContext constructor pushed on the context stack. This newed
1959
+ // instance is the reason that AstContext can't be BASE_EMBEDDED.
1960
+ test_context_ = new TestContext(owner, if_true, if_false);
1961
+ } else {
1962
+ function_return_ = owner->graph()->CreateBasicBlock();
1963
+ function_return()->MarkAsInlineReturnTarget();
1964
+ }
1965
+ // Set this after possibly allocating a new TestContext above.
1966
+ call_context_ = owner->ast_context();
1967
+ }
1968
+
1969
+ // Push on the state stack.
1970
+ owner->set_function_state(this);
1971
+ }
1972
+
1973
+
1974
+ FunctionState::~FunctionState() {
1975
+ delete test_context_;
1976
+ owner_->set_function_state(outer_);
1977
+ }
1978
+
1979
+
1933
1980
  // Implementation of utility classes to represent an expression's context in
1934
1981
  // the AST.
1935
1982
  AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
1936
- : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
1983
+ : owner_(owner),
1984
+ kind_(kind),
1985
+ outer_(owner->ast_context()),
1986
+ for_typeof_(false) {
1937
1987
  owner->set_ast_context(this); // Push.
1938
1988
  #ifdef DEBUG
1939
1989
  original_length_ = owner->environment()->length();
@@ -2015,20 +2065,8 @@ void TestContext::BuildBranch(HValue* value) {
2015
2065
  HTest* test = new HTest(value, empty_true, empty_false);
2016
2066
  builder->current_block()->Finish(test);
2017
2067
 
2018
- HValue* const no_return_value = NULL;
2019
- HBasicBlock* true_target = if_true();
2020
- if (true_target->IsInlineReturnTarget()) {
2021
- empty_true->AddLeaveInlined(no_return_value, true_target);
2022
- } else {
2023
- empty_true->Goto(true_target);
2024
- }
2025
-
2026
- HBasicBlock* false_target = if_false();
2027
- if (false_target->IsInlineReturnTarget()) {
2028
- empty_false->AddLeaveInlined(no_return_value, false_target);
2029
- } else {
2030
- empty_false->Goto(false_target);
2031
- }
2068
+ empty_true->Goto(if_true(), false);
2069
+ empty_false->Goto(if_false(), false);
2032
2070
  builder->set_current_block(NULL);
2033
2071
  }
2034
2072
 
@@ -2068,40 +2106,10 @@ void TestContext::BuildBranch(HValue* value) {
2068
2106
  } while (false)
2069
2107
 
2070
2108
 
2071
- // 'thing' could be an expression, statement, or list of statements.
2072
- #define ADD_TO_SUBGRAPH(graph, thing) \
2073
- do { \
2074
- AddToSubgraph(graph, thing); \
2075
- if (HasStackOverflow()) return; \
2076
- } while (false)
2077
-
2078
-
2079
- class HGraphBuilder::SubgraphScope BASE_EMBEDDED {
2080
- public:
2081
- SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph)
2082
- : builder_(builder) {
2083
- old_subgraph_ = builder_->current_subgraph_;
2084
- subgraph_ = new_subgraph;
2085
- builder_->current_subgraph_ = subgraph_;
2086
- }
2087
-
2088
- ~SubgraphScope() {
2089
- builder_->current_subgraph_ = old_subgraph_;
2090
- }
2091
-
2092
- HSubgraph* subgraph() const { return subgraph_; }
2093
-
2094
- private:
2095
- HGraphBuilder* builder_;
2096
- HSubgraph* old_subgraph_;
2097
- HSubgraph* subgraph_;
2098
- };
2099
-
2100
-
2101
2109
  void HGraphBuilder::Bailout(const char* reason) {
2102
2110
  if (FLAG_trace_bailout) {
2103
- SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
2104
- PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason);
2111
+ SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
2112
+ PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2105
2113
  }
2106
2114
  SetStackOverflow();
2107
2115
  }
@@ -2119,6 +2127,14 @@ void HGraphBuilder::VisitForValue(Expression* expr) {
2119
2127
  }
2120
2128
 
2121
2129
 
2130
+ void HGraphBuilder::VisitForTypeOf(Expression* expr) {
2131
+ ValueContext for_value(this);
2132
+ for_value.set_for_typeof(true);
2133
+ Visit(expr);
2134
+ }
2135
+
2136
+
2137
+
2122
2138
  void HGraphBuilder::VisitForControl(Expression* expr,
2123
2139
  HBasicBlock* true_block,
2124
2140
  HBasicBlock* false_block) {
@@ -2148,88 +2164,87 @@ void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2148
2164
  }
2149
2165
 
2150
2166
 
2151
- HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
2152
- ASSERT(current_subgraph_ == NULL);
2153
- graph_ = new HGraph(info);
2167
+ HGraph* HGraphBuilder::CreateGraph() {
2168
+ graph_ = new HGraph(info());
2169
+ if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info());
2154
2170
 
2155
2171
  {
2156
2172
  HPhase phase("Block building");
2157
- graph_->Initialize(CreateBasicBlock(graph_->start_environment()));
2158
- current_subgraph_ = graph_;
2173
+ current_block_ = graph()->entry_block();
2159
2174
 
2160
- Scope* scope = info->scope();
2175
+ Scope* scope = info()->scope();
2176
+ if (scope->HasIllegalRedeclaration()) {
2177
+ Bailout("function with illegal redeclaration");
2178
+ return NULL;
2179
+ }
2161
2180
  SetupScope(scope);
2162
2181
  VisitDeclarations(scope->declarations());
2163
-
2164
2182
  AddInstruction(new HStackCheck());
2165
2183
 
2166
- ZoneList<Statement*>* stmts = info->function()->body();
2167
- HSubgraph* body = CreateGotoSubgraph(environment());
2168
- AddToSubgraph(body, stmts);
2184
+ // Add an edge to the body entry. This is warty: the graph's start
2185
+ // environment will be used by the Lithium translation as the initial
2186
+ // environment on graph entry, but it has now been mutated by the
2187
+ // Hydrogen translation of the instructions in the start block. This
2188
+ // environment uses values which have not been defined yet. These
2189
+ // Hydrogen instructions will then be replayed by the Lithium
2190
+ // translation, so they cannot have an environment effect. The edge to
2191
+ // the body's entry block (along with some special logic for the start
2192
+ // block in HInstruction::InsertAfter) seals the start block from
2193
+ // getting unwanted instructions inserted.
2194
+ //
2195
+ // TODO(kmillikin): Fix this. Stop mutating the initial environment.
2196
+ // Make the Hydrogen instructions in the initial block into Hydrogen
2197
+ // values (but not instructions), present in the initial environment and
2198
+ // not replayed by the Lithium translation.
2199
+ HEnvironment* initial_env = environment()->CopyWithoutHistory();
2200
+ HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2201
+ current_block()->Goto(body_entry);
2202
+ body_entry->SetJoinId(info()->function()->id());
2203
+ set_current_block(body_entry);
2204
+ VisitStatements(info()->function()->body());
2169
2205
  if (HasStackOverflow()) return NULL;
2170
- current_subgraph_->Append(NULL,
2171
- body->entry_block(),
2172
- body->exit_block(),
2173
- NULL);
2174
- body->entry_block()->SetJoinId(info->function()->id());
2175
2206
 
2176
- if (graph()->exit_block() != NULL) {
2177
- graph_->FinishExit(new HReturn(graph_->GetConstantUndefined()));
2207
+ if (current_block() != NULL) {
2208
+ HReturn* instr = new HReturn(graph()->GetConstantUndefined());
2209
+ current_block()->FinishExit(instr);
2210
+ set_current_block(NULL);
2178
2211
  }
2179
2212
  }
2180
2213
 
2181
- graph_->OrderBlocks();
2182
- graph_->AssignDominators();
2183
- graph_->EliminateRedundantPhis();
2184
- if (!graph_->CollectPhis()) {
2214
+ graph()->OrderBlocks();
2215
+ graph()->AssignDominators();
2216
+ graph()->EliminateRedundantPhis();
2217
+ if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2218
+ if (!graph()->CollectPhis()) {
2185
2219
  Bailout("Phi-use of arguments object");
2186
2220
  return NULL;
2187
2221
  }
2188
2222
 
2189
- HInferRepresentation rep(graph_);
2223
+ HInferRepresentation rep(graph());
2190
2224
  rep.Analyze();
2191
2225
 
2192
2226
  if (FLAG_use_range) {
2193
- HRangeAnalysis rangeAnalysis(graph_);
2227
+ HRangeAnalysis rangeAnalysis(graph());
2194
2228
  rangeAnalysis.Analyze();
2195
2229
  }
2196
2230
 
2197
- graph_->InitializeInferredTypes();
2198
- graph_->Canonicalize();
2199
- graph_->InsertRepresentationChanges();
2200
- graph_->ComputeMinusZeroChecks();
2231
+ graph()->InitializeInferredTypes();
2232
+ graph()->Canonicalize();
2233
+ graph()->InsertRepresentationChanges();
2234
+ graph()->ComputeMinusZeroChecks();
2201
2235
 
2202
2236
  // Eliminate redundant stack checks on backwards branches.
2203
- HStackCheckEliminator sce(graph_);
2237
+ HStackCheckEliminator sce(graph());
2204
2238
  sce.Process();
2205
2239
 
2206
2240
  // Perform common subexpression elimination and loop-invariant code motion.
2207
2241
  if (FLAG_use_gvn) {
2208
- HPhase phase("Global value numbering", graph_);
2209
- HGlobalValueNumberer gvn(graph_);
2242
+ HPhase phase("Global value numbering", graph());
2243
+ HGlobalValueNumberer gvn(graph(), info());
2210
2244
  gvn.Analyze();
2211
2245
  }
2212
2246
 
2213
- return graph_;
2214
- }
2215
-
2216
-
2217
- void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
2218
- SubgraphScope scope(this, graph);
2219
- Visit(stmt);
2220
- }
2221
-
2222
-
2223
- void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) {
2224
- SubgraphScope scope(this, graph);
2225
- VisitForValue(expr);
2226
- }
2227
-
2228
-
2229
- void HGraphBuilder::AddToSubgraph(HSubgraph* graph,
2230
- ZoneList<Statement*>* stmts) {
2231
- SubgraphScope scope(this, graph);
2232
- VisitStatements(stmts);
2247
+ return graph();
2233
2248
  }
2234
2249
 
2235
2250
 
@@ -2277,8 +2292,8 @@ void HGraphBuilder::SetupScope(Scope* scope) {
2277
2292
  // We don't yet handle the function name for named function expressions.
2278
2293
  if (scope->function() != NULL) BAILOUT("named function expression");
2279
2294
 
2280
- HConstant* undefined_constant =
2281
- new HConstant(Factory::undefined_value(), Representation::Tagged());
2295
+ HConstant* undefined_constant = new HConstant(
2296
+ isolate()->factory()->undefined_value(), Representation::Tagged());
2282
2297
  AddInstruction(undefined_constant);
2283
2298
  graph_->set_undefined_constant(undefined_constant);
2284
2299
 
@@ -2299,14 +2314,17 @@ void HGraphBuilder::SetupScope(Scope* scope) {
2299
2314
  // not have declarations).
2300
2315
  if (scope->arguments() != NULL) {
2301
2316
  if (!scope->arguments()->IsStackAllocated() ||
2302
- !scope->arguments_shadow()->IsStackAllocated()) {
2317
+ (scope->arguments_shadow() != NULL &&
2318
+ !scope->arguments_shadow()->IsStackAllocated())) {
2303
2319
  BAILOUT("context-allocated arguments");
2304
2320
  }
2305
2321
  HArgumentsObject* object = new HArgumentsObject;
2306
2322
  AddInstruction(object);
2307
2323
  graph()->SetArgumentsObject(object);
2308
2324
  environment()->Bind(scope->arguments(), object);
2309
- environment()->Bind(scope->arguments_shadow(), object);
2325
+ if (scope->arguments_shadow() != NULL) {
2326
+ environment()->Bind(scope->arguments_shadow(), object);
2327
+ }
2310
2328
  }
2311
2329
  }
2312
2330
 
@@ -2326,65 +2344,26 @@ HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2326
2344
  }
2327
2345
 
2328
2346
 
2329
- HSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer,
2330
- Handle<JSFunction> target,
2331
- FunctionLiteral* function) {
2332
- HConstant* undefined = graph()->GetConstantUndefined();
2333
- HEnvironment* inner =
2334
- outer->CopyForInlining(target, function, true, undefined);
2335
- HSubgraph* subgraph = new HSubgraph(graph());
2336
- subgraph->Initialize(CreateBasicBlock(inner));
2337
- return subgraph;
2338
- }
2339
-
2340
-
2341
- HSubgraph* HGraphBuilder::CreateGotoSubgraph(HEnvironment* env) {
2342
- HSubgraph* subgraph = new HSubgraph(graph());
2343
- HEnvironment* new_env = env->CopyWithoutHistory();
2344
- subgraph->Initialize(CreateBasicBlock(new_env));
2345
- return subgraph;
2346
- }
2347
-
2348
-
2349
- HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
2350
- HSubgraph* subgraph = new HSubgraph(graph());
2351
- subgraph->Initialize(graph()->CreateBasicBlock());
2352
- return subgraph;
2353
- }
2354
-
2355
-
2356
- HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) {
2357
- HSubgraph* subgraph = new HSubgraph(graph());
2358
- HEnvironment* new_env = env->Copy();
2359
- subgraph->Initialize(CreateBasicBlock(new_env));
2360
- return subgraph;
2361
- }
2362
-
2363
-
2364
- HSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) {
2365
- HSubgraph* subgraph = new HSubgraph(graph());
2366
- HBasicBlock* block = graph()->CreateBasicBlock();
2367
- HEnvironment* new_env = env->CopyAsLoopHeader(block);
2368
- block->SetInitialEnvironment(new_env);
2369
- subgraph->Initialize(block);
2370
- subgraph->entry_block()->AttachLoopInformation();
2371
- return subgraph;
2347
+ HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2348
+ HBasicBlock* header = graph()->CreateBasicBlock();
2349
+ HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2350
+ header->SetInitialEnvironment(entry_env);
2351
+ header->AttachLoopInformation();
2352
+ return header;
2372
2353
  }
2373
2354
 
2374
2355
 
2375
2356
  void HGraphBuilder::VisitBlock(Block* stmt) {
2376
- if (stmt->labels() != NULL) {
2377
- HSubgraph* block_graph = CreateGotoSubgraph(environment());
2378
- BreakAndContinueInfo break_info(stmt);
2379
- { BreakAndContinueScope push(&break_info, this);
2380
- ADD_TO_SUBGRAPH(block_graph, stmt->statements());
2381
- }
2382
- subgraph()->Append(stmt,
2383
- block_graph->entry_block(),
2384
- block_graph->exit_block(),
2385
- break_info.break_block());
2386
- } else {
2357
+ BreakAndContinueInfo break_info(stmt);
2358
+ { BreakAndContinueScope push(&break_info, this);
2387
2359
  VisitStatements(stmt->statements());
2360
+ CHECK_BAILOUT;
2361
+ }
2362
+ HBasicBlock* break_block = break_info.break_block();
2363
+ if (break_block != NULL) {
2364
+ if (current_block() != NULL) current_block()->Goto(break_block);
2365
+ break_block->SetJoinId(stmt->ExitId());
2366
+ set_current_block(break_block);
2388
2367
  }
2389
2368
  }
2390
2369
 
@@ -2406,21 +2385,23 @@ void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2406
2385
  AddSimulate(stmt->ElseId());
2407
2386
  Visit(stmt->else_statement());
2408
2387
  } else {
2409
- HSubgraph* then_graph = CreateEmptySubgraph();
2410
- HSubgraph* else_graph = CreateEmptySubgraph();
2411
- VISIT_FOR_CONTROL(stmt->condition(),
2412
- then_graph->entry_block(),
2413
- else_graph->entry_block());
2388
+ HBasicBlock* cond_true = graph()->CreateBasicBlock();
2389
+ HBasicBlock* cond_false = graph()->CreateBasicBlock();
2390
+ VISIT_FOR_CONTROL(stmt->condition(), cond_true, cond_false);
2391
+ cond_true->SetJoinId(stmt->ThenId());
2392
+ cond_false->SetJoinId(stmt->ElseId());
2414
2393
 
2415
- then_graph->entry_block()->SetJoinId(stmt->ThenId());
2416
- ADD_TO_SUBGRAPH(then_graph, stmt->then_statement());
2394
+ set_current_block(cond_true);
2395
+ Visit(stmt->then_statement());
2396
+ CHECK_BAILOUT;
2397
+ HBasicBlock* other = current_block();
2417
2398
 
2418
- else_graph->entry_block()->SetJoinId(stmt->ElseId());
2419
- ADD_TO_SUBGRAPH(else_graph, stmt->else_statement());
2399
+ set_current_block(cond_false);
2400
+ Visit(stmt->else_statement());
2401
+ CHECK_BAILOUT;
2420
2402
 
2421
- current_subgraph_->AppendJoin(then_graph->exit_block(),
2422
- else_graph->exit_block(),
2423
- stmt->id());
2403
+ HBasicBlock* join = CreateJoin(other, current_block(), stmt->id());
2404
+ set_current_block(join);
2424
2405
  }
2425
2406
  }
2426
2407
 
@@ -2476,7 +2457,8 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2476
2457
  // Not an inlined return, so an actual one.
2477
2458
  VISIT_FOR_VALUE(stmt->expression());
2478
2459
  HValue* result = environment()->Pop();
2479
- subgraph()->FinishExit(new HReturn(result));
2460
+ current_block()->FinishExit(new HReturn(result));
2461
+ set_current_block(NULL);
2480
2462
  } else {
2481
2463
  // Return from an inlined function, visit the subexpression in the
2482
2464
  // expression context of the call.
@@ -2485,20 +2467,16 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2485
2467
  VisitForControl(stmt->expression(),
2486
2468
  test->if_true(),
2487
2469
  test->if_false());
2470
+ } else if (context->IsEffect()) {
2471
+ VISIT_FOR_EFFECT(stmt->expression());
2472
+ current_block()->Goto(function_return(), false);
2488
2473
  } else {
2489
- HValue* return_value = NULL;
2490
- if (context->IsEffect()) {
2491
- VISIT_FOR_EFFECT(stmt->expression());
2492
- return_value = graph()->GetConstantUndefined();
2493
- } else {
2494
- ASSERT(context->IsValue());
2495
- VISIT_FOR_VALUE(stmt->expression());
2496
- return_value = environment()->Pop();
2497
- }
2498
- current_block()->AddLeaveInlined(return_value,
2499
- function_return_);
2500
- set_current_block(NULL);
2474
+ ASSERT(context->IsValue());
2475
+ VISIT_FOR_VALUE(stmt->expression());
2476
+ HValue* return_value = environment()->Pop();
2477
+ current_block()->AddLeaveInlined(return_value, function_return());
2501
2478
  }
2479
+ set_current_block(NULL);
2502
2480
  }
2503
2481
  }
2504
2482
 
@@ -2513,378 +2491,270 @@ void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
2513
2491
  }
2514
2492
 
2515
2493
 
2516
- HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
2517
- HValue* switch_value,
2518
- CaseClause* clause) {
2519
- AddToSubgraph(subgraph, clause->label());
2520
- if (HasStackOverflow()) return NULL;
2521
- HValue* clause_value = subgraph->exit_block()->last_environment()->Pop();
2522
- HCompare* compare = new HCompare(switch_value,
2523
- clause_value,
2524
- Token::EQ_STRICT);
2525
- compare->SetInputRepresentation(Representation::Integer32());
2526
- subgraph->exit_block()->AddInstruction(compare);
2527
- return compare;
2528
- }
2529
-
2530
-
2531
2494
  void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2495
+ // We only optimize switch statements with smi-literal smi comparisons,
2496
+ // with a bounded number of clauses.
2497
+ const int kCaseClauseLimit = 128;
2498
+ ZoneList<CaseClause*>* clauses = stmt->cases();
2499
+ int clause_count = clauses->length();
2500
+ if (clause_count > kCaseClauseLimit) {
2501
+ BAILOUT("SwitchStatement: too many clauses");
2502
+ }
2503
+
2532
2504
  VISIT_FOR_VALUE(stmt->tag());
2533
- // TODO(3168478): simulate added for tag should be enough.
2534
2505
  AddSimulate(stmt->EntryId());
2535
- HValue* switch_value = Pop();
2536
-
2537
- ZoneList<CaseClause*>* clauses = stmt->cases();
2538
- int num_clauses = clauses->length();
2539
- if (num_clauses == 0) return;
2540
- if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
2506
+ HValue* tag_value = Pop();
2507
+ HBasicBlock* first_test_block = current_block();
2541
2508
 
2542
- int num_smi_clauses = num_clauses;
2543
- for (int i = 0; i < num_clauses; i++) {
2509
+ // 1. Build all the tests, with dangling true branches. Unconditionally
2510
+ // deoptimize if we encounter a non-smi comparison.
2511
+ for (int i = 0; i < clause_count; ++i) {
2544
2512
  CaseClause* clause = clauses->at(i);
2545
2513
  if (clause->is_default()) continue;
2546
- clause->RecordTypeFeedback(oracle());
2547
- if (!clause->IsSmiCompare()) {
2548
- if (i == 0) BAILOUT("SwitchStatement: no smi compares");
2549
- // We will deoptimize if the first non-smi compare is reached.
2550
- num_smi_clauses = i;
2551
- break;
2552
- }
2553
2514
  if (!clause->label()->IsSmiLiteral()) {
2554
2515
  BAILOUT("SwitchStatement: non-literal switch label");
2555
2516
  }
2556
- }
2557
-
2558
- // The single exit block of the whole switch statement.
2559
- HBasicBlock* single_exit_block = graph_->CreateBasicBlock();
2560
-
2561
- // Build a series of empty subgraphs for the comparisons.
2562
- // The default clause does not have a comparison subgraph.
2563
- ZoneList<HSubgraph*> compare_graphs(num_smi_clauses);
2564
- for (int i = 0; i < num_smi_clauses; i++) {
2565
- if (clauses->at(i)->is_default()) {
2566
- compare_graphs.Add(NULL);
2567
- } else {
2568
- compare_graphs.Add(CreateEmptySubgraph());
2569
- }
2570
- }
2571
2517
 
2572
- HSubgraph* prev_graph = current_subgraph_;
2573
- HCompare* prev_compare_inst = NULL;
2574
- for (int i = 0; i < num_smi_clauses; i++) {
2575
- CaseClause* clause = clauses->at(i);
2576
- if (clause->is_default()) continue;
2577
-
2578
- // Finish the previous graph by connecting it to the current.
2579
- HSubgraph* subgraph = compare_graphs.at(i);
2580
- if (prev_compare_inst == NULL) {
2581
- ASSERT(prev_graph == current_subgraph_);
2582
- prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2583
- } else {
2584
- HBasicBlock* empty = graph()->CreateBasicBlock();
2585
- prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2586
- empty,
2587
- subgraph->entry_block()));
2518
+ // Unconditionally deoptimize on the first non-smi compare.
2519
+ clause->RecordTypeFeedback(oracle());
2520
+ if (!clause->IsSmiCompare()) {
2521
+ current_block()->FinishExitWithDeoptimization();
2522
+ set_current_block(NULL);
2523
+ break;
2588
2524
  }
2589
2525
 
2590
- // Build instructions for current subgraph.
2591
- ASSERT(clause->IsSmiCompare());
2592
- prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2593
- if (HasStackOverflow()) return;
2594
-
2595
- prev_graph = subgraph;
2596
- }
2597
-
2598
- // Finish last comparison if there was at least one comparison.
2599
- // last_false_block is the (empty) false-block of the last comparison. If
2600
- // there are no comparisons at all (a single default clause), it is just
2601
- // the last block of the current subgraph.
2602
- HBasicBlock* last_false_block = current_block();
2603
- if (prev_graph != current_subgraph_) {
2604
- last_false_block = graph()->CreateBasicBlock();
2605
- HBasicBlock* empty = graph()->CreateBasicBlock();
2606
- prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2607
- empty,
2608
- last_false_block));
2609
- }
2610
-
2611
- // If we have a non-smi compare clause, we deoptimize after trying
2612
- // all the previous compares.
2613
- if (num_smi_clauses < num_clauses) {
2614
- last_false_block->Finish(new HDeoptimize);
2615
- }
2526
+ // Otherwise generate a compare and branch.
2527
+ VISIT_FOR_VALUE(clause->label());
2528
+ HValue* label_value = Pop();
2529
+ HCompare* compare = new HCompare(tag_value, label_value, Token::EQ_STRICT);
2530
+ compare->SetInputRepresentation(Representation::Integer32());
2531
+ ASSERT(!compare->HasSideEffects());
2532
+ AddInstruction(compare);
2533
+ HBasicBlock* body_block = graph()->CreateBasicBlock();
2534
+ HBasicBlock* next_test_block = graph()->CreateBasicBlock();
2535
+ HTest* branch = new HTest(compare, body_block, next_test_block);
2536
+ current_block()->Finish(branch);
2537
+ set_current_block(next_test_block);
2538
+ }
2539
+
2540
+ // Save the current block to use for the default or to join with the
2541
+ // exit. This block is NULL if we deoptimized.
2542
+ HBasicBlock* last_block = current_block();
2543
+
2544
+ // 2. Loop over the clauses and the linked list of tests in lockstep,
2545
+ // translating the clause bodies.
2546
+ HBasicBlock* curr_test_block = first_test_block;
2547
+ HBasicBlock* fall_through_block = NULL;
2548
+ BreakAndContinueInfo break_info(stmt);
2549
+ { BreakAndContinueScope push(&break_info, this);
2550
+ for (int i = 0; i < clause_count; ++i) {
2551
+ CaseClause* clause = clauses->at(i);
2552
+
2553
+ // Identify the block where normal (non-fall-through) control flow
2554
+ // goes to.
2555
+ HBasicBlock* normal_block = NULL;
2556
+ if (clause->is_default() && last_block != NULL) {
2557
+ normal_block = last_block;
2558
+ last_block = NULL; // Cleared to indicate we've handled it.
2559
+ } else if (!curr_test_block->end()->IsDeoptimize()) {
2560
+ normal_block = curr_test_block->end()->FirstSuccessor();
2561
+ curr_test_block = curr_test_block->end()->SecondSuccessor();
2562
+ }
2616
2563
 
2617
- // Build statement blocks, connect them to their comparison block and
2618
- // to the previous statement block, if there is a fall-through.
2619
- HSubgraph* previous_subgraph = NULL;
2620
- for (int i = 0; i < num_clauses; i++) {
2621
- CaseClause* clause = clauses->at(i);
2622
- // Subgraph for the statements of the clause is only created when
2623
- // it's reachable either from the corresponding compare or as a
2624
- // fall-through from previous statements.
2625
- HSubgraph* subgraph = NULL;
2626
-
2627
- if (i < num_smi_clauses) {
2628
- if (clause->is_default()) {
2629
- if (!last_false_block->IsFinished()) {
2630
- // Default clause: Connect it to the last false block.
2631
- subgraph = CreateEmptySubgraph();
2632
- last_false_block->Finish(new HGoto(subgraph->entry_block()));
2564
+ // Identify a block to emit the body into.
2565
+ if (normal_block == NULL) {
2566
+ if (fall_through_block == NULL) {
2567
+ // (a) Unreachable.
2568
+ if (clause->is_default()) {
2569
+ continue; // Might still be reachable clause bodies.
2570
+ } else {
2571
+ break;
2572
+ }
2573
+ } else {
2574
+ // (b) Reachable only as fall through.
2575
+ set_current_block(fall_through_block);
2633
2576
  }
2577
+ } else if (fall_through_block == NULL) {
2578
+ // (c) Reachable only normally.
2579
+ set_current_block(normal_block);
2634
2580
  } else {
2635
- ASSERT(clause->IsSmiCompare());
2636
- // Connect with the corresponding comparison.
2637
- subgraph = CreateEmptySubgraph();
2638
- HBasicBlock* empty =
2639
- compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
2640
- empty->Finish(new HGoto(subgraph->entry_block()));
2581
+ // (d) Reachable both ways.
2582
+ HBasicBlock* join = CreateJoin(fall_through_block,
2583
+ normal_block,
2584
+ clause->EntryId());
2585
+ set_current_block(join);
2641
2586
  }
2642
- }
2643
-
2644
- // Check for fall-through from previous statement block.
2645
- if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
2646
- if (subgraph == NULL) subgraph = CreateEmptySubgraph();
2647
- previous_subgraph->exit_block()->
2648
- Finish(new HGoto(subgraph->entry_block()));
2649
- }
2650
2587
 
2651
- if (subgraph != NULL) {
2652
- BreakAndContinueInfo break_info(stmt);
2653
- { BreakAndContinueScope push(&break_info, this);
2654
- ADD_TO_SUBGRAPH(subgraph, clause->statements());
2655
- }
2656
- if (break_info.break_block() != NULL) {
2657
- break_info.break_block()->SetJoinId(stmt->ExitId());
2658
- break_info.break_block()->Finish(new HGoto(single_exit_block));
2659
- }
2588
+ VisitStatements(clause->statements());
2589
+ CHECK_BAILOUT;
2590
+ fall_through_block = current_block();
2660
2591
  }
2661
-
2662
- previous_subgraph = subgraph;
2663
- }
2664
-
2665
- // If the last statement block has a fall-through, connect it to the
2666
- // single exit block.
2667
- if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
2668
- previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
2669
2592
  }
2670
2593
 
2671
- // If there is no default clause finish the last comparison's false target.
2672
- if (!last_false_block->IsFinished()) {
2673
- last_false_block->Finish(new HGoto(single_exit_block));
2674
- }
2675
-
2676
- if (single_exit_block->HasPredecessor()) {
2677
- set_current_block(single_exit_block);
2594
+ // Create an up-to-3-way join. Use the break block if it exists since
2595
+ // it's already a join block.
2596
+ HBasicBlock* break_block = break_info.break_block();
2597
+ if (break_block == NULL) {
2598
+ set_current_block(CreateJoin(fall_through_block,
2599
+ last_block,
2600
+ stmt->ExitId()));
2678
2601
  } else {
2679
- set_current_block(NULL);
2602
+ if (fall_through_block != NULL) fall_through_block->Goto(break_block);
2603
+ if (last_block != NULL) last_block->Goto(break_block);
2604
+ break_block->SetJoinId(stmt->ExitId());
2605
+ set_current_block(break_block);
2680
2606
  }
2681
2607
  }
2682
2608
 
2683
- bool HGraph::HasOsrEntryAt(IterationStatement* statement) {
2609
+
2610
+ bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
2684
2611
  return statement->OsrEntryId() == info()->osr_ast_id();
2685
2612
  }
2686
2613
 
2687
2614
 
2688
- void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
2689
- if (!graph()->HasOsrEntryAt(statement)) return;
2615
+ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2616
+ if (!HasOsrEntryAt(statement)) return;
2690
2617
 
2691
2618
  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2692
2619
  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2693
2620
  HValue* true_value = graph()->GetConstantTrue();
2694
2621
  HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
2695
- exit_block()->Finish(test);
2622
+ current_block()->Finish(test);
2696
2623
 
2697
2624
  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2698
2625
  non_osr_entry->Goto(loop_predecessor);
2699
2626
 
2627
+ set_current_block(osr_entry);
2700
2628
  int osr_entry_id = statement->OsrEntryId();
2701
2629
  // We want the correct environment at the OsrEntry instruction. Build
2702
2630
  // it explicitly. The expression stack should be empty.
2703
- int count = osr_entry->last_environment()->length();
2704
- ASSERT(count == (osr_entry->last_environment()->parameter_count() +
2705
- osr_entry->last_environment()->local_count()));
2631
+ int count = environment()->length();
2632
+ ASSERT(count ==
2633
+ (environment()->parameter_count() + environment()->local_count()));
2706
2634
  for (int i = 0; i < count; ++i) {
2707
2635
  HUnknownOSRValue* unknown = new HUnknownOSRValue;
2708
- osr_entry->AddInstruction(unknown);
2709
- osr_entry->last_environment()->Bind(i, unknown);
2636
+ AddInstruction(unknown);
2637
+ environment()->Bind(i, unknown);
2710
2638
  }
2711
2639
 
2712
- osr_entry->AddSimulate(osr_entry_id);
2713
- osr_entry->AddInstruction(new HOsrEntry(osr_entry_id));
2714
- osr_entry->Goto(loop_predecessor);
2640
+ AddSimulate(osr_entry_id);
2641
+ AddInstruction(new HOsrEntry(osr_entry_id));
2642
+ current_block()->Goto(loop_predecessor);
2715
2643
  loop_predecessor->SetJoinId(statement->EntryId());
2716
- set_exit_block(loop_predecessor);
2644
+ set_current_block(loop_predecessor);
2717
2645
  }
2718
2646
 
2719
2647
 
2720
2648
  void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2721
2649
  ASSERT(current_block() != NULL);
2722
- subgraph()->PreProcessOsrEntry(stmt);
2650
+ PreProcessOsrEntry(stmt);
2651
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2652
+ current_block()->Goto(loop_entry, false);
2653
+ set_current_block(loop_entry);
2723
2654
 
2724
- HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment());
2725
2655
  BreakAndContinueInfo break_info(stmt);
2726
2656
  { BreakAndContinueScope push(&break_info, this);
2727
- ADD_TO_SUBGRAPH(body_graph, stmt->body());
2657
+ Visit(stmt->body());
2658
+ CHECK_BAILOUT;
2728
2659
  }
2729
- body_graph->ResolveContinue(stmt, break_info.continue_block());
2730
-
2731
- if (body_graph->exit_block() == NULL || stmt->cond()->ToBooleanIsTrue()) {
2732
- subgraph()->AppendEndless(stmt,
2733
- body_graph->entry_block(),
2734
- body_graph->exit_block(),
2735
- break_info.break_block());
2736
- } else {
2737
- HSubgraph* go_back = CreateEmptySubgraph();
2738
- HSubgraph* exit = CreateEmptySubgraph();
2739
- {
2740
- SubgraphScope scope(this, body_graph);
2741
- VISIT_FOR_CONTROL(stmt->cond(),
2742
- go_back->entry_block(),
2743
- exit->entry_block());
2744
- go_back->entry_block()->SetJoinId(stmt->BackEdgeId());
2745
- exit->entry_block()->SetJoinId(stmt->ExitId());
2746
- }
2747
- subgraph()->AppendDoWhile(stmt,
2748
- body_graph->entry_block(),
2749
- go_back->exit_block(),
2750
- exit->exit_block(),
2751
- break_info.break_block());
2660
+ HBasicBlock* body_exit =
2661
+ JoinContinue(stmt, current_block(), break_info.continue_block());
2662
+ HBasicBlock* loop_successor = NULL;
2663
+ if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
2664
+ set_current_block(body_exit);
2665
+ // The block for a true condition, the actual predecessor block of the
2666
+ // back edge.
2667
+ body_exit = graph()->CreateBasicBlock();
2668
+ loop_successor = graph()->CreateBasicBlock();
2669
+ VISIT_FOR_CONTROL(stmt->cond(), body_exit, loop_successor);
2670
+ body_exit->SetJoinId(stmt->BackEdgeId());
2671
+ loop_successor->SetJoinId(stmt->ExitId());
2752
2672
  }
2673
+ HBasicBlock* loop_exit = CreateLoop(stmt,
2674
+ loop_entry,
2675
+ body_exit,
2676
+ loop_successor,
2677
+ break_info.break_block());
2678
+ set_current_block(loop_exit);
2753
2679
  }
2754
2680
 
2755
2681
 
2756
2682
  void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2757
2683
  ASSERT(current_block() != NULL);
2758
- subgraph()->PreProcessOsrEntry(stmt);
2759
-
2760
- HSubgraph* cond_graph = NULL;
2761
- HSubgraph* body_graph = NULL;
2762
- HSubgraph* exit_graph = NULL;
2763
-
2764
- // If the condition is constant true, do not generate a condition subgraph.
2765
- if (stmt->cond()->ToBooleanIsTrue()) {
2766
- body_graph = CreateLoopHeaderSubgraph(environment());
2767
- } else {
2768
- cond_graph = CreateLoopHeaderSubgraph(environment());
2769
- body_graph = CreateEmptySubgraph();
2770
- exit_graph = CreateEmptySubgraph();
2771
- {
2772
- SubgraphScope scope(this, cond_graph);
2773
- VISIT_FOR_CONTROL(stmt->cond(),
2774
- body_graph->entry_block(),
2775
- exit_graph->entry_block());
2776
- body_graph->entry_block()->SetJoinId(stmt->BodyId());
2777
- exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2778
- }
2684
+ PreProcessOsrEntry(stmt);
2685
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2686
+ current_block()->Goto(loop_entry, false);
2687
+ set_current_block(loop_entry);
2688
+
2689
+ // If the condition is constant true, do not generate a branch.
2690
+ HBasicBlock* loop_successor = NULL;
2691
+ if (!stmt->cond()->ToBooleanIsTrue()) {
2692
+ HBasicBlock* body_entry = graph()->CreateBasicBlock();
2693
+ loop_successor = graph()->CreateBasicBlock();
2694
+ VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
2695
+ body_entry->SetJoinId(stmt->BodyId());
2696
+ loop_successor->SetJoinId(stmt->ExitId());
2697
+ set_current_block(body_entry);
2779
2698
  }
2780
2699
 
2781
2700
  BreakAndContinueInfo break_info(stmt);
2782
2701
  { BreakAndContinueScope push(&break_info, this);
2783
- ADD_TO_SUBGRAPH(body_graph, stmt->body());
2702
+ Visit(stmt->body());
2703
+ CHECK_BAILOUT;
2784
2704
  }
2785
- body_graph->ResolveContinue(stmt, break_info.continue_block());
2786
-
2787
- if (cond_graph != NULL) {
2788
- AppendPeeledWhile(stmt,
2789
- cond_graph->entry_block(),
2790
- exit_graph->exit_block(),
2791
- body_graph->exit_block(),
2792
- break_info.break_block());
2793
- } else {
2794
- // TODO(fschneider): Implement peeling for endless loops as well.
2795
- subgraph()->AppendEndless(stmt,
2796
- body_graph->entry_block(),
2797
- body_graph->exit_block(),
2798
- break_info.break_block());
2799
- }
2800
- }
2801
-
2802
-
2803
- void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt,
2804
- HBasicBlock* condition_entry,
2805
- HBasicBlock* exit_block,
2806
- HBasicBlock* body_exit,
2807
- HBasicBlock* break_block) {
2808
- HBasicBlock* loop_entry = NULL;
2809
- HBasicBlock* loop_exit = NULL;
2810
- if (FLAG_use_peeling && body_exit != NULL && stmt != peeled_statement_) {
2811
- // Save the last peeled iteration statement to prevent infinite recursion.
2812
- IterationStatement* outer_peeled_statement = peeled_statement_;
2813
- peeled_statement_ = stmt;
2814
- HSubgraph* loop = CreateGotoSubgraph(body_exit->last_environment());
2815
- ADD_TO_SUBGRAPH(loop, stmt);
2816
- peeled_statement_ = outer_peeled_statement;
2817
- loop_entry = loop->entry_block();
2818
- loop_exit = loop->exit_block();
2819
- }
2820
- subgraph()->AppendWhile(stmt,
2821
- condition_entry,
2822
- exit_block,
2823
- body_exit,
2824
- break_block,
2825
- loop_entry,
2826
- loop_exit);
2705
+ HBasicBlock* body_exit =
2706
+ JoinContinue(stmt, current_block(), break_info.continue_block());
2707
+ HBasicBlock* loop_exit = CreateLoop(stmt,
2708
+ loop_entry,
2709
+ body_exit,
2710
+ loop_successor,
2711
+ break_info.break_block());
2712
+ set_current_block(loop_exit);
2827
2713
  }
2828
2714
 
2829
2715
 
2830
2716
  void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
2831
- // Only visit the init statement in the peeled part of the loop.
2832
- if (stmt->init() != NULL && peeled_statement_ != stmt) {
2717
+ if (stmt->init() != NULL) {
2833
2718
  Visit(stmt->init());
2834
2719
  CHECK_BAILOUT;
2835
2720
  }
2836
2721
  ASSERT(current_block() != NULL);
2837
- subgraph()->PreProcessOsrEntry(stmt);
2722
+ PreProcessOsrEntry(stmt);
2723
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2724
+ current_block()->Goto(loop_entry, false);
2725
+ set_current_block(loop_entry);
2838
2726
 
2839
- HSubgraph* cond_graph = NULL;
2840
- HSubgraph* body_graph = NULL;
2841
- HSubgraph* exit_graph = NULL;
2727
+ HBasicBlock* loop_successor = NULL;
2842
2728
  if (stmt->cond() != NULL) {
2843
- cond_graph = CreateLoopHeaderSubgraph(environment());
2844
- body_graph = CreateEmptySubgraph();
2845
- exit_graph = CreateEmptySubgraph();
2846
- {
2847
- SubgraphScope scope(this, cond_graph);
2848
- VISIT_FOR_CONTROL(stmt->cond(),
2849
- body_graph->entry_block(),
2850
- exit_graph->entry_block());
2851
- body_graph->entry_block()->SetJoinId(stmt->BodyId());
2852
- exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2853
- }
2854
- } else {
2855
- body_graph = CreateLoopHeaderSubgraph(environment());
2729
+ HBasicBlock* body_entry = graph()->CreateBasicBlock();
2730
+ loop_successor = graph()->CreateBasicBlock();
2731
+ VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
2732
+ body_entry->SetJoinId(stmt->BodyId());
2733
+ loop_successor->SetJoinId(stmt->ExitId());
2734
+ set_current_block(body_entry);
2856
2735
  }
2736
+
2857
2737
  BreakAndContinueInfo break_info(stmt);
2858
2738
  { BreakAndContinueScope push(&break_info, this);
2859
- ADD_TO_SUBGRAPH(body_graph, stmt->body());
2739
+ Visit(stmt->body());
2740
+ CHECK_BAILOUT;
2860
2741
  }
2742
+ HBasicBlock* body_exit =
2743
+ JoinContinue(stmt, current_block(), break_info.continue_block());
2861
2744
 
2862
- HSubgraph* next_graph = NULL;
2863
- body_graph->ResolveContinue(stmt, break_info.continue_block());
2864
-
2865
- if (stmt->next() != NULL && body_graph->exit_block() != NULL) {
2866
- next_graph =
2867
- CreateGotoSubgraph(body_graph->exit_block()->last_environment());
2868
- ADD_TO_SUBGRAPH(next_graph, stmt->next());
2869
- body_graph->Append(NULL,
2870
- next_graph->entry_block(),
2871
- next_graph->exit_block(),
2872
- NULL);
2873
- next_graph->entry_block()->SetJoinId(stmt->ContinueId());
2745
+ if (stmt->next() != NULL && body_exit != NULL) {
2746
+ set_current_block(body_exit);
2747
+ Visit(stmt->next());
2748
+ CHECK_BAILOUT;
2749
+ body_exit = current_block();
2874
2750
  }
2875
2751
 
2876
- if (cond_graph != NULL) {
2877
- AppendPeeledWhile(stmt,
2878
- cond_graph->entry_block(),
2879
- exit_graph->exit_block(),
2880
- body_graph->exit_block(),
2881
- break_info.break_block());
2882
- } else {
2883
- subgraph()->AppendEndless(stmt,
2884
- body_graph->entry_block(),
2885
- body_graph->exit_block(),
2886
- break_info.break_block());
2887
- }
2752
+ HBasicBlock* loop_exit = CreateLoop(stmt,
2753
+ loop_entry,
2754
+ body_exit,
2755
+ loop_successor,
2756
+ break_info.break_block());
2757
+ set_current_block(loop_exit);
2888
2758
  }
2889
2759
 
2890
2760
 
@@ -2908,9 +2778,33 @@ void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
2908
2778
  }
2909
2779
 
2910
2780
 
2781
+ static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
2782
+ Code* unoptimized_code, FunctionLiteral* expr) {
2783
+ int start_position = expr->start_position();
2784
+ RelocIterator it(unoptimized_code);
2785
+ for (;!it.done(); it.next()) {
2786
+ RelocInfo* rinfo = it.rinfo();
2787
+ if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
2788
+ Object* obj = rinfo->target_object();
2789
+ if (obj->IsSharedFunctionInfo()) {
2790
+ SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
2791
+ if (shared->start_position() == start_position) {
2792
+ return Handle<SharedFunctionInfo>(shared);
2793
+ }
2794
+ }
2795
+ }
2796
+
2797
+ return Handle<SharedFunctionInfo>();
2798
+ }
2799
+
2800
+
2911
2801
  void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
2912
2802
  Handle<SharedFunctionInfo> shared_info =
2913
- Compiler::BuildFunctionInfo(expr, graph_->info()->script());
2803
+ SearchSharedFunctionInfo(info()->shared_info()->code(),
2804
+ expr);
2805
+ if (shared_info.is_null()) {
2806
+ shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
2807
+ }
2914
2808
  CHECK_BAILOUT;
2915
2809
  HFunctionLiteral* instr =
2916
2810
  new HFunctionLiteral(shared_info, expr->pretenure());
@@ -2925,48 +2819,46 @@ void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2925
2819
 
2926
2820
 
2927
2821
  void HGraphBuilder::VisitConditional(Conditional* expr) {
2928
- HSubgraph* then_graph = CreateEmptySubgraph();
2929
- HSubgraph* else_graph = CreateEmptySubgraph();
2930
- VISIT_FOR_CONTROL(expr->condition(),
2931
- then_graph->entry_block(),
2932
- else_graph->entry_block());
2933
-
2934
- then_graph->entry_block()->SetJoinId(expr->ThenId());
2935
- ADD_TO_SUBGRAPH(then_graph, expr->then_expression());
2822
+ HBasicBlock* cond_true = graph()->CreateBasicBlock();
2823
+ HBasicBlock* cond_false = graph()->CreateBasicBlock();
2824
+ VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false);
2825
+ cond_true->SetJoinId(expr->ThenId());
2826
+ cond_false->SetJoinId(expr->ElseId());
2827
+
2828
+ // Visit the true and false subexpressions in the same AST context as the
2829
+ // whole expression.
2830
+ set_current_block(cond_true);
2831
+ Visit(expr->then_expression());
2832
+ CHECK_BAILOUT;
2833
+ HBasicBlock* other = current_block();
2936
2834
 
2937
- else_graph->entry_block()->SetJoinId(expr->ElseId());
2938
- ADD_TO_SUBGRAPH(else_graph, expr->else_expression());
2835
+ set_current_block(cond_false);
2836
+ Visit(expr->else_expression());
2837
+ CHECK_BAILOUT;
2939
2838
 
2940
- current_subgraph_->AppendJoin(then_graph->exit_block(),
2941
- else_graph->exit_block(),
2942
- expr->id());
2943
- ast_context()->ReturnValue(Pop());
2839
+ if (!ast_context()->IsTest()) {
2840
+ HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
2841
+ set_current_block(join);
2842
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
2843
+ }
2944
2844
  }
2945
2845
 
2946
2846
 
2947
- void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2948
- LookupResult* lookup,
2949
- bool is_store) {
2950
- if (var->is_this()) {
2951
- BAILOUT("global this reference");
2847
+ HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
2848
+ Variable* var, LookupResult* lookup, bool is_store) {
2849
+ if (var->is_this() || !info()->has_global_object()) {
2850
+ return kUseGeneric;
2952
2851
  }
2953
- if (!graph()->info()->has_global_object()) {
2954
- BAILOUT("no global object to optimize VariableProxy");
2955
- }
2956
- Handle<GlobalObject> global(graph()->info()->global_object());
2852
+ Handle<GlobalObject> global(info()->global_object());
2957
2853
  global->Lookup(*var->name(), lookup);
2958
- if (!lookup->IsProperty()) {
2959
- BAILOUT("global variable cell not yet introduced");
2960
- }
2961
- if (lookup->type() != NORMAL) {
2962
- BAILOUT("global variable has accessors");
2963
- }
2964
- if (is_store && lookup->IsReadOnly()) {
2965
- BAILOUT("read-only global variable");
2966
- }
2967
- if (lookup->holder() != *global) {
2968
- BAILOUT("global property on prototype of global object");
2854
+ if (!lookup->IsProperty() ||
2855
+ lookup->type() != NORMAL ||
2856
+ (is_store && lookup->IsReadOnly()) ||
2857
+ lookup->holder() != *global) {
2858
+ return kUseGeneric;
2969
2859
  }
2860
+
2861
+ return kUseCell;
2970
2862
  }
2971
2863
 
2972
2864
 
@@ -2974,7 +2866,7 @@ HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
2974
2866
  ASSERT(var->IsContextSlot());
2975
2867
  HInstruction* context = new HContext;
2976
2868
  AddInstruction(context);
2977
- int length = graph()->info()->scope()->ContextChainLength(var->scope());
2869
+ int length = info()->scope()->ContextChainLength(var->scope());
2978
2870
  while (length-- > 0) {
2979
2871
  context = new HOuterContext(context);
2980
2872
  AddInstruction(context);
@@ -3002,19 +2894,33 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3002
2894
  ast_context()->ReturnInstruction(instr, expr->id());
3003
2895
  } else if (variable->is_global()) {
3004
2896
  LookupResult lookup;
3005
- LookupGlobalPropertyCell(variable, &lookup, false);
3006
- CHECK_BAILOUT;
2897
+ GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
3007
2898
 
3008
- Handle<GlobalObject> global(graph()->info()->global_object());
3009
- // TODO(3039103): Handle global property load through an IC call when access
3010
- // checks are enabled.
3011
- if (global->IsAccessCheckNeeded()) {
3012
- BAILOUT("global object requires access check");
2899
+ if (type == kUseCell &&
2900
+ info()->global_object()->IsAccessCheckNeeded()) {
2901
+ type = kUseGeneric;
2902
+ }
2903
+
2904
+ if (type == kUseCell) {
2905
+ Handle<GlobalObject> global(info()->global_object());
2906
+ Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2907
+ bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2908
+ HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole);
2909
+ ast_context()->ReturnInstruction(instr, expr->id());
2910
+ } else {
2911
+ HContext* context = new HContext;
2912
+ AddInstruction(context);
2913
+ HGlobalObject* global_object = new HGlobalObject(context);
2914
+ AddInstruction(global_object);
2915
+ HLoadGlobalGeneric* instr =
2916
+ new HLoadGlobalGeneric(context,
2917
+ global_object,
2918
+ variable->name(),
2919
+ ast_context()->is_for_typeof());
2920
+ instr->set_position(expr->position());
2921
+ ASSERT(instr->HasSideEffects());
2922
+ ast_context()->ReturnInstruction(instr, expr->id());
3013
2923
  }
3014
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3015
- bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3016
- HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
3017
- ast_context()->ReturnInstruction(instr, expr->id());
3018
2924
  } else {
3019
2925
  BAILOUT("reference to a variable which requires dynamic lookup");
3020
2926
  }
@@ -3042,7 +2948,8 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3042
2948
  expr->constant_properties(),
3043
2949
  expr->fast_elements(),
3044
2950
  expr->literal_index(),
3045
- expr->depth()));
2951
+ expr->depth(),
2952
+ expr->has_function()));
3046
2953
  // The object is expected in the bailout environment during computation
3047
2954
  // of the property values and is the value of the entire expression.
3048
2955
  PushAndAdd(literal);
@@ -3083,7 +2990,19 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3083
2990
  default: UNREACHABLE();
3084
2991
  }
3085
2992
  }
3086
- ast_context()->ReturnValue(Pop());
2993
+
2994
+ if (expr->has_function()) {
2995
+ // Return the result of the transformation to fast properties
2996
+ // instead of the original since this operation changes the map
2997
+ // of the object. This makes sure that the original object won't
2998
+ // be used by other optimized code before it is transformed
2999
+ // (e.g. because of code motion).
3000
+ HToFastProperties* result = new HToFastProperties(Pop());
3001
+ AddInstruction(result);
3002
+ ast_context()->ReturnValue(result);
3003
+ } else {
3004
+ ast_context()->ReturnValue(Pop());
3005
+ }
3087
3006
  }
3088
3007
 
3089
3008
 
@@ -3131,55 +3050,6 @@ void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3131
3050
  }
3132
3051
 
3133
3052
 
3134
- HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
3135
- ZoneMapList* maps,
3136
- ZoneList<HSubgraph*>* body_graphs,
3137
- HSubgraph* default_graph,
3138
- int join_id) {
3139
- ASSERT(maps->length() == body_graphs->length());
3140
- HBasicBlock* join_block = graph()->CreateBasicBlock();
3141
- AddInstruction(new HCheckNonSmi(receiver));
3142
-
3143
- for (int i = 0; i < maps->length(); ++i) {
3144
- // Build the branches, connect all the target subgraphs to the join
3145
- // block. Use the default as a target of the last branch.
3146
- HSubgraph* if_true = body_graphs->at(i);
3147
- HSubgraph* if_false = (i == maps->length() - 1)
3148
- ? default_graph
3149
- : CreateBranchSubgraph(environment());
3150
- HCompareMap* compare =
3151
- new HCompareMap(receiver,
3152
- maps->at(i),
3153
- if_true->entry_block(),
3154
- if_false->entry_block());
3155
- current_block()->Finish(compare);
3156
-
3157
- if (if_true->exit_block() != NULL) {
3158
- // In an effect context the value of the type switch is not needed.
3159
- // There is no need to merge it at the join block only to discard it.
3160
- if (ast_context()->IsEffect()) {
3161
- if_true->exit_block()->last_environment()->Drop(1);
3162
- }
3163
- if_true->exit_block()->Goto(join_block);
3164
- }
3165
-
3166
- set_current_block(if_false->exit_block());
3167
- }
3168
-
3169
- // Connect the default if necessary.
3170
- if (current_block() != NULL) {
3171
- if (ast_context()->IsEffect()) {
3172
- environment()->Drop(1);
3173
- }
3174
- current_block()->Goto(join_block);
3175
- }
3176
-
3177
- if (join_block->predecessors()->is_empty()) return NULL;
3178
- join_block->SetJoinId(join_id);
3179
- return join_block;
3180
- }
3181
-
3182
-
3183
3053
  // Sets the lookup result and returns true if the store can be inlined.
3184
3054
  static bool ComputeStoredField(Handle<Map> type,
3185
3055
  Handle<String> name,
@@ -3275,66 +3145,73 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3275
3145
  HValue* value,
3276
3146
  ZoneMapList* types,
3277
3147
  Handle<String> name) {
3278
- int number_of_types = Min(types->length(), kMaxStorePolymorphism);
3279
- ZoneMapList maps(number_of_types);
3280
- ZoneList<HSubgraph*> subgraphs(number_of_types);
3281
- bool needs_generic = (types->length() > kMaxStorePolymorphism);
3282
-
3283
- // Build subgraphs for each of the specific maps.
3284
- //
3285
- // TODO(ager): We should recognize when the prototype chains for
3286
- // different maps are identical. In that case we can avoid
3287
- // repeatedly generating the same prototype map checks.
3288
- for (int i = 0; i < number_of_types; ++i) {
3148
+ // TODO(ager): We should recognize when the prototype chains for different
3149
+ // maps are identical. In that case we can avoid repeatedly generating the
3150
+ // same prototype map checks.
3151
+ int count = 0;
3152
+ HBasicBlock* join = NULL;
3153
+ for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
3289
3154
  Handle<Map> map = types->at(i);
3290
3155
  LookupResult lookup;
3291
3156
  if (ComputeStoredField(map, name, &lookup)) {
3292
- HSubgraph* subgraph = CreateBranchSubgraph(environment());
3293
- SubgraphScope scope(this, subgraph);
3157
+ if (count == 0) {
3158
+ AddInstruction(new HCheckNonSmi(object)); // Only needed once.
3159
+ join = graph()->CreateBasicBlock();
3160
+ }
3161
+ ++count;
3162
+ HBasicBlock* if_true = graph()->CreateBasicBlock();
3163
+ HBasicBlock* if_false = graph()->CreateBasicBlock();
3164
+ HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
3165
+ current_block()->Finish(compare);
3166
+
3167
+ set_current_block(if_true);
3294
3168
  HInstruction* instr =
3295
3169
  BuildStoreNamedField(object, name, value, map, &lookup, false);
3296
- Push(value);
3297
3170
  instr->set_position(expr->position());
3171
+ // Goto will add the HSimulate for the store.
3298
3172
  AddInstruction(instr);
3299
- maps.Add(map);
3300
- subgraphs.Add(subgraph);
3301
- } else {
3302
- needs_generic = true;
3173
+ if (!ast_context()->IsEffect()) Push(value);
3174
+ current_block()->Goto(join);
3175
+
3176
+ set_current_block(if_false);
3303
3177
  }
3304
3178
  }
3305
3179
 
3306
- // If none of the properties were named fields we generate a
3307
- // generic store.
3308
- if (maps.length() == 0) {
3180
+ // Finish up. Unconditionally deoptimize if we've handled all the maps we
3181
+ // know about and do not want to handle ones we've never seen. Otherwise
3182
+ // use a generic IC.
3183
+ if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3184
+ current_block()->FinishExitWithDeoptimization();
3185
+ } else {
3309
3186
  HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3310
- Push(value);
3311
3187
  instr->set_position(expr->position());
3312
3188
  AddInstruction(instr);
3313
- if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3314
- ast_context()->ReturnValue(Pop());
3315
- } else {
3316
- // Build subgraph for generic store through IC.
3317
- HSubgraph* default_graph = CreateBranchSubgraph(environment());
3318
- { SubgraphScope scope(this, default_graph);
3319
- if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3320
- default_graph->FinishExit(new HDeoptimize());
3321
- } else {
3322
- HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3323
- Push(value);
3324
- instr->set_position(expr->position());
3325
- AddInstruction(instr);
3326
- }
3327
- }
3328
3189
 
3329
- HBasicBlock* new_exit_block =
3330
- BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3331
- set_current_block(new_exit_block);
3332
- // In an effect context, we did not materialized the value in the
3333
- // predecessor environments so there's no need to handle it here.
3334
- if (current_block() != NULL && !ast_context()->IsEffect()) {
3335
- ast_context()->ReturnValue(Pop());
3190
+ if (join != NULL) {
3191
+ if (!ast_context()->IsEffect()) Push(value);
3192
+ current_block()->Goto(join);
3193
+ } else {
3194
+ // The HSimulate for the store should not see the stored value in
3195
+ // effect contexts (it is not materialized at expr->id() in the
3196
+ // unoptimized code).
3197
+ if (instr->HasSideEffects()) {
3198
+ if (ast_context()->IsEffect()) {
3199
+ AddSimulate(expr->id());
3200
+ } else {
3201
+ Push(value);
3202
+ AddSimulate(expr->id());
3203
+ Drop(1);
3204
+ }
3205
+ }
3206
+ ast_context()->ReturnValue(value);
3207
+ return;
3336
3208
  }
3337
3209
  }
3210
+
3211
+ ASSERT(join != NULL);
3212
+ join->SetJoinId(expr->id());
3213
+ set_current_block(join);
3214
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3338
3215
  }
3339
3216
 
3340
3217
 
@@ -3381,11 +3258,14 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3381
3258
 
3382
3259
  if (expr->IsMonomorphic()) {
3383
3260
  Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3384
- // An object has either fast elements or pixel array elements, but never
3385
- // both. Pixel array maps that are assigned to pixel array elements are
3386
- // always created with the fast elements flag cleared.
3387
- if (receiver_type->has_pixel_array_elements()) {
3388
- instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
3261
+ // An object has either fast elements or external array elements, but
3262
+ // never both. Pixel array maps that are assigned to pixel array elements
3263
+ // are always created with the fast elements flag cleared.
3264
+ if (receiver_type->has_external_array_elements()) {
3265
+ instr = BuildStoreKeyedSpecializedArrayElement(object,
3266
+ key,
3267
+ value,
3268
+ expr);
3389
3269
  } else if (receiver_type->has_fast_elements()) {
3390
3270
  instr = BuildStoreKeyedFastElement(object, key, value, expr);
3391
3271
  }
@@ -3411,16 +3291,18 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3411
3291
  int position,
3412
3292
  int ast_id) {
3413
3293
  LookupResult lookup;
3414
- LookupGlobalPropertyCell(var, &lookup, true);
3415
- CHECK_BAILOUT;
3416
-
3417
- bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3418
- Handle<GlobalObject> global(graph()->info()->global_object());
3419
- Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3420
- HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
3421
- instr->set_position(position);
3422
- AddInstruction(instr);
3423
- if (instr->HasSideEffects()) AddSimulate(ast_id);
3294
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
3295
+ if (type == kUseCell) {
3296
+ bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3297
+ Handle<GlobalObject> global(info()->global_object());
3298
+ Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3299
+ HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
3300
+ instr->set_position(position);
3301
+ AddInstruction(instr);
3302
+ if (instr->HasSideEffects()) AddSimulate(ast_id);
3303
+ } else {
3304
+ BAILOUT("global store only supported for cells");
3305
+ }
3424
3306
  }
3425
3307
 
3426
3308
 
@@ -3604,71 +3486,8 @@ void HGraphBuilder::VisitThrow(Throw* expr) {
3604
3486
  instr->set_position(expr->position());
3605
3487
  AddInstruction(instr);
3606
3488
  AddSimulate(expr->id());
3607
- current_subgraph_->FinishExit(new HAbnormalExit);
3608
- }
3609
-
3610
-
3611
- void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
3612
- HValue* object,
3613
- ZoneMapList* types,
3614
- Handle<String> name) {
3615
- int number_of_types = Min(types->length(), kMaxLoadPolymorphism);
3616
- ZoneMapList maps(number_of_types);
3617
- ZoneList<HSubgraph*> subgraphs(number_of_types);
3618
- bool needs_generic = (types->length() > kMaxLoadPolymorphism);
3619
-
3620
- // Build subgraphs for each of the specific maps.
3621
- //
3622
- // TODO(ager): We should recognize when the prototype chains for
3623
- // different maps are identical. In that case we can avoid
3624
- // repeatedly generating the same prototype map checks.
3625
- for (int i = 0; i < number_of_types; ++i) {
3626
- Handle<Map> map = types->at(i);
3627
- LookupResult lookup;
3628
- map->LookupInDescriptors(NULL, *name, &lookup);
3629
- if (lookup.IsProperty() && lookup.type() == FIELD) {
3630
- HSubgraph* subgraph = CreateBranchSubgraph(environment());
3631
- SubgraphScope scope(this, subgraph);
3632
- HLoadNamedField* instr =
3633
- BuildLoadNamedField(object, expr, map, &lookup, false);
3634
- instr->set_position(expr->position());
3635
- instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
3636
- PushAndAdd(instr);
3637
- maps.Add(map);
3638
- subgraphs.Add(subgraph);
3639
- } else {
3640
- needs_generic = true;
3641
- }
3642
- }
3643
-
3644
- // If none of the properties were named fields we generate a
3645
- // generic load.
3646
- if (maps.length() == 0) {
3647
- HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3648
- instr->set_position(expr->position());
3649
- ast_context()->ReturnInstruction(instr, expr->id());
3650
- } else {
3651
- // Build subgraph for generic load through IC.
3652
- HSubgraph* default_graph = CreateBranchSubgraph(environment());
3653
- { SubgraphScope scope(this, default_graph);
3654
- if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3655
- default_graph->FinishExit(new HDeoptimize());
3656
- } else {
3657
- HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3658
- instr->set_position(expr->position());
3659
- PushAndAdd(instr);
3660
- }
3661
- }
3662
-
3663
- HBasicBlock* new_exit_block =
3664
- BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3665
- set_current_block(new_exit_block);
3666
- // In an effect context, we did not materialized the value in the
3667
- // predecessor environments so there's no need to handle it here.
3668
- if (current_block() != NULL && !ast_context()->IsEffect()) {
3669
- ast_context()->ReturnValue(Pop());
3670
- }
3671
- }
3489
+ current_block()->FinishExit(new HAbnormalExit);
3490
+ set_current_block(NULL);
3672
3491
  }
3673
3492
 
3674
3493
 
@@ -3761,25 +3580,28 @@ HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3761
3580
  }
3762
3581
 
3763
3582
 
3764
- HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object,
3765
- HValue* key,
3766
- Property* expr) {
3583
+ HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement(
3584
+ HValue* object,
3585
+ HValue* key,
3586
+ Property* expr) {
3767
3587
  ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3768
3588
  AddInstruction(new HCheckNonSmi(object));
3769
3589
  Handle<Map> map = expr->GetMonomorphicReceiverType();
3770
3590
  ASSERT(!map->has_fast_elements());
3771
- ASSERT(map->has_pixel_array_elements());
3591
+ ASSERT(map->has_external_array_elements());
3772
3592
  AddInstruction(new HCheckMap(object, map));
3773
3593
  HLoadElements* elements = new HLoadElements(object);
3774
3594
  AddInstruction(elements);
3775
- HInstruction* length = new HPixelArrayLength(elements);
3595
+ HInstruction* length = new HExternalArrayLength(elements);
3776
3596
  AddInstruction(length);
3777
3597
  AddInstruction(new HBoundsCheck(key, length));
3778
- HLoadPixelArrayExternalPointer* external_elements =
3779
- new HLoadPixelArrayExternalPointer(elements);
3598
+ HLoadExternalArrayPointer* external_elements =
3599
+ new HLoadExternalArrayPointer(elements);
3780
3600
  AddInstruction(external_elements);
3781
- HLoadPixelArrayElement* pixel_array_value =
3782
- new HLoadPixelArrayElement(external_elements, key);
3601
+ HLoadKeyedSpecializedArrayElement* pixel_array_value =
3602
+ new HLoadKeyedSpecializedArrayElement(external_elements,
3603
+ key,
3604
+ expr->GetExternalArrayType());
3783
3605
  return pixel_array_value;
3784
3606
  }
3785
3607
 
@@ -3803,7 +3625,8 @@ HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3803
3625
  ASSERT(map->has_fast_elements());
3804
3626
  AddInstruction(new HCheckMap(object, map));
3805
3627
  HInstruction* elements = AddInstruction(new HLoadElements(object));
3806
- AddInstruction(new HCheckMap(elements, Factory::fixed_array_map()));
3628
+ AddInstruction(new HCheckMap(elements,
3629
+ isolate()->factory()->fixed_array_map()));
3807
3630
  bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3808
3631
  HInstruction* length = NULL;
3809
3632
  if (is_array) {
@@ -3816,25 +3639,29 @@ HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3816
3639
  }
3817
3640
 
3818
3641
 
3819
- HInstruction* HGraphBuilder::BuildStoreKeyedPixelArrayElement(
3642
+ HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
3820
3643
  HValue* object,
3821
3644
  HValue* key,
3822
3645
  HValue* val,
3823
- Expression* expr) {
3646
+ Assignment* expr) {
3824
3647
  ASSERT(expr->IsMonomorphic());
3825
3648
  AddInstruction(new HCheckNonSmi(object));
3826
3649
  Handle<Map> map = expr->GetMonomorphicReceiverType();
3827
3650
  ASSERT(!map->has_fast_elements());
3828
- ASSERT(map->has_pixel_array_elements());
3651
+ ASSERT(map->has_external_array_elements());
3829
3652
  AddInstruction(new HCheckMap(object, map));
3830
3653
  HLoadElements* elements = new HLoadElements(object);
3831
3654
  AddInstruction(elements);
3832
- HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
3655
+ HInstruction* length = AddInstruction(new HExternalArrayLength(elements));
3833
3656
  AddInstruction(new HBoundsCheck(key, length));
3834
- HLoadPixelArrayExternalPointer* external_elements =
3835
- new HLoadPixelArrayExternalPointer(elements);
3657
+ HLoadExternalArrayPointer* external_elements =
3658
+ new HLoadExternalArrayPointer(elements);
3836
3659
  AddInstruction(external_elements);
3837
- return new HStorePixelArrayElement(external_elements, key, val);
3660
+ return new HStoreKeyedSpecializedArrayElement(
3661
+ external_elements,
3662
+ key,
3663
+ val,
3664
+ expr->GetExternalArrayType());
3838
3665
  }
3839
3666
 
3840
3667
 
@@ -3853,9 +3680,11 @@ bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3853
3680
  HInstruction* elements = AddInstruction(new HArgumentsElements);
3854
3681
  result = new HArgumentsLength(elements);
3855
3682
  } else {
3683
+ Push(graph()->GetArgumentsObject());
3856
3684
  VisitForValue(expr->key());
3857
3685
  if (HasStackOverflow()) return false;
3858
3686
  HValue* key = Pop();
3687
+ Drop(1); // Arguments object.
3859
3688
  HInstruction* elements = AddInstruction(new HArgumentsElements);
3860
3689
  HInstruction* length = AddInstruction(new HArgumentsLength(elements));
3861
3690
  AddInstruction(new HBoundsCheck(key, length));
@@ -3888,6 +3717,13 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3888
3717
  FIRST_STRING_TYPE,
3889
3718
  LAST_STRING_TYPE));
3890
3719
  instr = new HStringLength(string);
3720
+ } else if (expr->IsStringAccess()) {
3721
+ VISIT_FOR_VALUE(expr->key());
3722
+ HValue* index = Pop();
3723
+ HValue* string = Pop();
3724
+ HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
3725
+ AddInstruction(char_code);
3726
+ instr = new HStringCharFromCode(char_code);
3891
3727
 
3892
3728
  } else if (expr->IsFunctionPrototype()) {
3893
3729
  HValue* function = Pop();
@@ -3902,9 +3738,8 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3902
3738
  if (expr->IsMonomorphic()) {
3903
3739
  instr = BuildLoadNamed(obj, expr, types->first(), name);
3904
3740
  } else if (types != NULL && types->length() > 1) {
3905
- HandlePolymorphicLoadNamedField(expr, obj, types, name);
3906
- return;
3907
-
3741
+ AddInstruction(new HCheckNonSmi(obj));
3742
+ instr = new HLoadNamedFieldPolymorphic(obj, types, name);
3908
3743
  } else {
3909
3744
  instr = BuildLoadNamedGeneric(obj, expr);
3910
3745
  }
@@ -3920,8 +3755,8 @@ void HGraphBuilder::VisitProperty(Property* expr) {
3920
3755
  // An object has either fast elements or pixel array elements, but never
3921
3756
  // both. Pixel array maps that are assigned to pixel array elements are
3922
3757
  // always created with the fast elements flag cleared.
3923
- if (receiver_type->has_pixel_array_elements()) {
3924
- instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
3758
+ if (receiver_type->has_external_array_elements()) {
3759
+ instr = BuildLoadKeyedSpecializedArrayElement(obj, key, expr);
3925
3760
  } else if (receiver_type->has_fast_elements()) {
3926
3761
  instr = BuildLoadKeyedFastElement(obj, key, expr);
3927
3762
  }
@@ -3958,22 +3793,26 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3958
3793
  HValue* receiver,
3959
3794
  ZoneMapList* types,
3960
3795
  Handle<String> name) {
3961
- int argument_count = expr->arguments()->length() + 1; // Plus receiver.
3962
- int number_of_types = Min(types->length(), kMaxCallPolymorphism);
3963
- ZoneMapList maps(number_of_types);
3964
- ZoneList<HSubgraph*> subgraphs(number_of_types);
3965
- bool needs_generic = (types->length() > kMaxCallPolymorphism);
3966
-
3967
- // Build subgraphs for each of the specific maps.
3968
- //
3969
3796
  // TODO(ager): We should recognize when the prototype chains for different
3970
3797
  // maps are identical. In that case we can avoid repeatedly generating the
3971
3798
  // same prototype map checks.
3972
- for (int i = 0; i < number_of_types; ++i) {
3799
+ int argument_count = expr->arguments()->length() + 1; // Includes receiver.
3800
+ int count = 0;
3801
+ HBasicBlock* join = NULL;
3802
+ for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) {
3973
3803
  Handle<Map> map = types->at(i);
3974
3804
  if (expr->ComputeTarget(map, name)) {
3975
- HSubgraph* subgraph = CreateBranchSubgraph(environment());
3976
- SubgraphScope scope(this, subgraph);
3805
+ if (count == 0) {
3806
+ AddInstruction(new HCheckNonSmi(receiver)); // Only needed once.
3807
+ join = graph()->CreateBasicBlock();
3808
+ }
3809
+ ++count;
3810
+ HBasicBlock* if_true = graph()->CreateBasicBlock();
3811
+ HBasicBlock* if_false = graph()->CreateBasicBlock();
3812
+ HCompareMap* compare = new HCompareMap(receiver, map, if_true, if_false);
3813
+ current_block()->Finish(compare);
3814
+
3815
+ set_current_block(if_true);
3977
3816
  AddCheckConstantFunction(expr, receiver, map, false);
3978
3817
  if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3979
3818
  PrintF("Trying to inline the polymorphic call to %s\n",
@@ -3984,63 +3823,69 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3984
3823
  // during hydrogen processing.
3985
3824
  CHECK_BAILOUT;
3986
3825
  HCallConstantFunction* call =
3987
- new HCallConstantFunction(expr->target(), argument_count);
3826
+ new HCallConstantFunction(expr->target(), argument_count);
3988
3827
  call->set_position(expr->position());
3989
3828
  PreProcessCall(call);
3990
- PushAndAdd(call);
3829
+ AddInstruction(call);
3830
+ if (!ast_context()->IsEffect()) Push(call);
3991
3831
  }
3992
- maps.Add(map);
3993
- subgraphs.Add(subgraph);
3994
- } else {
3995
- needs_generic = true;
3832
+
3833
+ if (current_block() != NULL) current_block()->Goto(join);
3834
+ set_current_block(if_false);
3996
3835
  }
3997
3836
  }
3998
3837
 
3999
- // If we couldn't compute the target for any of the maps just perform an
4000
- // IC call.
4001
- if (maps.length() == 0) {
3838
+ // Finish up. Unconditionally deoptimize if we've handled all the maps we
3839
+ // know about and do not want to handle ones we've never seen. Otherwise
3840
+ // use a generic IC.
3841
+ if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3842
+ current_block()->FinishExitWithDeoptimization();
3843
+ } else {
4002
3844
  HContext* context = new HContext;
4003
3845
  AddInstruction(context);
4004
3846
  HCallNamed* call = new HCallNamed(context, name, argument_count);
4005
3847
  call->set_position(expr->position());
4006
3848
  PreProcessCall(call);
4007
- ast_context()->ReturnInstruction(call, expr->id());
4008
- } else {
4009
- // Build subgraph for generic call through IC.
4010
- HSubgraph* default_graph = CreateBranchSubgraph(environment());
4011
- { SubgraphScope scope(this, default_graph);
4012
- if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
4013
- default_graph->FinishExit(new HDeoptimize());
4014
- } else {
4015
- HContext* context = new HContext;
4016
- AddInstruction(context);
4017
- HCallNamed* call = new HCallNamed(context, name, argument_count);
4018
- call->set_position(expr->position());
4019
- PreProcessCall(call);
4020
- PushAndAdd(call);
4021
- }
4022
- }
4023
3849
 
4024
- HBasicBlock* new_exit_block =
4025
- BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
4026
- set_current_block(new_exit_block);
4027
- // In an effect context, we did not materialized the value in the
4028
- // predecessor environments so there's no need to handle it here.
4029
- if (new_exit_block != NULL && !ast_context()->IsEffect()) {
4030
- ast_context()->ReturnValue(Pop());
3850
+ if (join != NULL) {
3851
+ AddInstruction(call);
3852
+ if (!ast_context()->IsEffect()) Push(call);
3853
+ current_block()->Goto(join);
3854
+ } else {
3855
+ ast_context()->ReturnInstruction(call, expr->id());
3856
+ return;
4031
3857
  }
4032
3858
  }
3859
+
3860
+ // We assume that control flow is always live after an expression. So
3861
+ // even without predecessors to the join block, we set it as the exit
3862
+ // block and continue by adding instructions there.
3863
+ ASSERT(join != NULL);
3864
+ set_current_block(join);
3865
+ if (join->HasPredecessor()) {
3866
+ join->SetJoinId(expr->id());
3867
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3868
+ }
4033
3869
  }
4034
3870
 
4035
3871
 
4036
- void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
4037
- SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
4038
- SmartPointer<char> caller =
4039
- graph()->info()->function()->debug_name()->ToCString();
4040
- if (result) {
4041
- PrintF("Inlined %s called from %s.\n", *callee, *caller);
4042
- } else {
4043
- PrintF("Do not inline %s called from %s.\n", *callee, *caller);
3872
+ void HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) {
3873
+ if (FLAG_trace_inlining) {
3874
+ if (reason == NULL) {
3875
+ // We are currently in the context of inlined function thus we have
3876
+ // to go to an outer FunctionState to get caller.
3877
+ SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3878
+ SmartPointer<char> caller =
3879
+ function_state()->outer()->compilation_info()->function()->
3880
+ debug_name()->ToCString();
3881
+ PrintF("Inlined %s called from %s.\n", *callee, *caller);
3882
+ } else {
3883
+ SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3884
+ SmartPointer<char> caller =
3885
+ info()->function()->debug_name()->ToCString();
3886
+ PrintF("Did not inline %s called from %s (%s).\n",
3887
+ *callee, *caller, reason);
3888
+ }
4044
3889
  }
4045
3890
  }
4046
3891
 
@@ -4055,148 +3900,156 @@ bool HGraphBuilder::TryInline(Call* expr) {
4055
3900
  // Do a quick check on source code length to avoid parsing large
4056
3901
  // inlining candidates.
4057
3902
  if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
4058
- if (FLAG_trace_inlining) TraceInline(target, false);
3903
+ TraceInline(target, "target text too big");
4059
3904
  return false;
4060
3905
  }
4061
3906
 
4062
3907
  // Target must be inlineable.
4063
- if (!target->IsInlineable()) return false;
3908
+ if (!target->IsInlineable()) {
3909
+ TraceInline(target, "target not inlineable");
3910
+ return false;
3911
+ }
4064
3912
 
4065
3913
  // No context change required.
4066
- CompilationInfo* outer_info = graph()->info();
3914
+ CompilationInfo* outer_info = info();
4067
3915
  if (target->context() != outer_info->closure()->context() ||
4068
3916
  outer_info->scope()->contains_with() ||
4069
3917
  outer_info->scope()->num_heap_slots() > 0) {
3918
+ TraceInline(target, "target requires context change");
4070
3919
  return false;
4071
3920
  }
4072
3921
 
4073
3922
  // Don't inline deeper than two calls.
4074
3923
  HEnvironment* env = environment();
4075
- if (env->outer() != NULL && env->outer()->outer() != NULL) return false;
3924
+ if (env->outer() != NULL && env->outer()->outer() != NULL) {
3925
+ TraceInline(target, "inline depth limit reached");
3926
+ return false;
3927
+ }
4076
3928
 
4077
3929
  // Don't inline recursive functions.
4078
- if (target->shared() == outer_info->closure()->shared()) return false;
3930
+ if (target->shared() == outer_info->closure()->shared()) {
3931
+ TraceInline(target, "target is recursive");
3932
+ return false;
3933
+ }
4079
3934
 
4080
3935
  // We don't want to add more than a certain number of nodes from inlining.
4081
3936
  if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
4082
- if (FLAG_trace_inlining) TraceInline(target, false);
3937
+ TraceInline(target, "cumulative AST node limit reached");
4083
3938
  return false;
4084
3939
  }
4085
3940
 
4086
3941
  int count_before = AstNode::Count();
4087
3942
 
4088
3943
  // Parse and allocate variables.
4089
- CompilationInfo inner_info(target);
4090
- if (!ParserApi::Parse(&inner_info) ||
4091
- !Scope::Analyze(&inner_info)) {
4092
- if (Top::has_pending_exception()) {
3944
+ CompilationInfo target_info(target);
3945
+ if (!ParserApi::Parse(&target_info) ||
3946
+ !Scope::Analyze(&target_info)) {
3947
+ if (target_info.isolate()->has_pending_exception()) {
3948
+ // Parse or scope error, never optimize this function.
4093
3949
  SetStackOverflow();
3950
+ target->shared()->set_optimization_disabled(true);
4094
3951
  }
3952
+ TraceInline(target, "parse failure");
4095
3953
  return false;
4096
3954
  }
4097
- if (inner_info.scope()->num_heap_slots() > 0) return false;
4098
- FunctionLiteral* function = inner_info.function();
3955
+
3956
+ if (target_info.scope()->num_heap_slots() > 0) {
3957
+ TraceInline(target, "target has context-allocated variables");
3958
+ return false;
3959
+ }
3960
+ FunctionLiteral* function = target_info.function();
4099
3961
 
4100
3962
  // Count the number of AST nodes added by inlining this call.
4101
3963
  int nodes_added = AstNode::Count() - count_before;
4102
3964
  if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
4103
- if (FLAG_trace_inlining) TraceInline(target, false);
3965
+ TraceInline(target, "target AST is too large");
4104
3966
  return false;
4105
3967
  }
4106
3968
 
4107
3969
  // Check if we can handle all declarations in the inlined functions.
4108
- VisitDeclarations(inner_info.scope()->declarations());
3970
+ VisitDeclarations(target_info.scope()->declarations());
4109
3971
  if (HasStackOverflow()) {
3972
+ TraceInline(target, "target has non-trivial declaration");
4110
3973
  ClearStackOverflow();
4111
3974
  return false;
4112
3975
  }
4113
3976
 
4114
3977
  // Don't inline functions that uses the arguments object or that
4115
3978
  // have a mismatching number of parameters.
4116
- Handle<SharedFunctionInfo> shared(target->shared());
3979
+ Handle<SharedFunctionInfo> target_shared(target->shared());
4117
3980
  int arity = expr->arguments()->length();
4118
3981
  if (function->scope()->arguments() != NULL ||
4119
- arity != shared->formal_parameter_count()) {
3982
+ arity != target_shared->formal_parameter_count()) {
3983
+ TraceInline(target, "target requires special argument handling");
4120
3984
  return false;
4121
3985
  }
4122
3986
 
4123
3987
  // All statements in the body must be inlineable.
4124
3988
  for (int i = 0, count = function->body()->length(); i < count; ++i) {
4125
- if (!function->body()->at(i)->IsInlineable()) return false;
3989
+ if (!function->body()->at(i)->IsInlineable()) {
3990
+ TraceInline(target, "target contains unsupported syntax");
3991
+ return false;
3992
+ }
4126
3993
  }
4127
3994
 
4128
3995
  // Generate the deoptimization data for the unoptimized version of
4129
3996
  // the target function if we don't already have it.
4130
- if (!shared->has_deoptimization_support()) {
3997
+ if (!target_shared->has_deoptimization_support()) {
4131
3998
  // Note that we compile here using the same AST that we will use for
4132
3999
  // generating the optimized inline code.
4133
- inner_info.EnableDeoptimizationSupport();
4134
- if (!FullCodeGenerator::MakeCode(&inner_info)) return false;
4135
- shared->EnableDeoptimizationSupport(*inner_info.code());
4136
- Compiler::RecordFunctionCompilation(
4137
- Logger::FUNCTION_TAG, &inner_info, shared);
4000
+ target_info.EnableDeoptimizationSupport();
4001
+ if (!FullCodeGenerator::MakeCode(&target_info)) {
4002
+ TraceInline(target, "could not generate deoptimization info");
4003
+ return false;
4004
+ }
4005
+ target_shared->EnableDeoptimizationSupport(*target_info.code());
4006
+ Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
4007
+ &target_info,
4008
+ target_shared);
4138
4009
  }
4139
4010
 
4011
+ // ----------------------------------------------------------------
4140
4012
  // Save the pending call context and type feedback oracle. Set up new ones
4141
4013
  // for the inlined function.
4142
- ASSERT(shared->has_deoptimization_support());
4143
- AstContext* saved_call_context = call_context();
4144
- HBasicBlock* saved_function_return = function_return();
4145
- TypeFeedbackOracle* saved_oracle = oracle();
4146
- // On-stack replacement cannot target inlined functions. Since we don't
4147
- // use a separate CompilationInfo structure for the inlined function, we
4148
- // save and restore the AST ID in the original compilation info.
4149
- int saved_osr_ast_id = graph()->info()->osr_ast_id();
4150
-
4151
- TestContext* test_context = NULL;
4152
- if (ast_context()->IsTest()) {
4153
- // Inlined body is treated as if it occurs in an 'inlined' call context
4154
- // with true and false blocks that will forward to the real ones.
4155
- HBasicBlock* if_true = graph()->CreateBasicBlock();
4156
- HBasicBlock* if_false = graph()->CreateBasicBlock();
4157
- if_true->MarkAsInlineReturnTarget();
4158
- if_false->MarkAsInlineReturnTarget();
4159
- // AstContext constructor pushes on the context stack.
4160
- test_context = new TestContext(this, if_true, if_false);
4161
- function_return_ = NULL;
4162
- } else {
4163
- // Inlined body is treated as if it occurs in the original call context.
4164
- function_return_ = graph()->CreateBasicBlock();
4165
- function_return_->MarkAsInlineReturnTarget();
4166
- }
4167
- call_context_ = ast_context();
4168
- TypeFeedbackOracle new_oracle(
4169
- Handle<Code>(shared->code()),
4014
+ ASSERT(target_shared->has_deoptimization_support());
4015
+ TypeFeedbackOracle target_oracle(
4016
+ Handle<Code>(target_shared->code()),
4170
4017
  Handle<Context>(target->context()->global_context()));
4171
- oracle_ = &new_oracle;
4172
- graph()->info()->SetOsrAstId(AstNode::kNoNumber);
4018
+ FunctionState target_state(this, &target_info, &target_oracle);
4173
4019
 
4174
- HSubgraph* body = CreateInlinedSubgraph(env, target, function);
4175
- body->exit_block()->AddInstruction(new HEnterInlined(target, function));
4176
- AddToSubgraph(body, function->body());
4020
+ HConstant* undefined = graph()->GetConstantUndefined();
4021
+ HEnvironment* inner_env =
4022
+ environment()->CopyForInlining(target, function, true, undefined);
4023
+ HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4024
+ current_block()->Goto(body_entry);
4025
+
4026
+ body_entry->SetJoinId(expr->ReturnId());
4027
+ set_current_block(body_entry);
4028
+ AddInstruction(new HEnterInlined(target, function));
4029
+ VisitStatements(function->body());
4177
4030
  if (HasStackOverflow()) {
4178
4031
  // Bail out if the inline function did, as we cannot residualize a call
4179
4032
  // instead.
4180
- delete test_context;
4181
- call_context_ = saved_call_context;
4182
- function_return_ = saved_function_return;
4183
- oracle_ = saved_oracle;
4184
- graph()->info()->SetOsrAstId(saved_osr_ast_id);
4033
+ TraceInline(target, "inline graph construction failed");
4185
4034
  return false;
4186
4035
  }
4187
4036
 
4188
4037
  // Update inlined nodes count.
4189
4038
  inlined_count_ += nodes_added;
4190
4039
 
4191
- if (FLAG_trace_inlining) TraceInline(target, true);
4040
+ TraceInline(target, NULL);
4192
4041
 
4193
- if (body->exit_block() != NULL) {
4042
+ if (current_block() != NULL) {
4194
4043
  // Add a return of undefined if control can fall off the body. In a
4195
4044
  // test context, undefined is false.
4196
- HValue* return_value = graph()->GetConstantUndefined();
4197
- if (test_context == NULL) {
4198
- ASSERT(function_return_ != NULL);
4199
- body->exit_block()->AddLeaveInlined(return_value, function_return_);
4045
+ if (inlined_test_context() == NULL) {
4046
+ ASSERT(function_return() != NULL);
4047
+ ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4048
+ if (call_context()->IsEffect()) {
4049
+ current_block()->Goto(function_return(), false);
4050
+ } else {
4051
+ current_block()->AddLeaveInlined(undefined, function_return());
4052
+ }
4200
4053
  } else {
4201
4054
  // The graph builder assumes control can reach both branches of a
4202
4055
  // test, so we materialize the undefined value and test it rather than
@@ -4205,46 +4058,29 @@ bool HGraphBuilder::TryInline(Call* expr) {
4205
4058
  // TODO(3168478): refactor to avoid this.
4206
4059
  HBasicBlock* empty_true = graph()->CreateBasicBlock();
4207
4060
  HBasicBlock* empty_false = graph()->CreateBasicBlock();
4208
- HTest* test = new HTest(return_value, empty_true, empty_false);
4209
- body->exit_block()->Finish(test);
4061
+ HTest* test = new HTest(undefined, empty_true, empty_false);
4062
+ current_block()->Finish(test);
4210
4063
 
4211
- HValue* const no_return_value = NULL;
4212
- empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
4213
- empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4064
+ empty_true->Goto(inlined_test_context()->if_true(), false);
4065
+ empty_false->Goto(inlined_test_context()->if_false(), false);
4214
4066
  }
4215
- body->set_exit_block(NULL);
4216
4067
  }
4217
4068
 
4218
- // Record the environment at the inlined function call.
4219
- AddSimulate(expr->ReturnId());
4220
-
4221
- // Jump to the function entry (without re-recording the environment).
4222
- current_block()->Finish(new HGoto(body->entry_block()));
4223
-
4224
4069
  // Fix up the function exits.
4225
- if (test_context != NULL) {
4226
- HBasicBlock* if_true = test_context->if_true();
4227
- HBasicBlock* if_false = test_context->if_false();
4070
+ if (inlined_test_context() != NULL) {
4071
+ HBasicBlock* if_true = inlined_test_context()->if_true();
4072
+ HBasicBlock* if_false = inlined_test_context()->if_false();
4228
4073
  if_true->SetJoinId(expr->id());
4229
4074
  if_false->SetJoinId(expr->id());
4230
- ASSERT(ast_context() == test_context);
4231
- delete test_context; // Destructor pops from expression context stack.
4075
+ ASSERT(ast_context() == inlined_test_context());
4076
+ // Pop the return test context from the expression context stack.
4077
+ ClearInlinedTestContext();
4232
4078
 
4233
4079
  // Forward to the real test context.
4234
- HValue* const no_return_value = NULL;
4235
4080
  HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4236
- if (true_target->IsInlineReturnTarget()) {
4237
- if_true->AddLeaveInlined(no_return_value, true_target);
4238
- } else {
4239
- if_true->Goto(true_target);
4240
- }
4241
-
4242
4081
  HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4243
- if (false_target->IsInlineReturnTarget()) {
4244
- if_false->AddLeaveInlined(no_return_value, false_target);
4245
- } else {
4246
- if_false->Goto(false_target);
4247
- }
4082
+ if_true->Goto(true_target, false);
4083
+ if_false->Goto(false_target, false);
4248
4084
 
4249
4085
  // TODO(kmillikin): Come up with a better way to handle this. It is too
4250
4086
  // subtle. NULL here indicates that the enclosing context has no control
@@ -4252,29 +4088,14 @@ bool HGraphBuilder::TryInline(Call* expr) {
4252
4088
  set_current_block(NULL);
4253
4089
 
4254
4090
  } else {
4255
- function_return_->SetJoinId(expr->id());
4256
- set_current_block(function_return_);
4091
+ function_return()->SetJoinId(expr->id());
4092
+ set_current_block(function_return());
4257
4093
  }
4258
4094
 
4259
- call_context_ = saved_call_context;
4260
- function_return_ = saved_function_return;
4261
- oracle_ = saved_oracle;
4262
- graph()->info()->SetOsrAstId(saved_osr_ast_id);
4263
-
4264
4095
  return true;
4265
4096
  }
4266
4097
 
4267
4098
 
4268
- void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4269
- ASSERT(target->IsInlineReturnTarget());
4270
- AddInstruction(new HLeaveInlined);
4271
- HEnvironment* outer = last_environment()->outer();
4272
- if (return_value != NULL) outer->Push(return_value);
4273
- UpdateEnvironment(outer);
4274
- Goto(target);
4275
- }
4276
-
4277
-
4278
4099
  bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4279
4100
  HValue* receiver,
4280
4101
  Handle<Map> receiver_map,
@@ -4286,6 +4107,7 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4286
4107
  int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4287
4108
  switch (id) {
4288
4109
  case kStringCharCodeAt:
4110
+ case kStringCharAt:
4289
4111
  if (argument_count == 2 && check_type == STRING_CHECK) {
4290
4112
  HValue* index = Pop();
4291
4113
  HValue* string = Pop();
@@ -4293,7 +4115,13 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4293
4115
  AddInstruction(new HCheckPrototypeMaps(
4294
4116
  oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
4295
4117
  expr->holder()));
4296
- HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
4118
+ HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
4119
+ if (id == kStringCharCodeAt) {
4120
+ ast_context()->ReturnInstruction(char_code, expr->id());
4121
+ return true;
4122
+ }
4123
+ AddInstruction(char_code);
4124
+ HStringCharFromCode* result = new HStringCharFromCode(char_code);
4297
4125
  ast_context()->ReturnInstruction(result, expr->id());
4298
4126
  return true;
4299
4127
  }
@@ -4368,7 +4196,7 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
4368
4196
  Property* prop = callee->AsProperty();
4369
4197
  ASSERT(prop != NULL);
4370
4198
 
4371
- if (graph()->info()->scope()->arguments() == NULL) return false;
4199
+ if (info()->scope()->arguments() == NULL) return false;
4372
4200
 
4373
4201
  Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4374
4202
  if (!name->IsEqualTo(CStrVector("apply"))) return false;
@@ -4405,13 +4233,6 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
4405
4233
  }
4406
4234
 
4407
4235
 
4408
- static bool HasCustomCallGenerator(Handle<JSFunction> function) {
4409
- SharedFunctionInfo* info = function->shared();
4410
- return info->HasBuiltinFunctionId() &&
4411
- CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
4412
- }
4413
-
4414
-
4415
4236
  void HGraphBuilder::VisitCall(Call* expr) {
4416
4237
  Expression* callee = expr->expression();
4417
4238
  int argument_count = expr->arguments()->length() + 1; // Plus receiver.
@@ -4469,11 +4290,11 @@ void HGraphBuilder::VisitCall(Call* expr) {
4469
4290
  return;
4470
4291
  }
4471
4292
 
4472
- if (HasCustomCallGenerator(expr->target()) ||
4293
+ if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) ||
4473
4294
  expr->check_type() != RECEIVER_MAP_CHECK) {
4474
4295
  // When the target has a custom call IC generator, use the IC,
4475
- // because it is likely to generate better code. Also use the
4476
- // IC when a primitive receiver check is required.
4296
+ // because it is likely to generate better code. Also use the IC
4297
+ // when a primitive receiver check is required.
4477
4298
  HContext* context = new HContext;
4478
4299
  AddInstruction(context);
4479
4300
  call = PreProcessCall(new HCallNamed(context, name, argument_count));
@@ -4481,16 +4302,6 @@ void HGraphBuilder::VisitCall(Call* expr) {
4481
4302
  AddCheckConstantFunction(expr, receiver, receiver_map, true);
4482
4303
 
4483
4304
  if (TryInline(expr)) {
4484
- if (current_block() != NULL) {
4485
- HValue* return_value = Pop();
4486
- // If we inlined a function in a test context then we need to emit
4487
- // a simulate here to shadow the ones at the end of the
4488
- // predecessor blocks. Those environments contain the return
4489
- // value on top and do not correspond to any actual state of the
4490
- // unoptimized code.
4491
- if (ast_context()->IsEffect()) AddSimulate(expr->id());
4492
- ast_context()->ReturnValue(return_value);
4493
- }
4494
4305
  return;
4495
4306
  } else {
4496
4307
  // Check for bailout, as the TryInline call in the if condition above
@@ -4521,14 +4332,17 @@ void HGraphBuilder::VisitCall(Call* expr) {
4521
4332
  }
4522
4333
 
4523
4334
  if (global_call) {
4335
+ bool known_global_function = false;
4524
4336
  // If there is a global property cell for the name at compile time and
4525
4337
  // access check is not enabled we assume that the function will not change
4526
4338
  // and generate optimized code for calling the function.
4527
- CompilationInfo* info = graph()->info();
4528
- bool known_global_function = info->has_global_object() &&
4529
- !info->global_object()->IsAccessCheckNeeded() &&
4530
- expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()),
4531
- var->name());
4339
+ LookupResult lookup;
4340
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
4341
+ if (type == kUseCell &&
4342
+ !info()->global_object()->IsAccessCheckNeeded()) {
4343
+ Handle<GlobalObject> global(info()->global_object());
4344
+ known_global_function = expr->ComputeGlobalTarget(global, &lookup);
4345
+ }
4532
4346
  if (known_global_function) {
4533
4347
  // Push the global object instead of the global receiver because
4534
4348
  // code generated by the full code generator expects it.
@@ -4553,16 +4367,6 @@ void HGraphBuilder::VisitCall(Call* expr) {
4553
4367
  environment()->SetExpressionStackAt(receiver_index, global_receiver);
4554
4368
 
4555
4369
  if (TryInline(expr)) {
4556
- if (current_block() != NULL) {
4557
- HValue* return_value = Pop();
4558
- // If we inlined a function in a test context then we need to
4559
- // emit a simulate here to shadow the ones at the end of the
4560
- // predecessor blocks. Those environments contain the return
4561
- // value on top and do not correspond to any actual state of the
4562
- // unoptimized code.
4563
- if (ast_context()->IsEffect()) AddSimulate(expr->id());
4564
- ast_context()->ReturnValue(return_value);
4565
- }
4566
4370
  return;
4567
4371
  }
4568
4372
  // Check for bailout, as trying to inline might fail due to bailout
@@ -4642,7 +4446,7 @@ void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
4642
4446
  BAILOUT("call to a JavaScript runtime function");
4643
4447
  }
4644
4448
 
4645
- Runtime::Function* function = expr->function();
4449
+ const Runtime::Function* function = expr->function();
4646
4450
  ASSERT(function != NULL);
4647
4451
  if (function->intrinsic_type == Runtime::INLINE) {
4648
4452
  ASSERT(expr->name()->length() > 0);
@@ -4717,29 +4521,35 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4717
4521
  context->if_false(),
4718
4522
  context->if_true());
4719
4523
  } else if (ast_context()->IsValue()) {
4720
- HSubgraph* true_graph = CreateEmptySubgraph();
4721
- HSubgraph* false_graph = CreateEmptySubgraph();
4524
+ HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4525
+ HBasicBlock* materialize_true = graph()->CreateBasicBlock();
4722
4526
  VISIT_FOR_CONTROL(expr->expression(),
4723
- false_graph->entry_block(),
4724
- true_graph->entry_block());
4725
- true_graph->entry_block()->SetJoinId(expr->expression()->id());
4726
- true_graph->exit_block()->last_environment()->Push(
4727
- graph_->GetConstantTrue());
4728
-
4729
- false_graph->entry_block()->SetJoinId(expr->expression()->id());
4730
- false_graph->exit_block()->last_environment()->Push(
4731
- graph_->GetConstantFalse());
4732
-
4733
- current_subgraph_->AppendJoin(true_graph->exit_block(),
4734
- false_graph->exit_block(),
4735
- expr->id());
4527
+ materialize_false,
4528
+ materialize_true);
4529
+ materialize_false->SetJoinId(expr->expression()->id());
4530
+ materialize_true->SetJoinId(expr->expression()->id());
4531
+
4532
+ set_current_block(materialize_false);
4533
+ Push(graph()->GetConstantFalse());
4534
+ set_current_block(materialize_true);
4535
+ Push(graph()->GetConstantTrue());
4536
+
4537
+ HBasicBlock* join =
4538
+ CreateJoin(materialize_false, materialize_true, expr->id());
4539
+ set_current_block(join);
4736
4540
  ast_context()->ReturnValue(Pop());
4737
4541
  } else {
4738
4542
  ASSERT(ast_context()->IsEffect());
4739
- VISIT_FOR_EFFECT(expr->expression());
4543
+ VisitForEffect(expr->expression());
4740
4544
  }
4741
4545
 
4742
- } else if (op == Token::BIT_NOT || op == Token::SUB) {
4546
+ } else if (op == Token::TYPEOF) {
4547
+ VisitForTypeOf(expr->expression());
4548
+ if (HasStackOverflow()) return;
4549
+ HValue* value = Pop();
4550
+ ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4551
+
4552
+ } else {
4743
4553
  VISIT_FOR_VALUE(expr->expression());
4744
4554
  HValue* value = Pop();
4745
4555
  HInstruction* instr = NULL;
@@ -4748,19 +4558,16 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4748
4558
  instr = new HBitNot(value);
4749
4559
  break;
4750
4560
  case Token::SUB:
4751
- instr = new HMul(graph_->GetConstantMinus1(), value);
4561
+ instr = new HMul(value, graph_->GetConstantMinus1());
4562
+ break;
4563
+ case Token::ADD:
4564
+ instr = new HMul(value, graph_->GetConstant1());
4752
4565
  break;
4753
4566
  default:
4754
- UNREACHABLE();
4567
+ BAILOUT("Value: unsupported unary operation");
4755
4568
  break;
4756
4569
  }
4757
4570
  ast_context()->ReturnInstruction(instr, expr->id());
4758
- } else if (op == Token::TYPEOF) {
4759
- VISIT_FOR_VALUE(expr->expression());
4760
- HValue* value = Pop();
4761
- ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4762
- } else {
4763
- BAILOUT("Value: unsupported unary operation");
4764
4571
  }
4765
4572
  }
4766
4573
 
@@ -5034,28 +4841,23 @@ void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
5034
4841
  VISIT_FOR_VALUE(expr->left());
5035
4842
  ASSERT(current_block() != NULL);
5036
4843
 
5037
- HValue* left = Top();
5038
- HEnvironment* environment_copy = environment()->Copy();
5039
- environment_copy->Pop();
5040
- HSubgraph* right_subgraph;
5041
- right_subgraph = CreateBranchSubgraph(environment_copy);
5042
- ADD_TO_SUBGRAPH(right_subgraph, expr->right());
5043
-
5044
- ASSERT(current_block() != NULL &&
5045
- right_subgraph->exit_block() != NULL);
5046
4844
  // We need an extra block to maintain edge-split form.
5047
4845
  HBasicBlock* empty_block = graph()->CreateBasicBlock();
5048
- HBasicBlock* join_block = graph()->CreateBasicBlock();
5049
-
4846
+ HBasicBlock* eval_right = graph()->CreateBasicBlock();
5050
4847
  HTest* test = is_logical_and
5051
- ? new HTest(left, right_subgraph->entry_block(), empty_block)
5052
- : new HTest(left, empty_block, right_subgraph->entry_block());
4848
+ ? new HTest(Top(), eval_right, empty_block)
4849
+ : new HTest(Top(), empty_block, eval_right);
5053
4850
  current_block()->Finish(test);
5054
- empty_block->Goto(join_block);
5055
- right_subgraph->exit_block()->Goto(join_block);
5056
- join_block->SetJoinId(expr->id());
4851
+
4852
+ set_current_block(eval_right);
4853
+ Drop(1); // Value of the left subexpression.
4854
+ VISIT_FOR_VALUE(expr->right());
4855
+
4856
+ HBasicBlock* join_block =
4857
+ CreateJoin(empty_block, current_block(), expr->id());
5057
4858
  set_current_block(join_block);
5058
4859
  ast_context()->ReturnValue(Pop());
4860
+
5059
4861
  } else {
5060
4862
  ASSERT(ast_context()->IsEffect());
5061
4863
  // In an effect context, we don't need the value of the left
@@ -5146,7 +4948,8 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5146
4948
  if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
5147
4949
  left_unary != NULL && left_unary->op() == Token::TYPEOF &&
5148
4950
  right_literal != NULL && right_literal->handle()->IsString()) {
5149
- VISIT_FOR_VALUE(left_unary->expression());
4951
+ VisitForTypeOf(left_unary->expression());
4952
+ if (HasStackOverflow()) return;
5150
4953
  HValue* left = Pop();
5151
4954
  HInstruction* instr = new HTypeofIs(left,
5152
4955
  Handle<String>::cast(right_literal->handle()));
@@ -5162,7 +4965,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5162
4965
  HValue* left = Pop();
5163
4966
  Token::Value op = expr->op();
5164
4967
 
5165
- TypeInfo info = oracle()->CompareType(expr);
4968
+ TypeInfo type_info = oracle()->CompareType(expr);
5166
4969
  HInstruction* instr = NULL;
5167
4970
  if (op == Token::INSTANCEOF) {
5168
4971
  // Check to see if the rhs of the instanceof is a global function not
@@ -5171,12 +4974,11 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5171
4974
  Handle<JSFunction> target = Handle<JSFunction>::null();
5172
4975
  Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5173
4976
  bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5174
- CompilationInfo* info = graph()->info();
5175
4977
  if (global_function &&
5176
- info->has_global_object() &&
5177
- !info->global_object()->IsAccessCheckNeeded()) {
4978
+ info()->has_global_object() &&
4979
+ !info()->global_object()->IsAccessCheckNeeded()) {
5178
4980
  Handle<String> name = var->name();
5179
- Handle<GlobalObject> global(info->global_object());
4981
+ Handle<GlobalObject> global(info()->global_object());
5180
4982
  LookupResult lookup;
5181
4983
  global->Lookup(*name, &lookup);
5182
4984
  if (lookup.IsProperty() &&
@@ -5185,7 +4987,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5185
4987
  Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5186
4988
  // If the function is in new space we assume it's more likely to
5187
4989
  // change and thus prefer the general IC code.
5188
- if (!Heap::InNewSpace(*candidate)) {
4990
+ if (!isolate()->heap()->InNewSpace(*candidate)) {
5189
4991
  target = candidate;
5190
4992
  }
5191
4993
  }
@@ -5203,7 +5005,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5203
5005
  }
5204
5006
  } else if (op == Token::IN) {
5205
5007
  BAILOUT("Unsupported comparison: in");
5206
- } else if (info.IsNonPrimitive()) {
5008
+ } else if (type_info.IsNonPrimitive()) {
5207
5009
  switch (op) {
5208
5010
  case Token::EQ:
5209
5011
  case Token::EQ_STRICT: {
@@ -5220,7 +5022,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5220
5022
  }
5221
5023
  } else {
5222
5024
  HCompare* compare = new HCompare(left, right, op);
5223
- Representation r = ToRepresentation(info);
5025
+ Representation r = ToRepresentation(type_info);
5224
5026
  compare->SetInputRepresentation(r);
5225
5027
  instr = compare;
5226
5028
  }
@@ -5344,7 +5146,14 @@ void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
5344
5146
  // Support for construct call checks.
5345
5147
  void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
5346
5148
  ASSERT(call->arguments()->length() == 0);
5347
- ast_context()->ReturnInstruction(new HIsConstructCall, call->id());
5149
+ if (function_state()->outer() != NULL) {
5150
+ // We are generating graph for inlined function. Currently
5151
+ // constructor inlining is not supported and we can just return
5152
+ // false from %_IsConstructCall().
5153
+ ast_context()->ReturnValue(graph()->GetConstantFalse());
5154
+ } else {
5155
+ ast_context()->ReturnInstruction(new HIsConstructCall, call->id());
5156
+ }
5348
5157
  }
5349
5158
 
5350
5159
 
@@ -5404,19 +5213,24 @@ void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
5404
5213
 
5405
5214
  // Fast support for string.charAt(n) and string[n].
5406
5215
  void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
5407
- BAILOUT("inlined runtime function: StringCharFromCode");
5216
+ ASSERT(call->arguments()->length() == 1);
5217
+ VISIT_FOR_VALUE(call->arguments()->at(0));
5218
+ HValue* char_code = Pop();
5219
+ HStringCharFromCode* result = new HStringCharFromCode(char_code);
5220
+ ast_context()->ReturnInstruction(result, call->id());
5408
5221
  }
5409
5222
 
5410
5223
 
5411
5224
  // Fast support for string.charAt(n) and string[n].
5412
5225
  void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
5413
- ASSERT_EQ(2, call->arguments()->length());
5414
- VisitArgumentList(call->arguments());
5415
- CHECK_BAILOUT;
5416
- HContext* context = new HContext;
5417
- AddInstruction(context);
5418
- HCallStub* result = new HCallStub(context, CodeStub::StringCharAt, 2);
5419
- Drop(2);
5226
+ ASSERT(call->arguments()->length() == 2);
5227
+ VISIT_FOR_VALUE(call->arguments()->at(0));
5228
+ VISIT_FOR_VALUE(call->arguments()->at(1));
5229
+ HValue* index = Pop();
5230
+ HValue* string = Pop();
5231
+ HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index);
5232
+ AddInstruction(char_code);
5233
+ HStringCharFromCode* result = new HStringCharFromCode(char_code);
5420
5234
  ast_context()->ReturnInstruction(result, call->id());
5421
5235
  }
5422
5236
 
@@ -5966,12 +5780,12 @@ void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
5966
5780
  Tag tag(this, "intervals");
5967
5781
  PrintStringProperty("name", name);
5968
5782
 
5969
- const ZoneList<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
5783
+ const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
5970
5784
  for (int i = 0; i < fixed_d->length(); ++i) {
5971
5785
  TraceLiveRange(fixed_d->at(i), "fixed");
5972
5786
  }
5973
5787
 
5974
- const ZoneList<LiveRange*>* fixed = allocator->fixed_live_ranges();
5788
+ const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
5975
5789
  for (int i = 0; i < fixed->length(); ++i) {
5976
5790
  TraceLiveRange(fixed->at(i), "fixed");
5977
5791
  }
@@ -6042,6 +5856,11 @@ void HTracer::FlushToFile() {
6042
5856
  }
6043
5857
 
6044
5858
 
5859
+ void HStatistics::Initialize(CompilationInfo* info) {
5860
+ source_size_ += info->shared_info()->SourceSize();
5861
+ }
5862
+
5863
+
6045
5864
  void HStatistics::Print() {
6046
5865
  PrintF("Timing results:\n");
6047
5866
  int64_t sum = 0;
@@ -6059,9 +5878,15 @@ void HStatistics::Print() {
6059
5878
  double size_percent = static_cast<double>(size) * 100 / total_size_;
6060
5879
  PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
6061
5880
  }
6062
- PrintF("%30s - %7.3f ms %8u bytes\n", "Sum",
6063
- static_cast<double>(sum) / 1000,
6064
- total_size_);
5881
+ double source_size_in_kb = static_cast<double>(source_size_) / 1024;
5882
+ double normalized_time = source_size_in_kb > 0
5883
+ ? (static_cast<double>(sum) / 1000) / source_size_in_kb
5884
+ : 0;
5885
+ double normalized_bytes = source_size_in_kb > 0
5886
+ ? total_size_ / source_size_in_kb
5887
+ : 0;
5888
+ PrintF("%30s - %7.3f ms %7.3f bytes\n", "Sum",
5889
+ normalized_time, normalized_bytes);
6065
5890
  PrintF("---------------------------------------------------------------\n");
6066
5891
  PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
6067
5892
  "Total",
@@ -6106,13 +5931,13 @@ void HPhase::Begin(const char* name,
6106
5931
  if (allocator != NULL && chunk_ == NULL) {
6107
5932
  chunk_ = allocator->chunk();
6108
5933
  }
6109
- if (FLAG_time_hydrogen) start_ = OS::Ticks();
5934
+ if (FLAG_hydrogen_stats) start_ = OS::Ticks();
6110
5935
  start_allocation_size_ = Zone::allocation_size_;
6111
5936
  }
6112
5937
 
6113
5938
 
6114
5939
  void HPhase::End() const {
6115
- if (FLAG_time_hydrogen) {
5940
+ if (FLAG_hydrogen_stats) {
6116
5941
  int64_t end = OS::Ticks();
6117
5942
  unsigned size = Zone::allocation_size_ - start_allocation_size_;
6118
5943
  HStatistics::Instance()->SaveTiming(name_, end - start_, size);