libv8-sgonyea 3.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (500) hide show
  1. data/.gitignore +8 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +4 -0
  4. data/README.md +76 -0
  5. data/Rakefile +113 -0
  6. data/ext/libv8/extconf.rb +28 -0
  7. data/lib/libv8.rb +15 -0
  8. data/lib/libv8/Makefile +30 -0
  9. data/lib/libv8/detect_cpu.rb +27 -0
  10. data/lib/libv8/fpic-on-linux-amd64.patch +13 -0
  11. data/lib/libv8/v8/.gitignore +35 -0
  12. data/lib/libv8/v8/AUTHORS +44 -0
  13. data/lib/libv8/v8/ChangeLog +2839 -0
  14. data/lib/libv8/v8/LICENSE +52 -0
  15. data/lib/libv8/v8/LICENSE.strongtalk +29 -0
  16. data/lib/libv8/v8/LICENSE.v8 +26 -0
  17. data/lib/libv8/v8/LICENSE.valgrind +45 -0
  18. data/lib/libv8/v8/SConstruct +1478 -0
  19. data/lib/libv8/v8/build/README.txt +49 -0
  20. data/lib/libv8/v8/build/all.gyp +18 -0
  21. data/lib/libv8/v8/build/armu.gypi +32 -0
  22. data/lib/libv8/v8/build/common.gypi +144 -0
  23. data/lib/libv8/v8/build/gyp_v8 +145 -0
  24. data/lib/libv8/v8/include/v8-debug.h +395 -0
  25. data/lib/libv8/v8/include/v8-preparser.h +117 -0
  26. data/lib/libv8/v8/include/v8-profiler.h +505 -0
  27. data/lib/libv8/v8/include/v8-testing.h +104 -0
  28. data/lib/libv8/v8/include/v8.h +4124 -0
  29. data/lib/libv8/v8/include/v8stdint.h +53 -0
  30. data/lib/libv8/v8/preparser/SConscript +38 -0
  31. data/lib/libv8/v8/preparser/preparser-process.cc +379 -0
  32. data/lib/libv8/v8/src/SConscript +368 -0
  33. data/lib/libv8/v8/src/accessors.cc +767 -0
  34. data/lib/libv8/v8/src/accessors.h +123 -0
  35. data/lib/libv8/v8/src/allocation-inl.h +49 -0
  36. data/lib/libv8/v8/src/allocation.cc +122 -0
  37. data/lib/libv8/v8/src/allocation.h +143 -0
  38. data/lib/libv8/v8/src/api.cc +5845 -0
  39. data/lib/libv8/v8/src/api.h +574 -0
  40. data/lib/libv8/v8/src/apinatives.js +110 -0
  41. data/lib/libv8/v8/src/apiutils.h +73 -0
  42. data/lib/libv8/v8/src/arguments.h +118 -0
  43. data/lib/libv8/v8/src/arm/assembler-arm-inl.h +353 -0
  44. data/lib/libv8/v8/src/arm/assembler-arm.cc +2661 -0
  45. data/lib/libv8/v8/src/arm/assembler-arm.h +1375 -0
  46. data/lib/libv8/v8/src/arm/builtins-arm.cc +1658 -0
  47. data/lib/libv8/v8/src/arm/code-stubs-arm.cc +6398 -0
  48. data/lib/libv8/v8/src/arm/code-stubs-arm.h +673 -0
  49. data/lib/libv8/v8/src/arm/codegen-arm.cc +52 -0
  50. data/lib/libv8/v8/src/arm/codegen-arm.h +91 -0
  51. data/lib/libv8/v8/src/arm/constants-arm.cc +152 -0
  52. data/lib/libv8/v8/src/arm/constants-arm.h +775 -0
  53. data/lib/libv8/v8/src/arm/cpu-arm.cc +120 -0
  54. data/lib/libv8/v8/src/arm/debug-arm.cc +317 -0
  55. data/lib/libv8/v8/src/arm/deoptimizer-arm.cc +754 -0
  56. data/lib/libv8/v8/src/arm/disasm-arm.cc +1506 -0
  57. data/lib/libv8/v8/src/arm/frames-arm.cc +45 -0
  58. data/lib/libv8/v8/src/arm/frames-arm.h +168 -0
  59. data/lib/libv8/v8/src/arm/full-codegen-arm.cc +4375 -0
  60. data/lib/libv8/v8/src/arm/ic-arm.cc +1562 -0
  61. data/lib/libv8/v8/src/arm/lithium-arm.cc +2206 -0
  62. data/lib/libv8/v8/src/arm/lithium-arm.h +2348 -0
  63. data/lib/libv8/v8/src/arm/lithium-codegen-arm.cc +4526 -0
  64. data/lib/libv8/v8/src/arm/lithium-codegen-arm.h +403 -0
  65. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.cc +305 -0
  66. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.h +84 -0
  67. data/lib/libv8/v8/src/arm/macro-assembler-arm.cc +3163 -0
  68. data/lib/libv8/v8/src/arm/macro-assembler-arm.h +1126 -0
  69. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.cc +1287 -0
  70. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.h +253 -0
  71. data/lib/libv8/v8/src/arm/simulator-arm.cc +3424 -0
  72. data/lib/libv8/v8/src/arm/simulator-arm.h +431 -0
  73. data/lib/libv8/v8/src/arm/stub-cache-arm.cc +4243 -0
  74. data/lib/libv8/v8/src/array.js +1366 -0
  75. data/lib/libv8/v8/src/assembler.cc +1207 -0
  76. data/lib/libv8/v8/src/assembler.h +858 -0
  77. data/lib/libv8/v8/src/ast-inl.h +112 -0
  78. data/lib/libv8/v8/src/ast.cc +1146 -0
  79. data/lib/libv8/v8/src/ast.h +2188 -0
  80. data/lib/libv8/v8/src/atomicops.h +167 -0
  81. data/lib/libv8/v8/src/atomicops_internals_arm_gcc.h +145 -0
  82. data/lib/libv8/v8/src/atomicops_internals_mips_gcc.h +169 -0
  83. data/lib/libv8/v8/src/atomicops_internals_x86_gcc.cc +133 -0
  84. data/lib/libv8/v8/src/atomicops_internals_x86_gcc.h +287 -0
  85. data/lib/libv8/v8/src/atomicops_internals_x86_macosx.h +301 -0
  86. data/lib/libv8/v8/src/atomicops_internals_x86_msvc.h +203 -0
  87. data/lib/libv8/v8/src/bignum-dtoa.cc +655 -0
  88. data/lib/libv8/v8/src/bignum-dtoa.h +81 -0
  89. data/lib/libv8/v8/src/bignum.cc +768 -0
  90. data/lib/libv8/v8/src/bignum.h +140 -0
  91. data/lib/libv8/v8/src/bootstrapper.cc +2184 -0
  92. data/lib/libv8/v8/src/bootstrapper.h +188 -0
  93. data/lib/libv8/v8/src/builtins.cc +1707 -0
  94. data/lib/libv8/v8/src/builtins.h +371 -0
  95. data/lib/libv8/v8/src/bytecodes-irregexp.h +105 -0
  96. data/lib/libv8/v8/src/cached-powers.cc +177 -0
  97. data/lib/libv8/v8/src/cached-powers.h +65 -0
  98. data/lib/libv8/v8/src/char-predicates-inl.h +94 -0
  99. data/lib/libv8/v8/src/char-predicates.h +67 -0
  100. data/lib/libv8/v8/src/checks.cc +110 -0
  101. data/lib/libv8/v8/src/checks.h +296 -0
  102. data/lib/libv8/v8/src/circular-queue-inl.h +53 -0
  103. data/lib/libv8/v8/src/circular-queue.cc +122 -0
  104. data/lib/libv8/v8/src/circular-queue.h +103 -0
  105. data/lib/libv8/v8/src/code-stubs.cc +267 -0
  106. data/lib/libv8/v8/src/code-stubs.h +1011 -0
  107. data/lib/libv8/v8/src/code.h +70 -0
  108. data/lib/libv8/v8/src/codegen.cc +231 -0
  109. data/lib/libv8/v8/src/codegen.h +84 -0
  110. data/lib/libv8/v8/src/compilation-cache.cc +540 -0
  111. data/lib/libv8/v8/src/compilation-cache.h +287 -0
  112. data/lib/libv8/v8/src/compiler.cc +786 -0
  113. data/lib/libv8/v8/src/compiler.h +312 -0
  114. data/lib/libv8/v8/src/contexts.cc +347 -0
  115. data/lib/libv8/v8/src/contexts.h +391 -0
  116. data/lib/libv8/v8/src/conversions-inl.h +106 -0
  117. data/lib/libv8/v8/src/conversions.cc +1131 -0
  118. data/lib/libv8/v8/src/conversions.h +135 -0
  119. data/lib/libv8/v8/src/counters.cc +93 -0
  120. data/lib/libv8/v8/src/counters.h +254 -0
  121. data/lib/libv8/v8/src/cpu-profiler-inl.h +101 -0
  122. data/lib/libv8/v8/src/cpu-profiler.cc +609 -0
  123. data/lib/libv8/v8/src/cpu-profiler.h +302 -0
  124. data/lib/libv8/v8/src/cpu.h +69 -0
  125. data/lib/libv8/v8/src/d8-debug.cc +367 -0
  126. data/lib/libv8/v8/src/d8-debug.h +158 -0
  127. data/lib/libv8/v8/src/d8-posix.cc +695 -0
  128. data/lib/libv8/v8/src/d8-readline.cc +130 -0
  129. data/lib/libv8/v8/src/d8-windows.cc +42 -0
  130. data/lib/libv8/v8/src/d8.cc +803 -0
  131. data/lib/libv8/v8/src/d8.gyp +91 -0
  132. data/lib/libv8/v8/src/d8.h +235 -0
  133. data/lib/libv8/v8/src/d8.js +2798 -0
  134. data/lib/libv8/v8/src/data-flow.cc +66 -0
  135. data/lib/libv8/v8/src/data-flow.h +205 -0
  136. data/lib/libv8/v8/src/date.js +1103 -0
  137. data/lib/libv8/v8/src/dateparser-inl.h +127 -0
  138. data/lib/libv8/v8/src/dateparser.cc +178 -0
  139. data/lib/libv8/v8/src/dateparser.h +266 -0
  140. data/lib/libv8/v8/src/debug-agent.cc +447 -0
  141. data/lib/libv8/v8/src/debug-agent.h +129 -0
  142. data/lib/libv8/v8/src/debug-debugger.js +2569 -0
  143. data/lib/libv8/v8/src/debug.cc +3165 -0
  144. data/lib/libv8/v8/src/debug.h +1057 -0
  145. data/lib/libv8/v8/src/deoptimizer.cc +1256 -0
  146. data/lib/libv8/v8/src/deoptimizer.h +602 -0
  147. data/lib/libv8/v8/src/disasm.h +80 -0
  148. data/lib/libv8/v8/src/disassembler.cc +343 -0
  149. data/lib/libv8/v8/src/disassembler.h +58 -0
  150. data/lib/libv8/v8/src/diy-fp.cc +58 -0
  151. data/lib/libv8/v8/src/diy-fp.h +117 -0
  152. data/lib/libv8/v8/src/double.h +238 -0
  153. data/lib/libv8/v8/src/dtoa.cc +103 -0
  154. data/lib/libv8/v8/src/dtoa.h +85 -0
  155. data/lib/libv8/v8/src/execution.cc +849 -0
  156. data/lib/libv8/v8/src/execution.h +297 -0
  157. data/lib/libv8/v8/src/extensions/experimental/break-iterator.cc +250 -0
  158. data/lib/libv8/v8/src/extensions/experimental/break-iterator.h +89 -0
  159. data/lib/libv8/v8/src/extensions/experimental/collator.cc +218 -0
  160. data/lib/libv8/v8/src/extensions/experimental/collator.h +69 -0
  161. data/lib/libv8/v8/src/extensions/experimental/experimental.gyp +94 -0
  162. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.cc +78 -0
  163. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.h +54 -0
  164. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.cc +112 -0
  165. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.h +60 -0
  166. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.cc +43 -0
  167. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.h +49 -0
  168. data/lib/libv8/v8/src/extensions/experimental/i18n.js +180 -0
  169. data/lib/libv8/v8/src/extensions/experimental/language-matcher.cc +251 -0
  170. data/lib/libv8/v8/src/extensions/experimental/language-matcher.h +95 -0
  171. data/lib/libv8/v8/src/extensions/externalize-string-extension.cc +141 -0
  172. data/lib/libv8/v8/src/extensions/externalize-string-extension.h +50 -0
  173. data/lib/libv8/v8/src/extensions/gc-extension.cc +58 -0
  174. data/lib/libv8/v8/src/extensions/gc-extension.h +49 -0
  175. data/lib/libv8/v8/src/factory.cc +1222 -0
  176. data/lib/libv8/v8/src/factory.h +442 -0
  177. data/lib/libv8/v8/src/fast-dtoa.cc +736 -0
  178. data/lib/libv8/v8/src/fast-dtoa.h +83 -0
  179. data/lib/libv8/v8/src/fixed-dtoa.cc +405 -0
  180. data/lib/libv8/v8/src/fixed-dtoa.h +55 -0
  181. data/lib/libv8/v8/src/flag-definitions.h +560 -0
  182. data/lib/libv8/v8/src/flags.cc +551 -0
  183. data/lib/libv8/v8/src/flags.h +79 -0
  184. data/lib/libv8/v8/src/frames-inl.h +247 -0
  185. data/lib/libv8/v8/src/frames.cc +1243 -0
  186. data/lib/libv8/v8/src/frames.h +870 -0
  187. data/lib/libv8/v8/src/full-codegen.cc +1374 -0
  188. data/lib/libv8/v8/src/full-codegen.h +771 -0
  189. data/lib/libv8/v8/src/func-name-inferrer.cc +92 -0
  190. data/lib/libv8/v8/src/func-name-inferrer.h +111 -0
  191. data/lib/libv8/v8/src/gdb-jit.cc +1555 -0
  192. data/lib/libv8/v8/src/gdb-jit.h +143 -0
  193. data/lib/libv8/v8/src/global-handles.cc +665 -0
  194. data/lib/libv8/v8/src/global-handles.h +284 -0
  195. data/lib/libv8/v8/src/globals.h +325 -0
  196. data/lib/libv8/v8/src/handles-inl.h +177 -0
  197. data/lib/libv8/v8/src/handles.cc +987 -0
  198. data/lib/libv8/v8/src/handles.h +382 -0
  199. data/lib/libv8/v8/src/hashmap.cc +230 -0
  200. data/lib/libv8/v8/src/hashmap.h +123 -0
  201. data/lib/libv8/v8/src/heap-inl.h +704 -0
  202. data/lib/libv8/v8/src/heap-profiler.cc +1173 -0
  203. data/lib/libv8/v8/src/heap-profiler.h +397 -0
  204. data/lib/libv8/v8/src/heap.cc +5930 -0
  205. data/lib/libv8/v8/src/heap.h +2268 -0
  206. data/lib/libv8/v8/src/hydrogen-instructions.cc +1769 -0
  207. data/lib/libv8/v8/src/hydrogen-instructions.h +3971 -0
  208. data/lib/libv8/v8/src/hydrogen.cc +6239 -0
  209. data/lib/libv8/v8/src/hydrogen.h +1202 -0
  210. data/lib/libv8/v8/src/ia32/assembler-ia32-inl.h +446 -0
  211. data/lib/libv8/v8/src/ia32/assembler-ia32.cc +2487 -0
  212. data/lib/libv8/v8/src/ia32/assembler-ia32.h +1144 -0
  213. data/lib/libv8/v8/src/ia32/builtins-ia32.cc +1621 -0
  214. data/lib/libv8/v8/src/ia32/code-stubs-ia32.cc +6198 -0
  215. data/lib/libv8/v8/src/ia32/code-stubs-ia32.h +517 -0
  216. data/lib/libv8/v8/src/ia32/codegen-ia32.cc +265 -0
  217. data/lib/libv8/v8/src/ia32/codegen-ia32.h +79 -0
  218. data/lib/libv8/v8/src/ia32/cpu-ia32.cc +88 -0
  219. data/lib/libv8/v8/src/ia32/debug-ia32.cc +312 -0
  220. data/lib/libv8/v8/src/ia32/deoptimizer-ia32.cc +774 -0
  221. data/lib/libv8/v8/src/ia32/disasm-ia32.cc +1628 -0
  222. data/lib/libv8/v8/src/ia32/frames-ia32.cc +45 -0
  223. data/lib/libv8/v8/src/ia32/frames-ia32.h +142 -0
  224. data/lib/libv8/v8/src/ia32/full-codegen-ia32.cc +4338 -0
  225. data/lib/libv8/v8/src/ia32/ic-ia32.cc +1597 -0
  226. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.cc +4461 -0
  227. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.h +375 -0
  228. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.cc +475 -0
  229. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.h +110 -0
  230. data/lib/libv8/v8/src/ia32/lithium-ia32.cc +2261 -0
  231. data/lib/libv8/v8/src/ia32/lithium-ia32.h +2396 -0
  232. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.cc +2136 -0
  233. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.h +775 -0
  234. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.cc +1263 -0
  235. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.h +216 -0
  236. data/lib/libv8/v8/src/ia32/simulator-ia32.cc +30 -0
  237. data/lib/libv8/v8/src/ia32/simulator-ia32.h +74 -0
  238. data/lib/libv8/v8/src/ia32/stub-cache-ia32.cc +3847 -0
  239. data/lib/libv8/v8/src/ic-inl.h +130 -0
  240. data/lib/libv8/v8/src/ic.cc +2577 -0
  241. data/lib/libv8/v8/src/ic.h +736 -0
  242. data/lib/libv8/v8/src/inspector.cc +63 -0
  243. data/lib/libv8/v8/src/inspector.h +62 -0
  244. data/lib/libv8/v8/src/interpreter-irregexp.cc +659 -0
  245. data/lib/libv8/v8/src/interpreter-irregexp.h +49 -0
  246. data/lib/libv8/v8/src/isolate-inl.h +50 -0
  247. data/lib/libv8/v8/src/isolate.cc +1869 -0
  248. data/lib/libv8/v8/src/isolate.h +1382 -0
  249. data/lib/libv8/v8/src/json-parser.cc +504 -0
  250. data/lib/libv8/v8/src/json-parser.h +161 -0
  251. data/lib/libv8/v8/src/json.js +342 -0
  252. data/lib/libv8/v8/src/jsregexp.cc +5385 -0
  253. data/lib/libv8/v8/src/jsregexp.h +1492 -0
  254. data/lib/libv8/v8/src/list-inl.h +212 -0
  255. data/lib/libv8/v8/src/list.h +174 -0
  256. data/lib/libv8/v8/src/lithium-allocator-inl.h +142 -0
  257. data/lib/libv8/v8/src/lithium-allocator.cc +2123 -0
  258. data/lib/libv8/v8/src/lithium-allocator.h +630 -0
  259. data/lib/libv8/v8/src/lithium.cc +190 -0
  260. data/lib/libv8/v8/src/lithium.h +597 -0
  261. data/lib/libv8/v8/src/liveedit-debugger.js +1082 -0
  262. data/lib/libv8/v8/src/liveedit.cc +1691 -0
  263. data/lib/libv8/v8/src/liveedit.h +180 -0
  264. data/lib/libv8/v8/src/liveobjectlist-inl.h +126 -0
  265. data/lib/libv8/v8/src/liveobjectlist.cc +2589 -0
  266. data/lib/libv8/v8/src/liveobjectlist.h +322 -0
  267. data/lib/libv8/v8/src/log-inl.h +59 -0
  268. data/lib/libv8/v8/src/log-utils.cc +428 -0
  269. data/lib/libv8/v8/src/log-utils.h +231 -0
  270. data/lib/libv8/v8/src/log.cc +1993 -0
  271. data/lib/libv8/v8/src/log.h +476 -0
  272. data/lib/libv8/v8/src/macro-assembler.h +120 -0
  273. data/lib/libv8/v8/src/macros.py +178 -0
  274. data/lib/libv8/v8/src/mark-compact.cc +3143 -0
  275. data/lib/libv8/v8/src/mark-compact.h +506 -0
  276. data/lib/libv8/v8/src/math.js +264 -0
  277. data/lib/libv8/v8/src/messages.cc +179 -0
  278. data/lib/libv8/v8/src/messages.h +113 -0
  279. data/lib/libv8/v8/src/messages.js +1096 -0
  280. data/lib/libv8/v8/src/mips/assembler-mips-inl.h +312 -0
  281. data/lib/libv8/v8/src/mips/assembler-mips.cc +1960 -0
  282. data/lib/libv8/v8/src/mips/assembler-mips.h +1138 -0
  283. data/lib/libv8/v8/src/mips/builtins-mips.cc +1628 -0
  284. data/lib/libv8/v8/src/mips/code-stubs-mips.cc +6656 -0
  285. data/lib/libv8/v8/src/mips/code-stubs-mips.h +682 -0
  286. data/lib/libv8/v8/src/mips/codegen-mips.cc +52 -0
  287. data/lib/libv8/v8/src/mips/codegen-mips.h +98 -0
  288. data/lib/libv8/v8/src/mips/constants-mips.cc +352 -0
  289. data/lib/libv8/v8/src/mips/constants-mips.h +739 -0
  290. data/lib/libv8/v8/src/mips/cpu-mips.cc +96 -0
  291. data/lib/libv8/v8/src/mips/debug-mips.cc +308 -0
  292. data/lib/libv8/v8/src/mips/deoptimizer-mips.cc +91 -0
  293. data/lib/libv8/v8/src/mips/disasm-mips.cc +1050 -0
  294. data/lib/libv8/v8/src/mips/frames-mips.cc +47 -0
  295. data/lib/libv8/v8/src/mips/frames-mips.h +219 -0
  296. data/lib/libv8/v8/src/mips/full-codegen-mips.cc +4388 -0
  297. data/lib/libv8/v8/src/mips/ic-mips.cc +1580 -0
  298. data/lib/libv8/v8/src/mips/lithium-codegen-mips.h +65 -0
  299. data/lib/libv8/v8/src/mips/lithium-mips.h +307 -0
  300. data/lib/libv8/v8/src/mips/macro-assembler-mips.cc +4056 -0
  301. data/lib/libv8/v8/src/mips/macro-assembler-mips.h +1214 -0
  302. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.cc +1251 -0
  303. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.h +252 -0
  304. data/lib/libv8/v8/src/mips/simulator-mips.cc +2621 -0
  305. data/lib/libv8/v8/src/mips/simulator-mips.h +401 -0
  306. data/lib/libv8/v8/src/mips/stub-cache-mips.cc +4285 -0
  307. data/lib/libv8/v8/src/mirror-debugger.js +2382 -0
  308. data/lib/libv8/v8/src/mksnapshot.cc +328 -0
  309. data/lib/libv8/v8/src/natives.h +64 -0
  310. data/lib/libv8/v8/src/objects-debug.cc +738 -0
  311. data/lib/libv8/v8/src/objects-inl.h +4323 -0
  312. data/lib/libv8/v8/src/objects-printer.cc +829 -0
  313. data/lib/libv8/v8/src/objects-visiting.cc +148 -0
  314. data/lib/libv8/v8/src/objects-visiting.h +424 -0
  315. data/lib/libv8/v8/src/objects.cc +10585 -0
  316. data/lib/libv8/v8/src/objects.h +6838 -0
  317. data/lib/libv8/v8/src/parser.cc +4997 -0
  318. data/lib/libv8/v8/src/parser.h +765 -0
  319. data/lib/libv8/v8/src/platform-cygwin.cc +779 -0
  320. data/lib/libv8/v8/src/platform-freebsd.cc +826 -0
  321. data/lib/libv8/v8/src/platform-linux.cc +1149 -0
  322. data/lib/libv8/v8/src/platform-macos.cc +830 -0
  323. data/lib/libv8/v8/src/platform-nullos.cc +479 -0
  324. data/lib/libv8/v8/src/platform-openbsd.cc +640 -0
  325. data/lib/libv8/v8/src/platform-posix.cc +424 -0
  326. data/lib/libv8/v8/src/platform-solaris.cc +762 -0
  327. data/lib/libv8/v8/src/platform-tls-mac.h +62 -0
  328. data/lib/libv8/v8/src/platform-tls-win32.h +62 -0
  329. data/lib/libv8/v8/src/platform-tls.h +50 -0
  330. data/lib/libv8/v8/src/platform-win32.cc +2021 -0
  331. data/lib/libv8/v8/src/platform.h +667 -0
  332. data/lib/libv8/v8/src/preparse-data-format.h +62 -0
  333. data/lib/libv8/v8/src/preparse-data.cc +183 -0
  334. data/lib/libv8/v8/src/preparse-data.h +225 -0
  335. data/lib/libv8/v8/src/preparser-api.cc +220 -0
  336. data/lib/libv8/v8/src/preparser.cc +1450 -0
  337. data/lib/libv8/v8/src/preparser.h +493 -0
  338. data/lib/libv8/v8/src/prettyprinter.cc +1493 -0
  339. data/lib/libv8/v8/src/prettyprinter.h +223 -0
  340. data/lib/libv8/v8/src/profile-generator-inl.h +128 -0
  341. data/lib/libv8/v8/src/profile-generator.cc +3098 -0
  342. data/lib/libv8/v8/src/profile-generator.h +1126 -0
  343. data/lib/libv8/v8/src/property.cc +105 -0
  344. data/lib/libv8/v8/src/property.h +365 -0
  345. data/lib/libv8/v8/src/proxy.js +83 -0
  346. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp-inl.h +78 -0
  347. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp.cc +471 -0
  348. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp.h +142 -0
  349. data/lib/libv8/v8/src/regexp-macro-assembler-tracer.cc +373 -0
  350. data/lib/libv8/v8/src/regexp-macro-assembler-tracer.h +104 -0
  351. data/lib/libv8/v8/src/regexp-macro-assembler.cc +267 -0
  352. data/lib/libv8/v8/src/regexp-macro-assembler.h +243 -0
  353. data/lib/libv8/v8/src/regexp-stack.cc +111 -0
  354. data/lib/libv8/v8/src/regexp-stack.h +147 -0
  355. data/lib/libv8/v8/src/regexp.js +483 -0
  356. data/lib/libv8/v8/src/rewriter.cc +360 -0
  357. data/lib/libv8/v8/src/rewriter.h +50 -0
  358. data/lib/libv8/v8/src/runtime-profiler.cc +489 -0
  359. data/lib/libv8/v8/src/runtime-profiler.h +201 -0
  360. data/lib/libv8/v8/src/runtime.cc +12227 -0
  361. data/lib/libv8/v8/src/runtime.h +652 -0
  362. data/lib/libv8/v8/src/runtime.js +649 -0
  363. data/lib/libv8/v8/src/safepoint-table.cc +256 -0
  364. data/lib/libv8/v8/src/safepoint-table.h +270 -0
  365. data/lib/libv8/v8/src/scanner-base.cc +952 -0
  366. data/lib/libv8/v8/src/scanner-base.h +670 -0
  367. data/lib/libv8/v8/src/scanner.cc +345 -0
  368. data/lib/libv8/v8/src/scanner.h +146 -0
  369. data/lib/libv8/v8/src/scopeinfo.cc +646 -0
  370. data/lib/libv8/v8/src/scopeinfo.h +254 -0
  371. data/lib/libv8/v8/src/scopes.cc +1150 -0
  372. data/lib/libv8/v8/src/scopes.h +507 -0
  373. data/lib/libv8/v8/src/serialize.cc +1574 -0
  374. data/lib/libv8/v8/src/serialize.h +589 -0
  375. data/lib/libv8/v8/src/shell.h +55 -0
  376. data/lib/libv8/v8/src/simulator.h +43 -0
  377. data/lib/libv8/v8/src/small-pointer-list.h +163 -0
  378. data/lib/libv8/v8/src/smart-pointer.h +109 -0
  379. data/lib/libv8/v8/src/snapshot-common.cc +83 -0
  380. data/lib/libv8/v8/src/snapshot-empty.cc +54 -0
  381. data/lib/libv8/v8/src/snapshot.h +91 -0
  382. data/lib/libv8/v8/src/spaces-inl.h +529 -0
  383. data/lib/libv8/v8/src/spaces.cc +3145 -0
  384. data/lib/libv8/v8/src/spaces.h +2369 -0
  385. data/lib/libv8/v8/src/splay-tree-inl.h +310 -0
  386. data/lib/libv8/v8/src/splay-tree.h +205 -0
  387. data/lib/libv8/v8/src/string-search.cc +41 -0
  388. data/lib/libv8/v8/src/string-search.h +568 -0
  389. data/lib/libv8/v8/src/string-stream.cc +592 -0
  390. data/lib/libv8/v8/src/string-stream.h +191 -0
  391. data/lib/libv8/v8/src/string.js +994 -0
  392. data/lib/libv8/v8/src/strtod.cc +440 -0
  393. data/lib/libv8/v8/src/strtod.h +40 -0
  394. data/lib/libv8/v8/src/stub-cache.cc +1965 -0
  395. data/lib/libv8/v8/src/stub-cache.h +924 -0
  396. data/lib/libv8/v8/src/third_party/valgrind/valgrind.h +3925 -0
  397. data/lib/libv8/v8/src/token.cc +63 -0
  398. data/lib/libv8/v8/src/token.h +288 -0
  399. data/lib/libv8/v8/src/type-info.cc +507 -0
  400. data/lib/libv8/v8/src/type-info.h +272 -0
  401. data/lib/libv8/v8/src/unbound-queue-inl.h +95 -0
  402. data/lib/libv8/v8/src/unbound-queue.h +69 -0
  403. data/lib/libv8/v8/src/unicode-inl.h +238 -0
  404. data/lib/libv8/v8/src/unicode.cc +1624 -0
  405. data/lib/libv8/v8/src/unicode.h +280 -0
  406. data/lib/libv8/v8/src/uri.js +408 -0
  407. data/lib/libv8/v8/src/utils-inl.h +48 -0
  408. data/lib/libv8/v8/src/utils.cc +371 -0
  409. data/lib/libv8/v8/src/utils.h +800 -0
  410. data/lib/libv8/v8/src/v8-counters.cc +62 -0
  411. data/lib/libv8/v8/src/v8-counters.h +314 -0
  412. data/lib/libv8/v8/src/v8.cc +213 -0
  413. data/lib/libv8/v8/src/v8.h +131 -0
  414. data/lib/libv8/v8/src/v8checks.h +64 -0
  415. data/lib/libv8/v8/src/v8dll-main.cc +44 -0
  416. data/lib/libv8/v8/src/v8globals.h +512 -0
  417. data/lib/libv8/v8/src/v8memory.h +82 -0
  418. data/lib/libv8/v8/src/v8natives.js +1310 -0
  419. data/lib/libv8/v8/src/v8preparserdll-main.cc +39 -0
  420. data/lib/libv8/v8/src/v8threads.cc +464 -0
  421. data/lib/libv8/v8/src/v8threads.h +165 -0
  422. data/lib/libv8/v8/src/v8utils.h +319 -0
  423. data/lib/libv8/v8/src/variables.cc +114 -0
  424. data/lib/libv8/v8/src/variables.h +167 -0
  425. data/lib/libv8/v8/src/version.cc +116 -0
  426. data/lib/libv8/v8/src/version.h +68 -0
  427. data/lib/libv8/v8/src/vm-state-inl.h +138 -0
  428. data/lib/libv8/v8/src/vm-state.h +71 -0
  429. data/lib/libv8/v8/src/win32-headers.h +96 -0
  430. data/lib/libv8/v8/src/x64/assembler-x64-inl.h +462 -0
  431. data/lib/libv8/v8/src/x64/assembler-x64.cc +3027 -0
  432. data/lib/libv8/v8/src/x64/assembler-x64.h +1633 -0
  433. data/lib/libv8/v8/src/x64/builtins-x64.cc +1520 -0
  434. data/lib/libv8/v8/src/x64/code-stubs-x64.cc +5132 -0
  435. data/lib/libv8/v8/src/x64/code-stubs-x64.h +514 -0
  436. data/lib/libv8/v8/src/x64/codegen-x64.cc +146 -0
  437. data/lib/libv8/v8/src/x64/codegen-x64.h +76 -0
  438. data/lib/libv8/v8/src/x64/cpu-x64.cc +88 -0
  439. data/lib/libv8/v8/src/x64/debug-x64.cc +319 -0
  440. data/lib/libv8/v8/src/x64/deoptimizer-x64.cc +815 -0
  441. data/lib/libv8/v8/src/x64/disasm-x64.cc +1832 -0
  442. data/lib/libv8/v8/src/x64/frames-x64.cc +45 -0
  443. data/lib/libv8/v8/src/x64/frames-x64.h +130 -0
  444. data/lib/libv8/v8/src/x64/full-codegen-x64.cc +4318 -0
  445. data/lib/libv8/v8/src/x64/ic-x64.cc +1608 -0
  446. data/lib/libv8/v8/src/x64/lithium-codegen-x64.cc +4267 -0
  447. data/lib/libv8/v8/src/x64/lithium-codegen-x64.h +367 -0
  448. data/lib/libv8/v8/src/x64/lithium-gap-resolver-x64.cc +320 -0
  449. data/lib/libv8/v8/src/x64/lithium-gap-resolver-x64.h +74 -0
  450. data/lib/libv8/v8/src/x64/lithium-x64.cc +2202 -0
  451. data/lib/libv8/v8/src/x64/lithium-x64.h +2333 -0
  452. data/lib/libv8/v8/src/x64/macro-assembler-x64.cc +3745 -0
  453. data/lib/libv8/v8/src/x64/macro-assembler-x64.h +1290 -0
  454. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.cc +1398 -0
  455. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.h +282 -0
  456. data/lib/libv8/v8/src/x64/simulator-x64.cc +27 -0
  457. data/lib/libv8/v8/src/x64/simulator-x64.h +72 -0
  458. data/lib/libv8/v8/src/x64/stub-cache-x64.cc +3610 -0
  459. data/lib/libv8/v8/src/zone-inl.h +140 -0
  460. data/lib/libv8/v8/src/zone.cc +196 -0
  461. data/lib/libv8/v8/src/zone.h +240 -0
  462. data/lib/libv8/v8/tools/codemap.js +265 -0
  463. data/lib/libv8/v8/tools/consarray.js +93 -0
  464. data/lib/libv8/v8/tools/csvparser.js +78 -0
  465. data/lib/libv8/v8/tools/disasm.py +92 -0
  466. data/lib/libv8/v8/tools/freebsd-tick-processor +10 -0
  467. data/lib/libv8/v8/tools/gc-nvp-trace-processor.py +342 -0
  468. data/lib/libv8/v8/tools/gcmole/README +62 -0
  469. data/lib/libv8/v8/tools/gcmole/gccause.lua +60 -0
  470. data/lib/libv8/v8/tools/gcmole/gcmole.cc +1261 -0
  471. data/lib/libv8/v8/tools/gcmole/gcmole.lua +378 -0
  472. data/lib/libv8/v8/tools/generate-ten-powers.scm +286 -0
  473. data/lib/libv8/v8/tools/grokdump.py +841 -0
  474. data/lib/libv8/v8/tools/gyp/v8.gyp +995 -0
  475. data/lib/libv8/v8/tools/js2c.py +364 -0
  476. data/lib/libv8/v8/tools/jsmin.py +280 -0
  477. data/lib/libv8/v8/tools/linux-tick-processor +35 -0
  478. data/lib/libv8/v8/tools/ll_prof.py +942 -0
  479. data/lib/libv8/v8/tools/logreader.js +185 -0
  480. data/lib/libv8/v8/tools/mac-nm +18 -0
  481. data/lib/libv8/v8/tools/mac-tick-processor +6 -0
  482. data/lib/libv8/v8/tools/oom_dump/README +31 -0
  483. data/lib/libv8/v8/tools/oom_dump/SConstruct +42 -0
  484. data/lib/libv8/v8/tools/oom_dump/oom_dump.cc +288 -0
  485. data/lib/libv8/v8/tools/presubmit.py +305 -0
  486. data/lib/libv8/v8/tools/process-heap-prof.py +120 -0
  487. data/lib/libv8/v8/tools/profile.js +751 -0
  488. data/lib/libv8/v8/tools/profile_view.js +219 -0
  489. data/lib/libv8/v8/tools/run-valgrind.py +77 -0
  490. data/lib/libv8/v8/tools/splaytree.js +316 -0
  491. data/lib/libv8/v8/tools/stats-viewer.py +468 -0
  492. data/lib/libv8/v8/tools/test.py +1510 -0
  493. data/lib/libv8/v8/tools/tickprocessor-driver.js +59 -0
  494. data/lib/libv8/v8/tools/tickprocessor.js +877 -0
  495. data/lib/libv8/v8/tools/utils.py +96 -0
  496. data/lib/libv8/v8/tools/visual_studio/README.txt +12 -0
  497. data/lib/libv8/v8/tools/windows-tick-processor.bat +30 -0
  498. data/lib/libv8/version.rb +5 -0
  499. data/libv8.gemspec +36 -0
  500. metadata +578 -0
@@ -0,0 +1,282 @@
1
+ // Copyright 2010 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #ifndef V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
29
+ #define V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
30
+
31
+ namespace v8 {
32
+ namespace internal {
33
+
34
+ #ifndef V8_INTERPRETED_REGEXP
35
+
36
+ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
37
+ public:
38
+ RegExpMacroAssemblerX64(Mode mode, int registers_to_save);
39
+ virtual ~RegExpMacroAssemblerX64();
40
+ virtual int stack_limit_slack();
41
+ virtual void AdvanceCurrentPosition(int by);
42
+ virtual void AdvanceRegister(int reg, int by);
43
+ virtual void Backtrack();
44
+ virtual void Bind(Label* label);
45
+ virtual void CheckAtStart(Label* on_at_start);
46
+ virtual void CheckCharacter(uint32_t c, Label* on_equal);
47
+ virtual void CheckCharacterAfterAnd(uint32_t c,
48
+ uint32_t mask,
49
+ Label* on_equal);
50
+ virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
51
+ virtual void CheckCharacterLT(uc16 limit, Label* on_less);
52
+ virtual void CheckCharacters(Vector<const uc16> str,
53
+ int cp_offset,
54
+ Label* on_failure,
55
+ bool check_end_of_string);
56
+ // A "greedy loop" is a loop that is both greedy and with a simple
57
+ // body. It has a particularly simple implementation.
58
+ virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
59
+ virtual void CheckNotAtStart(Label* on_not_at_start);
60
+ virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
61
+ virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
62
+ Label* on_no_match);
63
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
64
+ virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
65
+ virtual void CheckNotCharacterAfterAnd(uint32_t c,
66
+ uint32_t mask,
67
+ Label* on_not_equal);
68
+ virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
69
+ uc16 minus,
70
+ uc16 mask,
71
+ Label* on_not_equal);
72
+ // Checks whether the given offset from the current position is before
73
+ // the end of the string.
74
+ virtual void CheckPosition(int cp_offset, Label* on_outside_input);
75
+ virtual bool CheckSpecialCharacterClass(uc16 type,
76
+ Label* on_no_match);
77
+ virtual void Fail();
78
+ virtual Handle<HeapObject> GetCode(Handle<String> source);
79
+ virtual void GoTo(Label* label);
80
+ virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
81
+ virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
82
+ virtual void IfRegisterEqPos(int reg, Label* if_eq);
83
+ virtual IrregexpImplementation Implementation();
84
+ virtual void LoadCurrentCharacter(int cp_offset,
85
+ Label* on_end_of_input,
86
+ bool check_bounds = true,
87
+ int characters = 1);
88
+ virtual void PopCurrentPosition();
89
+ virtual void PopRegister(int register_index);
90
+ virtual void PushBacktrack(Label* label);
91
+ virtual void PushCurrentPosition();
92
+ virtual void PushRegister(int register_index,
93
+ StackCheckFlag check_stack_limit);
94
+ virtual void ReadCurrentPositionFromRegister(int reg);
95
+ virtual void ReadStackPointerFromRegister(int reg);
96
+ virtual void SetCurrentPositionFromEnd(int by);
97
+ virtual void SetRegister(int register_index, int to);
98
+ virtual void Succeed();
99
+ virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
100
+ virtual void ClearRegisters(int reg_from, int reg_to);
101
+ virtual void WriteStackPointerToRegister(int reg);
102
+
103
+ static Result Match(Handle<Code> regexp,
104
+ Handle<String> subject,
105
+ int* offsets_vector,
106
+ int offsets_vector_length,
107
+ int previous_index,
108
+ Isolate* isolate);
109
+
110
+ static Result Execute(Code* code,
111
+ String* input,
112
+ int start_offset,
113
+ const byte* input_start,
114
+ const byte* input_end,
115
+ int* output,
116
+ bool at_start);
117
+
118
+ // Called from RegExp if the stack-guard is triggered.
119
+ // If the code object is relocated, the return address is fixed before
120
+ // returning.
121
+ static int CheckStackGuardState(Address* return_address,
122
+ Code* re_code,
123
+ Address re_frame);
124
+
125
+ private:
126
+ // Offsets from rbp of function parameters and stored registers.
127
+ static const int kFramePointer = 0;
128
+ // Above the frame pointer - function parameters and return address.
129
+ static const int kReturn_eip = kFramePointer + kPointerSize;
130
+ static const int kFrameAlign = kReturn_eip + kPointerSize;
131
+
132
+ #ifdef _WIN64
133
+ // Parameters (first four passed as registers, but with room on stack).
134
+ // In Microsoft 64-bit Calling Convention, there is room on the callers
135
+ // stack (before the return address) to spill parameter registers. We
136
+ // use this space to store the register passed parameters.
137
+ static const int kInputString = kFrameAlign;
138
+ // StartIndex is passed as 32 bit int.
139
+ static const int kStartIndex = kInputString + kPointerSize;
140
+ static const int kInputStart = kStartIndex + kPointerSize;
141
+ static const int kInputEnd = kInputStart + kPointerSize;
142
+ static const int kRegisterOutput = kInputEnd + kPointerSize;
143
+ static const int kStackHighEnd = kRegisterOutput + kPointerSize;
144
+ // DirectCall is passed as 32 bit int (values 0 or 1).
145
+ static const int kDirectCall = kStackHighEnd + kPointerSize;
146
+ static const int kIsolate = kDirectCall + kPointerSize;
147
+ #else
148
+ // In AMD64 ABI Calling Convention, the first six integer parameters
149
+ // are passed as registers, and caller must allocate space on the stack
150
+ // if it wants them stored. We push the parameters after the frame pointer.
151
+ static const int kInputString = kFramePointer - kPointerSize;
152
+ static const int kStartIndex = kInputString - kPointerSize;
153
+ static const int kInputStart = kStartIndex - kPointerSize;
154
+ static const int kInputEnd = kInputStart - kPointerSize;
155
+ static const int kRegisterOutput = kInputEnd - kPointerSize;
156
+ static const int kStackHighEnd = kRegisterOutput - kPointerSize;
157
+ static const int kDirectCall = kFrameAlign;
158
+ static const int kIsolate = kDirectCall + kPointerSize;
159
+ #endif
160
+
161
+ #ifdef _WIN64
162
+ // Microsoft calling convention has three callee-saved registers
163
+ // (that we are using). We push these after the frame pointer.
164
+ static const int kBackup_rsi = kFramePointer - kPointerSize;
165
+ static const int kBackup_rdi = kBackup_rsi - kPointerSize;
166
+ static const int kBackup_rbx = kBackup_rdi - kPointerSize;
167
+ static const int kLastCalleeSaveRegister = kBackup_rbx;
168
+ #else
169
+ // AMD64 Calling Convention has only one callee-save register that
170
+ // we use. We push this after the frame pointer (and after the
171
+ // parameters).
172
+ static const int kBackup_rbx = kStackHighEnd - kPointerSize;
173
+ static const int kLastCalleeSaveRegister = kBackup_rbx;
174
+ #endif
175
+
176
+ // When adding local variables remember to push space for them in
177
+ // the frame in GetCode.
178
+ static const int kInputStartMinusOne =
179
+ kLastCalleeSaveRegister - kPointerSize;
180
+
181
+ // First register address. Following registers are below it on the stack.
182
+ static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
183
+
184
+ // Initial size of code buffer.
185
+ static const size_t kRegExpCodeSize = 1024;
186
+
187
+ // Load a number of characters at the given offset from the
188
+ // current position, into the current-character register.
189
+ void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
190
+
191
+ // Check whether preemption has been requested.
192
+ void CheckPreemption();
193
+
194
+ // Check whether we are exceeding the stack limit on the backtrack stack.
195
+ void CheckStackLimit();
196
+
197
+ // Generate a call to CheckStackGuardState.
198
+ void CallCheckStackGuardState();
199
+
200
+ // The rbp-relative location of a regexp register.
201
+ Operand register_location(int register_index);
202
+
203
+ // The register containing the current character after LoadCurrentCharacter.
204
+ inline Register current_character() { return rdx; }
205
+
206
+ // The register containing the backtrack stack top. Provides a meaningful
207
+ // name to the register.
208
+ inline Register backtrack_stackpointer() { return rcx; }
209
+
210
+ // The registers containing a self pointer to this code's Code object.
211
+ inline Register code_object_pointer() { return r8; }
212
+
213
+ // Byte size of chars in the string to match (decided by the Mode argument)
214
+ inline int char_size() { return static_cast<int>(mode_); }
215
+
216
+ // Equivalent to a conditional branch to the label, unless the label
217
+ // is NULL, in which case it is a conditional Backtrack.
218
+ void BranchOrBacktrack(Condition condition, Label* to);
219
+
220
+ void MarkPositionForCodeRelativeFixup() {
221
+ code_relative_fixup_positions_.Add(masm_.pc_offset());
222
+ }
223
+
224
+ void FixupCodeRelativePositions();
225
+
226
+ // Call and return internally in the generated code in a way that
227
+ // is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
228
+ inline void SafeCall(Label* to);
229
+ inline void SafeCallTarget(Label* label);
230
+ inline void SafeReturn();
231
+
232
+ // Pushes the value of a register on the backtrack stack. Decrements the
233
+ // stack pointer (rcx) by a word size and stores the register's value there.
234
+ inline void Push(Register source);
235
+
236
+ // Pushes a value on the backtrack stack. Decrements the stack pointer (rcx)
237
+ // by a word size and stores the value there.
238
+ inline void Push(Immediate value);
239
+
240
+ // Pushes the Code object relative offset of a label on the backtrack stack
241
+ // (i.e., a backtrack target). Decrements the stack pointer (rcx)
242
+ // by a word size and stores the value there.
243
+ inline void Push(Label* label);
244
+
245
+ // Pops a value from the backtrack stack. Reads the word at the stack pointer
246
+ // (rcx) and increments it by a word size.
247
+ inline void Pop(Register target);
248
+
249
+ // Drops the top value from the backtrack stack without reading it.
250
+ // Increments the stack pointer (rcx) by a word size.
251
+ inline void Drop();
252
+
253
+ MacroAssembler masm_;
254
+ MacroAssembler::NoRootArrayScope no_root_array_scope_;
255
+
256
+ ZoneList<int> code_relative_fixup_positions_;
257
+
258
+ // Which mode to generate code for (ASCII or UC16).
259
+ Mode mode_;
260
+
261
+ // One greater than maximal register index actually used.
262
+ int num_registers_;
263
+
264
+ // Number of registers to output at the end (the saved registers
265
+ // are always 0..num_saved_registers_-1)
266
+ int num_saved_registers_;
267
+
268
+ // Labels used internally.
269
+ Label entry_label_;
270
+ Label start_label_;
271
+ Label success_label_;
272
+ Label backtrack_label_;
273
+ Label exit_label_;
274
+ Label check_preempt_label_;
275
+ Label stack_overflow_label_;
276
+ };
277
+
278
+ #endif // V8_INTERPRETED_REGEXP
279
+
280
+ }} // namespace v8::internal
281
+
282
+ #endif // V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
@@ -0,0 +1,27 @@
1
+ // Copyright 2009 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
@@ -0,0 +1,72 @@
1
+ // Copyright 2011 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #ifndef V8_X64_SIMULATOR_X64_H_
29
+ #define V8_X64_SIMULATOR_X64_H_
30
+
31
+ #include "allocation.h"
32
+
33
+ namespace v8 {
34
+ namespace internal {
35
+
36
+ // Since there is no simulator for the x64 architecture the only thing we can
37
+ // do is to call the entry directly.
38
+ // TODO(X64): Don't pass p0, since it isn't used?
39
+ #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
40
+ (entry(p0, p1, p2, p3, p4))
41
+
42
+ typedef int (*regexp_matcher)(String*, int, const byte*,
43
+ const byte*, int*, Address, int, Isolate*);
44
+
45
+ // Call the generated regexp code directly. The code at the entry address should
46
+ // expect eight int/pointer sized arguments and return an int.
47
+ #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
48
+ (FUNCTION_CAST<regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7))
49
+
50
+ #define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
51
+ (reinterpret_cast<TryCatch*>(try_catch_address))
52
+
53
+ // The stack limit beyond which we will throw stack overflow errors in
54
+ // generated code. Because generated code on x64 uses the C stack, we
55
+ // just use the C stack limit.
56
+ class SimulatorStack : public v8::internal::AllStatic {
57
+ public:
58
+ static inline uintptr_t JsLimitFromCLimit(Isolate* isolate,
59
+ uintptr_t c_limit) {
60
+ return c_limit;
61
+ }
62
+
63
+ static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
64
+ return try_catch_address;
65
+ }
66
+
67
+ static inline void UnregisterCTryCatch() { }
68
+ };
69
+
70
+ } } // namespace v8::internal
71
+
72
+ #endif // V8_X64_SIMULATOR_X64_H_
@@ -0,0 +1,3610 @@
1
+ // Copyright 2011 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #include "v8.h"
29
+
30
+ #if defined(V8_TARGET_ARCH_X64)
31
+
32
+ #include "ic-inl.h"
33
+ #include "codegen.h"
34
+ #include "stub-cache.h"
35
+
36
+ namespace v8 {
37
+ namespace internal {
38
+
39
+ #define __ ACCESS_MASM(masm)
40
+
41
+
42
+ static void ProbeTable(Isolate* isolate,
43
+ MacroAssembler* masm,
44
+ Code::Flags flags,
45
+ StubCache::Table table,
46
+ Register name,
47
+ Register offset) {
48
+ ASSERT_EQ(8, kPointerSize);
49
+ ASSERT_EQ(16, sizeof(StubCache::Entry));
50
+ // The offset register holds the entry offset times four (due to masking
51
+ // and shifting optimizations).
52
+ ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
53
+ Label miss;
54
+
55
+ __ LoadAddress(kScratchRegister, key_offset);
56
+ // Check that the key in the entry matches the name.
57
+ // Multiply entry offset by 16 to get the entry address. Since the
58
+ // offset register already holds the entry offset times four, multiply
59
+ // by a further four.
60
+ __ cmpl(name, Operand(kScratchRegister, offset, times_4, 0));
61
+ __ j(not_equal, &miss);
62
+ // Get the code entry from the cache.
63
+ // Use key_offset + kPointerSize, rather than loading value_offset.
64
+ __ movq(kScratchRegister,
65
+ Operand(kScratchRegister, offset, times_4, kPointerSize));
66
+ // Check that the flags match what we're looking for.
67
+ __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
68
+ __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
69
+ __ cmpl(offset, Immediate(flags));
70
+ __ j(not_equal, &miss);
71
+
72
+ // Jump to the first instruction in the code stub.
73
+ __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
74
+ __ jmp(kScratchRegister);
75
+
76
+ __ bind(&miss);
77
+ }
78
+
79
+
80
+ // Helper function used to check that the dictionary doesn't contain
81
+ // the property. This function may return false negatives, so miss_label
82
+ // must always call a backup property check that is complete.
83
+ // This function is safe to call if the receiver has fast properties.
84
+ // Name must be a symbol and receiver must be a heap object.
85
+ MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
86
+ MacroAssembler* masm,
87
+ Label* miss_label,
88
+ Register receiver,
89
+ String* name,
90
+ Register r0,
91
+ Register r1) {
92
+ ASSERT(name->IsSymbol());
93
+ Counters* counters = masm->isolate()->counters();
94
+ __ IncrementCounter(counters->negative_lookups(), 1);
95
+ __ IncrementCounter(counters->negative_lookups_miss(), 1);
96
+
97
+ __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
98
+
99
+ const int kInterceptorOrAccessCheckNeededMask =
100
+ (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
101
+
102
+ // Bail out if the receiver has a named interceptor or requires access checks.
103
+ __ testb(FieldOperand(r0, Map::kBitFieldOffset),
104
+ Immediate(kInterceptorOrAccessCheckNeededMask));
105
+ __ j(not_zero, miss_label);
106
+
107
+ // Check that receiver is a JSObject.
108
+ __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE);
109
+ __ j(below, miss_label);
110
+
111
+ // Load properties array.
112
+ Register properties = r0;
113
+ __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
114
+
115
+ // Check that the properties array is a dictionary.
116
+ __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
117
+ Heap::kHashTableMapRootIndex);
118
+ __ j(not_equal, miss_label);
119
+
120
+ Label done;
121
+ MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup(
122
+ masm,
123
+ miss_label,
124
+ &done,
125
+ properties,
126
+ name,
127
+ r1);
128
+ if (result->IsFailure()) return result;
129
+
130
+ __ bind(&done);
131
+ __ DecrementCounter(counters->negative_lookups_miss(), 1);
132
+
133
+ return result;
134
+ }
135
+
136
+
137
+ void StubCache::GenerateProbe(MacroAssembler* masm,
138
+ Code::Flags flags,
139
+ Register receiver,
140
+ Register name,
141
+ Register scratch,
142
+ Register extra,
143
+ Register extra2) {
144
+ Isolate* isolate = masm->isolate();
145
+ Label miss;
146
+ USE(extra); // The register extra is not used on the X64 platform.
147
+ USE(extra2); // The register extra2 is not used on the X64 platform.
148
+ // Make sure that code is valid. The shifting code relies on the
149
+ // entry size being 16.
150
+ ASSERT(sizeof(Entry) == 16);
151
+
152
+ // Make sure the flags do not name a specific type.
153
+ ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
154
+
155
+ // Make sure that there are no register conflicts.
156
+ ASSERT(!scratch.is(receiver));
157
+ ASSERT(!scratch.is(name));
158
+
159
+ // Check scratch register is valid, extra and extra2 are unused.
160
+ ASSERT(!scratch.is(no_reg));
161
+ ASSERT(extra2.is(no_reg));
162
+
163
+ // Check that the receiver isn't a smi.
164
+ __ JumpIfSmi(receiver, &miss);
165
+
166
+ // Get the map of the receiver and compute the hash.
167
+ __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
168
+ // Use only the low 32 bits of the map pointer.
169
+ __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
170
+ __ xor_(scratch, Immediate(flags));
171
+ __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
172
+
173
+ // Probe the primary table.
174
+ ProbeTable(isolate, masm, flags, kPrimary, name, scratch);
175
+
176
+ // Primary miss: Compute hash for secondary probe.
177
+ __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
178
+ __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
179
+ __ xor_(scratch, Immediate(flags));
180
+ __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
181
+ __ subl(scratch, name);
182
+ __ addl(scratch, Immediate(flags));
183
+ __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
184
+
185
+ // Probe the secondary table.
186
+ ProbeTable(isolate, masm, flags, kSecondary, name, scratch);
187
+
188
+ // Cache miss: Fall-through and let caller handle the miss by
189
+ // entering the runtime system.
190
+ __ bind(&miss);
191
+ }
192
+
193
+
194
+ void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
195
+ int index,
196
+ Register prototype) {
197
+ // Load the global or builtins object from the current context.
198
+ __ movq(prototype,
199
+ Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
200
+ // Load the global context from the global or builtins object.
201
+ __ movq(prototype,
202
+ FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
203
+ // Load the function from the global context.
204
+ __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
205
+ // Load the initial map. The global functions all have initial maps.
206
+ __ movq(prototype,
207
+ FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
208
+ // Load the prototype from the initial map.
209
+ __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
210
+ }
211
+
212
+
213
+ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
214
+ MacroAssembler* masm, int index, Register prototype, Label* miss) {
215
+ Isolate* isolate = masm->isolate();
216
+ // Check we're still in the same context.
217
+ __ Move(prototype, isolate->global());
218
+ __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)),
219
+ prototype);
220
+ __ j(not_equal, miss);
221
+ // Get the global function with the given index.
222
+ JSFunction* function =
223
+ JSFunction::cast(isolate->global_context()->get(index));
224
+ // Load its initial map. The global functions all have initial maps.
225
+ __ Move(prototype, Handle<Map>(function->initial_map()));
226
+ // Load the prototype from the initial map.
227
+ __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
228
+ }
229
+
230
+
231
+ void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
232
+ Register receiver,
233
+ Register scratch,
234
+ Label* miss_label) {
235
+ // Check that the receiver isn't a smi.
236
+ __ JumpIfSmi(receiver, miss_label);
237
+
238
+ // Check that the object is a JS array.
239
+ __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
240
+ __ j(not_equal, miss_label);
241
+
242
+ // Load length directly from the JS array.
243
+ __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset));
244
+ __ ret(0);
245
+ }
246
+
247
+
248
+ // Generate code to check if an object is a string. If the object is
249
+ // a string, the map's instance type is left in the scratch register.
250
+ static void GenerateStringCheck(MacroAssembler* masm,
251
+ Register receiver,
252
+ Register scratch,
253
+ Label* smi,
254
+ Label* non_string_object) {
255
+ // Check that the object isn't a smi.
256
+ __ JumpIfSmi(receiver, smi);
257
+
258
+ // Check that the object is a string.
259
+ __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
260
+ __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
261
+ ASSERT(kNotStringTag != 0);
262
+ __ testl(scratch, Immediate(kNotStringTag));
263
+ __ j(not_zero, non_string_object);
264
+ }
265
+
266
+
267
+ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
268
+ Register receiver,
269
+ Register scratch1,
270
+ Register scratch2,
271
+ Label* miss,
272
+ bool support_wrappers) {
273
+ Label check_wrapper;
274
+
275
+ // Check if the object is a string leaving the instance type in the
276
+ // scratch register.
277
+ GenerateStringCheck(masm, receiver, scratch1, miss,
278
+ support_wrappers ? &check_wrapper : miss);
279
+
280
+ // Load length directly from the string.
281
+ __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
282
+ __ ret(0);
283
+
284
+ if (support_wrappers) {
285
+ // Check if the object is a JSValue wrapper.
286
+ __ bind(&check_wrapper);
287
+ __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
288
+ __ j(not_equal, miss);
289
+
290
+ // Check if the wrapped value is a string and load the length
291
+ // directly if it is.
292
+ __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
293
+ GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
294
+ __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
295
+ __ ret(0);
296
+ }
297
+ }
298
+
299
+
300
+ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
301
+ Register receiver,
302
+ Register result,
303
+ Register scratch,
304
+ Label* miss_label) {
305
+ __ TryGetFunctionPrototype(receiver, result, miss_label);
306
+ if (!result.is(rax)) __ movq(rax, result);
307
+ __ ret(0);
308
+ }
309
+
310
+
311
+ // Load a fast property out of a holder object (src). In-object properties
312
+ // are loaded directly otherwise the property is loaded from the properties
313
+ // fixed array.
314
+ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
315
+ Register dst, Register src,
316
+ JSObject* holder, int index) {
317
+ // Adjust for the number of properties stored in the holder.
318
+ index -= holder->map()->inobject_properties();
319
+ if (index < 0) {
320
+ // Get the property straight out of the holder.
321
+ int offset = holder->map()->instance_size() + (index * kPointerSize);
322
+ __ movq(dst, FieldOperand(src, offset));
323
+ } else {
324
+ // Calculate the offset into the properties array.
325
+ int offset = index * kPointerSize + FixedArray::kHeaderSize;
326
+ __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
327
+ __ movq(dst, FieldOperand(dst, offset));
328
+ }
329
+ }
330
+
331
+
332
+ static void PushInterceptorArguments(MacroAssembler* masm,
333
+ Register receiver,
334
+ Register holder,
335
+ Register name,
336
+ JSObject* holder_obj) {
337
+ __ push(name);
338
+ InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
339
+ ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor));
340
+ __ Move(kScratchRegister, Handle<Object>(interceptor));
341
+ __ push(kScratchRegister);
342
+ __ push(receiver);
343
+ __ push(holder);
344
+ __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset));
345
+ }
346
+
347
+
348
+ static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
349
+ Register receiver,
350
+ Register holder,
351
+ Register name,
352
+ JSObject* holder_obj) {
353
+ PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
354
+
355
+ ExternalReference ref =
356
+ ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
357
+ masm->isolate());
358
+ __ Set(rax, 5);
359
+ __ LoadAddress(rbx, ref);
360
+
361
+ CEntryStub stub(1);
362
+ __ CallStub(&stub);
363
+ }
364
+
365
+
366
+ // Number of pointers to be reserved on stack for fast API call.
367
+ static const int kFastApiCallArguments = 3;
368
+
369
+
370
+ // Reserves space for the extra arguments to API function in the
371
+ // caller's frame.
372
+ //
373
+ // These arguments are set by CheckPrototypes and GenerateFastApiCall.
374
+ static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
375
+ // ----------- S t a t e -------------
376
+ // -- rsp[0] : return address
377
+ // -- rsp[8] : last argument in the internal frame of the caller
378
+ // -----------------------------------
379
+ __ movq(scratch, Operand(rsp, 0));
380
+ __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
381
+ __ movq(Operand(rsp, 0), scratch);
382
+ __ Move(scratch, Smi::FromInt(0));
383
+ for (int i = 1; i <= kFastApiCallArguments; i++) {
384
+ __ movq(Operand(rsp, i * kPointerSize), scratch);
385
+ }
386
+ }
387
+
388
+
389
+ // Undoes the effects of ReserveSpaceForFastApiCall.
390
+ static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
391
+ // ----------- S t a t e -------------
392
+ // -- rsp[0] : return address.
393
+ // -- rsp[8] : last fast api call extra argument.
394
+ // -- ...
395
+ // -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument.
396
+ // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
397
+ // frame.
398
+ // -----------------------------------
399
+ __ movq(scratch, Operand(rsp, 0));
400
+ __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
401
+ __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
402
+ }
403
+
404
+
405
+ // Generates call to API function.
406
+ static MaybeObject* GenerateFastApiCall(MacroAssembler* masm,
407
+ const CallOptimization& optimization,
408
+ int argc) {
409
+ // ----------- S t a t e -------------
410
+ // -- rsp[0] : return address
411
+ // -- rsp[8] : object passing the type check
412
+ // (last fast api call extra argument,
413
+ // set by CheckPrototypes)
414
+ // -- rsp[16] : api function
415
+ // (first fast api call extra argument)
416
+ // -- rsp[24] : api call data
417
+ // -- rsp[32] : last argument
418
+ // -- ...
419
+ // -- rsp[(argc + 3) * 8] : first argument
420
+ // -- rsp[(argc + 4) * 8] : receiver
421
+ // -----------------------------------
422
+ // Get the function and setup the context.
423
+ JSFunction* function = optimization.constant_function();
424
+ __ Move(rdi, Handle<JSFunction>(function));
425
+ __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
426
+
427
+ // Pass the additional arguments.
428
+ __ movq(Operand(rsp, 2 * kPointerSize), rdi);
429
+ Object* call_data = optimization.api_call_info()->data();
430
+ Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
431
+ if (masm->isolate()->heap()->InNewSpace(call_data)) {
432
+ __ Move(rcx, api_call_info_handle);
433
+ __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
434
+ __ movq(Operand(rsp, 3 * kPointerSize), rbx);
435
+ } else {
436
+ __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(call_data));
437
+ }
438
+
439
+ // Prepare arguments.
440
+ __ lea(rbx, Operand(rsp, 3 * kPointerSize));
441
+
442
+ Object* callback = optimization.api_call_info()->callback();
443
+ Address api_function_address = v8::ToCData<Address>(callback);
444
+ ApiFunction fun(api_function_address);
445
+
446
+ #ifdef _WIN64
447
+ // Win64 uses first register--rcx--for returned value.
448
+ Register arguments_arg = rdx;
449
+ #else
450
+ Register arguments_arg = rdi;
451
+ #endif
452
+
453
+ // Allocate the v8::Arguments structure in the arguments' space since
454
+ // it's not controlled by GC.
455
+ const int kApiStackSpace = 4;
456
+
457
+ __ PrepareCallApiFunction(kApiStackSpace);
458
+
459
+ __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_.
460
+ __ addq(rbx, Immediate(argc * kPointerSize));
461
+ __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_.
462
+ __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_.
463
+ // v8::Arguments::is_construct_call_.
464
+ __ Set(StackSpaceOperand(3), 0);
465
+
466
+ // v8::InvocationCallback's argument.
467
+ __ lea(arguments_arg, StackSpaceOperand(0));
468
+ // Emitting a stub call may try to allocate (if the code is not
469
+ // already generated). Do not allow the assembler to perform a
470
+ // garbage collection but instead return the allocation failure
471
+ // object.
472
+ return masm->TryCallApiFunctionAndReturn(&fun,
473
+ argc + kFastApiCallArguments + 1);
474
+ }
475
+
476
+
477
+ class CallInterceptorCompiler BASE_EMBEDDED {
478
+ public:
479
+ CallInterceptorCompiler(StubCompiler* stub_compiler,
480
+ const ParameterCount& arguments,
481
+ Register name)
482
+ : stub_compiler_(stub_compiler),
483
+ arguments_(arguments),
484
+ name_(name) {}
485
+
486
+ MaybeObject* Compile(MacroAssembler* masm,
487
+ JSObject* object,
488
+ JSObject* holder,
489
+ String* name,
490
+ LookupResult* lookup,
491
+ Register receiver,
492
+ Register scratch1,
493
+ Register scratch2,
494
+ Register scratch3,
495
+ Label* miss) {
496
+ ASSERT(holder->HasNamedInterceptor());
497
+ ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
498
+
499
+ // Check that the receiver isn't a smi.
500
+ __ JumpIfSmi(receiver, miss);
501
+
502
+ CallOptimization optimization(lookup);
503
+
504
+ if (optimization.is_constant_call()) {
505
+ return CompileCacheable(masm,
506
+ object,
507
+ receiver,
508
+ scratch1,
509
+ scratch2,
510
+ scratch3,
511
+ holder,
512
+ lookup,
513
+ name,
514
+ optimization,
515
+ miss);
516
+ } else {
517
+ CompileRegular(masm,
518
+ object,
519
+ receiver,
520
+ scratch1,
521
+ scratch2,
522
+ scratch3,
523
+ name,
524
+ holder,
525
+ miss);
526
+ return masm->isolate()->heap()->undefined_value(); // Success.
527
+ }
528
+ }
529
+
530
+ private:
531
+ MaybeObject* CompileCacheable(MacroAssembler* masm,
532
+ JSObject* object,
533
+ Register receiver,
534
+ Register scratch1,
535
+ Register scratch2,
536
+ Register scratch3,
537
+ JSObject* interceptor_holder,
538
+ LookupResult* lookup,
539
+ String* name,
540
+ const CallOptimization& optimization,
541
+ Label* miss_label) {
542
+ ASSERT(optimization.is_constant_call());
543
+ ASSERT(!lookup->holder()->IsGlobalObject());
544
+
545
+ int depth1 = kInvalidProtoDepth;
546
+ int depth2 = kInvalidProtoDepth;
547
+ bool can_do_fast_api_call = false;
548
+ if (optimization.is_simple_api_call() &&
549
+ !lookup->holder()->IsGlobalObject()) {
550
+ depth1 =
551
+ optimization.GetPrototypeDepthOfExpectedType(object,
552
+ interceptor_holder);
553
+ if (depth1 == kInvalidProtoDepth) {
554
+ depth2 =
555
+ optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
556
+ lookup->holder());
557
+ }
558
+ can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
559
+ (depth2 != kInvalidProtoDepth);
560
+ }
561
+
562
+ Counters* counters = masm->isolate()->counters();
563
+ __ IncrementCounter(counters->call_const_interceptor(), 1);
564
+
565
+ if (can_do_fast_api_call) {
566
+ __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
567
+ ReserveSpaceForFastApiCall(masm, scratch1);
568
+ }
569
+
570
+ // Check that the maps from receiver to interceptor's holder
571
+ // haven't changed and thus we can invoke interceptor.
572
+ Label miss_cleanup;
573
+ Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
574
+ Register holder =
575
+ stub_compiler_->CheckPrototypes(object, receiver,
576
+ interceptor_holder, scratch1,
577
+ scratch2, scratch3, name, depth1, miss);
578
+
579
+ // Invoke an interceptor and if it provides a value,
580
+ // branch to |regular_invoke|.
581
+ Label regular_invoke;
582
+ LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
583
+ &regular_invoke);
584
+
585
+ // Interceptor returned nothing for this property. Try to use cached
586
+ // constant function.
587
+
588
+ // Check that the maps from interceptor's holder to constant function's
589
+ // holder haven't changed and thus we can use cached constant function.
590
+ if (interceptor_holder != lookup->holder()) {
591
+ stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
592
+ lookup->holder(), scratch1,
593
+ scratch2, scratch3, name, depth2, miss);
594
+ } else {
595
+ // CheckPrototypes has a side effect of fetching a 'holder'
596
+ // for API (object which is instanceof for the signature). It's
597
+ // safe to omit it here, as if present, it should be fetched
598
+ // by the previous CheckPrototypes.
599
+ ASSERT(depth2 == kInvalidProtoDepth);
600
+ }
601
+
602
+ // Invoke function.
603
+ if (can_do_fast_api_call) {
604
+ MaybeObject* result = GenerateFastApiCall(masm,
605
+ optimization,
606
+ arguments_.immediate());
607
+ if (result->IsFailure()) return result;
608
+ } else {
609
+ __ InvokeFunction(optimization.constant_function(), arguments_,
610
+ JUMP_FUNCTION);
611
+ }
612
+
613
+ // Deferred code for fast API call case---clean preallocated space.
614
+ if (can_do_fast_api_call) {
615
+ __ bind(&miss_cleanup);
616
+ FreeSpaceForFastApiCall(masm, scratch1);
617
+ __ jmp(miss_label);
618
+ }
619
+
620
+ // Invoke a regular function.
621
+ __ bind(&regular_invoke);
622
+ if (can_do_fast_api_call) {
623
+ FreeSpaceForFastApiCall(masm, scratch1);
624
+ }
625
+
626
+ return masm->isolate()->heap()->undefined_value(); // Success.
627
+ }
628
+
629
+ void CompileRegular(MacroAssembler* masm,
630
+ JSObject* object,
631
+ Register receiver,
632
+ Register scratch1,
633
+ Register scratch2,
634
+ Register scratch3,
635
+ String* name,
636
+ JSObject* interceptor_holder,
637
+ Label* miss_label) {
638
+ Register holder =
639
+ stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
640
+ scratch1, scratch2, scratch3, name,
641
+ miss_label);
642
+
643
+ __ EnterInternalFrame();
644
+ // Save the name_ register across the call.
645
+ __ push(name_);
646
+
647
+ PushInterceptorArguments(masm,
648
+ receiver,
649
+ holder,
650
+ name_,
651
+ interceptor_holder);
652
+
653
+ __ CallExternalReference(
654
+ ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
655
+ masm->isolate()),
656
+ 5);
657
+
658
+ // Restore the name_ register.
659
+ __ pop(name_);
660
+ __ LeaveInternalFrame();
661
+ }
662
+
663
+ void LoadWithInterceptor(MacroAssembler* masm,
664
+ Register receiver,
665
+ Register holder,
666
+ JSObject* holder_obj,
667
+ Label* interceptor_succeeded) {
668
+ __ EnterInternalFrame();
669
+ __ push(holder); // Save the holder.
670
+ __ push(name_); // Save the name.
671
+
672
+ CompileCallLoadPropertyWithInterceptor(masm,
673
+ receiver,
674
+ holder,
675
+ name_,
676
+ holder_obj);
677
+
678
+ __ pop(name_); // Restore the name.
679
+ __ pop(receiver); // Restore the holder.
680
+ __ LeaveInternalFrame();
681
+
682
+ __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
683
+ __ j(not_equal, interceptor_succeeded);
684
+ }
685
+
686
+ StubCompiler* stub_compiler_;
687
+ const ParameterCount& arguments_;
688
+ Register name_;
689
+ };
690
+
691
+
692
+ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
693
+ ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
694
+ Code* code = NULL;
695
+ if (kind == Code::LOAD_IC) {
696
+ code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
697
+ } else {
698
+ code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
699
+ }
700
+
701
+ Handle<Code> ic(code);
702
+ __ Jump(ic, RelocInfo::CODE_TARGET);
703
+ }
704
+
705
+
706
+ void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
707
+ Code* code = masm->isolate()->builtins()->builtin(
708
+ Builtins::kKeyedLoadIC_MissForceGeneric);
709
+ Handle<Code> ic(code);
710
+ __ Jump(ic, RelocInfo::CODE_TARGET);
711
+ }
712
+
713
+
714
+ // Both name_reg and receiver_reg are preserved on jumps to miss_label,
715
+ // but may be destroyed if store is successful.
716
+ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
717
+ JSObject* object,
718
+ int index,
719
+ Map* transition,
720
+ Register receiver_reg,
721
+ Register name_reg,
722
+ Register scratch,
723
+ Label* miss_label) {
724
+ // Check that the object isn't a smi.
725
+ __ JumpIfSmi(receiver_reg, miss_label);
726
+
727
+ // Check that the map of the object hasn't changed.
728
+ __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
729
+ Handle<Map>(object->map()));
730
+ __ j(not_equal, miss_label);
731
+
732
+ // Perform global security token check if needed.
733
+ if (object->IsJSGlobalProxy()) {
734
+ __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
735
+ }
736
+
737
+ // Stub never generated for non-global objects that require access
738
+ // checks.
739
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
740
+
741
+ // Perform map transition for the receiver if necessary.
742
+ if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
743
+ // The properties must be extended before we can store the value.
744
+ // We jump to a runtime call that extends the properties array.
745
+ __ pop(scratch); // Return address.
746
+ __ push(receiver_reg);
747
+ __ Push(Handle<Map>(transition));
748
+ __ push(rax);
749
+ __ push(scratch);
750
+ __ TailCallExternalReference(
751
+ ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
752
+ masm->isolate()),
753
+ 3,
754
+ 1);
755
+ return;
756
+ }
757
+
758
+ if (transition != NULL) {
759
+ // Update the map of the object; no write barrier updating is
760
+ // needed because the map is never in new space.
761
+ __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
762
+ Handle<Map>(transition));
763
+ }
764
+
765
+ // Adjust for the number of properties stored in the object. Even in the
766
+ // face of a transition we can use the old map here because the size of the
767
+ // object and the number of in-object properties is not going to change.
768
+ index -= object->map()->inobject_properties();
769
+
770
+ if (index < 0) {
771
+ // Set the property straight into the object.
772
+ int offset = object->map()->instance_size() + (index * kPointerSize);
773
+ __ movq(FieldOperand(receiver_reg, offset), rax);
774
+
775
+ // Update the write barrier for the array address.
776
+ // Pass the value being stored in the now unused name_reg.
777
+ __ movq(name_reg, rax);
778
+ __ RecordWrite(receiver_reg, offset, name_reg, scratch);
779
+ } else {
780
+ // Write to the properties array.
781
+ int offset = index * kPointerSize + FixedArray::kHeaderSize;
782
+ // Get the properties array (optimistically).
783
+ __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
784
+ __ movq(FieldOperand(scratch, offset), rax);
785
+
786
+ // Update the write barrier for the array address.
787
+ // Pass the value being stored in the now unused name_reg.
788
+ __ movq(name_reg, rax);
789
+ __ RecordWrite(scratch, offset, name_reg, receiver_reg);
790
+ }
791
+
792
+ // Return the value (register rax).
793
+ __ ret(0);
794
+ }
795
+
796
+
797
+ // Generate code to check that a global property cell is empty. Create
798
+ // the property cell at compilation time if no cell exists for the
799
+ // property.
800
+ MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
801
+ MacroAssembler* masm,
802
+ GlobalObject* global,
803
+ String* name,
804
+ Register scratch,
805
+ Label* miss) {
806
+ Object* probe;
807
+ { MaybeObject* maybe_probe = global->EnsurePropertyCell(name);
808
+ if (!maybe_probe->ToObject(&probe)) return maybe_probe;
809
+ }
810
+ JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
811
+ ASSERT(cell->value()->IsTheHole());
812
+ __ Move(scratch, Handle<Object>(cell));
813
+ __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
814
+ masm->isolate()->factory()->the_hole_value());
815
+ __ j(not_equal, miss);
816
+ return cell;
817
+ }
818
+
819
+
820
+ #undef __
821
+ #define __ ACCESS_MASM((masm()))
822
+
823
+
824
+ Register StubCompiler::CheckPrototypes(JSObject* object,
825
+ Register object_reg,
826
+ JSObject* holder,
827
+ Register holder_reg,
828
+ Register scratch1,
829
+ Register scratch2,
830
+ String* name,
831
+ int save_at_depth,
832
+ Label* miss) {
833
+ // Make sure there's no overlap between holder and object registers.
834
+ ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
835
+ ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
836
+ && !scratch2.is(scratch1));
837
+
838
+ // Keep track of the current object in register reg. On the first
839
+ // iteration, reg is an alias for object_reg, on later iterations,
840
+ // it is an alias for holder_reg.
841
+ Register reg = object_reg;
842
+ int depth = 0;
843
+
844
+ if (save_at_depth == depth) {
845
+ __ movq(Operand(rsp, kPointerSize), object_reg);
846
+ }
847
+
848
+ // Check the maps in the prototype chain.
849
+ // Traverse the prototype chain from the object and do map checks.
850
+ JSObject* current = object;
851
+ while (current != holder) {
852
+ depth++;
853
+
854
+ // Only global objects and objects that do not require access
855
+ // checks are allowed in stubs.
856
+ ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
857
+
858
+ JSObject* prototype = JSObject::cast(current->GetPrototype());
859
+ if (!current->HasFastProperties() &&
860
+ !current->IsJSGlobalObject() &&
861
+ !current->IsJSGlobalProxy()) {
862
+ if (!name->IsSymbol()) {
863
+ MaybeObject* lookup_result = heap()->LookupSymbol(name);
864
+ if (lookup_result->IsFailure()) {
865
+ set_failure(Failure::cast(lookup_result));
866
+ return reg;
867
+ } else {
868
+ name = String::cast(lookup_result->ToObjectUnchecked());
869
+ }
870
+ }
871
+ ASSERT(current->property_dictionary()->FindEntry(name) ==
872
+ StringDictionary::kNotFound);
873
+
874
+ MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(),
875
+ miss,
876
+ reg,
877
+ name,
878
+ scratch1,
879
+ scratch2);
880
+ if (negative_lookup->IsFailure()) {
881
+ set_failure(Failure::cast(negative_lookup));
882
+ return reg;
883
+ }
884
+
885
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
886
+ reg = holder_reg; // from now the object is in holder_reg
887
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
888
+ } else if (heap()->InNewSpace(prototype)) {
889
+ // Get the map of the current object.
890
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
891
+ __ Cmp(scratch1, Handle<Map>(current->map()));
892
+ // Branch on the result of the map check.
893
+ __ j(not_equal, miss);
894
+ // Check access rights to the global object. This has to happen
895
+ // after the map check so that we know that the object is
896
+ // actually a global object.
897
+ if (current->IsJSGlobalProxy()) {
898
+ __ CheckAccessGlobalProxy(reg, scratch1, miss);
899
+
900
+ // Restore scratch register to be the map of the object.
901
+ // We load the prototype from the map in the scratch register.
902
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
903
+ }
904
+ // The prototype is in new space; we cannot store a reference
905
+ // to it in the code. Load it from the map.
906
+ reg = holder_reg; // from now the object is in holder_reg
907
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
908
+
909
+ } else {
910
+ // Check the map of the current object.
911
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
912
+ Handle<Map>(current->map()));
913
+ // Branch on the result of the map check.
914
+ __ j(not_equal, miss);
915
+ // Check access rights to the global object. This has to happen
916
+ // after the map check so that we know that the object is
917
+ // actually a global object.
918
+ if (current->IsJSGlobalProxy()) {
919
+ __ CheckAccessGlobalProxy(reg, scratch1, miss);
920
+ }
921
+ // The prototype is in old space; load it directly.
922
+ reg = holder_reg; // from now the object is in holder_reg
923
+ __ Move(reg, Handle<JSObject>(prototype));
924
+ }
925
+
926
+ if (save_at_depth == depth) {
927
+ __ movq(Operand(rsp, kPointerSize), reg);
928
+ }
929
+
930
+ // Go to the next object in the prototype chain.
931
+ current = prototype;
932
+ }
933
+
934
+ // Check the holder map.
935
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map()));
936
+ __ j(not_equal, miss);
937
+
938
+ // Log the check depth.
939
+ LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
940
+
941
+ // Perform security check for access to the global object and return
942
+ // the holder register.
943
+ ASSERT(current == holder);
944
+ ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
945
+ if (current->IsJSGlobalProxy()) {
946
+ __ CheckAccessGlobalProxy(reg, scratch1, miss);
947
+ }
948
+
949
+ // If we've skipped any global objects, it's not enough to verify
950
+ // that their maps haven't changed. We also need to check that the
951
+ // property cell for the property is still empty.
952
+ current = object;
953
+ while (current != holder) {
954
+ if (current->IsGlobalObject()) {
955
+ MaybeObject* cell = GenerateCheckPropertyCell(masm(),
956
+ GlobalObject::cast(current),
957
+ name,
958
+ scratch1,
959
+ miss);
960
+ if (cell->IsFailure()) {
961
+ set_failure(Failure::cast(cell));
962
+ return reg;
963
+ }
964
+ }
965
+ current = JSObject::cast(current->GetPrototype());
966
+ }
967
+
968
+ // Return the register containing the holder.
969
+ return reg;
970
+ }
971
+
972
+
973
+ void StubCompiler::GenerateLoadField(JSObject* object,
974
+ JSObject* holder,
975
+ Register receiver,
976
+ Register scratch1,
977
+ Register scratch2,
978
+ Register scratch3,
979
+ int index,
980
+ String* name,
981
+ Label* miss) {
982
+ // Check that the receiver isn't a smi.
983
+ __ JumpIfSmi(receiver, miss);
984
+
985
+ // Check the prototype chain.
986
+ Register reg =
987
+ CheckPrototypes(object, receiver, holder,
988
+ scratch1, scratch2, scratch3, name, miss);
989
+
990
+ // Get the value from the properties.
991
+ GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
992
+ __ ret(0);
993
+ }
994
+
995
+
996
+ MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
997
+ JSObject* holder,
998
+ Register receiver,
999
+ Register name_reg,
1000
+ Register scratch1,
1001
+ Register scratch2,
1002
+ Register scratch3,
1003
+ AccessorInfo* callback,
1004
+ String* name,
1005
+ Label* miss) {
1006
+ // Check that the receiver isn't a smi.
1007
+ __ JumpIfSmi(receiver, miss);
1008
+
1009
+ // Check that the maps haven't changed.
1010
+ Register reg =
1011
+ CheckPrototypes(object, receiver, holder, scratch1,
1012
+ scratch2, scratch3, name, miss);
1013
+
1014
+ Handle<AccessorInfo> callback_handle(callback);
1015
+
1016
+ // Insert additional parameters into the stack frame above return address.
1017
+ ASSERT(!scratch2.is(reg));
1018
+ __ pop(scratch2); // Get return address to place it below.
1019
+
1020
+ __ push(receiver); // receiver
1021
+ __ push(reg); // holder
1022
+ if (heap()->InNewSpace(callback_handle->data())) {
1023
+ __ Move(scratch1, callback_handle);
1024
+ __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data
1025
+ } else {
1026
+ __ Push(Handle<Object>(callback_handle->data()));
1027
+ }
1028
+ __ push(name_reg); // name
1029
+ // Save a pointer to where we pushed the arguments pointer.
1030
+ // This will be passed as the const AccessorInfo& to the C++ callback.
1031
+
1032
+ #ifdef _WIN64
1033
+ // Win64 uses first register--rcx--for returned value.
1034
+ Register accessor_info_arg = r8;
1035
+ Register name_arg = rdx;
1036
+ #else
1037
+ Register accessor_info_arg = rsi;
1038
+ Register name_arg = rdi;
1039
+ #endif
1040
+
1041
+ ASSERT(!name_arg.is(scratch2));
1042
+ __ movq(name_arg, rsp);
1043
+ __ push(scratch2); // Restore return address.
1044
+
1045
+ // Do call through the api.
1046
+ Address getter_address = v8::ToCData<Address>(callback->getter());
1047
+ ApiFunction fun(getter_address);
1048
+
1049
+ // 3 elements array for v8::Agruments::values_ and handler for name.
1050
+ const int kStackSpace = 4;
1051
+
1052
+ // Allocate v8::AccessorInfo in non-GCed stack space.
1053
+ const int kArgStackSpace = 1;
1054
+
1055
+ __ PrepareCallApiFunction(kArgStackSpace);
1056
+ __ lea(rax, Operand(name_arg, 3 * kPointerSize));
1057
+
1058
+ // v8::AccessorInfo::args_.
1059
+ __ movq(StackSpaceOperand(0), rax);
1060
+
1061
+ // The context register (rsi) has been saved in PrepareCallApiFunction and
1062
+ // could be used to pass arguments.
1063
+ __ lea(accessor_info_arg, StackSpaceOperand(0));
1064
+
1065
+ // Emitting a stub call may try to allocate (if the code is not
1066
+ // already generated). Do not allow the assembler to perform a
1067
+ // garbage collection but instead return the allocation failure
1068
+ // object.
1069
+ return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
1070
+ }
1071
+
1072
+
1073
+ void StubCompiler::GenerateLoadConstant(JSObject* object,
1074
+ JSObject* holder,
1075
+ Register receiver,
1076
+ Register scratch1,
1077
+ Register scratch2,
1078
+ Register scratch3,
1079
+ Object* value,
1080
+ String* name,
1081
+ Label* miss) {
1082
+ // Check that the receiver isn't a smi.
1083
+ __ JumpIfSmi(receiver, miss);
1084
+
1085
+ // Check that the maps haven't changed.
1086
+ Register reg =
1087
+ CheckPrototypes(object, receiver, holder,
1088
+ scratch1, scratch2, scratch3, name, miss);
1089
+
1090
+ // Return the constant value.
1091
+ __ Move(rax, Handle<Object>(value));
1092
+ __ ret(0);
1093
+ }
1094
+
1095
+
1096
+ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
1097
+ JSObject* interceptor_holder,
1098
+ LookupResult* lookup,
1099
+ Register receiver,
1100
+ Register name_reg,
1101
+ Register scratch1,
1102
+ Register scratch2,
1103
+ Register scratch3,
1104
+ String* name,
1105
+ Label* miss) {
1106
+ ASSERT(interceptor_holder->HasNamedInterceptor());
1107
+ ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1108
+
1109
+ // Check that the receiver isn't a smi.
1110
+ __ JumpIfSmi(receiver, miss);
1111
+
1112
+ // So far the most popular follow ups for interceptor loads are FIELD
1113
+ // and CALLBACKS, so inline only them, other cases may be added
1114
+ // later.
1115
+ bool compile_followup_inline = false;
1116
+ if (lookup->IsProperty() && lookup->IsCacheable()) {
1117
+ if (lookup->type() == FIELD) {
1118
+ compile_followup_inline = true;
1119
+ } else if (lookup->type() == CALLBACKS &&
1120
+ lookup->GetCallbackObject()->IsAccessorInfo() &&
1121
+ AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
1122
+ compile_followup_inline = true;
1123
+ }
1124
+ }
1125
+
1126
+ if (compile_followup_inline) {
1127
+ // Compile the interceptor call, followed by inline code to load the
1128
+ // property from further up the prototype chain if the call fails.
1129
+ // Check that the maps haven't changed.
1130
+ Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1131
+ scratch1, scratch2, scratch3,
1132
+ name, miss);
1133
+ ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1134
+
1135
+ // Save necessary data before invoking an interceptor.
1136
+ // Requires a frame to make GC aware of pushed pointers.
1137
+ __ EnterInternalFrame();
1138
+
1139
+ if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1140
+ // CALLBACKS case needs a receiver to be passed into C++ callback.
1141
+ __ push(receiver);
1142
+ }
1143
+ __ push(holder_reg);
1144
+ __ push(name_reg);
1145
+
1146
+ // Invoke an interceptor. Note: map checks from receiver to
1147
+ // interceptor's holder has been compiled before (see a caller
1148
+ // of this method.)
1149
+ CompileCallLoadPropertyWithInterceptor(masm(),
1150
+ receiver,
1151
+ holder_reg,
1152
+ name_reg,
1153
+ interceptor_holder);
1154
+
1155
+ // Check if interceptor provided a value for property. If it's
1156
+ // the case, return immediately.
1157
+ Label interceptor_failed;
1158
+ __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
1159
+ __ j(equal, &interceptor_failed);
1160
+ __ LeaveInternalFrame();
1161
+ __ ret(0);
1162
+
1163
+ __ bind(&interceptor_failed);
1164
+ __ pop(name_reg);
1165
+ __ pop(holder_reg);
1166
+ if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1167
+ __ pop(receiver);
1168
+ }
1169
+
1170
+ __ LeaveInternalFrame();
1171
+
1172
+ // Check that the maps from interceptor's holder to lookup's holder
1173
+ // haven't changed. And load lookup's holder into |holder| register.
1174
+ if (interceptor_holder != lookup->holder()) {
1175
+ holder_reg = CheckPrototypes(interceptor_holder,
1176
+ holder_reg,
1177
+ lookup->holder(),
1178
+ scratch1,
1179
+ scratch2,
1180
+ scratch3,
1181
+ name,
1182
+ miss);
1183
+ }
1184
+
1185
+ if (lookup->type() == FIELD) {
1186
+ // We found FIELD property in prototype chain of interceptor's holder.
1187
+ // Retrieve a field from field's holder.
1188
+ GenerateFastPropertyLoad(masm(), rax, holder_reg,
1189
+ lookup->holder(), lookup->GetFieldIndex());
1190
+ __ ret(0);
1191
+ } else {
1192
+ // We found CALLBACKS property in prototype chain of interceptor's
1193
+ // holder.
1194
+ ASSERT(lookup->type() == CALLBACKS);
1195
+ ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
1196
+ AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1197
+ ASSERT(callback != NULL);
1198
+ ASSERT(callback->getter() != NULL);
1199
+
1200
+ // Tail call to runtime.
1201
+ // Important invariant in CALLBACKS case: the code above must be
1202
+ // structured to never clobber |receiver| register.
1203
+ __ pop(scratch2); // return address
1204
+ __ push(receiver);
1205
+ __ push(holder_reg);
1206
+ __ Move(holder_reg, Handle<AccessorInfo>(callback));
1207
+ __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
1208
+ __ push(holder_reg);
1209
+ __ push(name_reg);
1210
+ __ push(scratch2); // restore return address
1211
+
1212
+ ExternalReference ref =
1213
+ ExternalReference(IC_Utility(IC::kLoadCallbackProperty),
1214
+ isolate());
1215
+ __ TailCallExternalReference(ref, 5, 1);
1216
+ }
1217
+ } else { // !compile_followup_inline
1218
+ // Call the runtime system to load the interceptor.
1219
+ // Check that the maps haven't changed.
1220
+ Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1221
+ scratch1, scratch2, scratch3,
1222
+ name, miss);
1223
+ __ pop(scratch2); // save old return address
1224
+ PushInterceptorArguments(masm(), receiver, holder_reg,
1225
+ name_reg, interceptor_holder);
1226
+ __ push(scratch2); // restore old return address
1227
+
1228
+ ExternalReference ref = ExternalReference(
1229
+ IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
1230
+ __ TailCallExternalReference(ref, 5, 1);
1231
+ }
1232
+ }
1233
+
1234
+
1235
+ void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
1236
+ if (kind_ == Code::KEYED_CALL_IC) {
1237
+ __ Cmp(rcx, Handle<String>(name));
1238
+ __ j(not_equal, miss);
1239
+ }
1240
+ }
1241
+
1242
+
1243
+ void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
1244
+ JSObject* holder,
1245
+ String* name,
1246
+ Label* miss) {
1247
+ ASSERT(holder->IsGlobalObject());
1248
+
1249
+ // Get the number of arguments.
1250
+ const int argc = arguments().immediate();
1251
+
1252
+ // Get the receiver from the stack.
1253
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1254
+
1255
+ // If the object is the holder then we know that it's a global
1256
+ // object which can only happen for contextual calls. In this case,
1257
+ // the receiver cannot be a smi.
1258
+ if (object != holder) {
1259
+ __ JumpIfSmi(rdx, miss);
1260
+ }
1261
+
1262
+ // Check that the maps haven't changed.
1263
+ CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss);
1264
+ }
1265
+
1266
+
1267
+ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
1268
+ JSFunction* function,
1269
+ Label* miss) {
1270
+ // Get the value from the cell.
1271
+ __ Move(rdi, Handle<JSGlobalPropertyCell>(cell));
1272
+ __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
1273
+
1274
+ // Check that the cell contains the same function.
1275
+ if (heap()->InNewSpace(function)) {
1276
+ // We can't embed a pointer to a function in new space so we have
1277
+ // to verify that the shared function info is unchanged. This has
1278
+ // the nice side effect that multiple closures based on the same
1279
+ // function can all use this call IC. Before we load through the
1280
+ // function, we have to verify that it still is a function.
1281
+ __ JumpIfSmi(rdi, miss);
1282
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
1283
+ __ j(not_equal, miss);
1284
+
1285
+ // Check the shared function info. Make sure it hasn't changed.
1286
+ __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
1287
+ __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
1288
+ __ j(not_equal, miss);
1289
+ } else {
1290
+ __ Cmp(rdi, Handle<JSFunction>(function));
1291
+ __ j(not_equal, miss);
1292
+ }
1293
+ }
1294
+
1295
+
1296
+ MaybeObject* CallStubCompiler::GenerateMissBranch() {
1297
+ MaybeObject* maybe_obj =
1298
+ isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1299
+ kind_,
1300
+ extra_ic_state_);
1301
+ Object* obj;
1302
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1303
+ __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
1304
+ return obj;
1305
+ }
1306
+
1307
+
1308
+ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
1309
+ JSObject* holder,
1310
+ int index,
1311
+ String* name) {
1312
+ // ----------- S t a t e -------------
1313
+ // rcx : function name
1314
+ // rsp[0] : return address
1315
+ // rsp[8] : argument argc
1316
+ // rsp[16] : argument argc - 1
1317
+ // ...
1318
+ // rsp[argc * 8] : argument 1
1319
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
1320
+ // -----------------------------------
1321
+ Label miss;
1322
+
1323
+ GenerateNameCheck(name, &miss);
1324
+
1325
+ // Get the receiver from the stack.
1326
+ const int argc = arguments().immediate();
1327
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1328
+
1329
+ // Check that the receiver isn't a smi.
1330
+ __ JumpIfSmi(rdx, &miss);
1331
+
1332
+ // Do the right check and compute the holder register.
1333
+ Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
1334
+ name, &miss);
1335
+
1336
+ GenerateFastPropertyLoad(masm(), rdi, reg, holder, index);
1337
+
1338
+ // Check that the function really is a function.
1339
+ __ JumpIfSmi(rdi, &miss);
1340
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
1341
+ __ j(not_equal, &miss);
1342
+
1343
+ // Patch the receiver on the stack with the global proxy if
1344
+ // necessary.
1345
+ if (object->IsGlobalObject()) {
1346
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1347
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
1348
+ }
1349
+
1350
+ // Invoke the function.
1351
+ __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
1352
+
1353
+ // Handle call cache miss.
1354
+ __ bind(&miss);
1355
+ MaybeObject* maybe_result = GenerateMissBranch();
1356
+ if (maybe_result->IsFailure()) return maybe_result;
1357
+
1358
+ // Return the generated code.
1359
+ return GetCode(FIELD, name);
1360
+ }
1361
+
1362
+
1363
+ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
1364
+ JSObject* holder,
1365
+ JSGlobalPropertyCell* cell,
1366
+ JSFunction* function,
1367
+ String* name) {
1368
+ // ----------- S t a t e -------------
1369
+ // -- rcx : name
1370
+ // -- rsp[0] : return address
1371
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1372
+ // -- ...
1373
+ // -- rsp[(argc + 1) * 8] : receiver
1374
+ // -----------------------------------
1375
+
1376
+ // If object is not an array, bail out to regular call.
1377
+ if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
1378
+
1379
+ Label miss;
1380
+
1381
+ GenerateNameCheck(name, &miss);
1382
+
1383
+ // Get the receiver from the stack.
1384
+ const int argc = arguments().immediate();
1385
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1386
+
1387
+ // Check that the receiver isn't a smi.
1388
+ __ JumpIfSmi(rdx, &miss);
1389
+
1390
+ CheckPrototypes(JSObject::cast(object),
1391
+ rdx,
1392
+ holder,
1393
+ rbx,
1394
+ rax,
1395
+ rdi,
1396
+ name,
1397
+ &miss);
1398
+
1399
+ if (argc == 0) {
1400
+ // Noop, return the length.
1401
+ __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1402
+ __ ret((argc + 1) * kPointerSize);
1403
+ } else {
1404
+ Label call_builtin;
1405
+
1406
+ // Get the elements array of the object.
1407
+ __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1408
+
1409
+ // Check that the elements are in fast mode and writable.
1410
+ __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
1411
+ factory()->fixed_array_map());
1412
+ __ j(not_equal, &call_builtin);
1413
+
1414
+ if (argc == 1) { // Otherwise fall through to call builtin.
1415
+ Label exit, with_write_barrier, attempt_to_grow_elements;
1416
+
1417
+ // Get the array's length into rax and calculate new length.
1418
+ __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1419
+ STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1420
+ __ addl(rax, Immediate(argc));
1421
+
1422
+ // Get the element's length into rcx.
1423
+ __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
1424
+
1425
+ // Check if we could survive without allocation.
1426
+ __ cmpl(rax, rcx);
1427
+ __ j(greater, &attempt_to_grow_elements);
1428
+
1429
+ // Save new length.
1430
+ __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1431
+
1432
+ // Push the element.
1433
+ __ movq(rcx, Operand(rsp, argc * kPointerSize));
1434
+ __ lea(rdx, FieldOperand(rbx,
1435
+ rax, times_pointer_size,
1436
+ FixedArray::kHeaderSize - argc * kPointerSize));
1437
+ __ movq(Operand(rdx, 0), rcx);
1438
+
1439
+ // Check if value is a smi.
1440
+ __ Integer32ToSmi(rax, rax); // Return new length as smi.
1441
+
1442
+ __ JumpIfNotSmi(rcx, &with_write_barrier);
1443
+
1444
+ __ bind(&exit);
1445
+ __ ret((argc + 1) * kPointerSize);
1446
+
1447
+ __ bind(&with_write_barrier);
1448
+
1449
+ __ InNewSpace(rbx, rcx, equal, &exit);
1450
+
1451
+ __ RecordWriteHelper(rbx, rdx, rcx);
1452
+
1453
+ __ ret((argc + 1) * kPointerSize);
1454
+
1455
+ __ bind(&attempt_to_grow_elements);
1456
+ if (!FLAG_inline_new) {
1457
+ __ jmp(&call_builtin);
1458
+ }
1459
+
1460
+ ExternalReference new_space_allocation_top =
1461
+ ExternalReference::new_space_allocation_top_address(isolate());
1462
+ ExternalReference new_space_allocation_limit =
1463
+ ExternalReference::new_space_allocation_limit_address(isolate());
1464
+
1465
+ const int kAllocationDelta = 4;
1466
+ // Load top.
1467
+ __ Load(rcx, new_space_allocation_top);
1468
+
1469
+ // Check if it's the end of elements.
1470
+ __ lea(rdx, FieldOperand(rbx,
1471
+ rax, times_pointer_size,
1472
+ FixedArray::kHeaderSize - argc * kPointerSize));
1473
+ __ cmpq(rdx, rcx);
1474
+ __ j(not_equal, &call_builtin);
1475
+ __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
1476
+ Operand limit_operand =
1477
+ masm()->ExternalOperand(new_space_allocation_limit);
1478
+ __ cmpq(rcx, limit_operand);
1479
+ __ j(above, &call_builtin);
1480
+
1481
+ // We fit and could grow elements.
1482
+ __ Store(new_space_allocation_top, rcx);
1483
+ __ movq(rcx, Operand(rsp, argc * kPointerSize));
1484
+
1485
+ // Push the argument...
1486
+ __ movq(Operand(rdx, 0), rcx);
1487
+ // ... and fill the rest with holes.
1488
+ __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
1489
+ for (int i = 1; i < kAllocationDelta; i++) {
1490
+ __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
1491
+ }
1492
+
1493
+ // Restore receiver to rdx as finish sequence assumes it's here.
1494
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1495
+
1496
+ // Increment element's and array's sizes.
1497
+ __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset),
1498
+ Smi::FromInt(kAllocationDelta));
1499
+
1500
+ // Make new length a smi before returning it.
1501
+ __ Integer32ToSmi(rax, rax);
1502
+ __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1503
+
1504
+ // Elements are in new space, so write barrier is not required.
1505
+ __ ret((argc + 1) * kPointerSize);
1506
+ }
1507
+
1508
+ __ bind(&call_builtin);
1509
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
1510
+ isolate()),
1511
+ argc + 1,
1512
+ 1);
1513
+ }
1514
+
1515
+ __ bind(&miss);
1516
+ MaybeObject* maybe_result = GenerateMissBranch();
1517
+ if (maybe_result->IsFailure()) return maybe_result;
1518
+
1519
+ // Return the generated code.
1520
+ return GetCode(function);
1521
+ }
1522
+
1523
+
1524
+ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
1525
+ JSObject* holder,
1526
+ JSGlobalPropertyCell* cell,
1527
+ JSFunction* function,
1528
+ String* name) {
1529
+ // ----------- S t a t e -------------
1530
+ // -- rcx : name
1531
+ // -- rsp[0] : return address
1532
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1533
+ // -- ...
1534
+ // -- rsp[(argc + 1) * 8] : receiver
1535
+ // -----------------------------------
1536
+
1537
+ // If object is not an array, bail out to regular call.
1538
+ if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
1539
+
1540
+ Label miss, return_undefined, call_builtin;
1541
+
1542
+ GenerateNameCheck(name, &miss);
1543
+
1544
+ // Get the receiver from the stack.
1545
+ const int argc = arguments().immediate();
1546
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1547
+
1548
+ // Check that the receiver isn't a smi.
1549
+ __ JumpIfSmi(rdx, &miss);
1550
+
1551
+ CheckPrototypes(JSObject::cast(object), rdx,
1552
+ holder, rbx,
1553
+ rax, rdi, name, &miss);
1554
+
1555
+ // Get the elements array of the object.
1556
+ __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1557
+
1558
+ // Check that the elements are in fast mode and writable.
1559
+ __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1560
+ Heap::kFixedArrayMapRootIndex);
1561
+ __ j(not_equal, &call_builtin);
1562
+
1563
+ // Get the array's length into rcx and calculate new length.
1564
+ __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
1565
+ __ subl(rcx, Immediate(1));
1566
+ __ j(negative, &return_undefined);
1567
+
1568
+ // Get the last element.
1569
+ __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
1570
+ __ movq(rax, FieldOperand(rbx,
1571
+ rcx, times_pointer_size,
1572
+ FixedArray::kHeaderSize));
1573
+ // Check if element is already the hole.
1574
+ __ cmpq(rax, r9);
1575
+ // If so, call slow-case to also check prototypes for value.
1576
+ __ j(equal, &call_builtin);
1577
+
1578
+ // Set the array's length.
1579
+ __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
1580
+
1581
+ // Fill with the hole and return original value.
1582
+ __ movq(FieldOperand(rbx,
1583
+ rcx, times_pointer_size,
1584
+ FixedArray::kHeaderSize),
1585
+ r9);
1586
+ __ ret((argc + 1) * kPointerSize);
1587
+
1588
+ __ bind(&return_undefined);
1589
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1590
+ __ ret((argc + 1) * kPointerSize);
1591
+
1592
+ __ bind(&call_builtin);
1593
+ __ TailCallExternalReference(
1594
+ ExternalReference(Builtins::c_ArrayPop, isolate()),
1595
+ argc + 1,
1596
+ 1);
1597
+
1598
+ __ bind(&miss);
1599
+ MaybeObject* maybe_result = GenerateMissBranch();
1600
+ if (maybe_result->IsFailure()) return maybe_result;
1601
+
1602
+ // Return the generated code.
1603
+ return GetCode(function);
1604
+ }
1605
+
1606
+
1607
+ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
1608
+ Object* object,
1609
+ JSObject* holder,
1610
+ JSGlobalPropertyCell* cell,
1611
+ JSFunction* function,
1612
+ String* name) {
1613
+ // ----------- S t a t e -------------
1614
+ // -- rcx : function name
1615
+ // -- rsp[0] : return address
1616
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1617
+ // -- ...
1618
+ // -- rsp[(argc + 1) * 8] : receiver
1619
+ // -----------------------------------
1620
+
1621
+ // If object is not a string, bail out to regular call.
1622
+ if (!object->IsString() || cell != NULL) return heap()->undefined_value();
1623
+
1624
+ const int argc = arguments().immediate();
1625
+
1626
+ Label miss;
1627
+ Label name_miss;
1628
+ Label index_out_of_range;
1629
+ Label* index_out_of_range_label = &index_out_of_range;
1630
+
1631
+ if (kind_ == Code::CALL_IC &&
1632
+ (CallICBase::StringStubState::decode(extra_ic_state_) ==
1633
+ DEFAULT_STRING_STUB)) {
1634
+ index_out_of_range_label = &miss;
1635
+ }
1636
+
1637
+ GenerateNameCheck(name, &name_miss);
1638
+
1639
+ // Check that the maps starting from the prototype haven't changed.
1640
+ GenerateDirectLoadGlobalFunctionPrototype(masm(),
1641
+ Context::STRING_FUNCTION_INDEX,
1642
+ rax,
1643
+ &miss);
1644
+ ASSERT(object != holder);
1645
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
1646
+ rbx, rdx, rdi, name, &miss);
1647
+
1648
+ Register receiver = rbx;
1649
+ Register index = rdi;
1650
+ Register scratch = rdx;
1651
+ Register result = rax;
1652
+ __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
1653
+ if (argc > 0) {
1654
+ __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
1655
+ } else {
1656
+ __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1657
+ }
1658
+
1659
+ StringCharCodeAtGenerator char_code_at_generator(receiver,
1660
+ index,
1661
+ scratch,
1662
+ result,
1663
+ &miss, // When not a string.
1664
+ &miss, // When not a number.
1665
+ index_out_of_range_label,
1666
+ STRING_INDEX_IS_NUMBER);
1667
+ char_code_at_generator.GenerateFast(masm());
1668
+ __ ret((argc + 1) * kPointerSize);
1669
+
1670
+ StubRuntimeCallHelper call_helper;
1671
+ char_code_at_generator.GenerateSlow(masm(), call_helper);
1672
+
1673
+ if (index_out_of_range.is_linked()) {
1674
+ __ bind(&index_out_of_range);
1675
+ __ LoadRoot(rax, Heap::kNanValueRootIndex);
1676
+ __ ret((argc + 1) * kPointerSize);
1677
+ }
1678
+
1679
+ __ bind(&miss);
1680
+ // Restore function name in rcx.
1681
+ __ Move(rcx, Handle<String>(name));
1682
+ __ bind(&name_miss);
1683
+ MaybeObject* maybe_result = GenerateMissBranch();
1684
+ if (maybe_result->IsFailure()) return maybe_result;
1685
+
1686
+ // Return the generated code.
1687
+ return GetCode(function);
1688
+ }
1689
+
1690
+
1691
+ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
1692
+ Object* object,
1693
+ JSObject* holder,
1694
+ JSGlobalPropertyCell* cell,
1695
+ JSFunction* function,
1696
+ String* name) {
1697
+ // ----------- S t a t e -------------
1698
+ // -- rcx : function name
1699
+ // -- rsp[0] : return address
1700
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1701
+ // -- ...
1702
+ // -- rsp[(argc + 1) * 8] : receiver
1703
+ // -----------------------------------
1704
+
1705
+ // If object is not a string, bail out to regular call.
1706
+ if (!object->IsString() || cell != NULL) return heap()->undefined_value();
1707
+
1708
+ const int argc = arguments().immediate();
1709
+
1710
+ Label miss;
1711
+ Label name_miss;
1712
+ Label index_out_of_range;
1713
+ Label* index_out_of_range_label = &index_out_of_range;
1714
+
1715
+ if (kind_ == Code::CALL_IC &&
1716
+ (CallICBase::StringStubState::decode(extra_ic_state_) ==
1717
+ DEFAULT_STRING_STUB)) {
1718
+ index_out_of_range_label = &miss;
1719
+ }
1720
+
1721
+ GenerateNameCheck(name, &name_miss);
1722
+
1723
+ // Check that the maps starting from the prototype haven't changed.
1724
+ GenerateDirectLoadGlobalFunctionPrototype(masm(),
1725
+ Context::STRING_FUNCTION_INDEX,
1726
+ rax,
1727
+ &miss);
1728
+ ASSERT(object != holder);
1729
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
1730
+ rbx, rdx, rdi, name, &miss);
1731
+
1732
+ Register receiver = rax;
1733
+ Register index = rdi;
1734
+ Register scratch1 = rbx;
1735
+ Register scratch2 = rdx;
1736
+ Register result = rax;
1737
+ __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
1738
+ if (argc > 0) {
1739
+ __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
1740
+ } else {
1741
+ __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1742
+ }
1743
+
1744
+ StringCharAtGenerator char_at_generator(receiver,
1745
+ index,
1746
+ scratch1,
1747
+ scratch2,
1748
+ result,
1749
+ &miss, // When not a string.
1750
+ &miss, // When not a number.
1751
+ index_out_of_range_label,
1752
+ STRING_INDEX_IS_NUMBER);
1753
+ char_at_generator.GenerateFast(masm());
1754
+ __ ret((argc + 1) * kPointerSize);
1755
+
1756
+ StubRuntimeCallHelper call_helper;
1757
+ char_at_generator.GenerateSlow(masm(), call_helper);
1758
+
1759
+ if (index_out_of_range.is_linked()) {
1760
+ __ bind(&index_out_of_range);
1761
+ __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
1762
+ __ ret((argc + 1) * kPointerSize);
1763
+ }
1764
+
1765
+ __ bind(&miss);
1766
+ // Restore function name in rcx.
1767
+ __ Move(rcx, Handle<String>(name));
1768
+ __ bind(&name_miss);
1769
+ MaybeObject* maybe_result = GenerateMissBranch();
1770
+ if (maybe_result->IsFailure()) return maybe_result;
1771
+
1772
+ // Return the generated code.
1773
+ return GetCode(function);
1774
+ }
1775
+
1776
+
1777
+ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
1778
+ Object* object,
1779
+ JSObject* holder,
1780
+ JSGlobalPropertyCell* cell,
1781
+ JSFunction* function,
1782
+ String* name) {
1783
+ // ----------- S t a t e -------------
1784
+ // -- rcx : function name
1785
+ // -- rsp[0] : return address
1786
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1787
+ // -- ...
1788
+ // -- rsp[(argc + 1) * 8] : receiver
1789
+ // -----------------------------------
1790
+
1791
+ const int argc = arguments().immediate();
1792
+
1793
+ // If the object is not a JSObject or we got an unexpected number of
1794
+ // arguments, bail out to the regular call.
1795
+ if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
1796
+
1797
+ Label miss;
1798
+ GenerateNameCheck(name, &miss);
1799
+
1800
+ if (cell == NULL) {
1801
+ __ movq(rdx, Operand(rsp, 2 * kPointerSize));
1802
+
1803
+ __ JumpIfSmi(rdx, &miss);
1804
+
1805
+ CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name,
1806
+ &miss);
1807
+ } else {
1808
+ ASSERT(cell->value() == function);
1809
+ GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
1810
+ GenerateLoadFunctionFromCell(cell, function, &miss);
1811
+ }
1812
+
1813
+ // Load the char code argument.
1814
+ Register code = rbx;
1815
+ __ movq(code, Operand(rsp, 1 * kPointerSize));
1816
+
1817
+ // Check the code is a smi.
1818
+ Label slow;
1819
+ __ JumpIfNotSmi(code, &slow);
1820
+
1821
+ // Convert the smi code to uint16.
1822
+ __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
1823
+
1824
+ StringCharFromCodeGenerator char_from_code_generator(code, rax);
1825
+ char_from_code_generator.GenerateFast(masm());
1826
+ __ ret(2 * kPointerSize);
1827
+
1828
+ StubRuntimeCallHelper call_helper;
1829
+ char_from_code_generator.GenerateSlow(masm(), call_helper);
1830
+
1831
+ // Tail call the full function. We do not have to patch the receiver
1832
+ // because the function makes no use of it.
1833
+ __ bind(&slow);
1834
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
1835
+
1836
+ __ bind(&miss);
1837
+ // rcx: function name.
1838
+ MaybeObject* maybe_result = GenerateMissBranch();
1839
+ if (maybe_result->IsFailure()) return maybe_result;
1840
+
1841
+ // Return the generated code.
1842
+ return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
1843
+ }
1844
+
1845
+
1846
+ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
1847
+ JSObject* holder,
1848
+ JSGlobalPropertyCell* cell,
1849
+ JSFunction* function,
1850
+ String* name) {
1851
+ // TODO(872): implement this.
1852
+ return heap()->undefined_value();
1853
+ }
1854
+
1855
+
1856
+ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
1857
+ JSObject* holder,
1858
+ JSGlobalPropertyCell* cell,
1859
+ JSFunction* function,
1860
+ String* name) {
1861
+ // ----------- S t a t e -------------
1862
+ // -- rcx : function name
1863
+ // -- rsp[0] : return address
1864
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1865
+ // -- ...
1866
+ // -- rsp[(argc + 1) * 8] : receiver
1867
+ // -----------------------------------
1868
+
1869
+ const int argc = arguments().immediate();
1870
+
1871
+ // If the object is not a JSObject or we got an unexpected number of
1872
+ // arguments, bail out to the regular call.
1873
+ if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
1874
+
1875
+ Label miss;
1876
+ GenerateNameCheck(name, &miss);
1877
+
1878
+ if (cell == NULL) {
1879
+ __ movq(rdx, Operand(rsp, 2 * kPointerSize));
1880
+
1881
+ __ JumpIfSmi(rdx, &miss);
1882
+
1883
+ CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name,
1884
+ &miss);
1885
+ } else {
1886
+ ASSERT(cell->value() == function);
1887
+ GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
1888
+ GenerateLoadFunctionFromCell(cell, function, &miss);
1889
+ }
1890
+
1891
+ // Load the (only) argument into rax.
1892
+ __ movq(rax, Operand(rsp, 1 * kPointerSize));
1893
+
1894
+ // Check if the argument is a smi.
1895
+ Label not_smi;
1896
+ STATIC_ASSERT(kSmiTag == 0);
1897
+ __ JumpIfNotSmi(rax, &not_smi);
1898
+ __ SmiToInteger32(rax, rax);
1899
+
1900
+ // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
1901
+ // otherwise.
1902
+ __ movl(rbx, rax);
1903
+ __ sarl(rbx, Immediate(kBitsPerInt - 1));
1904
+
1905
+ // Do bitwise not or do nothing depending on ebx.
1906
+ __ xorl(rax, rbx);
1907
+
1908
+ // Add 1 or do nothing depending on ebx.
1909
+ __ subl(rax, rbx);
1910
+
1911
+ // If the result is still negative, go to the slow case.
1912
+ // This only happens for the most negative smi.
1913
+ Label slow;
1914
+ __ j(negative, &slow);
1915
+
1916
+ // Smi case done.
1917
+ __ Integer32ToSmi(rax, rax);
1918
+ __ ret(2 * kPointerSize);
1919
+
1920
+ // Check if the argument is a heap number and load its value.
1921
+ __ bind(&not_smi);
1922
+ __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
1923
+ __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
1924
+
1925
+ // Check the sign of the argument. If the argument is positive,
1926
+ // just return it.
1927
+ Label negative_sign;
1928
+ const int sign_mask_shift =
1929
+ (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
1930
+ __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift,
1931
+ RelocInfo::NONE);
1932
+ __ testq(rbx, rdi);
1933
+ __ j(not_zero, &negative_sign);
1934
+ __ ret(2 * kPointerSize);
1935
+
1936
+ // If the argument is negative, clear the sign, and return a new
1937
+ // number. We still have the sign mask in rdi.
1938
+ __ bind(&negative_sign);
1939
+ __ xor_(rbx, rdi);
1940
+ __ AllocateHeapNumber(rax, rdx, &slow);
1941
+ __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
1942
+ __ ret(2 * kPointerSize);
1943
+
1944
+ // Tail call the full function. We do not have to patch the receiver
1945
+ // because the function makes no use of it.
1946
+ __ bind(&slow);
1947
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
1948
+
1949
+ __ bind(&miss);
1950
+ // rcx: function name.
1951
+ MaybeObject* maybe_result = GenerateMissBranch();
1952
+ if (maybe_result->IsFailure()) return maybe_result;
1953
+
1954
+ // Return the generated code.
1955
+ return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
1956
+ }
1957
+
1958
+
1959
+ MaybeObject* CallStubCompiler::CompileFastApiCall(
1960
+ const CallOptimization& optimization,
1961
+ Object* object,
1962
+ JSObject* holder,
1963
+ JSGlobalPropertyCell* cell,
1964
+ JSFunction* function,
1965
+ String* name) {
1966
+ ASSERT(optimization.is_simple_api_call());
1967
+ // Bail out if object is a global object as we don't want to
1968
+ // repatch it to global receiver.
1969
+ if (object->IsGlobalObject()) return heap()->undefined_value();
1970
+ if (cell != NULL) return heap()->undefined_value();
1971
+ if (!object->IsJSObject()) return heap()->undefined_value();
1972
+ int depth = optimization.GetPrototypeDepthOfExpectedType(
1973
+ JSObject::cast(object), holder);
1974
+ if (depth == kInvalidProtoDepth) return heap()->undefined_value();
1975
+
1976
+ Label miss, miss_before_stack_reserved;
1977
+
1978
+ GenerateNameCheck(name, &miss_before_stack_reserved);
1979
+
1980
+ // Get the receiver from the stack.
1981
+ const int argc = arguments().immediate();
1982
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1983
+
1984
+ // Check that the receiver isn't a smi.
1985
+ __ JumpIfSmi(rdx, &miss_before_stack_reserved);
1986
+
1987
+ Counters* counters = isolate()->counters();
1988
+ __ IncrementCounter(counters->call_const(), 1);
1989
+ __ IncrementCounter(counters->call_const_fast_api(), 1);
1990
+
1991
+ // Allocate space for v8::Arguments implicit values. Must be initialized
1992
+ // before calling any runtime function.
1993
+ __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1994
+
1995
+ // Check that the maps haven't changed and find a Holder as a side effect.
1996
+ CheckPrototypes(JSObject::cast(object), rdx, holder,
1997
+ rbx, rax, rdi, name, depth, &miss);
1998
+
1999
+ // Move the return address on top of the stack.
2000
+ __ movq(rax, Operand(rsp, 3 * kPointerSize));
2001
+ __ movq(Operand(rsp, 0 * kPointerSize), rax);
2002
+
2003
+ MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
2004
+ if (result->IsFailure()) return result;
2005
+
2006
+ __ bind(&miss);
2007
+ __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
2008
+
2009
+ __ bind(&miss_before_stack_reserved);
2010
+ MaybeObject* maybe_result = GenerateMissBranch();
2011
+ if (maybe_result->IsFailure()) return maybe_result;
2012
+
2013
+ // Return the generated code.
2014
+ return GetCode(function);
2015
+ }
2016
+
2017
+
2018
+ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
2019
+ JSObject* holder,
2020
+ JSFunction* function,
2021
+ String* name,
2022
+ CheckType check) {
2023
+ // ----------- S t a t e -------------
2024
+ // rcx : function name
2025
+ // rsp[0] : return address
2026
+ // rsp[8] : argument argc
2027
+ // rsp[16] : argument argc - 1
2028
+ // ...
2029
+ // rsp[argc * 8] : argument 1
2030
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
2031
+ // -----------------------------------
2032
+
2033
+ if (HasCustomCallGenerator(function)) {
2034
+ MaybeObject* maybe_result = CompileCustomCall(
2035
+ object, holder, NULL, function, name);
2036
+ Object* result;
2037
+ if (!maybe_result->ToObject(&result)) return maybe_result;
2038
+ // undefined means bail out to regular compiler.
2039
+ if (!result->IsUndefined()) return result;
2040
+ }
2041
+
2042
+ Label miss;
2043
+
2044
+ GenerateNameCheck(name, &miss);
2045
+
2046
+ // Get the receiver from the stack.
2047
+ const int argc = arguments().immediate();
2048
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2049
+
2050
+ // Check that the receiver isn't a smi.
2051
+ if (check != NUMBER_CHECK) {
2052
+ __ JumpIfSmi(rdx, &miss);
2053
+ }
2054
+
2055
+ // Make sure that it's okay not to patch the on stack receiver
2056
+ // unless we're doing a receiver map check.
2057
+ ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2058
+
2059
+ Counters* counters = isolate()->counters();
2060
+ SharedFunctionInfo* function_info = function->shared();
2061
+ switch (check) {
2062
+ case RECEIVER_MAP_CHECK:
2063
+ __ IncrementCounter(counters->call_const(), 1);
2064
+
2065
+ // Check that the maps haven't changed.
2066
+ CheckPrototypes(JSObject::cast(object), rdx, holder,
2067
+ rbx, rax, rdi, name, &miss);
2068
+
2069
+ // Patch the receiver on the stack with the global proxy if
2070
+ // necessary.
2071
+ if (object->IsGlobalObject()) {
2072
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2073
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
2074
+ }
2075
+ break;
2076
+
2077
+ case STRING_CHECK:
2078
+ if (!function->IsBuiltin() && !function_info->strict_mode()) {
2079
+ // Calling non-strict non-builtins with a value as the receiver
2080
+ // requires boxing.
2081
+ __ jmp(&miss);
2082
+ } else {
2083
+ // Check that the object is a two-byte string or a symbol.
2084
+ __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
2085
+ __ j(above_equal, &miss);
2086
+ // Check that the maps starting from the prototype haven't changed.
2087
+ GenerateDirectLoadGlobalFunctionPrototype(
2088
+ masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
2089
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
2090
+ rbx, rdx, rdi, name, &miss);
2091
+ }
2092
+ break;
2093
+
2094
+ case NUMBER_CHECK: {
2095
+ if (!function->IsBuiltin() && !function_info->strict_mode()) {
2096
+ // Calling non-strict non-builtins with a value as the receiver
2097
+ // requires boxing.
2098
+ __ jmp(&miss);
2099
+ } else {
2100
+ Label fast;
2101
+ // Check that the object is a smi or a heap number.
2102
+ __ JumpIfSmi(rdx, &fast);
2103
+ __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
2104
+ __ j(not_equal, &miss);
2105
+ __ bind(&fast);
2106
+ // Check that the maps starting from the prototype haven't changed.
2107
+ GenerateDirectLoadGlobalFunctionPrototype(
2108
+ masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
2109
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
2110
+ rbx, rdx, rdi, name, &miss);
2111
+ }
2112
+ break;
2113
+ }
2114
+
2115
+ case BOOLEAN_CHECK: {
2116
+ if (!function->IsBuiltin() && !function_info->strict_mode()) {
2117
+ // Calling non-strict non-builtins with a value as the receiver
2118
+ // requires boxing.
2119
+ __ jmp(&miss);
2120
+ } else {
2121
+ Label fast;
2122
+ // Check that the object is a boolean.
2123
+ __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
2124
+ __ j(equal, &fast);
2125
+ __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
2126
+ __ j(not_equal, &miss);
2127
+ __ bind(&fast);
2128
+ // Check that the maps starting from the prototype haven't changed.
2129
+ GenerateDirectLoadGlobalFunctionPrototype(
2130
+ masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
2131
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
2132
+ rbx, rdx, rdi, name, &miss);
2133
+ }
2134
+ break;
2135
+ }
2136
+
2137
+ default:
2138
+ UNREACHABLE();
2139
+ }
2140
+
2141
+ __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
2142
+
2143
+ // Handle call cache miss.
2144
+ __ bind(&miss);
2145
+ MaybeObject* maybe_result = GenerateMissBranch();
2146
+ if (maybe_result->IsFailure()) return maybe_result;
2147
+
2148
+ // Return the generated code.
2149
+ return GetCode(function);
2150
+ }
2151
+
2152
+
2153
+ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
2154
+ JSObject* holder,
2155
+ String* name) {
2156
+ // ----------- S t a t e -------------
2157
+ // rcx : function name
2158
+ // rsp[0] : return address
2159
+ // rsp[8] : argument argc
2160
+ // rsp[16] : argument argc - 1
2161
+ // ...
2162
+ // rsp[argc * 8] : argument 1
2163
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
2164
+ // -----------------------------------
2165
+ Label miss;
2166
+
2167
+ GenerateNameCheck(name, &miss);
2168
+
2169
+ // Get the number of arguments.
2170
+ const int argc = arguments().immediate();
2171
+
2172
+ LookupResult lookup;
2173
+ LookupPostInterceptor(holder, name, &lookup);
2174
+
2175
+ // Get the receiver from the stack.
2176
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2177
+
2178
+ CallInterceptorCompiler compiler(this, arguments(), rcx);
2179
+ MaybeObject* result = compiler.Compile(masm(),
2180
+ object,
2181
+ holder,
2182
+ name,
2183
+ &lookup,
2184
+ rdx,
2185
+ rbx,
2186
+ rdi,
2187
+ rax,
2188
+ &miss);
2189
+ if (result->IsFailure()) return result;
2190
+
2191
+ // Restore receiver.
2192
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2193
+
2194
+ // Check that the function really is a function.
2195
+ __ JumpIfSmi(rax, &miss);
2196
+ __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2197
+ __ j(not_equal, &miss);
2198
+
2199
+ // Patch the receiver on the stack with the global proxy if
2200
+ // necessary.
2201
+ if (object->IsGlobalObject()) {
2202
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2203
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
2204
+ }
2205
+
2206
+ // Invoke the function.
2207
+ __ movq(rdi, rax);
2208
+ __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
2209
+
2210
+ // Handle load cache miss.
2211
+ __ bind(&miss);
2212
+ MaybeObject* maybe_result = GenerateMissBranch();
2213
+ if (maybe_result->IsFailure()) return maybe_result;
2214
+
2215
+ // Return the generated code.
2216
+ return GetCode(INTERCEPTOR, name);
2217
+ }
2218
+
2219
+
2220
+ MaybeObject* CallStubCompiler::CompileCallGlobal(
2221
+ JSObject* object,
2222
+ GlobalObject* holder,
2223
+ JSGlobalPropertyCell* cell,
2224
+ JSFunction* function,
2225
+ String* name,
2226
+ Code::ExtraICState extra_ic_state) {
2227
+ // ----------- S t a t e -------------
2228
+ // rcx : function name
2229
+ // rsp[0] : return address
2230
+ // rsp[8] : argument argc
2231
+ // rsp[16] : argument argc - 1
2232
+ // ...
2233
+ // rsp[argc * 8] : argument 1
2234
+ // rsp[(argc + 1) * 8] : argument 0 = receiver
2235
+ // -----------------------------------
2236
+
2237
+ if (HasCustomCallGenerator(function)) {
2238
+ MaybeObject* maybe_result = CompileCustomCall(
2239
+ object, holder, cell, function, name);
2240
+ Object* result;
2241
+ if (!maybe_result->ToObject(&result)) return maybe_result;
2242
+ // undefined means bail out to regular compiler.
2243
+ if (!result->IsUndefined()) return result;
2244
+ }
2245
+
2246
+ Label miss;
2247
+
2248
+ GenerateNameCheck(name, &miss);
2249
+
2250
+ // Get the number of arguments.
2251
+ const int argc = arguments().immediate();
2252
+
2253
+ GenerateGlobalReceiverCheck(object, holder, name, &miss);
2254
+
2255
+ GenerateLoadFunctionFromCell(cell, function, &miss);
2256
+
2257
+ // Patch the receiver on the stack with the global proxy.
2258
+ if (object->IsGlobalObject()) {
2259
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2260
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
2261
+ }
2262
+
2263
+ // Setup the context (function already in rdi).
2264
+ __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2265
+
2266
+ // Jump to the cached code (tail call).
2267
+ Counters* counters = isolate()->counters();
2268
+ __ IncrementCounter(counters->call_global_inline(), 1);
2269
+ ASSERT(function->is_compiled());
2270
+ ParameterCount expected(function->shared()->formal_parameter_count());
2271
+ CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
2272
+ ? CALL_AS_FUNCTION
2273
+ : CALL_AS_METHOD;
2274
+ if (V8::UseCrankshaft()) {
2275
+ // TODO(kasperl): For now, we always call indirectly through the
2276
+ // code field in the function to allow recompilation to take effect
2277
+ // without changing any of the call sites.
2278
+ __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2279
+ __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
2280
+ NullCallWrapper(), call_kind);
2281
+ } else {
2282
+ Handle<Code> code(function->code());
2283
+ __ InvokeCode(code, expected, arguments(),
2284
+ RelocInfo::CODE_TARGET, JUMP_FUNCTION,
2285
+ NullCallWrapper(), call_kind);
2286
+ }
2287
+ // Handle call cache miss.
2288
+ __ bind(&miss);
2289
+ __ IncrementCounter(counters->call_global_inline_miss(), 1);
2290
+ MaybeObject* maybe_result = GenerateMissBranch();
2291
+ if (maybe_result->IsFailure()) return maybe_result;
2292
+
2293
+ // Return the generated code.
2294
+ return GetCode(NORMAL, name);
2295
+ }
2296
+
2297
+
2298
+ MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
2299
+ int index,
2300
+ Map* transition,
2301
+ String* name) {
2302
+ // ----------- S t a t e -------------
2303
+ // -- rax : value
2304
+ // -- rcx : name
2305
+ // -- rdx : receiver
2306
+ // -- rsp[0] : return address
2307
+ // -----------------------------------
2308
+ Label miss;
2309
+
2310
+ // Generate store field code. Preserves receiver and name on jump to miss.
2311
+ GenerateStoreField(masm(),
2312
+ object,
2313
+ index,
2314
+ transition,
2315
+ rdx, rcx, rbx,
2316
+ &miss);
2317
+
2318
+ // Handle store cache miss.
2319
+ __ bind(&miss);
2320
+ Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2321
+ __ Jump(ic, RelocInfo::CODE_TARGET);
2322
+
2323
+ // Return the generated code.
2324
+ return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2325
+ }
2326
+
2327
+
2328
+ MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
2329
+ AccessorInfo* callback,
2330
+ String* name) {
2331
+ // ----------- S t a t e -------------
2332
+ // -- rax : value
2333
+ // -- rcx : name
2334
+ // -- rdx : receiver
2335
+ // -- rsp[0] : return address
2336
+ // -----------------------------------
2337
+ Label miss;
2338
+
2339
+ // Check that the object isn't a smi.
2340
+ __ JumpIfSmi(rdx, &miss);
2341
+
2342
+ // Check that the map of the object hasn't changed.
2343
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2344
+ Handle<Map>(object->map()));
2345
+ __ j(not_equal, &miss);
2346
+
2347
+ // Perform global security token check if needed.
2348
+ if (object->IsJSGlobalProxy()) {
2349
+ __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2350
+ }
2351
+
2352
+ // Stub never generated for non-global objects that require access
2353
+ // checks.
2354
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2355
+
2356
+ __ pop(rbx); // remove the return address
2357
+ __ push(rdx); // receiver
2358
+ __ Push(Handle<AccessorInfo>(callback)); // callback info
2359
+ __ push(rcx); // name
2360
+ __ push(rax); // value
2361
+ __ push(rbx); // restore return address
2362
+
2363
+ // Do tail-call to the runtime system.
2364
+ ExternalReference store_callback_property =
2365
+ ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2366
+ __ TailCallExternalReference(store_callback_property, 4, 1);
2367
+
2368
+ // Handle store cache miss.
2369
+ __ bind(&miss);
2370
+ Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2371
+ __ Jump(ic, RelocInfo::CODE_TARGET);
2372
+
2373
+ // Return the generated code.
2374
+ return GetCode(CALLBACKS, name);
2375
+ }
2376
+
2377
+
2378
+ MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
2379
+ String* name) {
2380
+ // ----------- S t a t e -------------
2381
+ // -- rax : value
2382
+ // -- rcx : name
2383
+ // -- rdx : receiver
2384
+ // -- rsp[0] : return address
2385
+ // -----------------------------------
2386
+ Label miss;
2387
+
2388
+ // Check that the object isn't a smi.
2389
+ __ JumpIfSmi(rdx, &miss);
2390
+
2391
+ // Check that the map of the object hasn't changed.
2392
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2393
+ Handle<Map>(receiver->map()));
2394
+ __ j(not_equal, &miss);
2395
+
2396
+ // Perform global security token check if needed.
2397
+ if (receiver->IsJSGlobalProxy()) {
2398
+ __ CheckAccessGlobalProxy(rdx, rbx, &miss);
2399
+ }
2400
+
2401
+ // Stub never generated for non-global objects that require access
2402
+ // checks.
2403
+ ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2404
+
2405
+ __ pop(rbx); // remove the return address
2406
+ __ push(rdx); // receiver
2407
+ __ push(rcx); // name
2408
+ __ push(rax); // value
2409
+ __ Push(Smi::FromInt(strict_mode_));
2410
+ __ push(rbx); // restore return address
2411
+
2412
+ // Do tail-call to the runtime system.
2413
+ ExternalReference store_ic_property =
2414
+ ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2415
+ __ TailCallExternalReference(store_ic_property, 4, 1);
2416
+
2417
+ // Handle store cache miss.
2418
+ __ bind(&miss);
2419
+ Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2420
+ __ Jump(ic, RelocInfo::CODE_TARGET);
2421
+
2422
+ // Return the generated code.
2423
+ return GetCode(INTERCEPTOR, name);
2424
+ }
2425
+
2426
+
2427
+ MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
2428
+ JSGlobalPropertyCell* cell,
2429
+ String* name) {
2430
+ // ----------- S t a t e -------------
2431
+ // -- rax : value
2432
+ // -- rcx : name
2433
+ // -- rdx : receiver
2434
+ // -- rsp[0] : return address
2435
+ // -----------------------------------
2436
+ Label miss;
2437
+
2438
+ // Check that the map of the global has not changed.
2439
+ __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2440
+ Handle<Map>(object->map()));
2441
+ __ j(not_equal, &miss);
2442
+
2443
+ // Check that the value in the cell is not the hole. If it is, this
2444
+ // cell could have been deleted and reintroducing the global needs
2445
+ // to update the property details in the property dictionary of the
2446
+ // global object. We bail out to the runtime system to do that.
2447
+ __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
2448
+ __ CompareRoot(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
2449
+ Heap::kTheHoleValueRootIndex);
2450
+ __ j(equal, &miss);
2451
+
2452
+ // Store the value in the cell.
2453
+ __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rax);
2454
+
2455
+ // Return the value (register rax).
2456
+ Counters* counters = isolate()->counters();
2457
+ __ IncrementCounter(counters->named_store_global_inline(), 1);
2458
+ __ ret(0);
2459
+
2460
+ // Handle store cache miss.
2461
+ __ bind(&miss);
2462
+ __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
2463
+ Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2464
+ __ Jump(ic, RelocInfo::CODE_TARGET);
2465
+
2466
+ // Return the generated code.
2467
+ return GetCode(NORMAL, name);
2468
+ }
2469
+
2470
+
2471
+ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
2472
+ int index,
2473
+ Map* transition,
2474
+ String* name) {
2475
+ // ----------- S t a t e -------------
2476
+ // -- rax : value
2477
+ // -- rcx : key
2478
+ // -- rdx : receiver
2479
+ // -- rsp[0] : return address
2480
+ // -----------------------------------
2481
+ Label miss;
2482
+
2483
+ Counters* counters = isolate()->counters();
2484
+ __ IncrementCounter(counters->keyed_store_field(), 1);
2485
+
2486
+ // Check that the name has not changed.
2487
+ __ Cmp(rcx, Handle<String>(name));
2488
+ __ j(not_equal, &miss);
2489
+
2490
+ // Generate store field code. Preserves receiver and name on jump to miss.
2491
+ GenerateStoreField(masm(),
2492
+ object,
2493
+ index,
2494
+ transition,
2495
+ rdx, rcx, rbx,
2496
+ &miss);
2497
+
2498
+ // Handle store cache miss.
2499
+ __ bind(&miss);
2500
+ __ DecrementCounter(counters->keyed_store_field(), 1);
2501
+ Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2502
+ __ Jump(ic, RelocInfo::CODE_TARGET);
2503
+
2504
+ // Return the generated code.
2505
+ return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2506
+ }
2507
+
2508
+
2509
+ MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
2510
+ Map* receiver_map) {
2511
+ // ----------- S t a t e -------------
2512
+ // -- rax : value
2513
+ // -- rcx : key
2514
+ // -- rdx : receiver
2515
+ // -- rsp[0] : return address
2516
+ // -----------------------------------
2517
+ bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2518
+ MaybeObject* maybe_stub =
2519
+ KeyedStoreFastElementStub(is_js_array).TryGetCode();
2520
+ Code* stub;
2521
+ if (!maybe_stub->To(&stub)) return maybe_stub;
2522
+ __ DispatchMap(rdx,
2523
+ Handle<Map>(receiver_map),
2524
+ Handle<Code>(stub),
2525
+ DO_SMI_CHECK);
2526
+
2527
+ Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2528
+ __ jmp(ic, RelocInfo::CODE_TARGET);
2529
+
2530
+ // Return the generated code.
2531
+ return GetCode(NORMAL, NULL);
2532
+ }
2533
+
2534
+
2535
+ MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2536
+ MapList* receiver_maps,
2537
+ CodeList* handler_ics) {
2538
+ // ----------- S t a t e -------------
2539
+ // -- rax : value
2540
+ // -- rcx : key
2541
+ // -- rdx : receiver
2542
+ // -- rsp[0] : return address
2543
+ // -----------------------------------
2544
+ Label miss;
2545
+ __ JumpIfSmi(rdx, &miss);
2546
+
2547
+ Register map_reg = rbx;
2548
+ __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2549
+ int receiver_count = receiver_maps->length();
2550
+ for (int current = 0; current < receiver_count; ++current) {
2551
+ // Check map and tail call if there's a match
2552
+ Handle<Map> map(receiver_maps->at(current));
2553
+ __ Cmp(map_reg, map);
2554
+ __ j(equal,
2555
+ Handle<Code>(handler_ics->at(current)),
2556
+ RelocInfo::CODE_TARGET);
2557
+ }
2558
+
2559
+ __ bind(&miss);
2560
+ Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2561
+ __ jmp(ic, RelocInfo::CODE_TARGET);
2562
+
2563
+ // Return the generated code.
2564
+ return GetCode(NORMAL, NULL, MEGAMORPHIC);
2565
+ }
2566
+
2567
+
2568
+ MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2569
+ JSObject* object,
2570
+ JSObject* last) {
2571
+ // ----------- S t a t e -------------
2572
+ // -- rax : receiver
2573
+ // -- rcx : name
2574
+ // -- rsp[0] : return address
2575
+ // -----------------------------------
2576
+ Label miss;
2577
+
2578
+ // Check that receiver is not a smi.
2579
+ __ JumpIfSmi(rax, &miss);
2580
+
2581
+ // Check the maps of the full prototype chain. Also check that
2582
+ // global property cells up to (but not including) the last object
2583
+ // in the prototype chain are empty.
2584
+ CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
2585
+
2586
+ // If the last object in the prototype chain is a global object,
2587
+ // check that the global property cell is empty.
2588
+ if (last->IsGlobalObject()) {
2589
+ MaybeObject* cell = GenerateCheckPropertyCell(masm(),
2590
+ GlobalObject::cast(last),
2591
+ name,
2592
+ rdx,
2593
+ &miss);
2594
+ if (cell->IsFailure()) {
2595
+ miss.Unuse();
2596
+ return cell;
2597
+ }
2598
+ }
2599
+
2600
+ // Return undefined if maps of the full prototype chain are still the
2601
+ // same and no global property with this name contains a value.
2602
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2603
+ __ ret(0);
2604
+
2605
+ __ bind(&miss);
2606
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
2607
+
2608
+ // Return the generated code.
2609
+ return GetCode(NONEXISTENT, heap()->empty_string());
2610
+ }
2611
+
2612
+
2613
+ MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
2614
+ JSObject* holder,
2615
+ int index,
2616
+ String* name) {
2617
+ // ----------- S t a t e -------------
2618
+ // -- rax : receiver
2619
+ // -- rcx : name
2620
+ // -- rsp[0] : return address
2621
+ // -----------------------------------
2622
+ Label miss;
2623
+
2624
+ GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss);
2625
+ __ bind(&miss);
2626
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
2627
+
2628
+ // Return the generated code.
2629
+ return GetCode(FIELD, name);
2630
+ }
2631
+
2632
+
2633
+ MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
2634
+ JSObject* object,
2635
+ JSObject* holder,
2636
+ AccessorInfo* callback) {
2637
+ // ----------- S t a t e -------------
2638
+ // -- rax : receiver
2639
+ // -- rcx : name
2640
+ // -- rsp[0] : return address
2641
+ // -----------------------------------
2642
+ Label miss;
2643
+
2644
+ MaybeObject* result = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx,
2645
+ rdi, callback, name, &miss);
2646
+ if (result->IsFailure()) {
2647
+ miss.Unuse();
2648
+ return result;
2649
+ }
2650
+
2651
+ __ bind(&miss);
2652
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
2653
+
2654
+ // Return the generated code.
2655
+ return GetCode(CALLBACKS, name);
2656
+ }
2657
+
2658
+
2659
+ MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
2660
+ JSObject* holder,
2661
+ Object* value,
2662
+ String* name) {
2663
+ // ----------- S t a t e -------------
2664
+ // -- rax : receiver
2665
+ // -- rcx : name
2666
+ // -- rsp[0] : return address
2667
+ // -----------------------------------
2668
+ Label miss;
2669
+
2670
+ GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss);
2671
+ __ bind(&miss);
2672
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
2673
+
2674
+ // Return the generated code.
2675
+ return GetCode(CONSTANT_FUNCTION, name);
2676
+ }
2677
+
2678
+
2679
+ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
2680
+ JSObject* holder,
2681
+ String* name) {
2682
+ // ----------- S t a t e -------------
2683
+ // -- rax : receiver
2684
+ // -- rcx : name
2685
+ // -- rsp[0] : return address
2686
+ // -----------------------------------
2687
+ Label miss;
2688
+
2689
+ LookupResult lookup;
2690
+ LookupPostInterceptor(holder, name, &lookup);
2691
+
2692
+ // TODO(368): Compile in the whole chain: all the interceptors in
2693
+ // prototypes and ultimate answer.
2694
+ GenerateLoadInterceptor(receiver,
2695
+ holder,
2696
+ &lookup,
2697
+ rax,
2698
+ rcx,
2699
+ rdx,
2700
+ rbx,
2701
+ rdi,
2702
+ name,
2703
+ &miss);
2704
+
2705
+ __ bind(&miss);
2706
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
2707
+
2708
+ // Return the generated code.
2709
+ return GetCode(INTERCEPTOR, name);
2710
+ }
2711
+
2712
+
2713
+ MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
2714
+ GlobalObject* holder,
2715
+ JSGlobalPropertyCell* cell,
2716
+ String* name,
2717
+ bool is_dont_delete) {
2718
+ // ----------- S t a t e -------------
2719
+ // -- rax : receiver
2720
+ // -- rcx : name
2721
+ // -- rsp[0] : return address
2722
+ // -----------------------------------
2723
+ Label miss;
2724
+
2725
+ // If the object is the holder then we know that it's a global
2726
+ // object which can only happen for contextual loads. In this case,
2727
+ // the receiver cannot be a smi.
2728
+ if (object != holder) {
2729
+ __ JumpIfSmi(rax, &miss);
2730
+ }
2731
+
2732
+ // Check that the maps haven't changed.
2733
+ CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss);
2734
+
2735
+ // Get the value from the cell.
2736
+ __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
2737
+ __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
2738
+
2739
+ // Check for deleted property if property can actually be deleted.
2740
+ if (!is_dont_delete) {
2741
+ __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2742
+ __ j(equal, &miss);
2743
+ } else if (FLAG_debug_code) {
2744
+ __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2745
+ __ Check(not_equal, "DontDelete cells can't contain the hole");
2746
+ }
2747
+
2748
+ Counters* counters = isolate()->counters();
2749
+ __ IncrementCounter(counters->named_load_global_stub(), 1);
2750
+ __ movq(rax, rbx);
2751
+ __ ret(0);
2752
+
2753
+ __ bind(&miss);
2754
+ __ IncrementCounter(counters->named_load_global_stub_miss(), 1);
2755
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
2756
+
2757
+ // Return the generated code.
2758
+ return GetCode(NORMAL, name);
2759
+ }
2760
+
2761
+
2762
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
2763
+ JSObject* receiver,
2764
+ JSObject* holder,
2765
+ int index) {
2766
+ // ----------- S t a t e -------------
2767
+ // -- rax : key
2768
+ // -- rdx : receiver
2769
+ // -- rsp[0] : return address
2770
+ // -----------------------------------
2771
+ Label miss;
2772
+
2773
+ Counters* counters = isolate()->counters();
2774
+ __ IncrementCounter(counters->keyed_load_field(), 1);
2775
+
2776
+ // Check that the name has not changed.
2777
+ __ Cmp(rax, Handle<String>(name));
2778
+ __ j(not_equal, &miss);
2779
+
2780
+ GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss);
2781
+
2782
+ __ bind(&miss);
2783
+ __ DecrementCounter(counters->keyed_load_field(), 1);
2784
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2785
+
2786
+ // Return the generated code.
2787
+ return GetCode(FIELD, name);
2788
+ }
2789
+
2790
+
2791
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
2792
+ String* name,
2793
+ JSObject* receiver,
2794
+ JSObject* holder,
2795
+ AccessorInfo* callback) {
2796
+ // ----------- S t a t e -------------
2797
+ // -- rax : key
2798
+ // -- rdx : receiver
2799
+ // -- rsp[0] : return address
2800
+ // -----------------------------------
2801
+ Label miss;
2802
+
2803
+ Counters* counters = isolate()->counters();
2804
+ __ IncrementCounter(counters->keyed_load_callback(), 1);
2805
+
2806
+ // Check that the name has not changed.
2807
+ __ Cmp(rax, Handle<String>(name));
2808
+ __ j(not_equal, &miss);
2809
+
2810
+ MaybeObject* result = GenerateLoadCallback(receiver, holder, rdx, rax, rbx,
2811
+ rcx, rdi, callback, name, &miss);
2812
+ if (result->IsFailure()) {
2813
+ miss.Unuse();
2814
+ return result;
2815
+ }
2816
+
2817
+ __ bind(&miss);
2818
+
2819
+ __ DecrementCounter(counters->keyed_load_callback(), 1);
2820
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2821
+
2822
+ // Return the generated code.
2823
+ return GetCode(CALLBACKS, name);
2824
+ }
2825
+
2826
+
2827
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
2828
+ JSObject* receiver,
2829
+ JSObject* holder,
2830
+ Object* value) {
2831
+ // ----------- S t a t e -------------
2832
+ // -- rax : key
2833
+ // -- rdx : receiver
2834
+ // -- rsp[0] : return address
2835
+ // -----------------------------------
2836
+ Label miss;
2837
+
2838
+ Counters* counters = isolate()->counters();
2839
+ __ IncrementCounter(counters->keyed_load_constant_function(), 1);
2840
+
2841
+ // Check that the name has not changed.
2842
+ __ Cmp(rax, Handle<String>(name));
2843
+ __ j(not_equal, &miss);
2844
+
2845
+ GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi,
2846
+ value, name, &miss);
2847
+ __ bind(&miss);
2848
+ __ DecrementCounter(counters->keyed_load_constant_function(), 1);
2849
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2850
+
2851
+ // Return the generated code.
2852
+ return GetCode(CONSTANT_FUNCTION, name);
2853
+ }
2854
+
2855
+
2856
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
2857
+ JSObject* holder,
2858
+ String* name) {
2859
+ // ----------- S t a t e -------------
2860
+ // -- rax : key
2861
+ // -- rdx : receiver
2862
+ // -- rsp[0] : return address
2863
+ // -----------------------------------
2864
+ Label miss;
2865
+
2866
+ Counters* counters = isolate()->counters();
2867
+ __ IncrementCounter(counters->keyed_load_interceptor(), 1);
2868
+
2869
+ // Check that the name has not changed.
2870
+ __ Cmp(rax, Handle<String>(name));
2871
+ __ j(not_equal, &miss);
2872
+
2873
+ LookupResult lookup;
2874
+ LookupPostInterceptor(holder, name, &lookup);
2875
+ GenerateLoadInterceptor(receiver,
2876
+ holder,
2877
+ &lookup,
2878
+ rdx,
2879
+ rax,
2880
+ rcx,
2881
+ rbx,
2882
+ rdi,
2883
+ name,
2884
+ &miss);
2885
+ __ bind(&miss);
2886
+ __ DecrementCounter(counters->keyed_load_interceptor(), 1);
2887
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2888
+
2889
+ // Return the generated code.
2890
+ return GetCode(INTERCEPTOR, name);
2891
+ }
2892
+
2893
+
2894
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
2895
+ // ----------- S t a t e -------------
2896
+ // -- rax : key
2897
+ // -- rdx : receiver
2898
+ // -- rsp[0] : return address
2899
+ // -----------------------------------
2900
+ Label miss;
2901
+
2902
+ Counters* counters = isolate()->counters();
2903
+ __ IncrementCounter(counters->keyed_load_array_length(), 1);
2904
+
2905
+ // Check that the name has not changed.
2906
+ __ Cmp(rax, Handle<String>(name));
2907
+ __ j(not_equal, &miss);
2908
+
2909
+ GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
2910
+ __ bind(&miss);
2911
+ __ DecrementCounter(counters->keyed_load_array_length(), 1);
2912
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2913
+
2914
+ // Return the generated code.
2915
+ return GetCode(CALLBACKS, name);
2916
+ }
2917
+
2918
+
2919
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
2920
+ // ----------- S t a t e -------------
2921
+ // -- rax : key
2922
+ // -- rdx : receiver
2923
+ // -- rsp[0] : return address
2924
+ // -----------------------------------
2925
+ Label miss;
2926
+
2927
+ Counters* counters = isolate()->counters();
2928
+ __ IncrementCounter(counters->keyed_load_string_length(), 1);
2929
+
2930
+ // Check that the name has not changed.
2931
+ __ Cmp(rax, Handle<String>(name));
2932
+ __ j(not_equal, &miss);
2933
+
2934
+ GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
2935
+ __ bind(&miss);
2936
+ __ DecrementCounter(counters->keyed_load_string_length(), 1);
2937
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2938
+
2939
+ // Return the generated code.
2940
+ return GetCode(CALLBACKS, name);
2941
+ }
2942
+
2943
+
2944
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
2945
+ // ----------- S t a t e -------------
2946
+ // -- rax : key
2947
+ // -- rdx : receiver
2948
+ // -- rsp[0] : return address
2949
+ // -----------------------------------
2950
+ Label miss;
2951
+
2952
+ Counters* counters = isolate()->counters();
2953
+ __ IncrementCounter(counters->keyed_load_function_prototype(), 1);
2954
+
2955
+ // Check that the name has not changed.
2956
+ __ Cmp(rax, Handle<String>(name));
2957
+ __ j(not_equal, &miss);
2958
+
2959
+ GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
2960
+ __ bind(&miss);
2961
+ __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
2962
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2963
+
2964
+ // Return the generated code.
2965
+ return GetCode(CALLBACKS, name);
2966
+ }
2967
+
2968
+
2969
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
2970
+ // ----------- S t a t e -------------
2971
+ // -- rax : key
2972
+ // -- rdx : receiver
2973
+ // -- rsp[0] : return address
2974
+ // -----------------------------------
2975
+ MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
2976
+ Code* stub;
2977
+ if (!maybe_stub->To(&stub)) return maybe_stub;
2978
+ __ DispatchMap(rdx,
2979
+ Handle<Map>(receiver_map),
2980
+ Handle<Code>(stub),
2981
+ DO_SMI_CHECK);
2982
+
2983
+ Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2984
+ __ jmp(ic, RelocInfo::CODE_TARGET);
2985
+
2986
+ // Return the generated code.
2987
+ return GetCode(NORMAL, NULL);
2988
+ }
2989
+
2990
+
2991
+ MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
2992
+ MapList* receiver_maps,
2993
+ CodeList* handler_ics) {
2994
+ // ----------- S t a t e -------------
2995
+ // -- rax : key
2996
+ // -- rdx : receiver
2997
+ // -- rsp[0] : return address
2998
+ // -----------------------------------
2999
+ Label miss;
3000
+ __ JumpIfSmi(rdx, &miss);
3001
+
3002
+ Register map_reg = rbx;
3003
+ __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
3004
+ int receiver_count = receiver_maps->length();
3005
+ for (int current = 0; current < receiver_count; ++current) {
3006
+ // Check map and tail call if there's a match
3007
+ Handle<Map> map(receiver_maps->at(current));
3008
+ __ Cmp(map_reg, map);
3009
+ __ j(equal,
3010
+ Handle<Code>(handler_ics->at(current)),
3011
+ RelocInfo::CODE_TARGET);
3012
+ }
3013
+
3014
+ __ bind(&miss);
3015
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3016
+
3017
+ // Return the generated code.
3018
+ return GetCode(NORMAL, NULL, MEGAMORPHIC);
3019
+ }
3020
+
3021
+
3022
+ // Specialized stub for constructing objects from functions which only have only
3023
+ // simple assignments of the form this.x = ...; in their body.
3024
+ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3025
+ // ----------- S t a t e -------------
3026
+ // -- rax : argc
3027
+ // -- rdi : constructor
3028
+ // -- rsp[0] : return address
3029
+ // -- rsp[4] : last argument
3030
+ // -----------------------------------
3031
+ Label generic_stub_call;
3032
+
3033
+ // Use r8 for holding undefined which is used in several places below.
3034
+ __ Move(r8, factory()->undefined_value());
3035
+
3036
+ #ifdef ENABLE_DEBUGGER_SUPPORT
3037
+ // Check to see whether there are any break points in the function code. If
3038
+ // there are jump to the generic constructor stub which calls the actual
3039
+ // code for the function thereby hitting the break points.
3040
+ __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
3041
+ __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kDebugInfoOffset));
3042
+ __ cmpq(rbx, r8);
3043
+ __ j(not_equal, &generic_stub_call);
3044
+ #endif
3045
+
3046
+ // Load the initial map and verify that it is in fact a map.
3047
+ __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
3048
+ // Will both indicate a NULL and a Smi.
3049
+ ASSERT(kSmiTag == 0);
3050
+ __ JumpIfSmi(rbx, &generic_stub_call);
3051
+ __ CmpObjectType(rbx, MAP_TYPE, rcx);
3052
+ __ j(not_equal, &generic_stub_call);
3053
+
3054
+ #ifdef DEBUG
3055
+ // Cannot construct functions this way.
3056
+ // rdi: constructor
3057
+ // rbx: initial map
3058
+ __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
3059
+ __ Assert(not_equal, "Function constructed by construct stub.");
3060
+ #endif
3061
+
3062
+ // Now allocate the JSObject in new space.
3063
+ // rdi: constructor
3064
+ // rbx: initial map
3065
+ __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
3066
+ __ shl(rcx, Immediate(kPointerSizeLog2));
3067
+ __ AllocateInNewSpace(rcx,
3068
+ rdx,
3069
+ rcx,
3070
+ no_reg,
3071
+ &generic_stub_call,
3072
+ NO_ALLOCATION_FLAGS);
3073
+
3074
+ // Allocated the JSObject, now initialize the fields and add the heap tag.
3075
+ // rbx: initial map
3076
+ // rdx: JSObject (untagged)
3077
+ __ movq(Operand(rdx, JSObject::kMapOffset), rbx);
3078
+ __ Move(rbx, factory()->empty_fixed_array());
3079
+ __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx);
3080
+ __ movq(Operand(rdx, JSObject::kElementsOffset), rbx);
3081
+
3082
+ // rax: argc
3083
+ // rdx: JSObject (untagged)
3084
+ // Load the address of the first in-object property into r9.
3085
+ __ lea(r9, Operand(rdx, JSObject::kHeaderSize));
3086
+ // Calculate the location of the first argument. The stack contains only the
3087
+ // return address on top of the argc arguments.
3088
+ __ lea(rcx, Operand(rsp, rax, times_pointer_size, 0));
3089
+
3090
+ // rax: argc
3091
+ // rcx: first argument
3092
+ // rdx: JSObject (untagged)
3093
+ // r8: undefined
3094
+ // r9: first in-object property of the JSObject
3095
+ // Fill the initialized properties with a constant value or a passed argument
3096
+ // depending on the this.x = ...; assignment in the function.
3097
+ SharedFunctionInfo* shared = function->shared();
3098
+ for (int i = 0; i < shared->this_property_assignments_count(); i++) {
3099
+ if (shared->IsThisPropertyAssignmentArgument(i)) {
3100
+ // Check if the argument assigned to the property is actually passed.
3101
+ // If argument is not passed the property is set to undefined,
3102
+ // otherwise find it on the stack.
3103
+ int arg_number = shared->GetThisPropertyAssignmentArgument(i);
3104
+ __ movq(rbx, r8);
3105
+ __ cmpq(rax, Immediate(arg_number));
3106
+ __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize));
3107
+ // Store value in the property.
3108
+ __ movq(Operand(r9, i * kPointerSize), rbx);
3109
+ } else {
3110
+ // Set the property to the constant value.
3111
+ Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
3112
+ __ Move(Operand(r9, i * kPointerSize), constant);
3113
+ }
3114
+ }
3115
+
3116
+ // Fill the unused in-object property fields with undefined.
3117
+ ASSERT(function->has_initial_map());
3118
+ for (int i = shared->this_property_assignments_count();
3119
+ i < function->initial_map()->inobject_properties();
3120
+ i++) {
3121
+ __ movq(Operand(r9, i * kPointerSize), r8);
3122
+ }
3123
+
3124
+ // rax: argc
3125
+ // rdx: JSObject (untagged)
3126
+ // Move argc to rbx and the JSObject to return to rax and tag it.
3127
+ __ movq(rbx, rax);
3128
+ __ movq(rax, rdx);
3129
+ __ or_(rax, Immediate(kHeapObjectTag));
3130
+
3131
+ // rax: JSObject
3132
+ // rbx: argc
3133
+ // Remove caller arguments and receiver from the stack and return.
3134
+ __ pop(rcx);
3135
+ __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize));
3136
+ __ push(rcx);
3137
+ Counters* counters = isolate()->counters();
3138
+ __ IncrementCounter(counters->constructed_objects(), 1);
3139
+ __ IncrementCounter(counters->constructed_objects_stub(), 1);
3140
+ __ ret(0);
3141
+
3142
+ // Jump to the generic stub in case the specialized code cannot handle the
3143
+ // construction.
3144
+ __ bind(&generic_stub_call);
3145
+ Code* code =
3146
+ isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
3147
+ Handle<Code> generic_construct_stub(code);
3148
+ __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3149
+
3150
+ // Return the generated code.
3151
+ return GetCode();
3152
+ }
3153
+
3154
+
3155
+ MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3156
+ JSObject*receiver, ExternalArrayType array_type) {
3157
+ // ----------- S t a t e -------------
3158
+ // -- rax : key
3159
+ // -- rdx : receiver
3160
+ // -- rsp[0] : return address
3161
+ // -----------------------------------
3162
+ MaybeObject* maybe_stub =
3163
+ KeyedLoadExternalArrayStub(array_type).TryGetCode();
3164
+ Code* stub;
3165
+ if (!maybe_stub->To(&stub)) return maybe_stub;
3166
+ __ DispatchMap(rdx,
3167
+ Handle<Map>(receiver->map()),
3168
+ Handle<Code>(stub),
3169
+ DO_SMI_CHECK);
3170
+
3171
+ Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3172
+ __ jmp(ic, RelocInfo::CODE_TARGET);
3173
+
3174
+ // Return the generated code.
3175
+ return GetCode();
3176
+ }
3177
+
3178
+ MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3179
+ JSObject* receiver, ExternalArrayType array_type) {
3180
+ // ----------- S t a t e -------------
3181
+ // -- rax : value
3182
+ // -- rcx : key
3183
+ // -- rdx : receiver
3184
+ // -- rsp[0] : return address
3185
+ // -----------------------------------
3186
+ MaybeObject* maybe_stub =
3187
+ KeyedStoreExternalArrayStub(array_type).TryGetCode();
3188
+ Code* stub;
3189
+ if (!maybe_stub->To(&stub)) return maybe_stub;
3190
+ __ DispatchMap(rdx,
3191
+ Handle<Map>(receiver->map()),
3192
+ Handle<Code>(stub),
3193
+ DO_SMI_CHECK);
3194
+
3195
+ Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3196
+ __ jmp(ic, RelocInfo::CODE_TARGET);
3197
+
3198
+ return GetCode();
3199
+ }
3200
+
3201
+
3202
+ #undef __
3203
+ #define __ ACCESS_MASM(masm)
3204
+
3205
+
3206
+ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3207
+ MacroAssembler* masm,
3208
+ ExternalArrayType array_type) {
3209
+ // ----------- S t a t e -------------
3210
+ // -- rax : key
3211
+ // -- rdx : receiver
3212
+ // -- rsp[0] : return address
3213
+ // -----------------------------------
3214
+ Label slow, miss_force_generic;
3215
+
3216
+ // This stub is meant to be tail-jumped to, the receiver must already
3217
+ // have been verified by the caller to not be a smi.
3218
+
3219
+ // Check that the key is a smi.
3220
+ __ JumpIfNotSmi(rax, &miss_force_generic);
3221
+
3222
+ // Check that the index is in range.
3223
+ __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3224
+ __ SmiToInteger32(rcx, rax);
3225
+ __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3226
+ // Unsigned comparison catches both negative and too-large values.
3227
+ __ j(above_equal, &miss_force_generic);
3228
+
3229
+ // rax: index (as a smi)
3230
+ // rdx: receiver (JSObject)
3231
+ // rcx: untagged index
3232
+ // rbx: elements array
3233
+ __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3234
+ // rbx: base pointer of external storage
3235
+ switch (array_type) {
3236
+ case kExternalByteArray:
3237
+ __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
3238
+ break;
3239
+ case kExternalPixelArray:
3240
+ case kExternalUnsignedByteArray:
3241
+ __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
3242
+ break;
3243
+ case kExternalShortArray:
3244
+ __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
3245
+ break;
3246
+ case kExternalUnsignedShortArray:
3247
+ __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
3248
+ break;
3249
+ case kExternalIntArray:
3250
+ __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
3251
+ break;
3252
+ case kExternalUnsignedIntArray:
3253
+ __ movl(rcx, Operand(rbx, rcx, times_4, 0));
3254
+ break;
3255
+ case kExternalFloatArray:
3256
+ __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
3257
+ break;
3258
+ case kExternalDoubleArray:
3259
+ __ movsd(xmm0, Operand(rbx, rcx, times_8, 0));
3260
+ break;
3261
+ default:
3262
+ UNREACHABLE();
3263
+ break;
3264
+ }
3265
+
3266
+ // rax: index
3267
+ // rdx: receiver
3268
+ // For integer array types:
3269
+ // rcx: value
3270
+ // For floating-point array type:
3271
+ // xmm0: value as double.
3272
+
3273
+ ASSERT(kSmiValueSize == 32);
3274
+ if (array_type == kExternalUnsignedIntArray) {
3275
+ // For the UnsignedInt array type, we need to see whether
3276
+ // the value can be represented in a Smi. If not, we need to convert
3277
+ // it to a HeapNumber.
3278
+ Label box_int;
3279
+
3280
+ __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear);
3281
+
3282
+ __ Integer32ToSmi(rax, rcx);
3283
+ __ ret(0);
3284
+
3285
+ __ bind(&box_int);
3286
+
3287
+ // Allocate a HeapNumber for the int and perform int-to-double
3288
+ // conversion.
3289
+ // The value is zero-extended since we loaded the value from memory
3290
+ // with movl.
3291
+ __ cvtqsi2sd(xmm0, rcx);
3292
+
3293
+ __ AllocateHeapNumber(rcx, rbx, &slow);
3294
+ // Set the value.
3295
+ __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3296
+ __ movq(rax, rcx);
3297
+ __ ret(0);
3298
+ } else if (array_type == kExternalFloatArray ||
3299
+ array_type == kExternalDoubleArray) {
3300
+ // For the floating-point array type, we need to always allocate a
3301
+ // HeapNumber.
3302
+ __ AllocateHeapNumber(rcx, rbx, &slow);
3303
+ // Set the value.
3304
+ __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3305
+ __ movq(rax, rcx);
3306
+ __ ret(0);
3307
+ } else {
3308
+ __ Integer32ToSmi(rax, rcx);
3309
+ __ ret(0);
3310
+ }
3311
+
3312
+ // Slow case: Jump to runtime.
3313
+ __ bind(&slow);
3314
+ Counters* counters = masm->isolate()->counters();
3315
+ __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3316
+
3317
+ // ----------- S t a t e -------------
3318
+ // -- rax : key
3319
+ // -- rdx : receiver
3320
+ // -- rsp[0] : return address
3321
+ // -----------------------------------
3322
+
3323
+ Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3324
+ __ jmp(ic, RelocInfo::CODE_TARGET);
3325
+
3326
+ // Miss case: Jump to runtime.
3327
+ __ bind(&miss_force_generic);
3328
+
3329
+ // ----------- S t a t e -------------
3330
+ // -- rax : key
3331
+ // -- rdx : receiver
3332
+ // -- rsp[0] : return address
3333
+ // -----------------------------------
3334
+ Handle<Code> miss_ic =
3335
+ masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3336
+ __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3337
+ }
3338
+
3339
+
3340
+ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3341
+ MacroAssembler* masm,
3342
+ ExternalArrayType array_type) {
3343
+ // ----------- S t a t e -------------
3344
+ // -- rax : value
3345
+ // -- rcx : key
3346
+ // -- rdx : receiver
3347
+ // -- rsp[0] : return address
3348
+ // -----------------------------------
3349
+ Label slow, miss_force_generic;
3350
+
3351
+ // This stub is meant to be tail-jumped to, the receiver must already
3352
+ // have been verified by the caller to not be a smi.
3353
+
3354
+ // Check that the key is a smi.
3355
+ __ JumpIfNotSmi(rcx, &miss_force_generic);
3356
+
3357
+ // Check that the index is in range.
3358
+ __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3359
+ __ SmiToInteger32(rdi, rcx); // Untag the index.
3360
+ __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
3361
+ // Unsigned comparison catches both negative and too-large values.
3362
+ __ j(above_equal, &miss_force_generic);
3363
+
3364
+ // Handle both smis and HeapNumbers in the fast path. Go to the
3365
+ // runtime for all other kinds of values.
3366
+ // rax: value
3367
+ // rcx: key (a smi)
3368
+ // rdx: receiver (a JSObject)
3369
+ // rbx: elements array
3370
+ // rdi: untagged key
3371
+ Label check_heap_number;
3372
+ if (array_type == kExternalPixelArray) {
3373
+ // Float to pixel conversion is only implemented in the runtime for now.
3374
+ __ JumpIfNotSmi(rax, &slow);
3375
+ } else {
3376
+ __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear);
3377
+ }
3378
+ // No more branches to slow case on this path. Key and receiver not needed.
3379
+ __ SmiToInteger32(rdx, rax);
3380
+ __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3381
+ // rbx: base pointer of external storage
3382
+ switch (array_type) {
3383
+ case kExternalPixelArray:
3384
+ { // Clamp the value to [0..255].
3385
+ Label done;
3386
+ __ testl(rdx, Immediate(0xFFFFFF00));
3387
+ __ j(zero, &done, Label::kNear);
3388
+ __ setcc(negative, rdx); // 1 if negative, 0 if positive.
3389
+ __ decb(rdx); // 0 if negative, 255 if positive.
3390
+ __ bind(&done);
3391
+ }
3392
+ __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3393
+ break;
3394
+ case kExternalByteArray:
3395
+ case kExternalUnsignedByteArray:
3396
+ __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3397
+ break;
3398
+ case kExternalShortArray:
3399
+ case kExternalUnsignedShortArray:
3400
+ __ movw(Operand(rbx, rdi, times_2, 0), rdx);
3401
+ break;
3402
+ case kExternalIntArray:
3403
+ case kExternalUnsignedIntArray:
3404
+ __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3405
+ break;
3406
+ case kExternalFloatArray:
3407
+ // Need to perform int-to-float conversion.
3408
+ __ cvtlsi2ss(xmm0, rdx);
3409
+ __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3410
+ break;
3411
+ case kExternalDoubleArray:
3412
+ // Need to perform int-to-float conversion.
3413
+ __ cvtlsi2sd(xmm0, rdx);
3414
+ __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3415
+ break;
3416
+ default:
3417
+ UNREACHABLE();
3418
+ break;
3419
+ }
3420
+ __ ret(0);
3421
+
3422
+ // TODO(danno): handle heap number -> pixel array conversion
3423
+ if (array_type != kExternalPixelArray) {
3424
+ __ bind(&check_heap_number);
3425
+ // rax: value
3426
+ // rcx: key (a smi)
3427
+ // rdx: receiver (a JSObject)
3428
+ // rbx: elements array
3429
+ // rdi: untagged key
3430
+ __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
3431
+ __ j(not_equal, &slow);
3432
+ // No more branches to slow case on this path.
3433
+
3434
+ // The WebGL specification leaves the behavior of storing NaN and
3435
+ // +/-Infinity into integer arrays basically undefined. For more
3436
+ // reproducible behavior, convert these to zero.
3437
+ __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
3438
+ __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3439
+ // rdi: untagged index
3440
+ // rbx: base pointer of external storage
3441
+ // top of FPU stack: value
3442
+ if (array_type == kExternalFloatArray) {
3443
+ __ cvtsd2ss(xmm0, xmm0);
3444
+ __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3445
+ __ ret(0);
3446
+ } else if (array_type == kExternalDoubleArray) {
3447
+ __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3448
+ __ ret(0);
3449
+ } else {
3450
+ // Perform float-to-int conversion with truncation (round-to-zero)
3451
+ // behavior.
3452
+
3453
+ // Convert to int32 and store the low byte/word.
3454
+ // If the value is NaN or +/-infinity, the result is 0x80000000,
3455
+ // which is automatically zero when taken mod 2^n, n < 32.
3456
+ // rdx: value (converted to an untagged integer)
3457
+ // rdi: untagged index
3458
+ // rbx: base pointer of external storage
3459
+ switch (array_type) {
3460
+ case kExternalByteArray:
3461
+ case kExternalUnsignedByteArray:
3462
+ __ cvttsd2si(rdx, xmm0);
3463
+ __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3464
+ break;
3465
+ case kExternalShortArray:
3466
+ case kExternalUnsignedShortArray:
3467
+ __ cvttsd2si(rdx, xmm0);
3468
+ __ movw(Operand(rbx, rdi, times_2, 0), rdx);
3469
+ break;
3470
+ case kExternalIntArray:
3471
+ case kExternalUnsignedIntArray: {
3472
+ // Convert to int64, so that NaN and infinities become
3473
+ // 0x8000000000000000, which is zero mod 2^32.
3474
+ __ cvttsd2siq(rdx, xmm0);
3475
+ __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3476
+ break;
3477
+ }
3478
+ default:
3479
+ UNREACHABLE();
3480
+ break;
3481
+ }
3482
+ __ ret(0);
3483
+ }
3484
+ }
3485
+
3486
+ // Slow case: call runtime.
3487
+ __ bind(&slow);
3488
+
3489
+ // ----------- S t a t e -------------
3490
+ // -- rax : value
3491
+ // -- rcx : key
3492
+ // -- rdx : receiver
3493
+ // -- rsp[0] : return address
3494
+ // -----------------------------------
3495
+
3496
+ Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3497
+ __ jmp(ic, RelocInfo::CODE_TARGET);
3498
+
3499
+ // Miss case: call runtime.
3500
+ __ bind(&miss_force_generic);
3501
+
3502
+ // ----------- S t a t e -------------
3503
+ // -- rax : value
3504
+ // -- rcx : key
3505
+ // -- rdx : receiver
3506
+ // -- rsp[0] : return address
3507
+ // -----------------------------------
3508
+
3509
+ Handle<Code> miss_ic =
3510
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3511
+ __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3512
+ }
3513
+
3514
+
3515
+ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3516
+ // ----------- S t a t e -------------
3517
+ // -- rax : key
3518
+ // -- rdx : receiver
3519
+ // -- rsp[0] : return address
3520
+ // -----------------------------------
3521
+ Label miss_force_generic;
3522
+
3523
+ // This stub is meant to be tail-jumped to, the receiver must already
3524
+ // have been verified by the caller to not be a smi.
3525
+
3526
+ // Check that the key is a smi.
3527
+ __ JumpIfNotSmi(rax, &miss_force_generic);
3528
+
3529
+ // Get the elements array.
3530
+ __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3531
+ __ AssertFastElements(rcx);
3532
+
3533
+ // Check that the key is within bounds.
3534
+ __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3535
+ __ j(above_equal, &miss_force_generic);
3536
+
3537
+ // Load the result and make sure it's not the hole.
3538
+ SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3539
+ __ movq(rbx, FieldOperand(rcx,
3540
+ index.reg,
3541
+ index.scale,
3542
+ FixedArray::kHeaderSize));
3543
+ __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3544
+ __ j(equal, &miss_force_generic);
3545
+ __ movq(rax, rbx);
3546
+ __ ret(0);
3547
+
3548
+ __ bind(&miss_force_generic);
3549
+ Code* code = masm->isolate()->builtins()->builtin(
3550
+ Builtins::kKeyedLoadIC_MissForceGeneric);
3551
+ Handle<Code> ic(code);
3552
+ __ jmp(ic, RelocInfo::CODE_TARGET);
3553
+ }
3554
+
3555
+
3556
+ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3557
+ bool is_js_array) {
3558
+ // ----------- S t a t e -------------
3559
+ // -- rax : value
3560
+ // -- rcx : key
3561
+ // -- rdx : receiver
3562
+ // -- rsp[0] : return address
3563
+ // -----------------------------------
3564
+ Label miss_force_generic;
3565
+
3566
+ // This stub is meant to be tail-jumped to, the receiver must already
3567
+ // have been verified by the caller to not be a smi.
3568
+
3569
+ // Check that the key is a smi.
3570
+ __ JumpIfNotSmi(rcx, &miss_force_generic);
3571
+
3572
+ // Get the elements array and make sure it is a fast element array, not 'cow'.
3573
+ __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3574
+ __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3575
+ Heap::kFixedArrayMapRootIndex);
3576
+ __ j(not_equal, &miss_force_generic);
3577
+
3578
+ // Check that the key is within bounds.
3579
+ if (is_js_array) {
3580
+ __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3581
+ __ j(above_equal, &miss_force_generic);
3582
+ } else {
3583
+ __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3584
+ __ j(above_equal, &miss_force_generic);
3585
+ }
3586
+
3587
+ // Do the store and update the write barrier. Make sure to preserve
3588
+ // the value in register eax.
3589
+ __ movq(rdx, rax);
3590
+ __ SmiToInteger32(rcx, rcx);
3591
+ __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
3592
+ rax);
3593
+ __ RecordWrite(rdi, 0, rdx, rcx);
3594
+
3595
+ // Done.
3596
+ __ ret(0);
3597
+
3598
+ // Handle store cache miss.
3599
+ __ bind(&miss_force_generic);
3600
+ Handle<Code> ic_force_generic =
3601
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3602
+ __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3603
+ }
3604
+
3605
+
3606
+ #undef __
3607
+
3608
+ } } // namespace v8::internal
3609
+
3610
+ #endif // V8_TARGET_ARCH_X64