diff -Nru webkit2gtk-2.12.3/CMakeLists.txt webkit2gtk-2.14.2/CMakeLists.txt --- webkit2gtk-2.12.3/CMakeLists.txt 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/CMakeLists.txt 2016-11-03 07:04:19.000000000 +0000 @@ -8,6 +8,8 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Source/cmake") +set(ENABLE_WEBCORE ON) + if (NOT DEFINED ENABLE_WEBKIT) set(ENABLE_WEBKIT ON) endif () @@ -19,7 +21,14 @@ # ----------------------------------------------------------------------------- # Determine which port will be built # ----------------------------------------------------------------------------- -set(ALL_PORTS Efl GTK AppleWin WinCairo Mac) +set(ALL_PORTS + AppleWin + Efl + GTK + JSCOnly + Mac + WinCairo +) set(PORT "NOPORT" CACHE STRING "choose which WebKit port to build (one of ${ALL_PORTS})") list(FIND ALL_PORTS ${PORT} RET) diff -Nru webkit2gtk-2.12.3/debian/changelog webkit2gtk-2.14.2/debian/changelog --- webkit2gtk-2.12.3/debian/changelog 2016-06-20 17:33:42.000000000 +0000 +++ webkit2gtk-2.14.2/debian/changelog 2017-01-07 14:21:55.000000000 +0000 @@ -1,10 +1,81 @@ -webkit2gtk (2.12.3-0ubuntu1~16.04~webkit1) xenial; urgency=medium +webkit2gtk (2.14.2-0ubuntu0.16.04.1~webkitteam1) xenial; urgency=medium - * Merge with Debian unstable. Remaining changes: - + Build with GeoClue 1, which is what we still use in Ubuntu. - * Pass -g1 for minimal debug information + * Backport from yakkety - -- Rico Tzschichholz Mon, 20 Jun 2016 19:31:36 +0200 + -- Rico Tzschichholz Sat, 07 Jan 2017 15:21:55 +0100 + +webkit2gtk (2.14.2-0ubuntu1) yakkety; urgency=medium + + * New upstream bugfix release (LP: #1639200) + + -- Jeremy Bicha Sun, 06 Nov 2016 20:55:02 -0500 + +webkit2gtk (2.14.1-0ubuntu1) yakkety; urgency=medium + + [ Alberto Garcia ] + * New upstream bugfix release (LP: #1632535) + + Fix multiple crash bugs including one affecting epiphany and + evolution (LP: #1631682) + * debian/patches/install-minibrowser.patch: + + Drop patch, this has been merged upstream. + * debian/rules: + + Set -DENABLE_MINIBROWSER=ON. + * debian/libjavascriptcoregtk-4.0-bin.install: + + Install the jsc executable in /usr/bin. + + -- Jeremy Bicha Wed, 12 Oct 2016 08:31:28 -0400 + +webkit2gtk (2.14.0-1) unstable; urgency=medium + + * New upstream release. + * debian/watch: + + Stop scanning the 2.13 branch. + * debian/gbp.conf: + + Update upstream branch name. + + -- Alberto Garcia Tue, 20 Sep 2016 15:31:35 +0300 + +webkit2gtk (2.13.92-1) experimental; urgency=medium + + * New upstream development release. + * debian/patches/fix-ftbfs-armel.patch: + + Fix FTBFS in Armel. + + -- Alberto Garcia Fri, 16 Sep 2016 11:32:19 +0300 + +webkit2gtk (2.13.91-1) experimental; urgency=medium + + * New upstream development release. + * debian/{control,copyright,watch}: + + Use https instead of http for webkitgtk.org. + * debian/patches/fix-ftbfs-m68k.patch: + + Drop this patch, the m68k build has been broken for ages. + * debian/patches/fix-ftbfs-alpha.patch, + debian/patches/fix-ftbfs-sparc64.patch: + + Refresh. + * debian/source/lintian-overrides: + + Update source-is-missing overrides. + * debian/libwebkit2gtk-4.0-37.symbols: + + Update. + * debian/rules: + + Don't use the gold linker in mips/mipsel, see #834147. + + -- Alberto Garcia Tue, 13 Sep 2016 11:40:22 +0300 + +webkit2gtk (2.13.4-1) experimental; urgency=medium + + * New upstream release. + * debian/patches/hide-gtk2-plugins.patch: + + Dropped, merged upstream. + * debian/patches/fix-ftbfs-alpha.patch, + debian/patches/fix-ftbfs-m68k.patch, + debian/patches/fix-ftbfs-sparc64.patch, + debian/patches/install-minibrowser.patch: + + Refreshed. + * debian/libwebkit2gtk-4.0-37.symbols: + + New symbols added, and some optional dom symbols dropped. + + -- Emilio Pozuelo Monfort Sun, 31 Jul 2016 20:46:25 +0200 webkit2gtk (2.12.3-1) unstable; urgency=high @@ -66,25 +137,12 @@ -- Alberto Garcia Tue, 22 Mar 2016 12:16:08 +0200 -webkit2gtk (2.10.9-1ubuntu1) xenial; urgency=medium - - * Merge with Debian unstable. Remaining changes: - + Build with GeoClue 1, which is what we still use in Ubuntu. - - -- Iain Lane Wed, 23 Mar 2016 18:09:37 +0000 - webkit2gtk (2.10.9-1) unstable; urgency=medium * New upstream release. -- Alberto Garcia Fri, 18 Mar 2016 12:35:25 +0200 -webkit2gtk (2.10.8-1ubuntu1) xenial; urgency=low - - * Build with GeoClue 1, which is what we still use in Ubuntu. - - -- Iain Lane Tue, 15 Mar 2016 10:59:14 +0000 - webkit2gtk (2.10.8-1) unstable; urgency=high * New upstream release. This fixes CVE-2016-1726 (Closes: #802380). @@ -117,12 +175,6 @@ -- Alberto Garcia Sat, 12 Mar 2016 00:07:55 +0200 -webkit2gtk (2.10.6-1ubuntu1) xenial; urgency=medium - - * Build with GeoClue 1, which is what we still use in Ubuntu. - - -- Iain Lane Fri, 12 Feb 2016 15:05:47 +0000 - webkit2gtk (2.10.6-1) unstable; urgency=medium * New upstream release. diff -Nru webkit2gtk-2.12.3/debian/control webkit2gtk-2.14.2/debian/control --- webkit2gtk-2.12.3/debian/control 2016-06-20 17:32:42.000000000 +0000 +++ webkit2gtk-2.14.2/debian/control 2016-11-07 01:55:02.000000000 +0000 @@ -34,11 +34,11 @@ libpng-dev, libwebp-dev, libxt-dev, - libgeoclue-dev, libgstreamer1.0-dev (>= 1.0.3), libgstreamer-plugins-base1.0-dev (>= 1.0.3), libenchant-dev (>= 0.22), gtk-doc-tools, + geoclue-2.0, libsecret-1-dev, gobject-introspection (>= 1.32.0), libgirepository1.0-dev (>= 0.9.12-4), @@ -47,7 +47,7 @@ libgles2-mesa-dev [armel armhf arm64] Build-Conflicts: gir-repository-dev Standards-Version: 3.9.8 -Homepage: http://webkitgtk.org/ +Homepage: https://webkitgtk.org/ Vcs-Browser: https://anonscm.debian.org/gitweb/?p=pkg-webkit/webkit.git Vcs-Git: https://alioth.debian.org/anonscm/git/pkg-webkit/webkit.git diff -Nru webkit2gtk-2.12.3/debian/copyright webkit2gtk-2.14.2/debian/copyright --- webkit2gtk-2.12.3/debian/copyright 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/copyright 2016-11-07 01:55:02.000000000 +0000 @@ -1,6 +1,6 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Contact: https://lists.webkit.org/mailman/listinfo/webkit-gtk -Source: http://webkitgtk.org/releases/ +Source: https://webkitgtk.org/releases/ Files: * Copyright: © 2002-2016 Apple Inc. and others diff -Nru webkit2gtk-2.12.3/debian/gbp.conf webkit2gtk-2.14.2/debian/gbp.conf --- webkit2gtk-2.12.3/debian/gbp.conf 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/gbp.conf 2016-11-07 01:55:02.000000000 +0000 @@ -1,5 +1,5 @@ [DEFAULT] debian-branch = wk2/unstable -upstream-branch = webkitgtk-2.12 +upstream-branch = webkitgtk-2.14 pristine-tar = False compression = xz diff -Nru webkit2gtk-2.12.3/debian/libjavascriptcoregtk-4.0-bin.install webkit2gtk-2.14.2/debian/libjavascriptcoregtk-4.0-bin.install --- webkit2gtk-2.12.3/debian/libjavascriptcoregtk-4.0-bin.install 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/libjavascriptcoregtk-4.0-bin.install 2016-11-07 01:55:02.000000000 +0000 @@ -1 +1 @@ -usr/bin/jsc +usr/lib/*/webkit2gtk-4.0/jsc usr/bin/ diff -Nru webkit2gtk-2.12.3/debian/libwebkit2gtk-4.0-37.symbols webkit2gtk-2.14.2/debian/libwebkit2gtk-4.0-37.symbols --- webkit2gtk-2.12.3/debian/libwebkit2gtk-4.0-37.symbols 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/libwebkit2gtk-4.0-37.symbols 2016-11-07 01:55:02.000000000 +0000 @@ -96,8 +96,11 @@ webkit_credential_new@Base 2.5.3 webkit_credential_persistence_get_type@Base 2.5.3 (optional)webkit_dom_attr_get_is_id@Base 2.5.3 + (optional)webkit_dom_attr_get_local_name@Base 2.13.91 webkit_dom_attr_get_name@Base 2.5.3 + (optional)webkit_dom_attr_get_namespace_uri@Base 2.13.91 webkit_dom_attr_get_owner_element@Base 2.5.3 + (optional)webkit_dom_attr_get_prefix@Base 2.13.91 webkit_dom_attr_get_specified@Base 2.5.3 webkit_dom_attr_get_type@Base 2.5.3 webkit_dom_attr_get_value@Base 2.5.3 @@ -192,7 +195,6 @@ webkit_dom_document_create_processing_instruction@Base 2.5.3 webkit_dom_document_create_range@Base 2.5.3 webkit_dom_document_create_text_node@Base 2.5.3 - (optional)webkit_dom_document_create_touch@Base 2.5.3 webkit_dom_document_create_tree_walker@Base 2.5.3 webkit_dom_document_element_from_point@Base 2.5.3 webkit_dom_document_evaluate@Base 2.5.3 @@ -220,6 +222,8 @@ (optional)webkit_dom_document_get_current_script@Base 2.5.3 webkit_dom_document_get_default_charset@Base 2.5.3 webkit_dom_document_get_default_view@Base 2.5.3 + (optional)webkit_dom_document_get_design_mode@Base 2.13.91 + webkit_dom_document_get_dir@Base 2.13.4 webkit_dom_document_get_doctype@Base 2.5.3 webkit_dom_document_get_document_element@Base 2.5.3 webkit_dom_document_get_document_uri@Base 2.5.3 @@ -232,6 +236,7 @@ webkit_dom_document_get_elements_by_tag_name_as_html_collection@Base 2.12.0 webkit_dom_document_get_elements_by_tag_name_ns@Base 2.5.3 webkit_dom_document_get_elements_by_tag_name_ns_as_html_collection@Base 2.12.0 + (optional)webkit_dom_document_get_embeds@Base 2.13.91 webkit_dom_document_get_first_element_child@Base 2.10.0 webkit_dom_document_get_forms@Base 2.5.3 webkit_dom_document_get_head@Base 2.5.3 @@ -244,10 +249,12 @@ webkit_dom_document_get_links@Base 2.5.3 (optional)webkit_dom_document_get_origin@Base 2.5.3 webkit_dom_document_get_override_style@Base 2.5.3 + (optional)webkit_dom_document_get_plugins@Base 2.13.91 (optional)webkit_dom_document_get_pointer_lock_element@Base 2.5.3 webkit_dom_document_get_preferred_stylesheet_set@Base 2.5.3 webkit_dom_document_get_ready_state@Base 2.5.3 webkit_dom_document_get_referrer@Base 2.5.3 + (optional)webkit_dom_document_get_scripts@Base 2.13.91 webkit_dom_document_get_scrolling_element@Base 2.10.0 webkit_dom_document_get_selected_stylesheet_set@Base 2.5.3 webkit_dom_document_get_style_sheets@Base 2.5.3 @@ -275,6 +282,8 @@ webkit_dom_document_set_body@Base 2.5.3 webkit_dom_document_set_charset@Base 2.5.3 webkit_dom_document_set_cookie@Base 2.5.3 + (optional)webkit_dom_document_set_design_mode@Base 2.13.91 + webkit_dom_document_set_dir@Base 2.13.4 webkit_dom_document_set_document_uri@Base 2.5.3 webkit_dom_document_set_selected_stylesheet_set@Base 2.5.3 webkit_dom_document_set_title@Base 2.5.3 @@ -290,12 +299,12 @@ (optional)webkit_dom_document_type_remove@Base 2.5.3 (optional)webkit_dom_document_webkit_cancel_full_screen@Base 2.5.3 (optional)webkit_dom_document_webkit_exit_fullscreen@Base 2.5.3 - (optional)webkit_dom_document_webkit_get_named_flows@Base 2.5.3 (optional)webkit_dom_dom_application_cache_abort@Base 2.5.3 (optional)webkit_dom_dom_application_cache_get_status@Base 2.5.3 (optional)webkit_dom_dom_application_cache_get_type@Base 2.5.3 (optional)webkit_dom_dom_application_cache_swap_cache@Base 2.5.3 (optional)webkit_dom_dom_application_cache_update@Base 2.5.3 + webkit_dom_dom_css_namespace_get_type@Base 2.13.4 webkit_dom_dom_implementation_create_css_style_sheet@Base 2.5.3 webkit_dom_dom_implementation_create_document@Base 2.5.3 webkit_dom_dom_implementation_create_document_type@Base 2.5.3 @@ -365,7 +374,9 @@ (optional)webkit_dom_dom_token_list_get_value@Base 2.12.0 (optional)webkit_dom_dom_token_list_item@Base 2.5.3 (optional)webkit_dom_dom_token_list_remove@Base 2.5.3 + (optional)webkit_dom_dom_token_list_replace@Base 2.13.91 (optional)webkit_dom_dom_token_list_set_value@Base 2.12.0 + webkit_dom_dom_token_list_toggle@Base 2.13.4 (optional)webkit_dom_dom_window_alert@Base 2.5.3 (optional)webkit_dom_dom_window_atob@Base 2.5.3 (optional)webkit_dom_dom_window_blur@Base 2.5.3 @@ -376,15 +387,12 @@ (optional)webkit_dom_dom_window_clear_timeout@Base 2.5.3 (optional)webkit_dom_dom_window_close@Base 2.5.3 (optional)webkit_dom_dom_window_confirm@Base 2.5.3 - (optional)webkit_dom_dom_window_css_get_type@Base 2.5.3 - (optional)webkit_dom_dom_window_css_supports@Base 2.5.3 (optional)webkit_dom_dom_window_find@Base 2.5.3 (optional)webkit_dom_dom_window_focus@Base 2.5.3 (optional)webkit_dom_dom_window_get_application_cache@Base 2.5.3 (optional)webkit_dom_dom_window_get_client_information@Base 2.5.3 (optional)webkit_dom_dom_window_get_closed@Base 2.5.3 (optional)webkit_dom_dom_window_get_computed_style@Base 2.5.3 - (optional)webkit_dom_dom_window_get_css@Base 2.5.3 (optional)webkit_dom_dom_window_get_default_status@Base 2.5.3 (optional)webkit_dom_dom_window_get_device_pixel_ratio@Base 2.5.3 (optional)webkit_dom_dom_window_get_document@Base 2.5.3 @@ -475,6 +483,8 @@ webkit_dom_element_get_id@Base 2.5.3 webkit_dom_element_get_inner_html@Base 2.8.1 webkit_dom_element_get_last_element_child@Base 2.5.3 + (optional)webkit_dom_element_get_local_name@Base 2.13.91 + (optional)webkit_dom_element_get_namespace_uri@Base 2.13.91 webkit_dom_element_get_next_element_sibling@Base 2.5.3 webkit_dom_element_get_offset_height@Base 2.5.3 webkit_dom_element_get_offset_left@Base 2.5.3 @@ -482,6 +492,7 @@ webkit_dom_element_get_offset_top@Base 2.5.3 webkit_dom_element_get_offset_width@Base 2.5.3 webkit_dom_element_get_outer_html@Base 2.8.1 + (optional)webkit_dom_element_get_prefix@Base 2.13.91 webkit_dom_element_get_previous_element_sibling@Base 2.5.3 webkit_dom_element_get_scroll_height@Base 2.5.3 webkit_dom_element_get_scroll_left@Base 2.5.3 @@ -494,6 +505,9 @@ webkit_dom_element_has_attribute@Base 2.5.3 webkit_dom_element_has_attribute_ns@Base 2.5.3 webkit_dom_element_has_attributes@Base 2.5.3 + (optional)webkit_dom_element_insert_adjacent_element@Base 2.13.91 + (optional)webkit_dom_element_insert_adjacent_html@Base 2.13.91 + (optional)webkit_dom_element_insert_adjacent_text@Base 2.13.91 (optional)webkit_dom_element_matches@Base 2.5.3 webkit_dom_element_query_selector@Base 2.5.3 webkit_dom_element_query_selector_all@Base 2.5.3 @@ -523,6 +537,7 @@ webkit_dom_event_get_bubbles@Base 2.5.3 webkit_dom_event_get_cancel_bubble@Base 2.5.3 webkit_dom_event_get_cancelable@Base 2.5.3 + webkit_dom_event_get_composed@Base 2.13.4 webkit_dom_event_get_current_target@Base 2.5.3 (optional)webkit_dom_event_get_default_prevented@Base 2.5.3 webkit_dom_event_get_event_phase@Base 2.5.3 @@ -545,6 +560,7 @@ webkit_dom_event_target_get_type@Base 2.5.3 webkit_dom_event_target_remove_event_listener@Base 2.5.3 webkit_dom_event_target_remove_event_listener_with_closure@Base 2.5.3 + webkit_dom_file_get_last_modified@Base 2.13.4 webkit_dom_file_get_name@Base 2.5.3 webkit_dom_file_get_type@Base 2.5.3 webkit_dom_file_list_get_length@Base 2.5.3 @@ -567,6 +583,7 @@ webkit_dom_html_anchor_element_get_hreflang@Base 2.5.3 webkit_dom_html_anchor_element_get_name@Base 2.5.3 (optional)webkit_dom_html_anchor_element_get_origin@Base 2.5.3 + webkit_dom_html_anchor_element_get_password@Base 2.13.4 webkit_dom_html_anchor_element_get_pathname@Base 2.5.3 (optional)webkit_dom_html_anchor_element_get_ping@Base 2.5.3 webkit_dom_html_anchor_element_get_port@Base 2.5.3 @@ -580,6 +597,7 @@ webkit_dom_html_anchor_element_get_text@Base 2.5.3 webkit_dom_html_anchor_element_get_type@Base 2.5.3 webkit_dom_html_anchor_element_get_type_attr@Base 2.5.3 + webkit_dom_html_anchor_element_get_username@Base 2.13.4 webkit_dom_html_anchor_element_set_charset@Base 2.5.3 webkit_dom_html_anchor_element_set_coords@Base 2.5.3 (optional)webkit_dom_html_anchor_element_set_download@Base 2.5.3 @@ -589,6 +607,7 @@ webkit_dom_html_anchor_element_set_href@Base 2.5.3 webkit_dom_html_anchor_element_set_hreflang@Base 2.5.3 webkit_dom_html_anchor_element_set_name@Base 2.5.3 + webkit_dom_html_anchor_element_set_password@Base 2.13.4 webkit_dom_html_anchor_element_set_pathname@Base 2.5.3 (optional)webkit_dom_html_anchor_element_set_ping@Base 2.5.3 webkit_dom_html_anchor_element_set_port@Base 2.5.3 @@ -600,6 +619,7 @@ webkit_dom_html_anchor_element_set_target@Base 2.5.3 webkit_dom_html_anchor_element_set_text@Base 2.8.1 webkit_dom_html_anchor_element_set_type_attr@Base 2.5.3 + webkit_dom_html_anchor_element_set_username@Base 2.13.4 webkit_dom_html_applet_element_get_align@Base 2.5.3 webkit_dom_html_applet_element_get_alt@Base 2.5.3 webkit_dom_html_applet_element_get_archive@Base 2.5.3 @@ -630,6 +650,8 @@ webkit_dom_html_area_element_get_hostname@Base 2.5.3 webkit_dom_html_area_element_get_href@Base 2.5.3 webkit_dom_html_area_element_get_no_href@Base 2.5.3 + webkit_dom_html_area_element_get_origin@Base 2.13.4 + webkit_dom_html_area_element_get_password@Base 2.13.4 webkit_dom_html_area_element_get_pathname@Base 2.5.3 (optional)webkit_dom_html_area_element_get_ping@Base 2.5.3 webkit_dom_html_area_element_get_port@Base 2.5.3 @@ -640,14 +662,24 @@ webkit_dom_html_area_element_get_shape@Base 2.5.3 webkit_dom_html_area_element_get_target@Base 2.5.3 webkit_dom_html_area_element_get_type@Base 2.5.3 + webkit_dom_html_area_element_get_username@Base 2.13.4 webkit_dom_html_area_element_set_alt@Base 2.5.3 webkit_dom_html_area_element_set_coords@Base 2.5.3 + webkit_dom_html_area_element_set_hash@Base 2.13.4 + webkit_dom_html_area_element_set_host@Base 2.13.4 + webkit_dom_html_area_element_set_hostname@Base 2.13.4 webkit_dom_html_area_element_set_href@Base 2.5.3 webkit_dom_html_area_element_set_no_href@Base 2.5.3 + webkit_dom_html_area_element_set_password@Base 2.13.4 + webkit_dom_html_area_element_set_pathname@Base 2.13.4 (optional)webkit_dom_html_area_element_set_ping@Base 2.5.3 + webkit_dom_html_area_element_set_port@Base 2.13.4 + webkit_dom_html_area_element_set_protocol@Base 2.13.4 webkit_dom_html_area_element_set_rel@Base 2.8.1 + webkit_dom_html_area_element_set_search@Base 2.13.4 webkit_dom_html_area_element_set_shape@Base 2.5.3 webkit_dom_html_area_element_set_target@Base 2.5.3 + webkit_dom_html_area_element_set_username@Base 2.13.4 (optional)webkit_dom_html_audio_element_get_type@Base 2.5.3 webkit_dom_html_base_element_get_href@Base 2.5.3 webkit_dom_html_base_element_get_target@Base 2.5.3 @@ -678,6 +710,7 @@ webkit_dom_html_br_element_get_type@Base 2.5.3 webkit_dom_html_br_element_set_clear@Base 2.5.3 (optional)webkit_dom_html_button_element_check_validity@Base 2.5.3 + (optional)webkit_dom_html_button_element_click@Base 2.13.91 webkit_dom_html_button_element_get_autofocus@Base 2.5.3 webkit_dom_html_button_element_get_button_type@Base 2.5.3 webkit_dom_html_button_element_get_disabled@Base 2.5.3 @@ -770,9 +803,6 @@ (optional)webkit_dom_html_element_get_translate@Base 2.5.3 webkit_dom_html_element_get_type@Base 2.5.3 (optional)webkit_dom_html_element_get_webkitdropzone@Base 2.5.3 - (optional)webkit_dom_html_element_insert_adjacent_element@Base 2.5.3 - (optional)webkit_dom_html_element_insert_adjacent_html@Base 2.5.3 - (optional)webkit_dom_html_element_insert_adjacent_text@Base 2.5.3 webkit_dom_html_element_set_access_key@Base 2.5.3 webkit_dom_html_element_set_content_editable@Base 2.5.3 webkit_dom_html_element_set_dir@Base 2.5.3 @@ -824,6 +854,7 @@ (optional)webkit_dom_html_form_element_check_validity@Base 2.5.3 webkit_dom_html_form_element_get_accept_charset@Base 2.5.3 webkit_dom_html_form_element_get_action@Base 2.5.3 + (optional)webkit_dom_html_input_element_get_auto_filled@Base 2.14.2 (optional)webkit_dom_html_form_element_get_autocapitalize@Base 2.5.3 (optional)webkit_dom_html_form_element_get_autocomplete@Base 2.5.3 (optional)webkit_dom_html_form_element_get_autocorrect@Base 2.5.3 @@ -840,6 +871,7 @@ webkit_dom_html_form_element_reset@Base 2.5.3 webkit_dom_html_form_element_set_accept_charset@Base 2.5.3 webkit_dom_html_form_element_set_action@Base 2.5.3 + (optional)webkit_dom_html_input_element_set_auto_filled@Base 2.14.2 (optional)webkit_dom_html_form_element_set_autocapitalize@Base 2.5.3 (optional)webkit_dom_html_form_element_set_autocomplete@Base 2.5.3 (optional)webkit_dom_html_form_element_set_autocorrect@Base 2.5.3 @@ -971,6 +1003,7 @@ (optional)webkit_dom_html_input_element_get_autocorrect@Base 2.5.3 webkit_dom_html_input_element_get_autofocus@Base 2.5.3 webkit_dom_html_input_element_get_capture@Base 2.5.3 + (optional)webkit_dom_html_input_element_get_capture_type@Base 2.13.91 webkit_dom_html_input_element_get_checked@Base 2.5.3 webkit_dom_html_input_element_get_default_checked@Base 2.5.3 webkit_dom_html_input_element_get_default_value@Base 2.5.3 @@ -1025,6 +1058,7 @@ webkit_dom_html_input_element_set_default_value@Base 2.5.3 (optional)webkit_dom_html_input_element_set_dir_name@Base 2.5.3 webkit_dom_html_input_element_set_disabled@Base 2.5.3 + (optional)webkit_dom_html_input_element_set_editing_value@Base 2.14.2 webkit_dom_html_input_element_set_files@Base 2.5.3 (optional)webkit_dom_html_input_element_set_form_action@Base 2.5.3 (optional)webkit_dom_html_input_element_set_form_enctype@Base 2.5.3 @@ -1088,7 +1122,9 @@ webkit_dom_html_li_element_get_value@Base 2.5.3 webkit_dom_html_li_element_set_type_attr@Base 2.5.3 webkit_dom_html_li_element_set_value@Base 2.5.3 + webkit_dom_html_link_element_get_as@Base 2.13.4 webkit_dom_html_link_element_get_charset@Base 2.5.3 + webkit_dom_html_link_element_get_cross_origin@Base 2.13.4 webkit_dom_html_link_element_get_disabled@Base 2.5.3 webkit_dom_html_link_element_get_href@Base 2.5.3 webkit_dom_html_link_element_get_hreflang@Base 2.5.3 @@ -1101,7 +1137,9 @@ webkit_dom_html_link_element_get_target@Base 2.5.3 webkit_dom_html_link_element_get_type@Base 2.5.3 webkit_dom_html_link_element_get_type_attr@Base 2.5.3 + webkit_dom_html_link_element_set_as@Base 2.13.4 webkit_dom_html_link_element_set_charset@Base 2.5.3 + webkit_dom_html_link_element_set_cross_origin@Base 2.13.4 webkit_dom_html_link_element_set_disabled@Base 2.5.3 webkit_dom_html_link_element_set_href@Base 2.5.3 webkit_dom_html_link_element_set_hreflang@Base 2.5.3 @@ -1146,6 +1184,7 @@ (optional)webkit_dom_html_media_element_get_buffered@Base 2.5.3 (optional)webkit_dom_html_media_element_get_controller@Base 2.5.3 (optional)webkit_dom_html_media_element_get_controls@Base 2.5.3 + webkit_dom_html_media_element_get_cross_origin@Base 2.13.4 (optional)webkit_dom_html_media_element_get_current_src@Base 2.5.3 (optional)webkit_dom_html_media_element_get_current_time@Base 2.5.3 (optional)webkit_dom_html_media_element_get_default_muted@Base 2.5.3 @@ -1176,9 +1215,9 @@ (optional)webkit_dom_html_media_element_get_webkit_video_decoded_byte_count@Base 2.5.3 (optional)webkit_dom_html_media_element_load@Base 2.5.3 (optional)webkit_dom_html_media_element_pause@Base 2.5.3 - (optional)webkit_dom_html_media_element_play@Base 2.5.3 (optional)webkit_dom_html_media_element_set_autoplay@Base 2.5.3 (optional)webkit_dom_html_media_element_set_controls@Base 2.5.3 + webkit_dom_html_media_element_set_cross_origin@Base 2.13.4 (optional)webkit_dom_html_media_element_set_current_time@Base 2.5.3 (optional)webkit_dom_html_media_element_set_default_muted@Base 2.5.3 (optional)webkit_dom_html_media_element_set_default_playback_rate@Base 2.5.3 @@ -1283,6 +1322,7 @@ webkit_dom_html_options_collection_get_selected_index@Base 2.5.3 webkit_dom_html_options_collection_get_type@Base 2.5.3 webkit_dom_html_options_collection_named_item@Base 2.5.3 + (optional)webkit_dom_html_options_collection_remove@Base 2.13.91 webkit_dom_html_options_collection_set_selected_index@Base 2.5.3 webkit_dom_html_paragraph_element_get_align@Base 2.5.3 webkit_dom_html_paragraph_element_get_type@Base 2.5.3 @@ -1362,11 +1402,13 @@ webkit_dom_html_select_element_set_value@Base 2.5.3 webkit_dom_html_style_element_get_disabled@Base 2.5.3 webkit_dom_html_style_element_get_media@Base 2.5.3 + webkit_dom_html_style_element_get_nonce@Base 2.13.4 webkit_dom_html_style_element_get_sheet@Base 2.5.3 webkit_dom_html_style_element_get_type@Base 2.5.3 webkit_dom_html_style_element_get_type_attr@Base 2.5.3 webkit_dom_html_style_element_set_disabled@Base 2.5.3 webkit_dom_html_style_element_set_media@Base 2.5.3 + webkit_dom_html_style_element_set_nonce@Base 2.13.4 webkit_dom_html_style_element_set_type_attr@Base 2.5.3 webkit_dom_html_table_caption_element_get_align@Base 2.5.3 webkit_dom_html_table_caption_element_get_type@Base 2.5.3 @@ -1539,6 +1581,7 @@ webkit_dom_html_u_list_element_set_compact@Base 2.5.3 webkit_dom_html_u_list_element_set_type_attr@Base 2.5.3 (optional)webkit_dom_html_video_element_get_height@Base 2.5.3 + webkit_dom_html_video_element_get_plays_inline@Base 2.13.4 (optional)webkit_dom_html_video_element_get_poster@Base 2.5.3 (optional)webkit_dom_html_video_element_get_type@Base 2.5.3 (optional)webkit_dom_html_video_element_get_video_height@Base 2.5.3 @@ -1550,6 +1593,7 @@ (optional)webkit_dom_html_video_element_get_webkit_wireless_video_playback_disabled@Base 2.5.3 (optional)webkit_dom_html_video_element_get_width@Base 2.5.3 (optional)webkit_dom_html_video_element_set_height@Base 2.5.3 + webkit_dom_html_video_element_set_plays_inline@Base 2.13.4 (optional)webkit_dom_html_video_element_set_poster@Base 2.5.3 (optional)webkit_dom_html_video_element_set_webkit_wireless_video_playback_disabled@Base 2.5.3 (optional)webkit_dom_html_video_element_set_width@Base 2.5.3 @@ -1567,7 +1611,6 @@ webkit_dom_keyboard_event_get_shift_key@Base 2.5.3 webkit_dom_keyboard_event_get_type@Base 2.5.3 webkit_dom_keyboard_event_init_keyboard_event@Base 2.5.3 - (optional)webkit_dom_location_get_ancestor_origins@Base 2.5.3 (optional)webkit_dom_location_get_hash@Base 2.5.3 (optional)webkit_dom_location_get_host@Base 2.5.3 (optional)webkit_dom_location_get_hostname@Base 2.5.3 @@ -1669,7 +1712,7 @@ (optional)webkit_dom_navigator_unregister_protocol_handler@Base 2.5.3 (optional)webkit_dom_navigator_vibrate@Base 2.5.3 webkit_dom_node_append_child@Base 2.5.3 - webkit_dom_node_clone_node@Base 2.5.3 + webkit_dom_node_clone_node_with_error@Base 2.13.4 webkit_dom_node_compare_document_position@Base 2.5.3 webkit_dom_node_contains@Base 2.5.3 webkit_dom_node_filter_accept_node@Base 2.5.3 @@ -1677,6 +1720,7 @@ webkit_dom_node_get_base_uri@Base 2.5.3 webkit_dom_node_get_child_nodes@Base 2.5.3 webkit_dom_node_get_first_child@Base 2.5.3 + webkit_dom_node_get_is_connected@Base 2.13.4 webkit_dom_node_get_last_child@Base 2.5.3 webkit_dom_node_get_local_name@Base 2.5.3 webkit_dom_node_get_namespace_uri@Base 2.5.3 @@ -1690,7 +1734,6 @@ webkit_dom_node_get_prefix@Base 2.5.3 webkit_dom_node_get_previous_sibling@Base 2.5.3 webkit_dom_node_get_text_content@Base 2.5.3 - webkit_dom_node_get_tree_root@Base 2.12.0 webkit_dom_node_get_type@Base 2.5.3 webkit_dom_node_has_child_nodes@Base 2.5.3 webkit_dom_node_insert_before@Base 2.5.3 @@ -1720,14 +1763,12 @@ webkit_dom_node_set_prefix@Base 2.5.3 webkit_dom_node_set_text_content@Base 2.5.3 webkit_dom_object_get_type@Base 2.5.3 + webkit_dom_performance_clear_resource_timings@Base 2.13.4 (optional)webkit_dom_performance_entry_get_duration@Base 2.5.3 (optional)webkit_dom_performance_entry_get_entry_type@Base 2.5.3 (optional)webkit_dom_performance_entry_get_name@Base 2.5.3 (optional)webkit_dom_performance_entry_get_start_time@Base 2.5.3 (optional)webkit_dom_performance_entry_get_type@Base 2.5.3 - (optional)webkit_dom_performance_entry_list_get_length@Base 2.5.3 - (optional)webkit_dom_performance_entry_list_get_type@Base 2.5.3 - (optional)webkit_dom_performance_entry_list_item@Base 2.5.3 (optional)webkit_dom_performance_get_navigation@Base 2.5.3 (optional)webkit_dom_performance_get_timing@Base 2.5.3 (optional)webkit_dom_performance_get_type@Base 2.5.3 @@ -1736,6 +1777,7 @@ (optional)webkit_dom_performance_navigation_get_redirect_count@Base 2.5.3 (optional)webkit_dom_performance_navigation_get_type@Base 2.5.3 (optional)webkit_dom_performance_now@Base 2.5.3 + webkit_dom_performance_set_resource_timing_buffer_size@Base 2.13.4 (optional)webkit_dom_performance_timing_get_connect_end@Base 2.5.3 (optional)webkit_dom_performance_timing_get_connect_start@Base 2.5.3 (optional)webkit_dom_performance_timing_get_dom_complete@Base 2.5.3 @@ -2200,6 +2242,7 @@ webkit_security_manager_uri_scheme_is_secure@Base 2.5.3 webkit_settings_get_allow_file_access_from_file_urls@Base 2.10.0 webkit_settings_get_allow_modal_dialogs@Base 2.5.3 + webkit_settings_get_allow_universal_access_from_file_urls@Base 2.13.4 webkit_settings_get_auto_load_images@Base 2.5.3 webkit_settings_get_cursive_font_family@Base 2.5.3 webkit_settings_get_default_charset@Base 2.5.3 @@ -2252,6 +2295,7 @@ webkit_settings_new_with_settings@Base 2.5.3 webkit_settings_set_allow_file_access_from_file_urls@Base 2.10.0 webkit_settings_set_allow_modal_dialogs@Base 2.5.3 + webkit_settings_set_allow_universal_access_from_file_urls@Base 2.13.4 webkit_settings_set_auto_load_images@Base 2.5.3 webkit_settings_set_cursive_font_family@Base 2.5.3 webkit_settings_set_default_charset@Base 2.5.3 diff -Nru webkit2gtk-2.12.3/debian/patches/fix-ftbfs-alpha.patch webkit2gtk-2.14.2/debian/patches/fix-ftbfs-alpha.patch --- webkit2gtk-2.12.3/debian/patches/fix-ftbfs-alpha.patch 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/fix-ftbfs-alpha.patch 2016-11-07 01:55:02.000000000 +0000 @@ -5,7 +5,7 @@ =================================================================== --- webkitgtk.orig/CMakeLists.txt +++ webkitgtk/CMakeLists.txt -@@ -43,6 +43,8 @@ if (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MAT +@@ -52,6 +52,8 @@ if (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MAT set(WTF_CPU_ARM 1) elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") set(WTF_CPU_ARM64 1) @@ -18,7 +18,7 @@ =================================================================== --- webkitgtk.orig/Source/JavaScriptCore/CMakeLists.txt +++ webkitgtk/Source/JavaScriptCore/CMakeLists.txt -@@ -1278,6 +1278,7 @@ endif () +@@ -1335,6 +1335,7 @@ endif () if (WTF_CPU_ARM) elseif (WTF_CPU_ARM64) diff -Nru webkit2gtk-2.12.3/debian/patches/fix-ftbfs-armel.patch webkit2gtk-2.14.2/debian/patches/fix-ftbfs-armel.patch --- webkit2gtk-2.12.3/debian/patches/fix-ftbfs-armel.patch 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/fix-ftbfs-armel.patch 2016-11-07 01:55:02.000000000 +0000 @@ -0,0 +1,31 @@ +From: Alberto Garcia +Subject: Build wtf/Atomics.cpp only if needed +Bug: https://bugs.webkit.org/show_bug.cgi?id=161900 +Index: webkitgtk/Source/WTF/wtf/CMakeLists.txt +=================================================================== +--- webkitgtk.orig/Source/WTF/wtf/CMakeLists.txt ++++ webkitgtk/Source/WTF/wtf/CMakeLists.txt +@@ -171,7 +171,6 @@ set(WTF_HEADERS + + set(WTF_SOURCES + Assertions.cpp +- Atomics.cpp + BitVector.cpp + CompilationThread.cpp + CrossThreadCopier.cpp +@@ -276,6 +275,15 @@ if (NOT USE_SYSTEM_MALLOC) + list(APPEND WTF_LIBRARIES bmalloc) + endif () + ++file(WRITE ${CMAKE_BINARY_DIR}/test_atomics.cpp ++ "int main(void)\n" ++ "{ long long x = 1; return (int) __sync_add_and_fetch_8(&x, 1); }\n") ++try_compile(ATOMICS_BUILD_SUCCEEDED ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/test_atomics.cpp) ++if (NOT ATOMICS_BUILD_SUCCEEDED) ++ list(APPEND WTF_SOURCES Atomics.cpp) ++endif () ++file(REMOVE ${CMAKE_BINARY_DIR}/test_atomics.cpp) ++ + list(APPEND WTF_SOURCES + unicode/icu/CollatorICU.cpp + ) diff -Nru webkit2gtk-2.12.3/debian/patches/fix-ftbfs-m68k.patch webkit2gtk-2.14.2/debian/patches/fix-ftbfs-m68k.patch --- webkit2gtk-2.12.3/debian/patches/fix-ftbfs-m68k.patch 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/fix-ftbfs-m68k.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,180 +0,0 @@ -From: Andreas Schwab -Subject: Fix FTBFS in m68k -Forwarded: no -Index: webkitgtk/CMakeLists.txt -=================================================================== ---- webkitgtk.orig/CMakeLists.txt -+++ webkitgtk/CMakeLists.txt -@@ -57,6 +57,8 @@ elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR - set(WTF_CPU_PPC64 1) - elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le") - set(WTF_CPU_PPC64LE 1) -+elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "m68k") -+ set(WTF_CPU_M68K 1) - elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "parisc*") - set(WTF_CPU_HPPA 1) - elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "s390") -Index: webkitgtk/Source/JavaScriptCore/CMakeLists.txt -=================================================================== ---- webkitgtk.orig/Source/JavaScriptCore/CMakeLists.txt -+++ webkitgtk/Source/JavaScriptCore/CMakeLists.txt -@@ -1282,6 +1282,7 @@ elseif (WTF_CPU_HPPA) - elseif (WTF_CPU_PPC) - elseif (WTF_CPU_PPC64) - elseif (WTF_CPU_PPC64LE) -+elseif (WTF_CPU_M68K) - elseif (WTF_CPU_S390) - elseif (WTF_CPU_S390X) - elseif (WTF_CPU_MIPS) -Index: webkitgtk/Source/WTF/wtf/Platform.h -=================================================================== ---- webkitgtk.orig/Source/WTF/wtf/Platform.h -+++ webkitgtk/Source/WTF/wtf/Platform.h -@@ -346,6 +346,12 @@ - #define WTF_CPU_NEEDS_ALIGNED_ACCESS 1 - #endif - -+/* CPU(M68K) - m68k */ -+#if defined(__mc68000__) -+#define WTF_CPU_M68K 1 -+#define WTF_CPU_BIG_ENDIAN 1 -+#endif -+ - /* ==== OS() - underlying operating system; only to be used for mandated low-level services like - virtual memory, not to choose a GUI toolkit ==== */ - -Index: webkitgtk/Source/WTF/wtf/dtoa/utils.h -=================================================================== ---- webkitgtk.orig/Source/WTF/wtf/dtoa/utils.h -+++ webkitgtk/Source/WTF/wtf/dtoa/utils.h -@@ -58,6 +58,8 @@ defined(_MIPS_ARCH_MIPS32R2) - #else - #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS - #endif // _WIN32 -+#elif defined(__mc68000__) -+#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS - #else - #error Target architecture was not detected as supported by Double-Conversion. - #endif -Index: webkitgtk/Source/WebCore/css/CSSProperty.cpp -=================================================================== ---- webkitgtk.orig/Source/WebCore/css/CSSProperty.cpp -+++ webkitgtk/Source/WebCore/css/CSSProperty.cpp -@@ -35,7 +35,11 @@ struct SameSizeAsCSSProperty { - void* value; - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(CSSProperty) <= sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small); -+#else - COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small); -+#endif - - CSSPropertyID StylePropertyMetadata::shorthandID() const - { -Index: webkitgtk/Source/WebCore/css/RuleSet.h -=================================================================== ---- webkitgtk.orig/Source/WebCore/css/RuleSet.h -+++ webkitgtk/Source/WebCore/css/RuleSet.h -@@ -143,7 +143,11 @@ struct SameSizeAsRuleData { - unsigned d[4]; - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(RuleData) <= sizeof(SameSizeAsRuleData), RuleData_should_stay_small); -+#else - COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small); -+#endif - - class RuleSet { - WTF_MAKE_NONCOPYABLE(RuleSet); WTF_MAKE_FAST_ALLOCATED; -Index: webkitgtk/Source/WebCore/dom/ElementRareData.cpp -=================================================================== ---- webkitgtk.orig/Source/WebCore/dom/ElementRareData.cpp -+++ webkitgtk/Source/WebCore/dom/ElementRareData.cpp -@@ -42,6 +42,10 @@ struct SameSizeAsElementRareData : NodeR - void* pointers[7]; - }; - -+#if CPU(M68K) -+static_assert(sizeof(ElementRareData) <= sizeof(SameSizeAsElementRareData), "ElementRareData should stay small"); -+#else - static_assert(sizeof(ElementRareData) == sizeof(SameSizeAsElementRareData), "ElementRareData should stay small"); -+#endif - - } // namespace WebCore -Index: webkitgtk/Source/WebCore/dom/NodeRareData.cpp -=================================================================== ---- webkitgtk.orig/Source/WebCore/dom/NodeRareData.cpp -+++ webkitgtk/Source/WebCore/dom/NodeRareData.cpp -@@ -38,6 +38,10 @@ struct SameSizeAsNodeRareData { - void* m_pointer[3]; - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(NodeRareData) <= sizeof(SameSizeAsNodeRareData), NodeRareDataShouldStaySmall); -+#else - COMPILE_ASSERT(sizeof(NodeRareData) == sizeof(SameSizeAsNodeRareData), NodeRareDataShouldStaySmall); -+#endif - - } // namespace WebCore -Index: webkitgtk/Source/WebCore/dom/ShadowRoot.cpp -=================================================================== ---- webkitgtk.orig/Source/WebCore/dom/ShadowRoot.cpp -+++ webkitgtk/Source/WebCore/dom/ShadowRoot.cpp -@@ -49,7 +49,11 @@ struct SameSizeAsShadowRoot : public Doc - #endif - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(ShadowRoot) <= sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small); -+#else - COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small); -+#endif - - ShadowRoot::ShadowRoot(Document& document, Type type) - : DocumentFragment(document, CreateShadowRoot) -Index: webkitgtk/Source/WebCore/rendering/style/RenderStyle.cpp -=================================================================== ---- webkitgtk.orig/Source/WebCore/rendering/style/RenderStyle.cpp -+++ webkitgtk/Source/WebCore/rendering/style/RenderStyle.cpp -@@ -66,7 +66,11 @@ struct SameSizeAsBorderValue { - int m_restBits; - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(BorderValue) <= sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow); -+#else - COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow); -+#endif - - struct SameSizeAsRenderStyle : public RefCounted { - void* dataRefs[7]; -@@ -81,7 +85,11 @@ struct SameSizeAsRenderStyle : public Re - } noninherited_flags; - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(RenderStyle) <= sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small); -+#else - COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small); -+#endif - - inline RenderStyle& defaultStyle() - { -Index: webkitgtk/Source/WebCore/rendering/style/StyleBoxData.cpp -=================================================================== ---- webkitgtk.orig/Source/WebCore/rendering/style/StyleBoxData.cpp -+++ webkitgtk/Source/WebCore/rendering/style/StyleBoxData.cpp -@@ -33,7 +33,11 @@ struct SameSizeAsStyleBoxData : public R - uint32_t bitfields; - }; - -+#if CPU(M68K) -+COMPILE_ASSERT(sizeof(StyleBoxData) <= sizeof(SameSizeAsStyleBoxData), StyleBoxData_should_not_grow); -+#else - COMPILE_ASSERT(sizeof(StyleBoxData) == sizeof(SameSizeAsStyleBoxData), StyleBoxData_should_not_grow); -+#endif - - StyleBoxData::StyleBoxData() - : m_minWidth(RenderStyle::initialMinSize()) diff -Nru webkit2gtk-2.12.3/debian/patches/fix-ftbfs-sparc64.patch webkit2gtk-2.14.2/debian/patches/fix-ftbfs-sparc64.patch --- webkit2gtk-2.12.3/debian/patches/fix-ftbfs-sparc64.patch 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/fix-ftbfs-sparc64.patch 2016-11-07 01:55:02.000000000 +0000 @@ -27,7 +27,7 @@ #define WTF_CPU_NEEDS_ALIGNED_ACCESS 1 #endif -@@ -703,6 +709,7 @@ +@@ -695,6 +701,7 @@ || CPU(ALPHA) \ || CPU(ARM64) \ || CPU(S390X) \ @@ -39,7 +39,7 @@ =================================================================== --- webkitgtk.orig/CMakeLists.txt +++ webkitgtk/CMakeLists.txt -@@ -65,6 +65,8 @@ elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR +@@ -72,6 +72,8 @@ elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR set(WTF_CPU_S390 1) elseif (LOWERCASE_CMAKE_SYSTEM_PROCESSOR MATCHES "s390x") set(WTF_CPU_S390X 1) @@ -52,7 +52,7 @@ =================================================================== --- webkitgtk.orig/Source/JavaScriptCore/CMakeLists.txt +++ webkitgtk/Source/JavaScriptCore/CMakeLists.txt -@@ -1287,6 +1287,7 @@ elseif (WTF_CPU_S390) +@@ -1343,6 +1343,7 @@ elseif (WTF_CPU_S390) elseif (WTF_CPU_S390X) elseif (WTF_CPU_MIPS) elseif (WTF_CPU_SH4) diff -Nru webkit2gtk-2.12.3/debian/patches/hide-gtk2-plugins.patch webkit2gtk-2.14.2/debian/patches/hide-gtk2-plugins.patch --- webkit2gtk-2.12.3/debian/patches/hide-gtk2-plugins.patch 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/hide-gtk2-plugins.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -From: Alberto Garcia -Subject: Hide plugins if the plugin process is not available -Forwarded: no -Index: webkitgtk/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp -=================================================================== ---- webkitgtk.orig/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp -+++ webkitgtk/Source/WebKit2/UIProcess/Plugins/unix/PluginProcessProxyUnix.cpp -@@ -83,13 +83,16 @@ bool PluginProcessProxy::scanPlugin(cons - - #if PLATFORM(GTK) - bool requiresGtk2 = pluginRequiresGtk2(pluginPath); -- if (requiresGtk2) -+ if (requiresGtk2) { - #if ENABLE(PLUGIN_PROCESS_GTK2) - pluginProcessPath.append('2'); -+ if (!fileExists(pluginProcessPath)) -+ return false; - #else - return false; - #endif - #endif -+ } - - CString binaryPath = fileSystemRepresentation(pluginProcessPath); - CString pluginPathCString = fileSystemRepresentation(pluginPath); -Index: webkitgtk/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp -=================================================================== ---- webkitgtk.orig/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp -+++ webkitgtk/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp -@@ -33,6 +33,7 @@ - - #include "NetscapePluginModule.h" - #include "PluginSearchPath.h" -+#include "ProcessExecutablePath.h" - #include - - #if PLATFORM(GTK) -@@ -69,8 +70,17 @@ Vector PluginInfoStore::individu - bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin) - { - #if PLATFORM(GTK) -- if (PluginInfoCache::singleton().getPluginInfo(pluginPath, plugin)) -+ if (PluginInfoCache::singleton().getPluginInfo(pluginPath, plugin)) { -+#if ENABLE(PLUGIN_PROCESS_GTK2) -+ if (plugin.requiresGtk2) { -+ String pluginProcessPath = executablePathOfPluginProcess(); -+ pluginProcessPath.append('2'); -+ if (!fileExists(pluginProcessPath)) -+ return false; -+ } -+#endif - return true; -+ } - - if (NetscapePluginModule::getPluginInfo(pluginPath, plugin)) { - PluginInfoCache::singleton().updatePluginInfo(pluginPath, plugin); diff -Nru webkit2gtk-2.12.3/debian/patches/install-minibrowser.patch webkit2gtk-2.14.2/debian/patches/install-minibrowser.patch --- webkit2gtk-2.12.3/debian/patches/install-minibrowser.patch 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/install-minibrowser.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -From: Alberto Garcia -Subject: Install the MiniBrowser binary -Forwarded: not-needed -Index: webkitgtk/Tools/MiniBrowser/gtk/CMakeLists.txt -=================================================================== ---- webkitgtk.orig/Tools/MiniBrowser/gtk/CMakeLists.txt -+++ webkitgtk/Tools/MiniBrowser/gtk/CMakeLists.txt -@@ -60,4 +60,4 @@ add_executable(MiniBrowser ${MiniBrowser - target_link_libraries(MiniBrowser ${MiniBrowser_LIBRARIES}) - set_target_properties(MiniBrowser PROPERTIES FOLDER "Tools") - --install(TARGETS MiniBrowser DESTINATION "${EXEC_INSTALL_DIR}") -+install(TARGETS MiniBrowser DESTINATION "${LIBEXEC_INSTALL_DIR}") -Index: webkitgtk/Source/cmake/OptionsGTK.cmake -=================================================================== ---- webkitgtk.orig/Source/cmake/OptionsGTK.cmake -+++ webkitgtk/Source/cmake/OptionsGTK.cmake -@@ -114,7 +114,7 @@ if (DEVELOPER_MODE) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MINIBROWSER PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_API_TESTS PRIVATE ON) - else () -- WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MINIBROWSER PUBLIC OFF) -+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MINIBROWSER PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_API_TESTS PRIVATE OFF) - if (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") - set(WebKit2_VERSION_SCRIPT "-Wl,--version-script,${CMAKE_MODULE_PATH}/gtksymbols.filter") diff -Nru webkit2gtk-2.12.3/debian/patches/series webkit2gtk-2.14.2/debian/patches/series --- webkit2gtk-2.12.3/debian/patches/series 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/patches/series 2016-11-07 01:55:02.000000000 +0000 @@ -1,5 +1,3 @@ -install-minibrowser.patch -fix-ftbfs-m68k.patch -hide-gtk2-plugins.patch fix-ftbfs-sparc64.patch fix-ftbfs-alpha.patch +fix-ftbfs-armel.patch diff -Nru webkit2gtk-2.12.3/debian/rules webkit2gtk-2.14.2/debian/rules --- webkit2gtk-2.12.3/debian/rules 2016-06-20 17:33:16.000000000 +0000 +++ webkit2gtk-2.14.2/debian/rules 2016-11-07 01:55:02.000000000 +0000 @@ -6,8 +6,8 @@ DEB_HOST_ARCH_BITS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_BITS) DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) -CPPFLAGS = $(shell dpkg-buildflags --get CPPFLAGS) -Wall -g1 -CFLAGS = $(shell dpkg-buildflags --get CFLAGS) -g1 +CPPFLAGS = $(shell dpkg-buildflags --get CPPFLAGS) -Wall +CFLAGS = $(shell dpkg-buildflags --get CFLAGS) LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed DEBHELPER_VERSION = $(shell dpkg-query -W -f='$${source:Version}' debhelper) @@ -24,7 +24,7 @@ LDFLAGS += -Wl,--no-relax endif -ifeq ($(DEB_BUILD_ARCH),arm64) +ifneq (,$(filter $(DEB_BUILD_ARCH),arm64 mips mipsel)) EXTRA_CMAKE_ARGUMENTS += -DUSE_LD_GOLD=OFF endif @@ -72,6 +72,7 @@ -DCMAKE_C_FLAGS_DEBUG="" \ -DCMAKE_CXX_FLAGS_RELEASE="" \ -DCMAKE_CXX_FLAGS_DEBUG="" \ + -DENABLE_MINIBROWSER=ON \ $(EXTRA_CMAKE_ARGUMENTS) override_dh_strip: diff -Nru webkit2gtk-2.12.3/debian/source/lintian-overrides webkit2gtk-2.14.2/debian/source/lintian-overrides --- webkit2gtk-2.12.3/debian/source/lintian-overrides 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/source/lintian-overrides 2016-11-07 01:55:02.000000000 +0000 @@ -2,6 +2,7 @@ webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/External/CodeMirror/sql.js line length is 3058 characters (>512) webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/External/ESLint/eslint.js line length is 804 characters (>512) webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/External/Esprima/esprima.js line length is 6439 characters (>512) +webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/Protocol/Legacy/10.0/InspectorBackendCommands.js line length is 646 characters (>512) webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/Protocol/Legacy/7.0/InspectorBackendCommands.js line length is 550 characters (>512) webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/Protocol/Legacy/8.0/InspectorBackendCommands.js line length is 565 characters (>512) webkit2gtk source: source-is-missing Source/WebInspectorUI/UserInterface/Protocol/Legacy/9.0/InspectorBackendCommands.js line length is 646 characters (>512) diff -Nru webkit2gtk-2.12.3/debian/watch webkit2gtk-2.14.2/debian/watch --- webkit2gtk-2.12.3/debian/watch 2016-05-24 09:17:47.000000000 +0000 +++ webkit2gtk-2.14.2/debian/watch 2016-11-07 01:55:02.000000000 +0000 @@ -1,2 +1,2 @@ version=3 -http://webkitgtk.org/releases/ webkitgtk-([\d]+\.[\d]*[02468]\.[\d]+).tar.xz +https://webkitgtk.org/releases/ webkitgtk-([\d]+\.[\d]*[02468]\.[\d]+).tar.xz diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/index-all.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/index-all.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/index-all.html 2016-05-24 08:28:03.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/index-all.html 2016-11-03 07:32:06.000000000 +0000 @@ -26,66 +26,66 @@

A

-
WebKitAuthenticationRequest, struct WebKitAuthenticationRequest +
WebKitAuthenticationRequest, struct WebKitAuthenticationRequest
-
WebKitAuthenticationRequest::cancelled, The “cancelled” signal +
WebKitAuthenticationRequest::cancelled, The “cancelled” signal
-
WebKitAuthenticationScheme, enum WebKitAuthenticationScheme +
WebKitAuthenticationScheme, enum WebKitAuthenticationScheme
-
webkit_authentication_request_authenticate, webkit_authentication_request_authenticate () +
webkit_authentication_request_authenticate, webkit_authentication_request_authenticate ()
-
webkit_authentication_request_cancel, webkit_authentication_request_cancel () +
webkit_authentication_request_cancel, webkit_authentication_request_cancel ()
-
webkit_authentication_request_can_save_credentials, webkit_authentication_request_can_save_credentials () +
webkit_authentication_request_can_save_credentials, webkit_authentication_request_can_save_credentials ()
-
webkit_authentication_request_get_host, webkit_authentication_request_get_host () +
webkit_authentication_request_get_host, webkit_authentication_request_get_host ()
-
webkit_authentication_request_get_port, webkit_authentication_request_get_port () +
webkit_authentication_request_get_port, webkit_authentication_request_get_port ()
-
webkit_authentication_request_get_proposed_credential, webkit_authentication_request_get_proposed_credential () +
webkit_authentication_request_get_proposed_credential, webkit_authentication_request_get_proposed_credential ()
-
webkit_authentication_request_get_realm, webkit_authentication_request_get_realm () +
webkit_authentication_request_get_realm, webkit_authentication_request_get_realm ()
-
webkit_authentication_request_get_scheme, webkit_authentication_request_get_scheme () +
webkit_authentication_request_get_scheme, webkit_authentication_request_get_scheme ()
-
webkit_authentication_request_is_for_proxy, webkit_authentication_request_is_for_proxy () +
webkit_authentication_request_is_for_proxy, webkit_authentication_request_is_for_proxy ()
-
webkit_authentication_request_is_retry, webkit_authentication_request_is_retry () +
webkit_authentication_request_is_retry, webkit_authentication_request_is_retry ()

B

-
WebKitBackForwardList, struct WebKitBackForwardList +
WebKitBackForwardList, struct WebKitBackForwardList
-
WebKitBackForwardList::changed, The “changed” signal +
WebKitBackForwardList::changed, The “changed” signal
-
WebKitBackForwardListItem, struct WebKitBackForwardListItem +
WebKitBackForwardListItem, struct WebKitBackForwardListItem
-
webkit_back_forward_list_get_back_item, webkit_back_forward_list_get_back_item () +
webkit_back_forward_list_get_back_item, webkit_back_forward_list_get_back_item ()
-
webkit_back_forward_list_get_back_list, webkit_back_forward_list_get_back_list () +
webkit_back_forward_list_get_back_list, webkit_back_forward_list_get_back_list ()
-
webkit_back_forward_list_get_back_list_with_limit, webkit_back_forward_list_get_back_list_with_limit () +
webkit_back_forward_list_get_back_list_with_limit, webkit_back_forward_list_get_back_list_with_limit ()
-
webkit_back_forward_list_get_current_item, webkit_back_forward_list_get_current_item () +
webkit_back_forward_list_get_current_item, webkit_back_forward_list_get_current_item ()
-
webkit_back_forward_list_get_forward_item, webkit_back_forward_list_get_forward_item () +
webkit_back_forward_list_get_forward_item, webkit_back_forward_list_get_forward_item ()
-
webkit_back_forward_list_get_forward_list, webkit_back_forward_list_get_forward_list () +
webkit_back_forward_list_get_forward_list, webkit_back_forward_list_get_forward_list ()
-
webkit_back_forward_list_get_forward_list_with_limit, webkit_back_forward_list_get_forward_list_with_limit () +
webkit_back_forward_list_get_forward_list_with_limit, webkit_back_forward_list_get_forward_list_with_limit ()
-
webkit_back_forward_list_get_length, webkit_back_forward_list_get_length () +
webkit_back_forward_list_get_length, webkit_back_forward_list_get_length ()
-
webkit_back_forward_list_get_nth_item, webkit_back_forward_list_get_nth_item () +
webkit_back_forward_list_get_nth_item, webkit_back_forward_list_get_nth_item ()
-
webkit_back_forward_list_item_get_original_uri, webkit_back_forward_list_item_get_original_uri () +
webkit_back_forward_list_item_get_original_uri, webkit_back_forward_list_item_get_original_uri ()
-
webkit_back_forward_list_item_get_title, webkit_back_forward_list_item_get_title () +
webkit_back_forward_list_item_get_title, webkit_back_forward_list_item_get_title ()
-
webkit_back_forward_list_item_get_uri, webkit_back_forward_list_item_get_uri () +
webkit_back_forward_list_item_get_uri, webkit_back_forward_list_item_get_uri ()
@@ -94,592 +94,592 @@
WebKitCacheModel, enum WebKitCacheModel
-
WEBKIT_CHECK_VERSION, WEBKIT_CHECK_VERSION() +
WEBKIT_CHECK_VERSION, WEBKIT_CHECK_VERSION()
-
WebKitColorChooserRequest, struct WebKitColorChooserRequest +
WebKitColorChooserRequest, struct WebKitColorChooserRequest
-
WebKitColorChooserRequest::finished, The “finished” signal +
WebKitColorChooserRequest::finished, The “finished” signal
-
WebKitColorChooserRequest:rgba, The “rgba” property +
WebKitColorChooserRequest:rgba, The “rgba” property
-
webkit_color_chooser_request_cancel, webkit_color_chooser_request_cancel () +
webkit_color_chooser_request_cancel, webkit_color_chooser_request_cancel ()
-
webkit_color_chooser_request_finish, webkit_color_chooser_request_finish () +
webkit_color_chooser_request_finish, webkit_color_chooser_request_finish ()
-
webkit_color_chooser_request_get_element_rectangle, webkit_color_chooser_request_get_element_rectangle () +
webkit_color_chooser_request_get_element_rectangle, webkit_color_chooser_request_get_element_rectangle ()
-
webkit_color_chooser_request_get_rgba, webkit_color_chooser_request_get_rgba () +
webkit_color_chooser_request_get_rgba, webkit_color_chooser_request_get_rgba ()
-
webkit_color_chooser_request_set_rgba, webkit_color_chooser_request_set_rgba () +
webkit_color_chooser_request_set_rgba, webkit_color_chooser_request_set_rgba ()
-
WebKitConsoleMessage, WebKitConsoleMessage +
WebKitConsoleMessage, WebKitConsoleMessage
-
WebKitConsoleMessageLevel, enum WebKitConsoleMessageLevel +
WebKitConsoleMessageLevel, enum WebKitConsoleMessageLevel
-
WebKitConsoleMessageSource, enum WebKitConsoleMessageSource +
WebKitConsoleMessageSource, enum WebKitConsoleMessageSource
-
webkit_console_message_copy, webkit_console_message_copy () +
webkit_console_message_copy, webkit_console_message_copy ()
-
webkit_console_message_free, webkit_console_message_free () +
webkit_console_message_free, webkit_console_message_free ()
-
webkit_console_message_get_level, webkit_console_message_get_level () +
webkit_console_message_get_level, webkit_console_message_get_level ()
-
webkit_console_message_get_line, webkit_console_message_get_line () +
webkit_console_message_get_line, webkit_console_message_get_line ()
-
webkit_console_message_get_source, webkit_console_message_get_source () +
webkit_console_message_get_source, webkit_console_message_get_source ()
-
webkit_console_message_get_source_id, webkit_console_message_get_source_id () +
webkit_console_message_get_source_id, webkit_console_message_get_source_id ()
-
webkit_console_message_get_text, webkit_console_message_get_text () +
webkit_console_message_get_text, webkit_console_message_get_text ()
-
WebKitContextMenu, WebKitContextMenu +
WebKitContextMenu, WebKitContextMenu
-
WebKitContextMenuAction, enum WebKitContextMenuAction +
WebKitContextMenuAction, enum WebKitContextMenuAction
-
WebKitContextMenuItem, WebKitContextMenuItem +
WebKitContextMenuItem, WebKitContextMenuItem
-
webkit_context_menu_append, webkit_context_menu_append () +
webkit_context_menu_append, webkit_context_menu_append ()
-
webkit_context_menu_first, webkit_context_menu_first () +
webkit_context_menu_first, webkit_context_menu_first ()
-
webkit_context_menu_get_items, webkit_context_menu_get_items () +
webkit_context_menu_get_items, webkit_context_menu_get_items ()
-
webkit_context_menu_get_item_at_position, webkit_context_menu_get_item_at_position () +
webkit_context_menu_get_item_at_position, webkit_context_menu_get_item_at_position ()
-
webkit_context_menu_get_n_items, webkit_context_menu_get_n_items () +
webkit_context_menu_get_n_items, webkit_context_menu_get_n_items ()
-
webkit_context_menu_get_user_data, webkit_context_menu_get_user_data () +
webkit_context_menu_get_user_data, webkit_context_menu_get_user_data ()
-
webkit_context_menu_insert, webkit_context_menu_insert () +
webkit_context_menu_insert, webkit_context_menu_insert ()
-
webkit_context_menu_item_get_action, webkit_context_menu_item_get_action () +
webkit_context_menu_item_get_action, webkit_context_menu_item_get_action ()
-
webkit_context_menu_item_get_stock_action, webkit_context_menu_item_get_stock_action () +
webkit_context_menu_item_get_stock_action, webkit_context_menu_item_get_stock_action ()
-
webkit_context_menu_item_get_submenu, webkit_context_menu_item_get_submenu () +
webkit_context_menu_item_get_submenu, webkit_context_menu_item_get_submenu ()
-
webkit_context_menu_item_is_separator, webkit_context_menu_item_is_separator () +
webkit_context_menu_item_is_separator, webkit_context_menu_item_is_separator ()
-
webkit_context_menu_item_new, webkit_context_menu_item_new () +
webkit_context_menu_item_new, webkit_context_menu_item_new ()
-
webkit_context_menu_item_new_from_stock_action, webkit_context_menu_item_new_from_stock_action () +
webkit_context_menu_item_new_from_stock_action, webkit_context_menu_item_new_from_stock_action ()
-
webkit_context_menu_item_new_from_stock_action_with_label, webkit_context_menu_item_new_from_stock_action_with_label () +
webkit_context_menu_item_new_from_stock_action_with_label, webkit_context_menu_item_new_from_stock_action_with_label ()
-
webkit_context_menu_item_new_separator, webkit_context_menu_item_new_separator () +
webkit_context_menu_item_new_separator, webkit_context_menu_item_new_separator ()
-
webkit_context_menu_item_new_with_submenu, webkit_context_menu_item_new_with_submenu () +
webkit_context_menu_item_new_with_submenu, webkit_context_menu_item_new_with_submenu ()
-
webkit_context_menu_item_set_submenu, webkit_context_menu_item_set_submenu () +
webkit_context_menu_item_set_submenu, webkit_context_menu_item_set_submenu ()
-
webkit_context_menu_last, webkit_context_menu_last () +
webkit_context_menu_last, webkit_context_menu_last ()
-
webkit_context_menu_move_item, webkit_context_menu_move_item () +
webkit_context_menu_move_item, webkit_context_menu_move_item ()
-
webkit_context_menu_new, webkit_context_menu_new () +
webkit_context_menu_new, webkit_context_menu_new ()
-
webkit_context_menu_new_with_items, webkit_context_menu_new_with_items () +
webkit_context_menu_new_with_items, webkit_context_menu_new_with_items ()
-
webkit_context_menu_prepend, webkit_context_menu_prepend () +
webkit_context_menu_prepend, webkit_context_menu_prepend ()
-
webkit_context_menu_remove, webkit_context_menu_remove () +
webkit_context_menu_remove, webkit_context_menu_remove ()
-
webkit_context_menu_remove_all, webkit_context_menu_remove_all () +
webkit_context_menu_remove_all, webkit_context_menu_remove_all ()
-
webkit_context_menu_set_user_data, webkit_context_menu_set_user_data () +
webkit_context_menu_set_user_data, webkit_context_menu_set_user_data ()
-
WebKitCookieAcceptPolicy, enum WebKitCookieAcceptPolicy +
WebKitCookieAcceptPolicy, enum WebKitCookieAcceptPolicy
-
WebKitCookieManager, struct WebKitCookieManager +
WebKitCookieManager, struct WebKitCookieManager
-
WebKitCookieManager::changed, The “changed” signal +
WebKitCookieManager::changed, The “changed” signal
-
WebKitCookiePersistentStorage, enum WebKitCookiePersistentStorage +
WebKitCookiePersistentStorage, enum WebKitCookiePersistentStorage
-
webkit_cookie_manager_delete_all_cookies, webkit_cookie_manager_delete_all_cookies () +
webkit_cookie_manager_delete_all_cookies, webkit_cookie_manager_delete_all_cookies ()
-
webkit_cookie_manager_delete_cookies_for_domain, webkit_cookie_manager_delete_cookies_for_domain () +
webkit_cookie_manager_delete_cookies_for_domain, webkit_cookie_manager_delete_cookies_for_domain ()
-
webkit_cookie_manager_get_accept_policy, webkit_cookie_manager_get_accept_policy () +
webkit_cookie_manager_get_accept_policy, webkit_cookie_manager_get_accept_policy ()
-
webkit_cookie_manager_get_accept_policy_finish, webkit_cookie_manager_get_accept_policy_finish () +
webkit_cookie_manager_get_accept_policy_finish, webkit_cookie_manager_get_accept_policy_finish ()
-
webkit_cookie_manager_get_domains_with_cookies, webkit_cookie_manager_get_domains_with_cookies () +
webkit_cookie_manager_get_domains_with_cookies, webkit_cookie_manager_get_domains_with_cookies ()
-
webkit_cookie_manager_get_domains_with_cookies_finish, webkit_cookie_manager_get_domains_with_cookies_finish () +
webkit_cookie_manager_get_domains_with_cookies_finish, webkit_cookie_manager_get_domains_with_cookies_finish ()
-
webkit_cookie_manager_set_accept_policy, webkit_cookie_manager_set_accept_policy () +
webkit_cookie_manager_set_accept_policy, webkit_cookie_manager_set_accept_policy ()
-
webkit_cookie_manager_set_persistent_storage, webkit_cookie_manager_set_persistent_storage () +
webkit_cookie_manager_set_persistent_storage, webkit_cookie_manager_set_persistent_storage ()
-
WebKitCredential, WebKitCredential +
WebKitCredential, WebKitCredential
-
WebKitCredentialPersistence, enum WebKitCredentialPersistence +
WebKitCredentialPersistence, enum WebKitCredentialPersistence
-
webkit_credential_copy, webkit_credential_copy () +
webkit_credential_copy, webkit_credential_copy ()
-
webkit_credential_free, webkit_credential_free () +
webkit_credential_free, webkit_credential_free ()
-
webkit_credential_get_password, webkit_credential_get_password () +
webkit_credential_get_password, webkit_credential_get_password ()
-
webkit_credential_get_persistence, webkit_credential_get_persistence () +
webkit_credential_get_persistence, webkit_credential_get_persistence ()
-
webkit_credential_get_username, webkit_credential_get_username () +
webkit_credential_get_username, webkit_credential_get_username ()
-
webkit_credential_has_password, webkit_credential_has_password () +
webkit_credential_has_password, webkit_credential_has_password ()
-
webkit_credential_new, webkit_credential_new () +
webkit_credential_new, webkit_credential_new ()

D

-
WebKitDownload, struct WebKitDownload +
WebKitDownload, struct WebKitDownload
-
WebKitDownload::created-destination, The “created-destination” signal +
WebKitDownload::created-destination, The “created-destination” signal
-
WebKitDownload::decide-destination, The “decide-destination” signal +
WebKitDownload::decide-destination, The “decide-destination” signal
-
WebKitDownload::failed, The “failed” signal +
WebKitDownload::failed, The “failed” signal
-
WebKitDownload::finished, The “finished” signal +
WebKitDownload::finished, The “finished” signal
-
WebKitDownload::received-data, The “received-data” signal +
WebKitDownload::received-data, The “received-data” signal
-
WebKitDownload:allow-overwrite, The “allow-overwrite” property +
WebKitDownload:allow-overwrite, The “allow-overwrite” property
-
WebKitDownload:destination, The “destination” property +
WebKitDownload:destination, The “destination” property
-
WebKitDownload:estimated-progress, The “estimated-progress” property +
WebKitDownload:estimated-progress, The “estimated-progress” property
-
WebKitDownload:response, The “response” property +
WebKitDownload:response, The “response” property
-
WebKitDownloadError, enum WebKitDownloadError +
WebKitDownloadError, enum WebKitDownloadError
-
webkit_download_cancel, webkit_download_cancel () +
webkit_download_cancel, webkit_download_cancel ()
-
WEBKIT_DOWNLOAD_ERROR, WEBKIT_DOWNLOAD_ERROR +
WEBKIT_DOWNLOAD_ERROR, WEBKIT_DOWNLOAD_ERROR
-
webkit_download_error_quark, webkit_download_error_quark () +
webkit_download_error_quark, webkit_download_error_quark ()
-
webkit_download_get_allow_overwrite, webkit_download_get_allow_overwrite () +
webkit_download_get_allow_overwrite, webkit_download_get_allow_overwrite ()
-
webkit_download_get_destination, webkit_download_get_destination () +
webkit_download_get_destination, webkit_download_get_destination ()
-
webkit_download_get_elapsed_time, webkit_download_get_elapsed_time () +
webkit_download_get_elapsed_time, webkit_download_get_elapsed_time ()
-
webkit_download_get_estimated_progress, webkit_download_get_estimated_progress () +
webkit_download_get_estimated_progress, webkit_download_get_estimated_progress ()
-
webkit_download_get_received_data_length, webkit_download_get_received_data_length () +
webkit_download_get_received_data_length, webkit_download_get_received_data_length ()
-
webkit_download_get_request, webkit_download_get_request () +
webkit_download_get_request, webkit_download_get_request ()
-
webkit_download_get_response, webkit_download_get_response () +
webkit_download_get_response, webkit_download_get_response ()
-
webkit_download_get_web_view, webkit_download_get_web_view () +
webkit_download_get_web_view, webkit_download_get_web_view ()
-
webkit_download_set_allow_overwrite, webkit_download_set_allow_overwrite () +
webkit_download_set_allow_overwrite, webkit_download_set_allow_overwrite ()
-
webkit_download_set_destination, webkit_download_set_destination () +
webkit_download_set_destination, webkit_download_set_destination ()

E

-
WEBKIT_EDITING_COMMAND_COPY, WEBKIT_EDITING_COMMAND_COPY +
WEBKIT_EDITING_COMMAND_COPY, WEBKIT_EDITING_COMMAND_COPY
-
WEBKIT_EDITING_COMMAND_CREATE_LINK, WEBKIT_EDITING_COMMAND_CREATE_LINK +
WEBKIT_EDITING_COMMAND_CREATE_LINK, WEBKIT_EDITING_COMMAND_CREATE_LINK
-
WEBKIT_EDITING_COMMAND_CUT, WEBKIT_EDITING_COMMAND_CUT +
WEBKIT_EDITING_COMMAND_CUT, WEBKIT_EDITING_COMMAND_CUT
-
WEBKIT_EDITING_COMMAND_INSERT_IMAGE, WEBKIT_EDITING_COMMAND_INSERT_IMAGE +
WEBKIT_EDITING_COMMAND_INSERT_IMAGE, WEBKIT_EDITING_COMMAND_INSERT_IMAGE
-
WEBKIT_EDITING_COMMAND_PASTE, WEBKIT_EDITING_COMMAND_PASTE +
WEBKIT_EDITING_COMMAND_PASTE, WEBKIT_EDITING_COMMAND_PASTE
-
WEBKIT_EDITING_COMMAND_REDO, WEBKIT_EDITING_COMMAND_REDO +
WEBKIT_EDITING_COMMAND_REDO, WEBKIT_EDITING_COMMAND_REDO
-
WEBKIT_EDITING_COMMAND_SELECT_ALL, WEBKIT_EDITING_COMMAND_SELECT_ALL +
WEBKIT_EDITING_COMMAND_SELECT_ALL, WEBKIT_EDITING_COMMAND_SELECT_ALL
-
WEBKIT_EDITING_COMMAND_UNDO, WEBKIT_EDITING_COMMAND_UNDO +
WEBKIT_EDITING_COMMAND_UNDO, WEBKIT_EDITING_COMMAND_UNDO
-
WebKitEditorState, struct WebKitEditorState +
WebKitEditorState, struct WebKitEditorState
-
WebKitEditorState:typing-attributes, The “typing-attributes” property +
WebKitEditorState:typing-attributes, The “typing-attributes” property
-
WebKitEditorTypingAttributes, enum WebKitEditorTypingAttributes +
WebKitEditorTypingAttributes, enum WebKitEditorTypingAttributes
-
webkit_editor_state_get_typing_attributes, webkit_editor_state_get_typing_attributes () +
webkit_editor_state_get_typing_attributes, webkit_editor_state_get_typing_attributes ()

F

-
WebKitFaviconDatabase, struct WebKitFaviconDatabase +
WebKitFaviconDatabase, struct WebKitFaviconDatabase
-
WebKitFaviconDatabase::favicon-changed, The “favicon-changed” signal +
WebKitFaviconDatabase::favicon-changed, The “favicon-changed” signal
-
WebKitFaviconDatabaseError, enum WebKitFaviconDatabaseError +
WebKitFaviconDatabaseError, enum WebKitFaviconDatabaseError
-
webkit_favicon_database_clear, webkit_favicon_database_clear () +
webkit_favicon_database_clear, webkit_favicon_database_clear ()
-
WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR +
WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR
-
webkit_favicon_database_get_favicon, webkit_favicon_database_get_favicon () +
webkit_favicon_database_get_favicon, webkit_favicon_database_get_favicon ()
-
webkit_favicon_database_get_favicon_finish, webkit_favicon_database_get_favicon_finish () +
webkit_favicon_database_get_favicon_finish, webkit_favicon_database_get_favicon_finish ()
-
webkit_favicon_database_get_favicon_uri, webkit_favicon_database_get_favicon_uri () +
webkit_favicon_database_get_favicon_uri, webkit_favicon_database_get_favicon_uri ()
-
WebKitFileChooserRequest, struct WebKitFileChooserRequest +
WebKitFileChooserRequest, struct WebKitFileChooserRequest
-
WebKitFileChooserRequest:filter, The “filter” property +
WebKitFileChooserRequest:filter, The “filter” property
-
WebKitFileChooserRequest:mime-types, The “mime-types” property +
WebKitFileChooserRequest:mime-types, The “mime-types” property
-
WebKitFileChooserRequest:select-multiple, The “select-multiple” property +
WebKitFileChooserRequest:select-multiple, The “select-multiple” property
-
WebKitFileChooserRequest:selected-files, The “selected-files” property +
WebKitFileChooserRequest:selected-files, The “selected-files” property
-
webkit_file_chooser_request_cancel, webkit_file_chooser_request_cancel () +
webkit_file_chooser_request_cancel, webkit_file_chooser_request_cancel ()
-
webkit_file_chooser_request_get_mime_types, webkit_file_chooser_request_get_mime_types () +
webkit_file_chooser_request_get_mime_types, webkit_file_chooser_request_get_mime_types ()
-
webkit_file_chooser_request_get_mime_types_filter, webkit_file_chooser_request_get_mime_types_filter () +
webkit_file_chooser_request_get_mime_types_filter, webkit_file_chooser_request_get_mime_types_filter ()
-
webkit_file_chooser_request_get_selected_files, webkit_file_chooser_request_get_selected_files () +
webkit_file_chooser_request_get_selected_files, webkit_file_chooser_request_get_selected_files ()
-
webkit_file_chooser_request_get_select_multiple, webkit_file_chooser_request_get_select_multiple () +
webkit_file_chooser_request_get_select_multiple, webkit_file_chooser_request_get_select_multiple ()
-
webkit_file_chooser_request_select_files, webkit_file_chooser_request_select_files () +
webkit_file_chooser_request_select_files, webkit_file_chooser_request_select_files ()
-
WebKitFindController, WebKitFindController +
WebKitFindController, WebKitFindController
-
WebKitFindController::counted-matches, The “counted-matches” signal +
WebKitFindController::counted-matches, The “counted-matches” signal
-
WebKitFindController::failed-to-find-text, The “failed-to-find-text” signal +
WebKitFindController::failed-to-find-text, The “failed-to-find-text” signal
-
WebKitFindController::found-text, The “found-text” signal +
WebKitFindController::found-text, The “found-text” signal
-
WebKitFindController:max-match-count, The “max-match-count” property +
WebKitFindController:max-match-count, The “max-match-count” property
-
WebKitFindController:options, The “options” property +
WebKitFindController:options, The “options” property
-
WebKitFindController:text, The “text” property +
WebKitFindController:text, The “text” property
-
WebKitFindController:web-view, The “web-view” property +
WebKitFindController:web-view, The “web-view” property
-
WebKitFindOptions, enum WebKitFindOptions +
WebKitFindOptions, enum WebKitFindOptions
-
webkit_find_controller_count_matches, webkit_find_controller_count_matches () +
webkit_find_controller_count_matches, webkit_find_controller_count_matches ()
-
webkit_find_controller_get_max_match_count, webkit_find_controller_get_max_match_count () +
webkit_find_controller_get_max_match_count, webkit_find_controller_get_max_match_count ()
-
webkit_find_controller_get_options, webkit_find_controller_get_options () +
webkit_find_controller_get_options, webkit_find_controller_get_options ()
-
webkit_find_controller_get_search_text, webkit_find_controller_get_search_text () +
webkit_find_controller_get_search_text, webkit_find_controller_get_search_text ()
-
webkit_find_controller_get_web_view, webkit_find_controller_get_web_view () +
webkit_find_controller_get_web_view, webkit_find_controller_get_web_view ()
-
webkit_find_controller_search, webkit_find_controller_search () +
webkit_find_controller_search, webkit_find_controller_search ()
-
webkit_find_controller_search_finish, webkit_find_controller_search_finish () +
webkit_find_controller_search_finish, webkit_find_controller_search_finish ()
-
webkit_find_controller_search_next, webkit_find_controller_search_next () +
webkit_find_controller_search_next, webkit_find_controller_search_next ()
-
webkit_find_controller_search_previous, webkit_find_controller_search_previous () +
webkit_find_controller_search_previous, webkit_find_controller_search_previous ()
-
WebKitFormSubmissionRequest, struct WebKitFormSubmissionRequest +
WebKitFormSubmissionRequest, struct WebKitFormSubmissionRequest
-
webkit_form_submission_request_get_text_fields, webkit_form_submission_request_get_text_fields () +
webkit_form_submission_request_get_text_fields, webkit_form_submission_request_get_text_fields ()
-
webkit_form_submission_request_submit, webkit_form_submission_request_submit () +
webkit_form_submission_request_submit, webkit_form_submission_request_submit ()
-
WebKitFrame, struct WebKitFrame +
WebKitFrame, struct WebKitFrame
-
webkit_frame_get_javascript_context_for_script_world, webkit_frame_get_javascript_context_for_script_world () +
webkit_frame_get_javascript_context_for_script_world, webkit_frame_get_javascript_context_for_script_world ()
-
webkit_frame_get_javascript_global_context, webkit_frame_get_javascript_global_context () +
webkit_frame_get_javascript_global_context, webkit_frame_get_javascript_global_context ()
-
webkit_frame_get_uri, webkit_frame_get_uri () +
webkit_frame_get_uri, webkit_frame_get_uri ()
-
webkit_frame_is_main_frame, webkit_frame_is_main_frame () +
webkit_frame_is_main_frame, webkit_frame_is_main_frame ()

G

-
WebKitGeolocationPermissionRequest, struct WebKitGeolocationPermissionRequest +
WebKitGeolocationPermissionRequest, struct WebKitGeolocationPermissionRequest
-
webkit_get_major_version, webkit_get_major_version () +
webkit_get_major_version, webkit_get_major_version ()
-
webkit_get_micro_version, webkit_get_micro_version () +
webkit_get_micro_version, webkit_get_micro_version ()
-
webkit_get_minor_version, webkit_get_minor_version () +
webkit_get_minor_version, webkit_get_minor_version ()

H

-
WebKitHitTestResult, struct WebKitHitTestResult +
WebKitHitTestResult, struct WebKitHitTestResult
-
WebKitHitTestResult:context, The “context” property +
WebKitHitTestResult:context, The “context” property
-
WebKitHitTestResult:image-uri, The “image-uri” property +
WebKitHitTestResult:image-uri, The “image-uri” property
-
WebKitHitTestResult:link-label, The “link-label” property +
WebKitHitTestResult:link-label, The “link-label” property
-
WebKitHitTestResult:link-title, The “link-title” property +
WebKitHitTestResult:link-title, The “link-title” property
-
WebKitHitTestResult:link-uri, The “link-uri” property +
WebKitHitTestResult:link-uri, The “link-uri” property
-
WebKitHitTestResult:media-uri, The “media-uri” property +
WebKitHitTestResult:media-uri, The “media-uri” property
-
WebKitHitTestResultContext, enum WebKitHitTestResultContext +
WebKitHitTestResultContext, enum WebKitHitTestResultContext
-
webkit_hit_test_result_context_is_editable, webkit_hit_test_result_context_is_editable () +
webkit_hit_test_result_context_is_editable, webkit_hit_test_result_context_is_editable ()
-
webkit_hit_test_result_context_is_image, webkit_hit_test_result_context_is_image () +
webkit_hit_test_result_context_is_image, webkit_hit_test_result_context_is_image ()
-
webkit_hit_test_result_context_is_link, webkit_hit_test_result_context_is_link () +
webkit_hit_test_result_context_is_link, webkit_hit_test_result_context_is_link ()
-
webkit_hit_test_result_context_is_media, webkit_hit_test_result_context_is_media () +
webkit_hit_test_result_context_is_media, webkit_hit_test_result_context_is_media ()
-
webkit_hit_test_result_context_is_scrollbar, webkit_hit_test_result_context_is_scrollbar () +
webkit_hit_test_result_context_is_scrollbar, webkit_hit_test_result_context_is_scrollbar ()
-
webkit_hit_test_result_context_is_selection, webkit_hit_test_result_context_is_selection () +
webkit_hit_test_result_context_is_selection, webkit_hit_test_result_context_is_selection ()
-
webkit_hit_test_result_get_context, webkit_hit_test_result_get_context () +
webkit_hit_test_result_get_context, webkit_hit_test_result_get_context ()
-
webkit_hit_test_result_get_image_uri, webkit_hit_test_result_get_image_uri () +
webkit_hit_test_result_get_image_uri, webkit_hit_test_result_get_image_uri ()
-
webkit_hit_test_result_get_link_label, webkit_hit_test_result_get_link_label () +
webkit_hit_test_result_get_link_label, webkit_hit_test_result_get_link_label ()
-
webkit_hit_test_result_get_link_title, webkit_hit_test_result_get_link_title () +
webkit_hit_test_result_get_link_title, webkit_hit_test_result_get_link_title ()
-
webkit_hit_test_result_get_link_uri, webkit_hit_test_result_get_link_uri () +
webkit_hit_test_result_get_link_uri, webkit_hit_test_result_get_link_uri ()
-
webkit_hit_test_result_get_media_uri, webkit_hit_test_result_get_media_uri () +
webkit_hit_test_result_get_media_uri, webkit_hit_test_result_get_media_uri ()

I

-
WebKitInsecureContentEvent, enum WebKitInsecureContentEvent +
WebKitInsecureContentEvent, enum WebKitInsecureContentEvent
-
WebKitInstallMissingMediaPluginsPermissionRequest, struct WebKitInstallMissingMediaPluginsPermissionRequest +
WebKitInstallMissingMediaPluginsPermissionRequest, struct WebKitInstallMissingMediaPluginsPermissionRequest
-
webkit_install_missing_media_plugins_permission_request_get_description, webkit_install_missing_media_plugins_permission_request_get_description () +
webkit_install_missing_media_plugins_permission_request_get_description, webkit_install_missing_media_plugins_permission_request_get_description ()

J

-
WebKitJavascriptError, enum WebKitJavascriptError +
WebKitJavascriptError, enum WebKitJavascriptError
-
WebKitJavascriptResult, WebKitJavascriptResult +
WebKitJavascriptResult, WebKitJavascriptResult
-
WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR +
WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR
-
webkit_javascript_error_quark, webkit_javascript_error_quark () +
webkit_javascript_error_quark, webkit_javascript_error_quark ()
-
webkit_javascript_result_get_global_context, webkit_javascript_result_get_global_context () +
webkit_javascript_result_get_global_context, webkit_javascript_result_get_global_context ()
-
webkit_javascript_result_get_value, webkit_javascript_result_get_value () +
webkit_javascript_result_get_value, webkit_javascript_result_get_value ()
-
webkit_javascript_result_ref, webkit_javascript_result_ref () +
webkit_javascript_result_ref, webkit_javascript_result_ref ()
-
webkit_javascript_result_unref, webkit_javascript_result_unref () +
webkit_javascript_result_unref, webkit_javascript_result_unref ()

L

-
WebKitLoadEvent, enum WebKitLoadEvent +
WebKitLoadEvent, enum WebKitLoadEvent

M

-
WEBKIT_MAJOR_VERSION, WEBKIT_MAJOR_VERSION +
WEBKIT_MAJOR_VERSION, WEBKIT_MAJOR_VERSION
-
WEBKIT_MICRO_VERSION, WEBKIT_MICRO_VERSION +
WEBKIT_MICRO_VERSION, WEBKIT_MICRO_VERSION
-
WebKitMimeInfo, WebKitMimeInfo +
WebKitMimeInfo, WebKitMimeInfo
-
webkit_mime_info_get_description, webkit_mime_info_get_description () +
webkit_mime_info_get_description, webkit_mime_info_get_description ()
-
webkit_mime_info_get_extensions, webkit_mime_info_get_extensions () +
webkit_mime_info_get_extensions, webkit_mime_info_get_extensions ()
-
webkit_mime_info_get_mime_type, webkit_mime_info_get_mime_type () +
webkit_mime_info_get_mime_type, webkit_mime_info_get_mime_type ()
-
webkit_mime_info_ref, webkit_mime_info_ref () +
webkit_mime_info_ref, webkit_mime_info_ref ()
-
webkit_mime_info_unref, webkit_mime_info_unref () +
webkit_mime_info_unref, webkit_mime_info_unref ()
-
WEBKIT_MINOR_VERSION, WEBKIT_MINOR_VERSION +
WEBKIT_MINOR_VERSION, WEBKIT_MINOR_VERSION

N

-
WebKitNavigationAction, WebKitNavigationAction +
WebKitNavigationAction, WebKitNavigationAction
-
WebKitNavigationPolicyDecision, struct WebKitNavigationPolicyDecision +
WebKitNavigationPolicyDecision, struct WebKitNavigationPolicyDecision
-
WebKitNavigationPolicyDecision:frame-name, The “frame-name” property +
WebKitNavigationPolicyDecision:frame-name, The “frame-name” property
-
WebKitNavigationPolicyDecision:modifiers, The “modifiers” property +
WebKitNavigationPolicyDecision:modifiers, The “modifiers” property
-
WebKitNavigationPolicyDecision:mouse-button, The “mouse-button” property +
WebKitNavigationPolicyDecision:mouse-button, The “mouse-button” property
-
WebKitNavigationPolicyDecision:navigation-action, The “navigation-action” property +
WebKitNavigationPolicyDecision:navigation-action, The “navigation-action” property
-
WebKitNavigationPolicyDecision:navigation-type, The “navigation-type” property +
WebKitNavigationPolicyDecision:navigation-type, The “navigation-type” property
-
WebKitNavigationPolicyDecision:request, The “request” property +
WebKitNavigationPolicyDecision:request, The “request” property
-
WebKitNavigationType, enum WebKitNavigationType +
WebKitNavigationType, enum WebKitNavigationType
-
webkit_navigation_action_copy, webkit_navigation_action_copy () +
webkit_navigation_action_copy, webkit_navigation_action_copy ()
-
webkit_navigation_action_free, webkit_navigation_action_free () +
webkit_navigation_action_free, webkit_navigation_action_free ()
-
webkit_navigation_action_get_modifiers, webkit_navigation_action_get_modifiers () +
webkit_navigation_action_get_modifiers, webkit_navigation_action_get_modifiers ()
-
webkit_navigation_action_get_mouse_button, webkit_navigation_action_get_mouse_button () +
webkit_navigation_action_get_mouse_button, webkit_navigation_action_get_mouse_button ()
-
webkit_navigation_action_get_navigation_type, webkit_navigation_action_get_navigation_type () +
webkit_navigation_action_get_navigation_type, webkit_navigation_action_get_navigation_type ()
-
webkit_navigation_action_get_request, webkit_navigation_action_get_request () +
webkit_navigation_action_get_request, webkit_navigation_action_get_request ()
-
webkit_navigation_action_is_user_gesture, webkit_navigation_action_is_user_gesture () +
webkit_navigation_action_is_user_gesture, webkit_navigation_action_is_user_gesture ()
-
webkit_navigation_policy_decision_get_frame_name, webkit_navigation_policy_decision_get_frame_name () +
webkit_navigation_policy_decision_get_frame_name, webkit_navigation_policy_decision_get_frame_name ()
-
webkit_navigation_policy_decision_get_modifiers, webkit_navigation_policy_decision_get_modifiers () +
webkit_navigation_policy_decision_get_modifiers, webkit_navigation_policy_decision_get_modifiers ()
-
webkit_navigation_policy_decision_get_mouse_button, webkit_navigation_policy_decision_get_mouse_button () +
webkit_navigation_policy_decision_get_mouse_button, webkit_navigation_policy_decision_get_mouse_button ()
-
webkit_navigation_policy_decision_get_navigation_action, webkit_navigation_policy_decision_get_navigation_action () +
webkit_navigation_policy_decision_get_navigation_action, webkit_navigation_policy_decision_get_navigation_action ()
-
webkit_navigation_policy_decision_get_navigation_type, webkit_navigation_policy_decision_get_navigation_type () +
webkit_navigation_policy_decision_get_navigation_type, webkit_navigation_policy_decision_get_navigation_type ()
-
webkit_navigation_policy_decision_get_request, webkit_navigation_policy_decision_get_request () +
webkit_navigation_policy_decision_get_request, webkit_navigation_policy_decision_get_request ()
-
WebKitNetworkError, enum WebKitNetworkError +
WebKitNetworkError, enum WebKitNetworkError
-
WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR +
WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR
-
webkit_network_error_quark, webkit_network_error_quark () +
webkit_network_error_quark, webkit_network_error_quark ()
-
WebKitNotification, struct WebKitNotification +
WebKitNotification, struct WebKitNotification
-
WebKitNotification::clicked, The “clicked” signal +
WebKitNotification::clicked, The “clicked” signal
-
WebKitNotification::closed, The “closed” signal +
WebKitNotification::closed, The “closed” signal
-
WebKitNotification:body, The “body” property +
WebKitNotification:body, The “body” property
-
WebKitNotification:id, The “id” property +
WebKitNotification:id, The “id” property
-
WebKitNotification:title, The “title” property +
WebKitNotification:title, The “title” property
-
WebKitNotificationPermissionRequest, struct WebKitNotificationPermissionRequest +
WebKitNotificationPermissionRequest, struct WebKitNotificationPermissionRequest
-
webkit_notification_clicked, webkit_notification_clicked () +
webkit_notification_clicked, webkit_notification_clicked ()
-
webkit_notification_close, webkit_notification_close () +
webkit_notification_close, webkit_notification_close ()
-
webkit_notification_get_body, webkit_notification_get_body () +
webkit_notification_get_body, webkit_notification_get_body ()
-
webkit_notification_get_id, webkit_notification_get_id () +
webkit_notification_get_id, webkit_notification_get_id ()
-
webkit_notification_get_title, webkit_notification_get_title () +
webkit_notification_get_title, webkit_notification_get_title ()

P

-
WebKitPermissionRequest, WebKitPermissionRequest +
WebKitPermissionRequest, WebKitPermissionRequest
-
webkit_permission_request_allow, webkit_permission_request_allow () +
webkit_permission_request_allow, webkit_permission_request_allow ()
-
webkit_permission_request_deny, webkit_permission_request_deny () +
webkit_permission_request_deny, webkit_permission_request_deny ()
-
WebKitPlugin, struct WebKitPlugin +
WebKitPlugin, struct WebKitPlugin
-
WebKitPluginError, enum WebKitPluginError +
WebKitPluginError, enum WebKitPluginError
-
WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR +
WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR
-
webkit_plugin_error_quark, webkit_plugin_error_quark () +
webkit_plugin_error_quark, webkit_plugin_error_quark ()
-
webkit_plugin_get_description, webkit_plugin_get_description () +
webkit_plugin_get_description, webkit_plugin_get_description ()
-
webkit_plugin_get_mime_info_list, webkit_plugin_get_mime_info_list () +
webkit_plugin_get_mime_info_list, webkit_plugin_get_mime_info_list ()
-
webkit_plugin_get_name, webkit_plugin_get_name () +
webkit_plugin_get_name, webkit_plugin_get_name ()
-
webkit_plugin_get_path, webkit_plugin_get_path () +
webkit_plugin_get_path, webkit_plugin_get_path ()
-
WebKitPolicyDecision, struct WebKitPolicyDecision +
WebKitPolicyDecision, struct WebKitPolicyDecision
-
WebKitPolicyDecisionType, enum WebKitPolicyDecisionType +
WebKitPolicyDecisionType, enum WebKitPolicyDecisionType
-
WebKitPolicyError, enum WebKitPolicyError +
WebKitPolicyError, enum WebKitPolicyError
-
webkit_policy_decision_download, webkit_policy_decision_download () +
webkit_policy_decision_download, webkit_policy_decision_download ()
-
webkit_policy_decision_ignore, webkit_policy_decision_ignore () +
webkit_policy_decision_ignore, webkit_policy_decision_ignore ()
-
webkit_policy_decision_use, webkit_policy_decision_use () +
webkit_policy_decision_use, webkit_policy_decision_use ()
-
WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR +
WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR
-
webkit_policy_error_quark, webkit_policy_error_quark () +
webkit_policy_error_quark, webkit_policy_error_quark ()
-
WebKitPrintError, enum WebKitPrintError +
WebKitPrintError, enum WebKitPrintError
-
WebKitPrintOperation, WebKitPrintOperation +
WebKitPrintOperation, WebKitPrintOperation
-
WebKitPrintOperation::failed, The “failed” signal +
WebKitPrintOperation::failed, The “failed” signal
-
WebKitPrintOperation::finished, The “finished” signal +
WebKitPrintOperation::finished, The “finished” signal
-
WebKitPrintOperation:page-setup, The “page-setup” property +
WebKitPrintOperation:page-setup, The “page-setup” property
-
WebKitPrintOperation:print-settings, The “print-settings” property +
WebKitPrintOperation:print-settings, The “print-settings” property
-
WebKitPrintOperation:web-view, The “web-view” property +
WebKitPrintOperation:web-view, The “web-view” property
-
WebKitPrintOperationResponse, enum WebKitPrintOperationResponse +
WebKitPrintOperationResponse, enum WebKitPrintOperationResponse
-
WEBKIT_PRINT_ERROR, WEBKIT_PRINT_ERROR +
WEBKIT_PRINT_ERROR, WEBKIT_PRINT_ERROR
-
webkit_print_error_quark, webkit_print_error_quark () +
webkit_print_error_quark, webkit_print_error_quark ()
-
webkit_print_operation_get_page_setup, webkit_print_operation_get_page_setup () +
webkit_print_operation_get_page_setup, webkit_print_operation_get_page_setup ()
-
webkit_print_operation_get_print_settings, webkit_print_operation_get_print_settings () +
webkit_print_operation_get_print_settings, webkit_print_operation_get_print_settings ()
-
webkit_print_operation_new, webkit_print_operation_new () +
webkit_print_operation_new, webkit_print_operation_new ()
-
webkit_print_operation_print, webkit_print_operation_print () +
webkit_print_operation_print, webkit_print_operation_print ()
-
webkit_print_operation_run_dialog, webkit_print_operation_run_dialog () +
webkit_print_operation_run_dialog, webkit_print_operation_run_dialog ()
-
webkit_print_operation_set_page_setup, webkit_print_operation_set_page_setup () +
webkit_print_operation_set_page_setup, webkit_print_operation_set_page_setup ()
-
webkit_print_operation_set_print_settings, webkit_print_operation_set_print_settings () +
webkit_print_operation_set_print_settings, webkit_print_operation_set_print_settings ()
WebKitProcessModel, enum WebKitProcessModel
@@ -688,384 +688,390 @@

R

-
WebKitResponsePolicyDecision, struct WebKitResponsePolicyDecision +
WebKitResponsePolicyDecision, struct WebKitResponsePolicyDecision
-
WebKitResponsePolicyDecision:request, The “request” property +
WebKitResponsePolicyDecision:request, The “request” property
-
WebKitResponsePolicyDecision:response, The “response” property +
WebKitResponsePolicyDecision:response, The “response” property
-
webkit_response_policy_decision_get_request, webkit_response_policy_decision_get_request () +
webkit_response_policy_decision_get_request, webkit_response_policy_decision_get_request ()
-
webkit_response_policy_decision_get_response, webkit_response_policy_decision_get_response () +
webkit_response_policy_decision_get_response, webkit_response_policy_decision_get_response ()
-
webkit_response_policy_decision_is_mime_type_supported, webkit_response_policy_decision_is_mime_type_supported () +
webkit_response_policy_decision_is_mime_type_supported, webkit_response_policy_decision_is_mime_type_supported ()

S

-
WebKitSaveMode, enum WebKitSaveMode +
WebKitSaveMode, enum WebKitSaveMode
-
WebKitScriptDialog, WebKitScriptDialog +
WebKitScriptDialog, WebKitScriptDialog
-
WebKitScriptDialogType, enum WebKitScriptDialogType +
WebKitScriptDialogType, enum WebKitScriptDialogType
-
WebKitScriptWorld, struct WebKitScriptWorld +
WebKitScriptWorld, struct WebKitScriptWorld
-
WebKitScriptWorld::window-object-cleared, The “window-object-cleared” signal +
WebKitScriptWorld::window-object-cleared, The “window-object-cleared” signal
-
webkit_script_dialog_confirm_set_confirmed, webkit_script_dialog_confirm_set_confirmed () +
webkit_script_dialog_confirm_set_confirmed, webkit_script_dialog_confirm_set_confirmed ()
-
webkit_script_dialog_get_dialog_type, webkit_script_dialog_get_dialog_type () +
webkit_script_dialog_get_dialog_type, webkit_script_dialog_get_dialog_type ()
-
webkit_script_dialog_get_message, webkit_script_dialog_get_message () +
webkit_script_dialog_get_message, webkit_script_dialog_get_message ()
-
webkit_script_dialog_prompt_get_default_text, webkit_script_dialog_prompt_get_default_text () +
webkit_script_dialog_prompt_get_default_text, webkit_script_dialog_prompt_get_default_text ()
-
webkit_script_dialog_prompt_set_text, webkit_script_dialog_prompt_set_text () +
webkit_script_dialog_prompt_set_text, webkit_script_dialog_prompt_set_text ()
-
webkit_script_world_get_default, webkit_script_world_get_default () +
webkit_script_world_get_default, webkit_script_world_get_default ()
-
webkit_script_world_new, webkit_script_world_new () +
webkit_script_world_new, webkit_script_world_new ()
-
WebKitSecurityManager, struct WebKitSecurityManager +
WebKitSecurityManager, struct WebKitSecurityManager
-
webkit_security_manager_register_uri_scheme_as_cors_enabled, webkit_security_manager_register_uri_scheme_as_cors_enabled () +
webkit_security_manager_register_uri_scheme_as_cors_enabled, webkit_security_manager_register_uri_scheme_as_cors_enabled ()
-
webkit_security_manager_register_uri_scheme_as_display_isolated, webkit_security_manager_register_uri_scheme_as_display_isolated () +
webkit_security_manager_register_uri_scheme_as_display_isolated, webkit_security_manager_register_uri_scheme_as_display_isolated ()
-
webkit_security_manager_register_uri_scheme_as_empty_document, webkit_security_manager_register_uri_scheme_as_empty_document () +
webkit_security_manager_register_uri_scheme_as_empty_document, webkit_security_manager_register_uri_scheme_as_empty_document ()
-
webkit_security_manager_register_uri_scheme_as_local, webkit_security_manager_register_uri_scheme_as_local () +
webkit_security_manager_register_uri_scheme_as_local, webkit_security_manager_register_uri_scheme_as_local ()
-
webkit_security_manager_register_uri_scheme_as_no_access, webkit_security_manager_register_uri_scheme_as_no_access () +
webkit_security_manager_register_uri_scheme_as_no_access, webkit_security_manager_register_uri_scheme_as_no_access ()
-
webkit_security_manager_register_uri_scheme_as_secure, webkit_security_manager_register_uri_scheme_as_secure () +
webkit_security_manager_register_uri_scheme_as_secure, webkit_security_manager_register_uri_scheme_as_secure ()
-
webkit_security_manager_uri_scheme_is_cors_enabled, webkit_security_manager_uri_scheme_is_cors_enabled () +
webkit_security_manager_uri_scheme_is_cors_enabled, webkit_security_manager_uri_scheme_is_cors_enabled ()
-
webkit_security_manager_uri_scheme_is_display_isolated, webkit_security_manager_uri_scheme_is_display_isolated () +
webkit_security_manager_uri_scheme_is_display_isolated, webkit_security_manager_uri_scheme_is_display_isolated ()
-
webkit_security_manager_uri_scheme_is_empty_document, webkit_security_manager_uri_scheme_is_empty_document () +
webkit_security_manager_uri_scheme_is_empty_document, webkit_security_manager_uri_scheme_is_empty_document ()
-
webkit_security_manager_uri_scheme_is_local, webkit_security_manager_uri_scheme_is_local () +
webkit_security_manager_uri_scheme_is_local, webkit_security_manager_uri_scheme_is_local ()
-
webkit_security_manager_uri_scheme_is_no_access, webkit_security_manager_uri_scheme_is_no_access () +
webkit_security_manager_uri_scheme_is_no_access, webkit_security_manager_uri_scheme_is_no_access ()
-
webkit_security_manager_uri_scheme_is_secure, webkit_security_manager_uri_scheme_is_secure () +
webkit_security_manager_uri_scheme_is_secure, webkit_security_manager_uri_scheme_is_secure ()
-
WebKitSettings, struct WebKitSettings +
WebKitSettings, struct WebKitSettings
-
WebKitSettings:allow-file-access-from-file-urls, The “allow-file-access-from-file-urls” property +
WebKitSettings:allow-file-access-from-file-urls, The “allow-file-access-from-file-urls” property
-
WebKitSettings:allow-modal-dialogs, The “allow-modal-dialogs” property +
WebKitSettings:allow-modal-dialogs, The “allow-modal-dialogs” property
-
WebKitSettings:auto-load-images, The “auto-load-images” property +
WebKitSettings:allow-universal-access-from-file-urls, The “allow-universal-access-from-file-urls” property
-
WebKitSettings:cursive-font-family, The “cursive-font-family” property +
WebKitSettings:auto-load-images, The “auto-load-images” property
-
WebKitSettings:default-charset, The “default-charset” property +
WebKitSettings:cursive-font-family, The “cursive-font-family” property
-
WebKitSettings:default-font-family, The “default-font-family” property +
WebKitSettings:default-charset, The “default-charset” property
-
WebKitSettings:default-font-size, The “default-font-size” property +
WebKitSettings:default-font-family, The “default-font-family” property
-
WebKitSettings:default-monospace-font-size, The “default-monospace-font-size” property +
WebKitSettings:default-font-size, The “default-font-size” property
-
WebKitSettings:draw-compositing-indicators, The “draw-compositing-indicators” property +
WebKitSettings:default-monospace-font-size, The “default-monospace-font-size” property
-
WebKitSettings:enable-accelerated-2d-canvas, The “enable-accelerated-2d-canvas” property +
WebKitSettings:draw-compositing-indicators, The “draw-compositing-indicators” property
-
WebKitSettings:enable-caret-browsing, The “enable-caret-browsing” property +
WebKitSettings:enable-accelerated-2d-canvas, The “enable-accelerated-2d-canvas” property
-
WebKitSettings:enable-developer-extras, The “enable-developer-extras” property +
WebKitSettings:enable-caret-browsing, The “enable-caret-browsing” property
-
WebKitSettings:enable-dns-prefetching, The “enable-dns-prefetching” property +
WebKitSettings:enable-developer-extras, The “enable-developer-extras” property
-
WebKitSettings:enable-frame-flattening, The “enable-frame-flattening” property +
WebKitSettings:enable-dns-prefetching, The “enable-dns-prefetching” property
-
WebKitSettings:enable-fullscreen, The “enable-fullscreen” property +
WebKitSettings:enable-frame-flattening, The “enable-frame-flattening” property
-
WebKitSettings:enable-html5-database, The “enable-html5-database” property +
WebKitSettings:enable-fullscreen, The “enable-fullscreen” property
-
WebKitSettings:enable-html5-local-storage, The “enable-html5-local-storage” property +
WebKitSettings:enable-html5-database, The “enable-html5-database” property
-
WebKitSettings:enable-hyperlink-auditing, The “enable-hyperlink-auditing” property +
WebKitSettings:enable-html5-local-storage, The “enable-html5-local-storage” property
-
WebKitSettings:enable-java, The “enable-java” property +
WebKitSettings:enable-hyperlink-auditing, The “enable-hyperlink-auditing” property
-
WebKitSettings:enable-javascript, The “enable-javascript” property +
WebKitSettings:enable-java, The “enable-java” property
-
WebKitSettings:enable-media-stream, The “enable-media-stream” property +
WebKitSettings:enable-javascript, The “enable-javascript” property
-
WebKitSettings:enable-mediasource, The “enable-mediasource” property +
WebKitSettings:enable-media-stream, The “enable-media-stream” property
-
WebKitSettings:enable-offline-web-application-cache, The “enable-offline-web-application-cache” property +
WebKitSettings:enable-mediasource, The “enable-mediasource” property
-
WebKitSettings:enable-page-cache, The “enable-page-cache” property +
WebKitSettings:enable-offline-web-application-cache, The “enable-offline-web-application-cache” property
-
WebKitSettings:enable-plugins, The “enable-plugins” property +
WebKitSettings:enable-page-cache, The “enable-page-cache” property
-
WebKitSettings:enable-private-browsing, The “enable-private-browsing” property +
WebKitSettings:enable-plugins, The “enable-plugins” property
-
WebKitSettings:enable-resizable-text-areas, The “enable-resizable-text-areas” property +
WebKitSettings:enable-private-browsing, The “enable-private-browsing” property
-
WebKitSettings:enable-site-specific-quirks, The “enable-site-specific-quirks” property +
WebKitSettings:enable-resizable-text-areas, The “enable-resizable-text-areas” property
-
WebKitSettings:enable-smooth-scrolling, The “enable-smooth-scrolling” property +
WebKitSettings:enable-site-specific-quirks, The “enable-site-specific-quirks” property
-
WebKitSettings:enable-spatial-navigation, The “enable-spatial-navigation” property +
WebKitSettings:enable-smooth-scrolling, The “enable-smooth-scrolling” property
-
WebKitSettings:enable-tabs-to-links, The “enable-tabs-to-links” property +
WebKitSettings:enable-spatial-navigation, The “enable-spatial-navigation” property
-
WebKitSettings:enable-webaudio, The “enable-webaudio” property +
WebKitSettings:enable-tabs-to-links, The “enable-tabs-to-links” property
-
WebKitSettings:enable-webgl, The “enable-webgl” property +
WebKitSettings:enable-webaudio, The “enable-webaudio” property
-
WebKitSettings:enable-write-console-messages-to-stdout, The “enable-write-console-messages-to-stdout” property +
WebKitSettings:enable-webgl, The “enable-webgl” property
-
WebKitSettings:enable-xss-auditor, The “enable-xss-auditor” property +
WebKitSettings:enable-write-console-messages-to-stdout, The “enable-write-console-messages-to-stdout” property
-
WebKitSettings:fantasy-font-family, The “fantasy-font-family” property +
WebKitSettings:enable-xss-auditor, The “enable-xss-auditor” property
-
WebKitSettings:javascript-can-access-clipboard, The “javascript-can-access-clipboard” property +
WebKitSettings:fantasy-font-family, The “fantasy-font-family” property
-
WebKitSettings:javascript-can-open-windows-automatically, The “javascript-can-open-windows-automatically” property +
WebKitSettings:javascript-can-access-clipboard, The “javascript-can-access-clipboard” property
-
WebKitSettings:load-icons-ignoring-image-load-setting, The “load-icons-ignoring-image-load-setting” property +
WebKitSettings:javascript-can-open-windows-automatically, The “javascript-can-open-windows-automatically” property
-
WebKitSettings:media-playback-allows-inline, The “media-playback-allows-inline” property +
WebKitSettings:load-icons-ignoring-image-load-setting, The “load-icons-ignoring-image-load-setting” property
-
WebKitSettings:media-playback-requires-user-gesture, The “media-playback-requires-user-gesture” property +
WebKitSettings:media-playback-allows-inline, The “media-playback-allows-inline” property
-
WebKitSettings:minimum-font-size, The “minimum-font-size” property +
WebKitSettings:media-playback-requires-user-gesture, The “media-playback-requires-user-gesture” property
-
WebKitSettings:monospace-font-family, The “monospace-font-family” property +
WebKitSettings:minimum-font-size, The “minimum-font-size” property
-
WebKitSettings:pictograph-font-family, The “pictograph-font-family” property +
WebKitSettings:monospace-font-family, The “monospace-font-family” property
-
WebKitSettings:print-backgrounds, The “print-backgrounds” property +
WebKitSettings:pictograph-font-family, The “pictograph-font-family” property
-
WebKitSettings:sans-serif-font-family, The “sans-serif-font-family” property +
WebKitSettings:print-backgrounds, The “print-backgrounds” property
-
WebKitSettings:serif-font-family, The “serif-font-family” property +
WebKitSettings:sans-serif-font-family, The “sans-serif-font-family” property
-
WebKitSettings:user-agent, The “user-agent” property +
WebKitSettings:serif-font-family, The “serif-font-family” property
-
WebKitSettings:zoom-text-only, The “zoom-text-only” property +
WebKitSettings:user-agent, The “user-agent” property
-
webkit_settings_get_allow_file_access_from_file_urls, webkit_settings_get_allow_file_access_from_file_urls () +
WebKitSettings:zoom-text-only, The “zoom-text-only” property
-
webkit_settings_get_allow_modal_dialogs, webkit_settings_get_allow_modal_dialogs () +
webkit_settings_get_allow_file_access_from_file_urls, webkit_settings_get_allow_file_access_from_file_urls ()
-
webkit_settings_get_auto_load_images, webkit_settings_get_auto_load_images () +
webkit_settings_get_allow_modal_dialogs, webkit_settings_get_allow_modal_dialogs ()
-
webkit_settings_get_cursive_font_family, webkit_settings_get_cursive_font_family () +
webkit_settings_get_allow_universal_access_from_file_urls, webkit_settings_get_allow_universal_access_from_file_urls ()
-
webkit_settings_get_default_charset, webkit_settings_get_default_charset () +
webkit_settings_get_auto_load_images, webkit_settings_get_auto_load_images ()
-
webkit_settings_get_default_font_family, webkit_settings_get_default_font_family () +
webkit_settings_get_cursive_font_family, webkit_settings_get_cursive_font_family ()
-
webkit_settings_get_default_font_size, webkit_settings_get_default_font_size () +
webkit_settings_get_default_charset, webkit_settings_get_default_charset ()
-
webkit_settings_get_default_monospace_font_size, webkit_settings_get_default_monospace_font_size () +
webkit_settings_get_default_font_family, webkit_settings_get_default_font_family ()
-
webkit_settings_get_draw_compositing_indicators, webkit_settings_get_draw_compositing_indicators () +
webkit_settings_get_default_font_size, webkit_settings_get_default_font_size ()
-
webkit_settings_get_enable_accelerated_2d_canvas, webkit_settings_get_enable_accelerated_2d_canvas () +
webkit_settings_get_default_monospace_font_size, webkit_settings_get_default_monospace_font_size ()
-
webkit_settings_get_enable_caret_browsing, webkit_settings_get_enable_caret_browsing () +
webkit_settings_get_draw_compositing_indicators, webkit_settings_get_draw_compositing_indicators ()
-
webkit_settings_get_enable_developer_extras, webkit_settings_get_enable_developer_extras () +
webkit_settings_get_enable_accelerated_2d_canvas, webkit_settings_get_enable_accelerated_2d_canvas ()
-
webkit_settings_get_enable_dns_prefetching, webkit_settings_get_enable_dns_prefetching () +
webkit_settings_get_enable_caret_browsing, webkit_settings_get_enable_caret_browsing ()
-
webkit_settings_get_enable_frame_flattening, webkit_settings_get_enable_frame_flattening () +
webkit_settings_get_enable_developer_extras, webkit_settings_get_enable_developer_extras ()
-
webkit_settings_get_enable_fullscreen, webkit_settings_get_enable_fullscreen () +
webkit_settings_get_enable_dns_prefetching, webkit_settings_get_enable_dns_prefetching ()
-
webkit_settings_get_enable_html5_database, webkit_settings_get_enable_html5_database () +
webkit_settings_get_enable_frame_flattening, webkit_settings_get_enable_frame_flattening ()
-
webkit_settings_get_enable_html5_local_storage, webkit_settings_get_enable_html5_local_storage () +
webkit_settings_get_enable_fullscreen, webkit_settings_get_enable_fullscreen ()
-
webkit_settings_get_enable_hyperlink_auditing, webkit_settings_get_enable_hyperlink_auditing () +
webkit_settings_get_enable_html5_database, webkit_settings_get_enable_html5_database ()
-
webkit_settings_get_enable_java, webkit_settings_get_enable_java () +
webkit_settings_get_enable_html5_local_storage, webkit_settings_get_enable_html5_local_storage ()
-
webkit_settings_get_enable_javascript, webkit_settings_get_enable_javascript () +
webkit_settings_get_enable_hyperlink_auditing, webkit_settings_get_enable_hyperlink_auditing ()
-
webkit_settings_get_enable_mediasource, webkit_settings_get_enable_mediasource () +
webkit_settings_get_enable_java, webkit_settings_get_enable_java ()
-
webkit_settings_get_enable_media_stream, webkit_settings_get_enable_media_stream () +
webkit_settings_get_enable_javascript, webkit_settings_get_enable_javascript ()
-
webkit_settings_get_enable_offline_web_application_cache, webkit_settings_get_enable_offline_web_application_cache () +
webkit_settings_get_enable_mediasource, webkit_settings_get_enable_mediasource ()
-
webkit_settings_get_enable_page_cache, webkit_settings_get_enable_page_cache () +
webkit_settings_get_enable_media_stream, webkit_settings_get_enable_media_stream ()
-
webkit_settings_get_enable_plugins, webkit_settings_get_enable_plugins () +
webkit_settings_get_enable_offline_web_application_cache, webkit_settings_get_enable_offline_web_application_cache ()
-
webkit_settings_get_enable_private_browsing, webkit_settings_get_enable_private_browsing () +
webkit_settings_get_enable_page_cache, webkit_settings_get_enable_page_cache ()
-
webkit_settings_get_enable_resizable_text_areas, webkit_settings_get_enable_resizable_text_areas () +
webkit_settings_get_enable_plugins, webkit_settings_get_enable_plugins ()
-
webkit_settings_get_enable_site_specific_quirks, webkit_settings_get_enable_site_specific_quirks () +
webkit_settings_get_enable_private_browsing, webkit_settings_get_enable_private_browsing ()
-
webkit_settings_get_enable_smooth_scrolling, webkit_settings_get_enable_smooth_scrolling () +
webkit_settings_get_enable_resizable_text_areas, webkit_settings_get_enable_resizable_text_areas ()
-
webkit_settings_get_enable_spatial_navigation, webkit_settings_get_enable_spatial_navigation () +
webkit_settings_get_enable_site_specific_quirks, webkit_settings_get_enable_site_specific_quirks ()
-
webkit_settings_get_enable_tabs_to_links, webkit_settings_get_enable_tabs_to_links () +
webkit_settings_get_enable_smooth_scrolling, webkit_settings_get_enable_smooth_scrolling ()
-
webkit_settings_get_enable_webaudio, webkit_settings_get_enable_webaudio () +
webkit_settings_get_enable_spatial_navigation, webkit_settings_get_enable_spatial_navigation ()
-
webkit_settings_get_enable_webgl, webkit_settings_get_enable_webgl () +
webkit_settings_get_enable_tabs_to_links, webkit_settings_get_enable_tabs_to_links ()
-
webkit_settings_get_enable_write_console_messages_to_stdout, webkit_settings_get_enable_write_console_messages_to_stdout () +
webkit_settings_get_enable_webaudio, webkit_settings_get_enable_webaudio ()
-
webkit_settings_get_enable_xss_auditor, webkit_settings_get_enable_xss_auditor () +
webkit_settings_get_enable_webgl, webkit_settings_get_enable_webgl ()
-
webkit_settings_get_fantasy_font_family, webkit_settings_get_fantasy_font_family () +
webkit_settings_get_enable_write_console_messages_to_stdout, webkit_settings_get_enable_write_console_messages_to_stdout ()
-
webkit_settings_get_javascript_can_access_clipboard, webkit_settings_get_javascript_can_access_clipboard () +
webkit_settings_get_enable_xss_auditor, webkit_settings_get_enable_xss_auditor ()
-
webkit_settings_get_javascript_can_open_windows_automatically, webkit_settings_get_javascript_can_open_windows_automatically () +
webkit_settings_get_fantasy_font_family, webkit_settings_get_fantasy_font_family ()
-
webkit_settings_get_load_icons_ignoring_image_load_setting, webkit_settings_get_load_icons_ignoring_image_load_setting () +
webkit_settings_get_javascript_can_access_clipboard, webkit_settings_get_javascript_can_access_clipboard ()
-
webkit_settings_get_media_playback_allows_inline, webkit_settings_get_media_playback_allows_inline () +
webkit_settings_get_javascript_can_open_windows_automatically, webkit_settings_get_javascript_can_open_windows_automatically ()
-
webkit_settings_get_media_playback_requires_user_gesture, webkit_settings_get_media_playback_requires_user_gesture () +
webkit_settings_get_load_icons_ignoring_image_load_setting, webkit_settings_get_load_icons_ignoring_image_load_setting ()
-
webkit_settings_get_minimum_font_size, webkit_settings_get_minimum_font_size () +
webkit_settings_get_media_playback_allows_inline, webkit_settings_get_media_playback_allows_inline ()
-
webkit_settings_get_monospace_font_family, webkit_settings_get_monospace_font_family () +
webkit_settings_get_media_playback_requires_user_gesture, webkit_settings_get_media_playback_requires_user_gesture ()
-
webkit_settings_get_pictograph_font_family, webkit_settings_get_pictograph_font_family () +
webkit_settings_get_minimum_font_size, webkit_settings_get_minimum_font_size ()
-
webkit_settings_get_print_backgrounds, webkit_settings_get_print_backgrounds () +
webkit_settings_get_monospace_font_family, webkit_settings_get_monospace_font_family ()
-
webkit_settings_get_sans_serif_font_family, webkit_settings_get_sans_serif_font_family () +
webkit_settings_get_pictograph_font_family, webkit_settings_get_pictograph_font_family ()
-
webkit_settings_get_serif_font_family, webkit_settings_get_serif_font_family () +
webkit_settings_get_print_backgrounds, webkit_settings_get_print_backgrounds ()
-
webkit_settings_get_user_agent, webkit_settings_get_user_agent () +
webkit_settings_get_sans_serif_font_family, webkit_settings_get_sans_serif_font_family ()
-
webkit_settings_get_zoom_text_only, webkit_settings_get_zoom_text_only () +
webkit_settings_get_serif_font_family, webkit_settings_get_serif_font_family ()
-
webkit_settings_new, webkit_settings_new () +
webkit_settings_get_user_agent, webkit_settings_get_user_agent ()
-
webkit_settings_new_with_settings, webkit_settings_new_with_settings () +
webkit_settings_get_zoom_text_only, webkit_settings_get_zoom_text_only ()
-
webkit_settings_set_allow_file_access_from_file_urls, webkit_settings_set_allow_file_access_from_file_urls () +
webkit_settings_new, webkit_settings_new ()
-
webkit_settings_set_allow_modal_dialogs, webkit_settings_set_allow_modal_dialogs () +
webkit_settings_new_with_settings, webkit_settings_new_with_settings ()
-
webkit_settings_set_auto_load_images, webkit_settings_set_auto_load_images () +
webkit_settings_set_allow_file_access_from_file_urls, webkit_settings_set_allow_file_access_from_file_urls ()
-
webkit_settings_set_cursive_font_family, webkit_settings_set_cursive_font_family () +
webkit_settings_set_allow_modal_dialogs, webkit_settings_set_allow_modal_dialogs ()
-
webkit_settings_set_default_charset, webkit_settings_set_default_charset () +
webkit_settings_set_allow_universal_access_from_file_urls, webkit_settings_set_allow_universal_access_from_file_urls ()
-
webkit_settings_set_default_font_family, webkit_settings_set_default_font_family () +
webkit_settings_set_auto_load_images, webkit_settings_set_auto_load_images ()
-
webkit_settings_set_default_font_size, webkit_settings_set_default_font_size () +
webkit_settings_set_cursive_font_family, webkit_settings_set_cursive_font_family ()
-
webkit_settings_set_default_monospace_font_size, webkit_settings_set_default_monospace_font_size () +
webkit_settings_set_default_charset, webkit_settings_set_default_charset ()
-
webkit_settings_set_draw_compositing_indicators, webkit_settings_set_draw_compositing_indicators () +
webkit_settings_set_default_font_family, webkit_settings_set_default_font_family ()
-
webkit_settings_set_enable_accelerated_2d_canvas, webkit_settings_set_enable_accelerated_2d_canvas () +
webkit_settings_set_default_font_size, webkit_settings_set_default_font_size ()
-
webkit_settings_set_enable_caret_browsing, webkit_settings_set_enable_caret_browsing () +
webkit_settings_set_default_monospace_font_size, webkit_settings_set_default_monospace_font_size ()
-
webkit_settings_set_enable_developer_extras, webkit_settings_set_enable_developer_extras () +
webkit_settings_set_draw_compositing_indicators, webkit_settings_set_draw_compositing_indicators ()
-
webkit_settings_set_enable_dns_prefetching, webkit_settings_set_enable_dns_prefetching () +
webkit_settings_set_enable_accelerated_2d_canvas, webkit_settings_set_enable_accelerated_2d_canvas ()
-
webkit_settings_set_enable_frame_flattening, webkit_settings_set_enable_frame_flattening () +
webkit_settings_set_enable_caret_browsing, webkit_settings_set_enable_caret_browsing ()
-
webkit_settings_set_enable_fullscreen, webkit_settings_set_enable_fullscreen () +
webkit_settings_set_enable_developer_extras, webkit_settings_set_enable_developer_extras ()
-
webkit_settings_set_enable_html5_database, webkit_settings_set_enable_html5_database () +
webkit_settings_set_enable_dns_prefetching, webkit_settings_set_enable_dns_prefetching ()
-
webkit_settings_set_enable_html5_local_storage, webkit_settings_set_enable_html5_local_storage () +
webkit_settings_set_enable_frame_flattening, webkit_settings_set_enable_frame_flattening ()
-
webkit_settings_set_enable_hyperlink_auditing, webkit_settings_set_enable_hyperlink_auditing () +
webkit_settings_set_enable_fullscreen, webkit_settings_set_enable_fullscreen ()
-
webkit_settings_set_enable_java, webkit_settings_set_enable_java () +
webkit_settings_set_enable_html5_database, webkit_settings_set_enable_html5_database ()
-
webkit_settings_set_enable_javascript, webkit_settings_set_enable_javascript () +
webkit_settings_set_enable_html5_local_storage, webkit_settings_set_enable_html5_local_storage ()
-
webkit_settings_set_enable_mediasource, webkit_settings_set_enable_mediasource () +
webkit_settings_set_enable_hyperlink_auditing, webkit_settings_set_enable_hyperlink_auditing ()
-
webkit_settings_set_enable_media_stream, webkit_settings_set_enable_media_stream () +
webkit_settings_set_enable_java, webkit_settings_set_enable_java ()
-
webkit_settings_set_enable_offline_web_application_cache, webkit_settings_set_enable_offline_web_application_cache () +
webkit_settings_set_enable_javascript, webkit_settings_set_enable_javascript ()
-
webkit_settings_set_enable_page_cache, webkit_settings_set_enable_page_cache () +
webkit_settings_set_enable_mediasource, webkit_settings_set_enable_mediasource ()
-
webkit_settings_set_enable_plugins, webkit_settings_set_enable_plugins () +
webkit_settings_set_enable_media_stream, webkit_settings_set_enable_media_stream ()
-
webkit_settings_set_enable_private_browsing, webkit_settings_set_enable_private_browsing () +
webkit_settings_set_enable_offline_web_application_cache, webkit_settings_set_enable_offline_web_application_cache ()
-
webkit_settings_set_enable_resizable_text_areas, webkit_settings_set_enable_resizable_text_areas () +
webkit_settings_set_enable_page_cache, webkit_settings_set_enable_page_cache ()
-
webkit_settings_set_enable_site_specific_quirks, webkit_settings_set_enable_site_specific_quirks () +
webkit_settings_set_enable_plugins, webkit_settings_set_enable_plugins ()
-
webkit_settings_set_enable_smooth_scrolling, webkit_settings_set_enable_smooth_scrolling () +
webkit_settings_set_enable_private_browsing, webkit_settings_set_enable_private_browsing ()
-
webkit_settings_set_enable_spatial_navigation, webkit_settings_set_enable_spatial_navigation () +
webkit_settings_set_enable_resizable_text_areas, webkit_settings_set_enable_resizable_text_areas ()
-
webkit_settings_set_enable_tabs_to_links, webkit_settings_set_enable_tabs_to_links () +
webkit_settings_set_enable_site_specific_quirks, webkit_settings_set_enable_site_specific_quirks ()
-
webkit_settings_set_enable_webaudio, webkit_settings_set_enable_webaudio () +
webkit_settings_set_enable_smooth_scrolling, webkit_settings_set_enable_smooth_scrolling ()
-
webkit_settings_set_enable_webgl, webkit_settings_set_enable_webgl () +
webkit_settings_set_enable_spatial_navigation, webkit_settings_set_enable_spatial_navigation ()
-
webkit_settings_set_enable_write_console_messages_to_stdout, webkit_settings_set_enable_write_console_messages_to_stdout () +
webkit_settings_set_enable_tabs_to_links, webkit_settings_set_enable_tabs_to_links ()
-
webkit_settings_set_enable_xss_auditor, webkit_settings_set_enable_xss_auditor () +
webkit_settings_set_enable_webaudio, webkit_settings_set_enable_webaudio ()
-
webkit_settings_set_fantasy_font_family, webkit_settings_set_fantasy_font_family () +
webkit_settings_set_enable_webgl, webkit_settings_set_enable_webgl ()
-
webkit_settings_set_javascript_can_access_clipboard, webkit_settings_set_javascript_can_access_clipboard () +
webkit_settings_set_enable_write_console_messages_to_stdout, webkit_settings_set_enable_write_console_messages_to_stdout ()
-
webkit_settings_set_javascript_can_open_windows_automatically, webkit_settings_set_javascript_can_open_windows_automatically () +
webkit_settings_set_enable_xss_auditor, webkit_settings_set_enable_xss_auditor ()
-
webkit_settings_set_load_icons_ignoring_image_load_setting, webkit_settings_set_load_icons_ignoring_image_load_setting () +
webkit_settings_set_fantasy_font_family, webkit_settings_set_fantasy_font_family ()
-
webkit_settings_set_media_playback_allows_inline, webkit_settings_set_media_playback_allows_inline () +
webkit_settings_set_javascript_can_access_clipboard, webkit_settings_set_javascript_can_access_clipboard ()
-
webkit_settings_set_media_playback_requires_user_gesture, webkit_settings_set_media_playback_requires_user_gesture () +
webkit_settings_set_javascript_can_open_windows_automatically, webkit_settings_set_javascript_can_open_windows_automatically ()
-
webkit_settings_set_minimum_font_size, webkit_settings_set_minimum_font_size () +
webkit_settings_set_load_icons_ignoring_image_load_setting, webkit_settings_set_load_icons_ignoring_image_load_setting ()
-
webkit_settings_set_monospace_font_family, webkit_settings_set_monospace_font_family () +
webkit_settings_set_media_playback_allows_inline, webkit_settings_set_media_playback_allows_inline ()
-
webkit_settings_set_pictograph_font_family, webkit_settings_set_pictograph_font_family () +
webkit_settings_set_media_playback_requires_user_gesture, webkit_settings_set_media_playback_requires_user_gesture ()
-
webkit_settings_set_print_backgrounds, webkit_settings_set_print_backgrounds () +
webkit_settings_set_minimum_font_size, webkit_settings_set_minimum_font_size ()
-
webkit_settings_set_sans_serif_font_family, webkit_settings_set_sans_serif_font_family () +
webkit_settings_set_monospace_font_family, webkit_settings_set_monospace_font_family ()
-
webkit_settings_set_serif_font_family, webkit_settings_set_serif_font_family () +
webkit_settings_set_pictograph_font_family, webkit_settings_set_pictograph_font_family ()
-
webkit_settings_set_user_agent, webkit_settings_set_user_agent () +
webkit_settings_set_print_backgrounds, webkit_settings_set_print_backgrounds ()
-
webkit_settings_set_user_agent_with_application_details, webkit_settings_set_user_agent_with_application_details () +
webkit_settings_set_sans_serif_font_family, webkit_settings_set_sans_serif_font_family ()
-
webkit_settings_set_zoom_text_only, webkit_settings_set_zoom_text_only () +
webkit_settings_set_serif_font_family, webkit_settings_set_serif_font_family ()
-
WebKitSnapshotError, enum WebKitSnapshotError +
webkit_settings_set_user_agent, webkit_settings_set_user_agent ()
-
WebKitSnapshotOptions, enum WebKitSnapshotOptions +
webkit_settings_set_user_agent_with_application_details, webkit_settings_set_user_agent_with_application_details ()
-
WebKitSnapshotRegion, enum WebKitSnapshotRegion +
webkit_settings_set_zoom_text_only, webkit_settings_set_zoom_text_only ()
-
WEBKIT_SNAPSHOT_ERROR, WEBKIT_SNAPSHOT_ERROR +
WebKitSnapshotError, enum WebKitSnapshotError
-
webkit_snapshot_error_quark, webkit_snapshot_error_quark () +
WebKitSnapshotOptions, enum WebKitSnapshotOptions +
+
WebKitSnapshotRegion, enum WebKitSnapshotRegion +
+
WEBKIT_SNAPSHOT_ERROR, WEBKIT_SNAPSHOT_ERROR +
+
webkit_snapshot_error_quark, webkit_snapshot_error_quark ()
@@ -1077,111 +1083,111 @@

U

-
WebKitURIRequest, struct WebKitURIRequest +
WebKitURIRequest, struct WebKitURIRequest
-
WebKitURIRequest:uri, The “uri” property +
WebKitURIRequest:uri, The “uri” property
-
WebKitURIResponse, struct WebKitURIResponse +
WebKitURIResponse, struct WebKitURIResponse
-
WebKitURIResponse:content-length, The “content-length” property +
WebKitURIResponse:content-length, The “content-length” property
-
WebKitURIResponse:http-headers, The “http-headers” property +
WebKitURIResponse:http-headers, The “http-headers” property
-
WebKitURIResponse:mime-type, The “mime-type” property +
WebKitURIResponse:mime-type, The “mime-type” property
-
WebKitURIResponse:status-code, The “status-code” property +
WebKitURIResponse:status-code, The “status-code” property
-
WebKitURIResponse:suggested-filename, The “suggested-filename” property +
WebKitURIResponse:suggested-filename, The “suggested-filename” property
-
WebKitURIResponse:uri, The “uri” property +
WebKitURIResponse:uri, The “uri” property
-
WebKitURISchemeRequest, struct WebKitURISchemeRequest +
WebKitURISchemeRequest, struct WebKitURISchemeRequest
WebKitURISchemeRequestCallback, WebKitURISchemeRequestCallback ()
-
webkit_uri_request_get_http_headers, webkit_uri_request_get_http_headers () +
webkit_uri_request_get_http_headers, webkit_uri_request_get_http_headers ()
-
webkit_uri_request_get_http_method, webkit_uri_request_get_http_method () +
webkit_uri_request_get_http_method, webkit_uri_request_get_http_method ()
-
webkit_uri_request_get_uri, webkit_uri_request_get_uri () +
webkit_uri_request_get_uri, webkit_uri_request_get_uri ()
-
webkit_uri_request_new, webkit_uri_request_new () +
webkit_uri_request_new, webkit_uri_request_new ()
-
webkit_uri_request_set_uri, webkit_uri_request_set_uri () +
webkit_uri_request_set_uri, webkit_uri_request_set_uri ()
-
webkit_uri_response_get_content_length, webkit_uri_response_get_content_length () +
webkit_uri_response_get_content_length, webkit_uri_response_get_content_length ()
-
webkit_uri_response_get_http_headers, webkit_uri_response_get_http_headers () +
webkit_uri_response_get_http_headers, webkit_uri_response_get_http_headers ()
-
webkit_uri_response_get_mime_type, webkit_uri_response_get_mime_type () +
webkit_uri_response_get_mime_type, webkit_uri_response_get_mime_type ()
-
webkit_uri_response_get_status_code, webkit_uri_response_get_status_code () +
webkit_uri_response_get_status_code, webkit_uri_response_get_status_code ()
-
webkit_uri_response_get_suggested_filename, webkit_uri_response_get_suggested_filename () +
webkit_uri_response_get_suggested_filename, webkit_uri_response_get_suggested_filename ()
-
webkit_uri_response_get_uri, webkit_uri_response_get_uri () +
webkit_uri_response_get_uri, webkit_uri_response_get_uri ()
-
webkit_uri_scheme_request_finish, webkit_uri_scheme_request_finish () +
webkit_uri_scheme_request_finish, webkit_uri_scheme_request_finish ()
-
webkit_uri_scheme_request_finish_error, webkit_uri_scheme_request_finish_error () +
webkit_uri_scheme_request_finish_error, webkit_uri_scheme_request_finish_error ()
-
webkit_uri_scheme_request_get_path, webkit_uri_scheme_request_get_path () +
webkit_uri_scheme_request_get_path, webkit_uri_scheme_request_get_path ()
-
webkit_uri_scheme_request_get_scheme, webkit_uri_scheme_request_get_scheme () +
webkit_uri_scheme_request_get_scheme, webkit_uri_scheme_request_get_scheme ()
-
webkit_uri_scheme_request_get_uri, webkit_uri_scheme_request_get_uri () +
webkit_uri_scheme_request_get_uri, webkit_uri_scheme_request_get_uri ()
-
webkit_uri_scheme_request_get_web_view, webkit_uri_scheme_request_get_web_view () +
webkit_uri_scheme_request_get_web_view, webkit_uri_scheme_request_get_web_view ()
-
WebKitUserContentInjectedFrames, enum WebKitUserContentInjectedFrames +
WebKitUserContentInjectedFrames, enum WebKitUserContentInjectedFrames
-
WebKitUserContentManager, struct WebKitUserContentManager +
WebKitUserContentManager, struct WebKitUserContentManager
-
WebKitUserContentManager::script-message-received, The “script-message-received” signal +
WebKitUserContentManager::script-message-received, The “script-message-received” signal
-
WebKitUserMediaPermissionRequest, struct WebKitUserMediaPermissionRequest +
WebKitUserMediaPermissionRequest, struct WebKitUserMediaPermissionRequest
-
WebKitUserMediaPermissionRequest:is-for-audio-device, The “is-for-audio-device” property +
WebKitUserMediaPermissionRequest:is-for-audio-device, The “is-for-audio-device” property
-
WebKitUserMediaPermissionRequest:is-for-video-device, The “is-for-video-device” property +
WebKitUserMediaPermissionRequest:is-for-video-device, The “is-for-video-device” property
-
WebKitUserScript, WebKitUserScript +
WebKitUserScript, WebKitUserScript
-
WebKitUserScriptInjectionTime, enum WebKitUserScriptInjectionTime +
WebKitUserScriptInjectionTime, enum WebKitUserScriptInjectionTime
-
WebKitUserStyleLevel, enum WebKitUserStyleLevel +
WebKitUserStyleLevel, enum WebKitUserStyleLevel
-
WebKitUserStyleSheet, WebKitUserStyleSheet +
WebKitUserStyleSheet, WebKitUserStyleSheet
-
webkit_user_content_manager_add_script, webkit_user_content_manager_add_script () +
webkit_user_content_manager_add_script, webkit_user_content_manager_add_script ()
-
webkit_user_content_manager_add_style_sheet, webkit_user_content_manager_add_style_sheet () +
webkit_user_content_manager_add_style_sheet, webkit_user_content_manager_add_style_sheet ()
-
webkit_user_content_manager_new, webkit_user_content_manager_new () +
webkit_user_content_manager_new, webkit_user_content_manager_new ()
-
webkit_user_content_manager_register_script_message_handler, webkit_user_content_manager_register_script_message_handler () +
webkit_user_content_manager_register_script_message_handler, webkit_user_content_manager_register_script_message_handler ()
-
webkit_user_content_manager_remove_all_scripts, webkit_user_content_manager_remove_all_scripts () +
webkit_user_content_manager_remove_all_scripts, webkit_user_content_manager_remove_all_scripts ()
-
webkit_user_content_manager_remove_all_style_sheets, webkit_user_content_manager_remove_all_style_sheets () +
webkit_user_content_manager_remove_all_style_sheets, webkit_user_content_manager_remove_all_style_sheets ()
-
webkit_user_content_manager_unregister_script_message_handler, webkit_user_content_manager_unregister_script_message_handler () +
webkit_user_content_manager_unregister_script_message_handler, webkit_user_content_manager_unregister_script_message_handler ()
-
webkit_user_media_permission_is_for_audio_device, webkit_user_media_permission_is_for_audio_device () +
webkit_user_media_permission_is_for_audio_device, webkit_user_media_permission_is_for_audio_device ()
-
webkit_user_media_permission_is_for_video_device, webkit_user_media_permission_is_for_video_device () +
webkit_user_media_permission_is_for_video_device, webkit_user_media_permission_is_for_video_device ()
-
webkit_user_script_new, webkit_user_script_new () +
webkit_user_script_new, webkit_user_script_new ()
-
webkit_user_script_ref, webkit_user_script_ref () +
webkit_user_script_ref, webkit_user_script_ref ()
-
webkit_user_script_unref, webkit_user_script_unref () +
webkit_user_script_unref, webkit_user_script_unref ()
-
webkit_user_style_sheet_new, webkit_user_style_sheet_new () +
webkit_user_style_sheet_new, webkit_user_style_sheet_new ()
-
webkit_user_style_sheet_ref, webkit_user_style_sheet_ref () +
webkit_user_style_sheet_ref, webkit_user_style_sheet_ref ()
-
webkit_user_style_sheet_unref, webkit_user_style_sheet_unref () +
webkit_user_style_sheet_unref, webkit_user_style_sheet_unref ()
@@ -1198,175 +1204,175 @@
WebKitWebContext:website-data-manager, The “website-data-manager” property
-
WebKitWebEditor, WebKitWebEditor +
WebKitWebEditor, WebKitWebEditor
-
WebKitWebEditor::selection-changed, The “selection-changed” signal +
WebKitWebEditor::selection-changed, The “selection-changed” signal
-
WebKitWebExtension, struct WebKitWebExtension +
WebKitWebExtension, struct WebKitWebExtension
-
WebKitWebExtension::page-created, The “page-created” signal +
WebKitWebExtension::page-created, The “page-created” signal
-
WebKitWebExtensionInitializeFunction, WebKitWebExtensionInitializeFunction () +
WebKitWebExtensionInitializeFunction, WebKitWebExtensionInitializeFunction ()
-
WebKitWebExtensionInitializeWithUserDataFunction, WebKitWebExtensionInitializeWithUserDataFunction () +
WebKitWebExtensionInitializeWithUserDataFunction, WebKitWebExtensionInitializeWithUserDataFunction ()
-
WebKitWebHitTestResult, struct WebKitWebHitTestResult +
WebKitWebHitTestResult, struct WebKitWebHitTestResult
-
WebKitWebHitTestResult:node, The “node” property +
WebKitWebHitTestResult:node, The “node” property
-
WebKitWebInspector, struct WebKitWebInspector +
WebKitWebInspector, struct WebKitWebInspector
-
WebKitWebInspector::attach, The “attach” signal +
WebKitWebInspector::attach, The “attach” signal
-
WebKitWebInspector::bring-to-front, The “bring-to-front” signal +
WebKitWebInspector::bring-to-front, The “bring-to-front” signal
-
WebKitWebInspector::closed, The “closed” signal +
WebKitWebInspector::closed, The “closed” signal
-
WebKitWebInspector::detach, The “detach” signal +
WebKitWebInspector::detach, The “detach” signal
-
WebKitWebInspector::open-window, The “open-window” signal +
WebKitWebInspector::open-window, The “open-window” signal
-
WebKitWebInspector:attached-height, The “attached-height” property +
WebKitWebInspector:attached-height, The “attached-height” property
-
WebKitWebInspector:can-attach, The “can-attach” property +
WebKitWebInspector:can-attach, The “can-attach” property
-
WebKitWebInspector:inspected-uri, The “inspected-uri” property +
WebKitWebInspector:inspected-uri, The “inspected-uri” property
-
WebKitWebPage, WebKitWebPage +
WebKitWebPage, WebKitWebPage
-
WebKitWebPage::console-message-sent, The “console-message-sent” signal +
WebKitWebPage::console-message-sent, The “console-message-sent” signal
-
WebKitWebPage::context-menu, The “context-menu” signal +
WebKitWebPage::context-menu, The “context-menu” signal
-
WebKitWebPage::document-loaded, The “document-loaded” signal +
WebKitWebPage::document-loaded, The “document-loaded” signal
-
WebKitWebPage::send-request, The “send-request” signal +
WebKitWebPage::send-request, The “send-request” signal
-
WebKitWebPage:uri, The “uri” property +
WebKitWebPage:uri, The “uri” property
-
WebKitWebResource, struct WebKitWebResource +
WebKitWebResource, struct WebKitWebResource
-
WebKitWebResource::failed, The “failed” signal +
WebKitWebResource::failed, The “failed” signal
-
WebKitWebResource::failed-with-tls-errors, The “failed-with-tls-errors” signal +
WebKitWebResource::failed-with-tls-errors, The “failed-with-tls-errors” signal
-
WebKitWebResource::finished, The “finished” signal +
WebKitWebResource::finished, The “finished” signal
-
WebKitWebResource::received-data, The “received-data” signal +
WebKitWebResource::received-data, The “received-data” signal
-
WebKitWebResource::sent-request, The “sent-request” signal +
WebKitWebResource::sent-request, The “sent-request” signal
-
WebKitWebResource:response, The “response” property +
WebKitWebResource:response, The “response” property
-
WebKitWebResource:uri, The “uri” property +
WebKitWebResource:uri, The “uri” property
-
WebKitWebsiteDataManager, struct WebKitWebsiteDataManager +
WebKitWebsiteDataManager, struct WebKitWebsiteDataManager
-
WebKitWebsiteDataManager:base-cache-directory, The “base-cache-directory” property +
WebKitWebsiteDataManager:base-cache-directory, The “base-cache-directory” property
-
WebKitWebsiteDataManager:base-data-directory, The “base-data-directory” property +
WebKitWebsiteDataManager:base-data-directory, The “base-data-directory” property
-
WebKitWebsiteDataManager:disk-cache-directory, The “disk-cache-directory” property +
WebKitWebsiteDataManager:disk-cache-directory, The “disk-cache-directory” property
-
WebKitWebsiteDataManager:indexeddb-directory, The “indexeddb-directory” property +
WebKitWebsiteDataManager:indexeddb-directory, The “indexeddb-directory” property
-
WebKitWebsiteDataManager:local-storage-directory, The “local-storage-directory” property +
WebKitWebsiteDataManager:local-storage-directory, The “local-storage-directory” property
-
WebKitWebsiteDataManager:offline-application-cache-directory, The “offline-application-cache-directory” property +
WebKitWebsiteDataManager:offline-application-cache-directory, The “offline-application-cache-directory” property
-
WebKitWebsiteDataManager:websql-directory, The “websql-directory” property +
WebKitWebsiteDataManager:websql-directory, The “websql-directory” property
-
webkit_website_data_manager_get_base_cache_directory, webkit_website_data_manager_get_base_cache_directory () +
webkit_website_data_manager_get_base_cache_directory, webkit_website_data_manager_get_base_cache_directory ()
-
webkit_website_data_manager_get_base_data_directory, webkit_website_data_manager_get_base_data_directory () +
webkit_website_data_manager_get_base_data_directory, webkit_website_data_manager_get_base_data_directory ()
-
webkit_website_data_manager_get_disk_cache_directory, webkit_website_data_manager_get_disk_cache_directory () +
webkit_website_data_manager_get_disk_cache_directory, webkit_website_data_manager_get_disk_cache_directory ()
-
webkit_website_data_manager_get_indexeddb_directory, webkit_website_data_manager_get_indexeddb_directory () +
webkit_website_data_manager_get_indexeddb_directory, webkit_website_data_manager_get_indexeddb_directory ()
-
webkit_website_data_manager_get_local_storage_directory, webkit_website_data_manager_get_local_storage_directory () +
webkit_website_data_manager_get_local_storage_directory, webkit_website_data_manager_get_local_storage_directory ()
-
webkit_website_data_manager_get_offline_application_cache_directory, webkit_website_data_manager_get_offline_application_cache_directory () +
webkit_website_data_manager_get_offline_application_cache_directory, webkit_website_data_manager_get_offline_application_cache_directory ()
-
webkit_website_data_manager_get_websql_directory, webkit_website_data_manager_get_websql_directory () +
webkit_website_data_manager_get_websql_directory, webkit_website_data_manager_get_websql_directory ()
-
webkit_website_data_manager_new, webkit_website_data_manager_new () +
webkit_website_data_manager_new, webkit_website_data_manager_new ()
-
WebKitWebView, WebKitWebView +
WebKitWebView, WebKitWebView
-
WebKitWebView::authenticate, The “authenticate” signal +
WebKitWebView::authenticate, The “authenticate” signal
-
WebKitWebView::close, The “close” signal +
WebKitWebView::close, The “close” signal
-
WebKitWebView::context-menu, The “context-menu” signal +
WebKitWebView::context-menu, The “context-menu” signal
-
WebKitWebView::context-menu-dismissed, The “context-menu-dismissed” signal +
WebKitWebView::context-menu-dismissed, The “context-menu-dismissed” signal
-
WebKitWebView::create, The “create” signal +
WebKitWebView::create, The “create” signal
-
WebKitWebView::decide-policy, The “decide-policy” signal +
WebKitWebView::decide-policy, The “decide-policy” signal
-
WebKitWebView::enter-fullscreen, The “enter-fullscreen” signal +
WebKitWebView::enter-fullscreen, The “enter-fullscreen” signal
-
WebKitWebView::insecure-content-detected, The “insecure-content-detected” signal +
WebKitWebView::insecure-content-detected, The “insecure-content-detected” signal
-
WebKitWebView::leave-fullscreen, The “leave-fullscreen” signal +
WebKitWebView::leave-fullscreen, The “leave-fullscreen” signal
-
WebKitWebView::load-changed, The “load-changed” signal +
WebKitWebView::load-changed, The “load-changed” signal
-
WebKitWebView::load-failed, The “load-failed” signal +
WebKitWebView::load-failed, The “load-failed” signal
-
WebKitWebView::load-failed-with-tls-errors, The “load-failed-with-tls-errors” signal +
WebKitWebView::load-failed-with-tls-errors, The “load-failed-with-tls-errors” signal
-
WebKitWebView::mouse-target-changed, The “mouse-target-changed” signal +
WebKitWebView::mouse-target-changed, The “mouse-target-changed” signal
-
WebKitWebView::permission-request, The “permission-request” signal +
WebKitWebView::permission-request, The “permission-request” signal
-
WebKitWebView::print, The “print” signal +
WebKitWebView::print, The “print” signal
-
WebKitWebView::ready-to-show, The “ready-to-show” signal +
WebKitWebView::ready-to-show, The “ready-to-show” signal
-
WebKitWebView::resource-load-started, The “resource-load-started” signal +
WebKitWebView::resource-load-started, The “resource-load-started” signal
-
WebKitWebView::run-as-modal, The “run-as-modal” signal +
WebKitWebView::run-as-modal, The “run-as-modal” signal
-
WebKitWebView::run-color-chooser, The “run-color-chooser” signal +
WebKitWebView::run-color-chooser, The “run-color-chooser” signal
-
WebKitWebView::run-file-chooser, The “run-file-chooser” signal +
WebKitWebView::run-file-chooser, The “run-file-chooser” signal
-
WebKitWebView::script-dialog, The “script-dialog” signal +
WebKitWebView::script-dialog, The “script-dialog” signal
-
WebKitWebView::show-notification, The “show-notification” signal +
WebKitWebView::show-notification, The “show-notification” signal
-
WebKitWebView::submit-form, The “submit-form” signal +
WebKitWebView::submit-form, The “submit-form” signal
-
WebKitWebView::web-process-crashed, The “web-process-crashed” signal +
WebKitWebView::web-process-crashed, The “web-process-crashed” signal
-
WebKitWebView:editable, The “editable” property +
WebKitWebView:editable, The “editable” property
-
WebKitWebView:estimated-load-progress, The “estimated-load-progress” property +
WebKitWebView:estimated-load-progress, The “estimated-load-progress” property
-
WebKitWebView:favicon, The “favicon” property +
WebKitWebView:favicon, The “favicon” property
-
WebKitWebView:is-loading, The “is-loading” property +
WebKitWebView:is-loading, The “is-loading” property
-
WebKitWebView:is-playing-audio, The “is-playing-audio” property +
WebKitWebView:is-playing-audio, The “is-playing-audio” property
-
WebKitWebView:related-view, The “related-view” property +
WebKitWebView:related-view, The “related-view” property
-
WebKitWebView:settings, The “settings” property +
WebKitWebView:settings, The “settings” property
-
WebKitWebView:title, The “title” property +
WebKitWebView:title, The “title” property
-
WebKitWebView:uri, The “uri” property +
WebKitWebView:uri, The “uri” property
-
WebKitWebView:user-content-manager, The “user-content-manager” property +
WebKitWebView:user-content-manager, The “user-content-manager” property
-
WebKitWebView:web-context, The “web-context” property +
WebKitWebView:web-context, The “web-context” property
-
WebKitWebView:zoom-level, The “zoom-level” property +
WebKitWebView:zoom-level, The “zoom-level” property
-
WebKitWebViewSessionState, WebKitWebViewSessionState +
WebKitWebViewSessionState, WebKitWebViewSessionState
webkit_web_context_allow_tls_certificate_for_host, webkit_web_context_allow_tls_certificate_for_host ()
@@ -1434,47 +1440,47 @@
webkit_web_context_set_web_process_count_limit, webkit_web_context_set_web_process_count_limit ()
-
webkit_web_editor_get_page, webkit_web_editor_get_page () +
webkit_web_editor_get_page, webkit_web_editor_get_page ()
-
webkit_web_extension_get_page, webkit_web_extension_get_page () +
webkit_web_extension_get_page, webkit_web_extension_get_page ()
-
webkit_web_hit_test_result_get_node, webkit_web_hit_test_result_get_node () +
webkit_web_hit_test_result_get_node, webkit_web_hit_test_result_get_node ()
-
webkit_web_inspector_attach, webkit_web_inspector_attach () +
webkit_web_inspector_attach, webkit_web_inspector_attach ()
-
webkit_web_inspector_close, webkit_web_inspector_close () +
webkit_web_inspector_close, webkit_web_inspector_close ()
-
webkit_web_inspector_detach, webkit_web_inspector_detach () +
webkit_web_inspector_detach, webkit_web_inspector_detach ()
-
webkit_web_inspector_get_attached_height, webkit_web_inspector_get_attached_height () +
webkit_web_inspector_get_attached_height, webkit_web_inspector_get_attached_height ()
-
webkit_web_inspector_get_can_attach, webkit_web_inspector_get_can_attach () +
webkit_web_inspector_get_can_attach, webkit_web_inspector_get_can_attach ()
-
webkit_web_inspector_get_inspected_uri, webkit_web_inspector_get_inspected_uri () +
webkit_web_inspector_get_inspected_uri, webkit_web_inspector_get_inspected_uri ()
-
webkit_web_inspector_get_web_view, webkit_web_inspector_get_web_view () +
webkit_web_inspector_get_web_view, webkit_web_inspector_get_web_view ()
-
webkit_web_inspector_is_attached, webkit_web_inspector_is_attached () +
webkit_web_inspector_is_attached, webkit_web_inspector_is_attached ()
-
webkit_web_inspector_show, webkit_web_inspector_show () +
webkit_web_inspector_show, webkit_web_inspector_show ()
-
webkit_web_page_get_dom_document, webkit_web_page_get_dom_document () +
webkit_web_page_get_dom_document, webkit_web_page_get_dom_document ()
-
webkit_web_page_get_editor, webkit_web_page_get_editor () +
webkit_web_page_get_editor, webkit_web_page_get_editor ()
-
webkit_web_page_get_id, webkit_web_page_get_id () +
webkit_web_page_get_id, webkit_web_page_get_id ()
-
webkit_web_page_get_main_frame, webkit_web_page_get_main_frame () +
webkit_web_page_get_main_frame, webkit_web_page_get_main_frame ()
-
webkit_web_page_get_uri, webkit_web_page_get_uri () +
webkit_web_page_get_uri, webkit_web_page_get_uri ()
-
webkit_web_resource_get_data, webkit_web_resource_get_data () +
webkit_web_resource_get_data, webkit_web_resource_get_data ()
-
webkit_web_resource_get_data_finish, webkit_web_resource_get_data_finish () +
webkit_web_resource_get_data_finish, webkit_web_resource_get_data_finish ()
-
webkit_web_resource_get_response, webkit_web_resource_get_response () +
webkit_web_resource_get_response, webkit_web_resource_get_response ()
-
webkit_web_resource_get_uri, webkit_web_resource_get_uri () +
webkit_web_resource_get_uri, webkit_web_resource_get_uri ()
webkit_web_view_can_execute_editing_command, webkit_web_view_can_execute_editing_command ()
@@ -1492,7 +1498,7 @@
webkit_web_view_execute_editing_command_with_argument, webkit_web_view_execute_editing_command_with_argument ()
-
webkit_web_view_get_background_color, webkit_web_view_get_background_color () +
webkit_web_view_get_background_color, webkit_web_view_get_background_color ()
webkit_web_view_get_back_forward_list, webkit_web_view_get_back_forward_list ()
@@ -1500,7 +1506,7 @@
webkit_web_view_get_custom_charset, webkit_web_view_get_custom_charset ()
-
webkit_web_view_get_editor_state, webkit_web_view_get_editor_state () +
webkit_web_view_get_editor_state, webkit_web_view_get_editor_state ()
webkit_web_view_get_estimated_load_progress, webkit_web_view_get_estimated_load_progress ()
@@ -1512,11 +1518,11 @@
webkit_web_view_get_javascript_global_context, webkit_web_view_get_javascript_global_context ()
-
webkit_web_view_get_main_resource, webkit_web_view_get_main_resource () +
webkit_web_view_get_main_resource, webkit_web_view_get_main_resource ()
webkit_web_view_get_page_id, webkit_web_view_get_page_id ()
-
webkit_web_view_get_session_state, webkit_web_view_get_session_state () +
webkit_web_view_get_session_state, webkit_web_view_get_session_state ()
webkit_web_view_get_settings, webkit_web_view_get_settings ()
@@ -1542,7 +1548,7 @@
webkit_web_view_go_to_back_forward_list_item, webkit_web_view_go_to_back_forward_list_item ()
-
webkit_web_view_is_editable, webkit_web_view_is_editable () +
webkit_web_view_is_editable, webkit_web_view_is_editable ()
webkit_web_view_is_loading, webkit_web_view_is_loading ()
@@ -1574,7 +1580,7 @@
webkit_web_view_reload_bypass_cache, webkit_web_view_reload_bypass_cache ()
-
webkit_web_view_restore_session_state, webkit_web_view_restore_session_state () +
webkit_web_view_restore_session_state, webkit_web_view_restore_session_state ()
webkit_web_view_run_javascript, webkit_web_view_run_javascript ()
@@ -1592,19 +1598,19 @@
webkit_web_view_save_to_file_finish, webkit_web_view_save_to_file_finish ()
-
webkit_web_view_session_state_new, webkit_web_view_session_state_new () +
webkit_web_view_session_state_new, webkit_web_view_session_state_new ()
-
webkit_web_view_session_state_ref, webkit_web_view_session_state_ref () +
webkit_web_view_session_state_ref, webkit_web_view_session_state_ref ()
-
webkit_web_view_session_state_serialize, webkit_web_view_session_state_serialize () +
webkit_web_view_session_state_serialize, webkit_web_view_session_state_serialize ()
-
webkit_web_view_session_state_unref, webkit_web_view_session_state_unref () +
webkit_web_view_session_state_unref, webkit_web_view_session_state_unref ()
webkit_web_view_set_background_color, webkit_web_view_set_background_color ()
webkit_web_view_set_custom_charset, webkit_web_view_set_custom_charset ()
-
webkit_web_view_set_editable, webkit_web_view_set_editable () +
webkit_web_view_set_editable, webkit_web_view_set_editable ()
webkit_web_view_set_settings, webkit_web_view_set_settings ()
@@ -1614,39 +1620,39 @@
webkit_web_view_try_close, webkit_web_view_try_close ()
-
WebKitWindowProperties, struct WebKitWindowProperties +
WebKitWindowProperties, struct WebKitWindowProperties
-
WebKitWindowProperties:fullscreen, The “fullscreen” property +
WebKitWindowProperties:fullscreen, The “fullscreen” property
-
WebKitWindowProperties:geometry, The “geometry” property +
WebKitWindowProperties:geometry, The “geometry” property
-
WebKitWindowProperties:locationbar-visible, The “locationbar-visible” property +
WebKitWindowProperties:locationbar-visible, The “locationbar-visible” property
-
WebKitWindowProperties:menubar-visible, The “menubar-visible” property +
WebKitWindowProperties:menubar-visible, The “menubar-visible” property
-
WebKitWindowProperties:resizable, The “resizable” property +
WebKitWindowProperties:resizable, The “resizable” property
-
WebKitWindowProperties:scrollbars-visible, The “scrollbars-visible” property +
WebKitWindowProperties:scrollbars-visible, The “scrollbars-visible” property
-
WebKitWindowProperties:statusbar-visible, The “statusbar-visible” property +
WebKitWindowProperties:statusbar-visible, The “statusbar-visible” property
-
WebKitWindowProperties:toolbar-visible, The “toolbar-visible” property +
WebKitWindowProperties:toolbar-visible, The “toolbar-visible” property
-
webkit_window_properties_get_fullscreen, webkit_window_properties_get_fullscreen () +
webkit_window_properties_get_fullscreen, webkit_window_properties_get_fullscreen ()
-
webkit_window_properties_get_geometry, webkit_window_properties_get_geometry () +
webkit_window_properties_get_geometry, webkit_window_properties_get_geometry ()
-
webkit_window_properties_get_locationbar_visible, webkit_window_properties_get_locationbar_visible () +
webkit_window_properties_get_locationbar_visible, webkit_window_properties_get_locationbar_visible ()
-
webkit_window_properties_get_menubar_visible, webkit_window_properties_get_menubar_visible () +
webkit_window_properties_get_menubar_visible, webkit_window_properties_get_menubar_visible ()
-
webkit_window_properties_get_resizable, webkit_window_properties_get_resizable () +
webkit_window_properties_get_resizable, webkit_window_properties_get_resizable ()
-
webkit_window_properties_get_scrollbars_visible, webkit_window_properties_get_scrollbars_visible () +
webkit_window_properties_get_scrollbars_visible, webkit_window_properties_get_scrollbars_visible ()
-
webkit_window_properties_get_statusbar_visible, webkit_window_properties_get_statusbar_visible () +
webkit_window_properties_get_statusbar_visible, webkit_window_properties_get_statusbar_visible ()
-
webkit_window_properties_get_toolbar_visible, webkit_window_properties_get_toolbar_visible () +
webkit_window_properties_get_toolbar_visible, webkit_window_properties_get_toolbar_visible ()
diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/index.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/index.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/index.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/index.html 2016-11-03 07:32:11.000000000 +0000 @@ -14,7 +14,7 @@
-

for WebKit2GTK+ 2.12.3

+

for WebKit2GTK+ 2.14.2


diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0.devhelp2 webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0.devhelp2 --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0.devhelp2 2016-05-24 08:27:55.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0.devhelp2 2016-11-03 07:31:59.000000000 +0000 @@ -377,9 +377,12 @@ + + + diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0-WebKitVersion.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0-WebKitVersion.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0-WebKitVersion.html 2016-05-24 08:27:57.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/webkit2gtk-4.0-WebKitVersion.html 2016-11-03 07:32:01.000000000 +0000 @@ -168,7 +168,7 @@

WEBKIT_MINOR_VERSION

-
#define WEBKIT_MINOR_VERSION (12)
+
#define WEBKIT_MINOR_VERSION (14)
 

Like webkit_get_minor_version(), but from the headers used at application compile time, rather than from the library linked @@ -177,7 +177,7 @@


WEBKIT_MICRO_VERSION

-
#define WEBKIT_MICRO_VERSION (3)
+
#define WEBKIT_MICRO_VERSION (2)
 

Like webkit_get_micro_version(), but from the headers used at application compile time, rather than from the library linked diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitAuthenticationRequest.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitAuthenticationRequest.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitAuthenticationRequest.html 2016-05-24 08:27:55.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitAuthenticationRequest.html 2016-11-03 07:31:59.000000000 +0000 @@ -187,7 +187,7 @@ void cancelled -Run Last +Run Last

@@ -900,7 +900,7 @@ -

Flags: Run Last

+

Flags: Run Last

Since: 2.2

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitBackForwardList.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitBackForwardList.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitBackForwardList.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitBackForwardList.html 2016-11-03 07:32:11.000000000 +0000 @@ -127,7 +127,7 @@ void changed -Run Last +Run Last @@ -504,7 +504,7 @@ -

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitColorChooserRequest.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitColorChooserRequest.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitColorChooserRequest.html 2016-05-24 08:27:55.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitColorChooserRequest.html 2016-11-03 07:31:59.000000000 +0000 @@ -95,7 +95,7 @@ -GdkRGBA * +GdkRGBA * rgba Read / Write / Construct @@ -112,7 +112,7 @@ void finished -Run Last +Run Last
@@ -139,7 +139,7 @@

Description

Whenever the user interacts with an <input type='color' /> HTML element, WebKit will need to show a dialog to choose a color. For that -to happen in a general way, instead of just opening a GtkColorChooser +to happen in a general way, instead of just opening a GtkColorChooser (which might be not desirable in some cases, which could prefer to use their own color chooser dialog), WebKit will fire the “run-color-chooser” signal with a WebKitColorChooserRequest @@ -148,7 +148,7 @@ and to cancel the request, in case nothing was selected.

In case the client application does not wish to handle this signal, WebKit will provide a default handler which will asynchronously run -a regular GtkColorChooserDialog for the user to interact with.

+a regular GtkColorChooserDialog for the user to interact with.

Functions

@@ -156,8 +156,8 @@

webkit_color_chooser_request_get_rgba ()

void
 webkit_color_chooser_request_get_rgba (WebKitColorChooserRequest *request,
-                                       GdkRGBA *rgba);
-

Gets the current GdkRGBA color of request + GdkRGBA *rgba); +

Gets the current GdkRGBA color of request

Parameters

@@ -175,7 +175,7 @@

rgba

-

a GdkRGBA to fill in with the current color.

+

a GdkRGBA to fill in with the current color.

[out] @@ -188,8 +188,8 @@

webkit_color_chooser_request_set_rgba ()

void
 webkit_color_chooser_request_set_rgba (WebKitColorChooserRequest *request,
-                                       const GdkRGBA *rgba);
-

Sets the current GdkRGBA color of request + const GdkRGBA *rgba); +

Sets the current GdkRGBA color of request

Parameters

@@ -207,7 +207,7 @@

rgba

-

a pointer GdkRGBA

+

a pointer GdkRGBA

  @@ -221,7 +221,7 @@
void
 webkit_color_chooser_request_get_element_rectangle
                                (WebKitColorChooserRequest *request,
-                                GdkRectangle *rect);
+ GdkRectangle *rect);

Gets the bounding box of the color input element.

Parameters

@@ -239,7 +239,7 @@

rect

-

a GdkRectangle to fill in with the element area.

+

a GdkRectangle to fill in with the element area.

[out] @@ -313,7 +313,7 @@

Property Details

The “rgba” property

-
  “rgba”                     GdkRGBA *
+
  “rgba”                     GdkRGBA *

The current RGBA color for the request.

Flags: Read / Write / Construct

@@ -353,7 +353,7 @@
-

Flags: Run Last

+

Flags: Run Last

Since: 2.8

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitContextMenuItem.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitContextMenuItem.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitContextMenuItem.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitContextMenuItem.html 2016-11-03 07:32:11.000000000 +0000 @@ -82,7 +82,7 @@ -GtkAction * +GtkAction * webkit_context_menu_item_get_action () @@ -151,7 +151,7 @@

Description

-

The WebKitContextMenu is composed of WebKitContextMenuItems. These items can be created from a GtkAction, from a +

The WebKitContextMenu is composed of WebKitContextMenuItems. These items can be created from a GtkAction, from a WebKitContextMenuAction or from a WebKitContextMenuAction and a label. These WebKitContextMenuActions denote stock actions for the items. You can also create separators and submenus.

@@ -161,7 +161,7 @@

webkit_context_menu_item_new ()

WebKitContextMenuItem *
-webkit_context_menu_item_new (GtkAction *action);
+webkit_context_menu_item_new (GtkAction *action);

Creates a new WebKitContextMenuItem for the given action .

@@ -174,7 +174,7 @@

action

-

a GtkAction

+

a GtkAction

 
@@ -194,9 +194,9 @@ Stock actions are handled automatically by WebKit so that, for example, when a menu item created with a WEBKIT_CONTEXT_MENU_ACTION_STOP is activated the action associated will be handled by WebKit and the current -load operation will be stopped. You can get the GtkAction of a +load operation will be stopped. You can get the GtkAction of a WebKitContextMenuItem created with a WebKitContextMenuAction with -webkit_context_menu_item_get_action() and connect to “activate” signal +webkit_context_menu_item_get_action() and connect to “activate” signal to be notified when the item is activated. But you can't prevent the asociated action from being performed.

@@ -308,7 +308,7 @@

webkit_context_menu_item_get_action ()

-
GtkAction *
+
GtkAction *
 webkit_context_menu_item_get_action (WebKitContextMenuItem *item);

Gets the action associated to item .

@@ -329,7 +329,7 @@

Returns

-

the GtkAction associated to the WebKitContextMenuItem, +

the GtkAction associated to the WebKitContextMenuItem, or NULL if item is a separator.

[transfer none]

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitCookieManager.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitCookieManager.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitCookieManager.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitCookieManager.html 2016-11-03 07:32:11.000000000 +0000 @@ -119,7 +119,7 @@ void changed -Run Last +Run Last
@@ -592,7 +592,7 @@
-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitDownload.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitDownload.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitDownload.html 2016-05-24 08:27:56.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitDownload.html 2016-11-03 07:32:00.000000000 +0000 @@ -178,27 +178,27 @@ void created-destination -Run Last +Run Last gboolean decide-destination -Run Last +Run Last void failed -Run Last +Run Last void finished -Run Last +Run Last void received-data -Run Last +Run Last @@ -306,7 +306,7 @@ If “decide-destination” signal is not handled and destination URI is not set when the download tranfer starts, the file will be saved with the filename suggested by the server in -G_USER_DIRECTORY_DOWNLOAD directory.

+G_USER_DIRECTORY_DOWNLOAD directory.

Parameters

@@ -655,7 +655,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -666,7 +666,7 @@ gpointer user_data)

This signal is emitted after response is received to decide a destination URI for the download. If this signal is not -handled the file will be downloaded to G_USER_DIRECTORY_DOWNLOAD +handled the file will be downloaded to G_USER_DIRECTORY_DOWNLOAD directory using suggested_filename .

@@ -701,7 +701,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

-

Flags: Run Last

+

Flags: Run Last


@@ -744,7 +744,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -776,7 +776,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -815,7 +815,7 @@
-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitFaviconDatabase.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitFaviconDatabase.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitFaviconDatabase.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitFaviconDatabase.html 2016-11-03 07:32:11.000000000 +0000 @@ -87,7 +87,7 @@ void favicon-changed -Run Last +Run Last @@ -149,6 +149,11 @@

This is an asynchronous method. When the operation is finished, callback will be invoked. You can then call webkit_favicon_database_get_favicon_finish() to get the result of the operation.

+

You must call webkit_web_context_set_favicon_database_directory() for +the WebKitWebContext associated with this WebKitFaviconDatabase +before attempting to use this function; otherwise, +webkit_favicon_database_get_favicon_finish() will return +WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED.

Parameters

@@ -393,7 +398,7 @@
-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitFileChooserRequest.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitFileChooserRequest.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitFileChooserRequest.html 2016-05-24 08:27:56.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitFileChooserRequest.html 2016-11-03 07:32:00.000000000 +0000 @@ -50,7 +50,7 @@ -GtkFileFilter * +GtkFileFilter * webkit_file_chooser_request_get_mime_types_filter () @@ -101,12 +101,12 @@ -GtkFileFilter * +GtkFileFilter * filter Read -GStrv +GStrv mime-types Read @@ -116,7 +116,7 @@ Read -GStrv +GStrv selected-files Read @@ -148,7 +148,7 @@ HTML element, WebKit will need to show a dialog to choose one or more files to be uploaded to the server along with the rest of the form data. For that to happen in a general way, instead of just -opening a GtkFileChooserDialog (which might be not desirable in +opening a GtkFileChooserDialog (which might be not desirable in some cases, which could prefer to use their own file chooser dialog), WebKit will fire the “run-file-chooser” signal with a WebKitFileChooserRequest object, which will allow @@ -158,7 +158,7 @@ selected.

In case the client application does not wish to handle this signal, WebKit will provide a default handler which will asynchronously run -a regular GtkFileChooserDialog for the user to interact with.

+a regular GtkFileChooserDialog for the user to interact with.

Functions

@@ -201,11 +201,11 @@

webkit_file_chooser_request_get_mime_types_filter ()

-
GtkFileFilter *
+
GtkFileFilter *
 webkit_file_chooser_request_get_mime_types_filter
                                (WebKitFileChooserRequest *request);

Get the filter currently associated with the request, ready to be -used by GtkFileChooser. This function should normally be called +used by GtkFileChooser. This function should normally be called before presenting the file chooser dialog to the user, to decide whether to apply a filter so the user would not be allowed to select files with other MIME types.

@@ -228,7 +228,7 @@

Returns

-

a GtkFileFilter if a list of accepted +

a GtkFileFilter if a list of accepted MIME types is defined or NULL otherwise. The returned object is owned by WebKitGTK+ should not be modified or freed.

[transfer none]

@@ -373,7 +373,7 @@

Property Details

The “filter” property

-
  “filter”                   GtkFileFilter *
+
  “filter”                   GtkFileFilter *

The filter currently associated with the request. See webkit_file_chooser_request_get_mime_types_filter() for more details.

@@ -382,7 +382,7 @@

The “mime-types” property

-
  “mime-types”               GStrv
+
  “mime-types”               GStrv

A NULL-terminated array of strings containing the list of MIME types the file chooser dialog should handle. See webkit_file_chooser_request_get_mime_types() for more details.

@@ -402,7 +402,7 @@

The “selected-files” property

-
  “selected-files”           GStrv
+
  “selected-files”           GStrv

A NULL-terminated array of strings containing the list of selected files associated to the current request. See webkit_file_chooser_request_get_selected_files() for more details.

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitFindController.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitFindController.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitFindController.html 2016-05-24 08:28:03.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitFindController.html 2016-11-03 07:32:06.000000000 +0000 @@ -162,17 +162,17 @@ void counted-matches -Run Last +Run Last void failed-to-find-text -Run Last +Run Last void found-text -Run Last +Run Last
@@ -657,7 +657,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -692,7 +692,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -733,7 +733,7 @@
-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitNavigationAction.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitNavigationAction.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitNavigationAction.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitNavigationAction.html 2016-11-03 07:32:11.000000000 +0000 @@ -237,7 +237,7 @@
guint
 webkit_navigation_action_get_modifiers
                                (WebKitNavigationAction *navigation);
-

Return a bitmask of GdkModifierType values describing the modifier keys that were in effect +

Return a bitmask of GdkModifierType values describing the modifier keys that were in effect when the navigation was requested

Parameters

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitNavigationPolicyDecision.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitNavigationPolicyDecision.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitNavigationPolicyDecision.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitNavigationPolicyDecision.html 2016-11-03 07:32:11.000000000 +0000 @@ -435,7 +435,7 @@
  “modifiers”                guint

If the navigation associated with this policy decision was originally triggered by a mouse event, this property contains a bitmask of various -GdkModifierType values describing the modifiers used for that click. +GdkModifierType values describing the modifiers used for that click. If the navigation was not triggered by a mouse event or no modifiers were active, the value of this property will be zero.

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitNotification.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitNotification.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitNotification.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitNotification.html 2016-11-03 07:32:11.000000000 +0000 @@ -124,12 +124,12 @@ void clicked -Run Last +Run Last void closed -Run Last +Run Last
@@ -352,7 +352,7 @@
-

Flags: Run Last

+

Flags: Run Last

Since: 2.12


@@ -386,7 +386,7 @@ -

Flags: Run Last

+

Flags: Run Last

Since: 2.8

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitPrintOperation.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitPrintOperation.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitPrintOperation.html 2016-05-24 08:27:57.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitPrintOperation.html 2016-11-03 07:32:01.000000000 +0000 @@ -52,7 +52,7 @@ -GtkPrintSettings * +GtkPrintSettings * webkit_print_operation_get_print_settings () @@ -68,7 +68,7 @@ -GtkPageSetup * +GtkPageSetup * webkit_print_operation_get_page_setup () @@ -112,13 +112,13 @@ -GtkPageSetup * +GtkPageSetup * page-setup Read / Write -GtkPrintSettings * +GtkPrintSettings * print-settings Read / Write @@ -143,12 +143,12 @@ void failed -Run Last +Run Last void finished -Run Last +Run Last @@ -181,7 +181,7 @@

Description

A WebKitPrintOperation controls a print operation in WebKit. With -a similar API to GtkPrintOperation, it lets you set the print +a similar API to GtkPrintOperation, it lets you set the print settings with webkit_print_operation_set_print_settings() or display the print dialog with webkit_print_operation_run_dialog().

@@ -217,7 +217,7 @@

webkit_print_operation_get_print_settings ()

-
GtkPrintSettings *
+
GtkPrintSettings *
 webkit_print_operation_get_print_settings
                                (WebKitPrintOperation *print_operation);

Return the current print settings of print_operation @@ -241,7 +241,7 @@

Returns

-

the current GtkPrintSettings of print_operation +

the current GtkPrintSettings of print_operation .

[transfer none]

@@ -252,7 +252,7 @@
void
 webkit_print_operation_set_print_settings
                                (WebKitPrintOperation *print_operation,
-                                GtkPrintSettings *print_settings);
+ GtkPrintSettings *print_settings);

Set the current print settings of print_operation . Current print settings are used for the initial values of the print dialog when webkit_print_operation_run_dialog() is called.

@@ -272,7 +272,7 @@

print_settings

-

a GtkPrintSettings to set

+

a GtkPrintSettings to set

  @@ -282,7 +282,7 @@

webkit_print_operation_get_page_setup ()

-
GtkPageSetup *
+
GtkPageSetup *
 webkit_print_operation_get_page_setup (WebKitPrintOperation *print_operation);

Return the current page setup of print_operation . It returns NULL until @@ -305,7 +305,7 @@

Returns

-

the current GtkPageSetup of print_operation +

the current GtkPageSetup of print_operation .

[transfer none]

@@ -315,7 +315,7 @@

webkit_print_operation_set_page_setup ()

void
 webkit_print_operation_set_page_setup (WebKitPrintOperation *print_operation,
-                                       GtkPageSetup *page_setup);
+ GtkPageSetup *page_setup);

Set the current page setup of print_operation . Current page setup is used for the initial values of the print dialog when webkit_print_operation_run_dialog() is called.

@@ -335,7 +335,7 @@

page_setup

-

a GtkPageSetup to set

+

a GtkPageSetup to set

  @@ -347,7 +347,7 @@

webkit_print_operation_run_dialog ()

WebKitPrintOperationResponse
 webkit_print_operation_run_dialog (WebKitPrintOperation *print_operation,
-                                   GtkWindow *parent);
+ GtkWindow *parent);

Run the print dialog and start printing using the options selected by the user. This method returns when the print dialog is closed. If the print dialog is cancelled WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL @@ -461,15 +461,15 @@

Property Details

The “page-setup” property

-
  “page-setup”               GtkPageSetup *
-

The initial GtkPageSetup for the print operation.

+
  “page-setup”               GtkPageSetup *
+

The initial GtkPageSetup for the print operation.

Flags: Read / Write


The “print-settings” property

-
  “print-settings”           GtkPrintSettings *
-

The initial GtkPrintSettings for the print operation.

+
  “print-settings”           GtkPrintSettings *
+

The initial GtkPrintSettings for the print operation.

Flags: Read / Write


@@ -519,7 +519,7 @@ -

Flags: Run Last

+

Flags: Run Last


@@ -551,7 +551,7 @@
-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitScriptWorld.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitScriptWorld.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitScriptWorld.html 2016-05-24 08:27:57.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitScriptWorld.html 2016-11-03 07:32:01.000000000 +0000 @@ -71,7 +71,7 @@ void window-object-cleared -Run Last +Run Last @@ -188,7 +188,7 @@ -

Flags: Run Last

+

Flags: Run Last

Since: 2.2

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitSettings.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitSettings.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitSettings.html 2016-05-24 08:27:56.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitSettings.html 2016-11-03 07:32:00.000000000 +0000 @@ -840,6 +840,22 @@ webkit_settings_set_allow_file_access_from_file_urls () + + +gboolean + + +webkit_settings_get_allow_universal_access_from_file_urls () + + + + +void + + +webkit_settings_set_allow_universal_access_from_file_urls () + + @@ -864,6 +880,11 @@ gboolean +allow-universal-access-from-file-urls +Read / Write / Construct + + +gboolean auto-load-images Read / Write / Construct @@ -4024,6 +4045,66 @@

Since: 2.10

+
+
+

webkit_settings_get_allow_universal_access_from_file_urls ()

+
gboolean
+webkit_settings_get_allow_universal_access_from_file_urls
+                               (WebKitSettings *settings);
+

Get the “allow-universal-access-from-file-urls” property.

+
+

Parameters

+
+++++ + + + + + +

settings

a WebKitSettings

 
+
+
+

Returns

+

TRUE If universal access from file URLs is allowed or FALSE otherwise.

+
+

Since: 2.14

+
+
+
+

webkit_settings_set_allow_universal_access_from_file_urls ()

+
void
+webkit_settings_set_allow_universal_access_from_file_urls
+                               (WebKitSettings *settings,
+                                gboolean allowed);
+

Set the “allow-universal-access-from-file-urls” property.

+
+

Parameters

+
+++++ + + + + + + + + + + + + +

settings

a WebKitSettings

 

allowed

Value to be set

 
+
+

Since: 2.14

+

Types and Values

@@ -4061,6 +4142,20 @@

+

The “allow-universal-access-from-file-urls” property

+
  “allow-universal-access-from-file-urls” gboolean
+

Whether or not JavaScript running in the context of a file scheme URL +should be allowed to access content from any origin. By default, when +something is loaded in a WebKitWebView using a file scheme URL, +access to the local file system and arbitrary local storage is not +allowed. This setting allows you to change that behaviour, so that +it would be possible to use local storage, for example.

+

Flags: Read / Write / Construct

+

Default value: FALSE

+

Since: 2.14

+
+
+

The “auto-load-images” property

  “auto-load-images”         gboolean

Determines whether images should be automatically loaded or not. diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitURIResponse.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitURIResponse.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitURIResponse.html 2016-05-24 08:27:57.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitURIResponse.html 2016-11-03 07:32:01.000000000 +0000 @@ -193,7 +193,7 @@ webkit_uri_response_get_status_code (WebKitURIResponse *response);

Get the status code of the WebKitURIResponse as returned by the server. It will normally be a SoupKnownStatusCode, for -example SOUP_STATUS_OK, though the server can respond with any +example SOUP_STATUS_OK, though the server can respond with any unsigned integer.

Parameters

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitUserContentManager.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitUserContentManager.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitUserContentManager.html 2016-05-24 08:28:06.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitUserContentManager.html 2016-11-03 07:32:10.000000000 +0000 @@ -111,7 +111,7 @@ void script-message-received -Has Details +Has Details
@@ -423,7 +423,7 @@ -

Flags: Has Details

+

Flags: Has Details

Since: 2.8

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebContext.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebContext.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebContext.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebContext.html 2016-11-03 07:32:11.000000000 +0000 @@ -351,12 +351,12 @@ void download-started -Run Last +Run Last void initialize-web-extensions -Run Last +Run Last @@ -1829,7 +1829,7 @@ -

Flags: Run Last

+

Flags: Run Last


@@ -1863,7 +1863,7 @@
-

Flags: Run Last

+

Flags: Run Last

Since: 2.4

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebEditor.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebEditor.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebEditor.html 2016-05-24 08:28:07.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebEditor.html 2016-11-03 07:32:11.000000000 +0000 @@ -61,7 +61,7 @@ void selection-changed -Run Last +Run Last @@ -160,7 +160,7 @@ -

Flags: Run Last

+

Flags: Run Last

Since: 2.10

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebExtension.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebExtension.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebExtension.html 2016-05-24 08:28:05.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebExtension.html 2016-11-03 07:32:09.000000000 +0000 @@ -79,7 +79,7 @@ void page-created -Run Last +Run Last @@ -368,7 +368,7 @@ -

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebInspector.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebInspector.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebInspector.html 2016-05-24 08:27:57.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebInspector.html 2016-11-03 07:32:01.000000000 +0000 @@ -156,27 +156,27 @@ gboolean attach -Run Last +Run Last gboolean bring-to-front -Run Last +Run Last void closed -Run Last +Run Last gboolean detach -Run Last +Run Last gboolean open-window -Run Last +Run Last @@ -204,7 +204,7 @@

Description

The WebKit Inspector is a graphical tool to inspect and change the content of a WebKitWebView. It also includes an interactive -JavaScript debugger. Using this class one can get a GtkWidget +JavaScript debugger. Using this class one can get a GtkWidget which can be embedded into an application to show the inspector.

The inspector is available when the WebKitSettings of the WebKitWebView has set the “enable-developer-extras” @@ -531,7 +531,7 @@ attached to the inspected view, so you only need to handle this signal if you want to attach the inspector view yourself (for example, to add the inspector view to a browser tab).

-

To prevent the inspector vew from being attached you can connect to this +

To prevent the inspector view from being attached you can connect to this signal and simply return TRUE.

Parameters

@@ -560,7 +560,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

-

Flags: Run Last

+

Flags: Run Last


@@ -576,7 +576,7 @@ window, the browser window should be raised and the tab containing the inspector view should be the active one. In both cases, if this signal is not handled, the default implementation -calls gtk_window_present() on the current toplevel GtkWindow of the +calls gtk_window_present() on the current toplevel GtkWindow of the inspector view.

Parameters

@@ -605,7 +605,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

-

Flags: Run Last

+

Flags: Run Last


@@ -638,7 +638,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -681,7 +681,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

-

Flags: Run Last

+

Flags: Run Last


@@ -690,7 +690,7 @@ user_function (WebKitWebInspector *inspector, gpointer user_data)

Emitted when the inspector is requested to open in a separate window. -If this signal is not handled, a GtkWindow with the inspector will be +If this signal is not handled, a GtkWindow with the inspector will be created and shown, so you only need to handle this signal if you want to use your own window. This signal is emitted after “detach” to show @@ -724,7 +724,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebPage.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebPage.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebPage.html 2016-05-24 08:27:57.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebPage.html 2016-11-03 07:32:01.000000000 +0000 @@ -112,22 +112,22 @@ void console-message-sent -Run Last +Run Last gboolean context-menu -Run Last +Run Last void document-loaded -Run Last +Run Last gboolean send-request -Run Last +Run Last @@ -358,7 +358,7 @@ -

Flags: Run Last

+

Flags: Run Last

Since: 2.12


@@ -415,7 +415,7 @@

TRUE if the proposed context_menu has been modified, or FALSE otherwise.

-

Flags: Run Last

+

Flags: Run Last

Since: 2.8


@@ -450,7 +450,7 @@ -

Flags: Run Last

+

Flags: Run Last


@@ -509,7 +509,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to continue emission of the event.

-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebResource.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebResource.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebResource.html 2016-05-24 08:28:03.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebResource.html 2016-11-03 07:32:06.000000000 +0000 @@ -112,27 +112,27 @@ void failed -Run Last +Run Last void failed-with-tls-errors -Run Last +Run Last void finished -Run Last +Run Last void received-data -Run Last +Run Last void sent-request -Run Last +Run Last @@ -409,7 +409,7 @@ -

Flags: Run Last

+

Flags: Run Last


@@ -453,7 +453,7 @@
-

Flags: Run Last

+

Flags: Run Last

Since: 2.8


@@ -487,7 +487,7 @@ -

Flags: Run Last

+

Flags: Run Last


@@ -526,7 +526,7 @@
-

Flags: Run Last

+

Flags: Run Last


@@ -577,7 +577,7 @@
-

Flags: Run Last

+

Flags: Run Last

diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebView.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebView.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWebView.html 2016-05-24 08:28:03.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWebView.html 2016-11-03 07:32:06.000000000 +0000 @@ -45,7 +45,7 @@ -GtkWidget * +GtkWidget * webkit_web_view_new () @@ -53,7 +53,7 @@ -GtkWidget * +GtkWidget * webkit_web_view_new_with_context () @@ -61,7 +61,7 @@ -GtkWidget * +GtkWidget * webkit_web_view_new_with_related_view () @@ -69,7 +69,7 @@ -GtkWidget * +GtkWidget * webkit_web_view_new_with_settings () @@ -77,7 +77,7 @@ -GtkWidget * +GtkWidget * webkit_web_view_new_with_user_content_manager () @@ -755,123 +755,123 @@ gboolean authenticate -Run Last +Run Last void close -Run Last +Run Last gboolean context-menu -Run Last +Run Last void context-menu-dismissed -Run Last +Run Last -GtkWidget* +GtkWidget* create -Run Last +Run Last gboolean decide-policy -Run Last +Run Last gboolean enter-fullscreen -Run Last +Run Last void insecure-content-detected -Run Last +Run Last gboolean leave-fullscreen -Run Last +Run Last void load-changed -Run Last +Run Last gboolean load-failed -Run Last +Run Last gboolean load-failed-with-tls-errors -Run Last +Run Last void mouse-target-changed -Run Last +Run Last gboolean permission-request -Run Last +Run Last gboolean print -Run Last +Run Last void ready-to-show -Run Last +Run Last void resource-load-started -Run Last +Run Last void run-as-modal -Run Last +Run Last gboolean run-color-chooser -Run Last +Run Last gboolean run-file-chooser -Run Last +Run Last gboolean script-dialog -Run Last +Run Last gboolean show-notification -Run Last +Run Last void submit-form -Run Last +Run Last gboolean web-process-crashed -Run Last +Run Last @@ -971,8 +971,8 @@ ╰── WebKitWebViewSessionState GObject ╰── GInitiallyUnowned - ╰── GtkWidget - ╰── GtkContainer + ╰── GtkWidget + ╰── GtkContainer ╰── WebKitWebViewBase ╰── WebKitWebView @@ -981,7 +981,7 @@

Implemented Interfaces

WebKitWebView implements - AtkImplementorIface and GtkBuildable.

+ AtkImplementorIface and GtkBuildable.

Description

@@ -991,13 +991,13 @@ string. With WebKitSettings you can control various aspects of the rendering and loading of the content.

Note that WebKitWebView is scrollable by itself, so you don't need -to embed it in a GtkScrolledWindow.

+to embed it in a GtkScrolledWindow.

Functions

webkit_web_view_new ()

-
GtkWidget *
+
GtkWidget *
 webkit_web_view_new (void);

Creates a new WebKitWebView with the default WebKitWebContext and no WebKitUserContentManager associated with it. @@ -1012,7 +1012,7 @@


webkit_web_view_new_with_context ()

-
GtkWidget *
+
GtkWidget *
 webkit_web_view_new_with_context (WebKitWebContext *context);

Creates a new WebKitWebView with the given WebKitWebContext and no WebKitUserContentManager associated with it. @@ -1041,7 +1041,7 @@


webkit_web_view_new_with_related_view ()

-
GtkWidget *
+
GtkWidget *
 webkit_web_view_new_with_related_view (WebKitWebView *web_view);

Creates a new WebKitWebView sharing the same web process with web_view . @@ -1079,7 +1079,7 @@


webkit_web_view_new_with_settings ()

-
GtkWidget *
+
GtkWidget *
 webkit_web_view_new_with_settings (WebKitSettings *settings);

Creates a new WebKitWebView with the given WebKitSettings. See also webkit_web_view_new_with_context(), and @@ -1108,7 +1108,7 @@


webkit_web_view_new_with_user_content_manager ()

-
GtkWidget *
+
GtkWidget *
 webkit_web_view_new_with_user_content_manager
                                (WebKitUserContentManager *user_content_manager);

Creates a new WebKitWebView with the given WebKitUserContentManager. @@ -3228,7 +3228,7 @@

webkit_web_view_set_background_color ()

void
 webkit_web_view_set_background_color (WebKitWebView *web_view,
-                                      const GdkRGBA *rgba);
+ const GdkRGBA *rgba);

Sets the color that will be used to draw the web_view background before the actual contents are rendered. Note that if the web page loaded in web_view @@ -3237,9 +3237,8 @@ color. By default the web_view background color is opaque white. -If the rgba - color is not fully opaque, the parent window must have a RGBA visual and -“app-paintable” property set to TRUE, for the transparencies to work.

+Note that the parent window must have a RGBA visual and +“app-paintable” property set to TRUE for backgrounds colors to work.

@@ -3259,25 +3258,19 @@ 13 14 15 -16 -17 -18 -19 +16 - + @@ -3316,7 +3309,7 @@

webkit_web_view_get_background_color ()

void
 webkit_web_view_get_background_color (WebKitWebView *web_view,
-                                      GdkRGBA *rgba);
+ GdkRGBA *rgba);

Gets the color that is used to draw the web_view background before the actual contents are rendered. @@ -3337,7 +3330,7 @@

- + @@ -4474,7 +4467,7 @@

TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

-

Flags: Run Last

+

Flags: Run Last

Since: 2.2


@@ -4511,7 +4504,7 @@
static void browser_window_set_background_color (BrowserWindow *window,
                                                  const GdkRGBA *rgba)
 {
     WebKitWebView *web_view;
+    GdkScreen *screen = gtk_window_get_screen (GTK_WINDOW (window));
+    GdkVisual *rgba_visual = gdk_screen_get_rgba_visual (screen);
 
-    if (rgba->alpha < 1) {
-        GdkScreen *screen = gtk_window_get_screen (GTK_WINDOW (window));
-        GdkVisual *rgba_visual = gdk_screen_get_rgba_visual (screen);
+    if (!rgba_visual)
+         return;
 
-        if (!rgba_visual)
-             return;
-
-        gtk_widget_set_visual (GTK_WIDGET (window), rgba_visual);
-        gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
-    }
+    gtk_widget_set_visual (GTK_WIDGET (window), rgba_visual);
+    gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
 
     web_view = browser_window_get_web_view (window);
     webkit_web_view_set_background_color (web_view, rgba);
@@ -3303,7 +3296,7 @@
 

rgba

a GdkRGBA

a GdkRGBA

 

rgba

a GdkRGBA to fill in with the background color.

a GdkRGBA to fill in with the background color.

[out]
-

Flags: Run Last

+

Flags: Run Last


@@ -4519,7 +4512,7 @@
gboolean
 user_function (WebKitWebView       *web_view,
                WebKitContextMenu   *context_menu,
-               GdkEvent            *event,
+               GdkEvent            *event,
                WebKitHitTestResult *hit_test_result,
                gpointer             user_data)

Emmited when a context menu is about to be displayed to give the application @@ -4542,7 +4535,7 @@ To build your own menu, you can remove all items from the proposed menu with webkit_context_menu_remove_all(), add your own items and return FALSE so that the menu will be shown. You can also ignore the proposed WebKitContextMenu, - build your own GtkMenu and return TRUE to prevent the proposed menu from being shown. + build your own GtkMenu and return TRUE to prevent the proposed menu from being shown.

  • If you just want the default menu to be shown always, simply don't connect to this @@ -4576,7 +4569,7 @@

    event

    -

    the GdkEvent that triggered the context menu

    +

    the GdkEvent that triggered the context menu

      @@ -4597,7 +4590,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

  • -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -4629,12 +4622,12 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    The “create” signal

    -
    GtkWidget*
    +
    GtkWidget*
     user_function (WebKitWebView          *web_view,
                    WebKitNavigationAction *navigation_action,
                    gpointer                user_data)
    @@ -4683,7 +4676,7 @@ or NULL to propagate the event further.

    [transfer full]

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -4801,7 +4794,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -4844,7 +4837,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to continue emission of the event.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -4888,7 +4881,7 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -4927,7 +4920,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to continue emission of the event.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5039,7 +5032,7 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5103,7 +5096,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5167,7 +5160,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last

    Since: 2.6


    @@ -5185,7 +5178,7 @@ hit_test_result argument. The modifiers argument is a bitmask of -GdkModifierType flags indicating the state of modifier keys. +GdkModifierType flags indicating the state of modifier keys. The signal is emitted again when the mouse is moved out of the current element with a new hit_test_result .

    @@ -5210,7 +5203,7 @@

    modifiers

    -

    a bitmask of GdkModifierType

    +

    a bitmask of GdkModifierType

      @@ -5221,7 +5214,7 @@ -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5337,7 +5330,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5388,7 +5381,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5425,7 +5418,7 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5473,7 +5466,7 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5510,7 +5503,7 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5530,7 +5523,7 @@

    It is possible to handle this request asynchronously by increasing the reference count of the request.

    The default signal handler will asynchronously run a regular -GtkColorChooser for the user to interact with.

    +GtkColorChooser for the user to interact with.

    Parameters

    @@ -5563,7 +5556,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last

    Since: 2.8


    @@ -5583,7 +5576,7 @@ argument.

    The default signal handler will asynchronously run a regular -GtkFileChooserDialog for the user to interact with.

    +GtkFileChooserDialog for the user to interact with.

    Parameters

    @@ -5616,7 +5609,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5679,7 +5672,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5725,7 +5718,7 @@

    Returns

    TRUE to stop other handlers from being invoked. FALSE otherwise.

    -

    Flags: Run Last

    +

    Flags: Run Last

    Since: 2.8


    @@ -5774,7 +5767,7 @@
    -

    Flags: Run Last

    +

    Flags: Run Last


    @@ -5810,7 +5803,7 @@

    TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.

    -

    Flags: Run Last

    +

    Flags: Run Last

    diff -Nru webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWindowProperties.html webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWindowProperties.html --- webkit2gtk-2.12.3/Documentation/webkit2gtk-4.0/html/WebKitWindowProperties.html 2016-05-24 08:28:08.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkit2gtk-4.0/html/WebKitWindowProperties.html 2016-11-03 07:32:12.000000000 +0000 @@ -124,7 +124,7 @@ -GdkRectangle * +GdkRectangle * geometry Read / Write / Construct Only @@ -290,7 +290,7 @@

    webkit_window_properties_get_geometry ()

    void
     webkit_window_properties_get_geometry (WebKitWindowProperties *window_properties,
    -                                       GdkRectangle *geometry);
    + GdkRectangle *geometry);

    Get the geometry the window should have on the screen when shown.

    Parameters

    @@ -524,7 +524,7 @@

    The “geometry” property

    -
      “geometry”                 GdkRectangle *
    +
      “geometry”                 GdkRectangle *

    The size and position of the window on the screen.

    Flags: Read / Write / Construct Only

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/api-index-deprecated.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/api-index-deprecated.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/api-index-deprecated.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/api-index-deprecated.html 2016-11-03 07:31:44.000000000 +0000 @@ -36,6 +36,10 @@
    +webkit_dom_document_get_default_charset, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_get_elements_by_class_name, function in WebKitDOMDocument
    @@ -86,6 +90,30 @@
    +webkit_dom_html_document_get_compat_mode, function in WebKitDOMHTMLDocument +
    +
    +
    +webkit_dom_html_document_get_design_mode, function in WebKitDOMHTMLDocument +
    +
    +
    +webkit_dom_html_document_get_embeds, function in WebKitDOMHTMLDocument +
    +
    +
    +webkit_dom_html_document_get_plugins, function in WebKitDOMHTMLDocument +
    +
    +
    +webkit_dom_html_document_get_scripts, function in WebKitDOMHTMLDocument +
    +
    +
    +webkit_dom_html_document_set_design_mode, function in WebKitDOMHTMLDocument +
    +
    +
    webkit_dom_html_element_get_children, function in WebKitDOMHTMLElement
    @@ -105,13 +133,41 @@ webkit_dom_html_element_set_outer_html, function in WebKitDOMHTMLElement
    +
    +webkit_dom_html_input_element_get_capture, function in WebKitDOMHTMLInputElement +
    +

    N

    +webkit_dom_node_clone_node, function in WebKitDOMNode +
    +
    +
    +webkit_dom_node_get_local_name, function in WebKitDOMNode +
    +
    +
    +webkit_dom_node_get_namespace_uri, function in WebKitDOMNode +
    +
    +
    +webkit_dom_node_get_prefix, function in WebKitDOMNode +
    +
    +
    webkit_dom_node_iterator_get_expand_entity_references, function in WebKitDOMNodeIterator
    +
    +webkit_dom_node_set_prefix, function in WebKitDOMNode +
    +

    T

    +webkit_dom_text_replace_whole_text, function in WebKitDOMText +
    +
    +
    webkit_dom_tree_walker_get_expand_entity_references, function in WebKitDOMTreeWalker
    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/index-all.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/index-all.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/index-all.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/index-all.html 2016-11-03 07:31:44.000000000 +0000 @@ -56,14 +56,26 @@ Index

    A

    +webkit_dom_attr_get_local_name, function in WebKitDOMAttr +
    +
    +
    webkit_dom_attr_get_name, function in WebKitDOMAttr
    +webkit_dom_attr_get_namespace_uri, function in WebKitDOMAttr +
    +
    +
    webkit_dom_attr_get_owner_element, function in WebKitDOMAttr
    +webkit_dom_attr_get_prefix, function in WebKitDOMAttr +
    +
    +
    webkit_dom_attr_get_specified, function in WebKitDOMAttr
    @@ -379,6 +391,10 @@
    +webkit_dom_document_get_compat_mode, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_get_cookie, function in WebKitDOMDocument
    @@ -391,6 +407,10 @@
    +webkit_dom_document_get_design_mode, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_get_doctype, function in WebKitDOMDocument
    @@ -439,6 +459,10 @@
    +webkit_dom_document_get_embeds, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_get_forms, function in WebKitDOMDocument
    @@ -471,6 +495,10 @@
    +webkit_dom_document_get_plugins, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_get_preferred_stylesheet_set, function in WebKitDOMDocument
    @@ -483,6 +511,10 @@
    +webkit_dom_document_get_scripts, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_get_selected_stylesheet_set, function in WebKitDOMDocument
    @@ -559,6 +591,10 @@
    +webkit_dom_document_set_design_mode, function in WebKitDOMDocument +
    +
    +
    webkit_dom_document_set_document_uri, function in WebKitDOMDocument
    @@ -724,6 +760,14 @@
    +webkit_dom_element_get_local_name, function in WebKitDOMElement +
    +
    +
    +webkit_dom_element_get_namespace_uri, function in WebKitDOMElement +
    +
    +
    webkit_dom_element_get_next_element_sibling, function in WebKitDOMElement
    @@ -752,6 +796,10 @@
    +webkit_dom_element_get_prefix, function in WebKitDOMElement +
    +
    +
    webkit_dom_element_get_previous_element_sibling, function in WebKitDOMElement
    @@ -2262,6 +2310,10 @@
    +webkit_dom_html_input_element_get_capture_type, function in WebKitDOMHTMLInputElement +
    +
    +
    webkit_dom_html_input_element_get_checked, function in WebKitDOMHTMLInputElement
    @@ -3825,6 +3877,10 @@
    +webkit_dom_node_clone_node_with_error, function in WebKitDOMNode +
    +
    +
    WEBKIT_DOM_NODE_COMMENT_NODE, macro in WebKitDOMNode
    @@ -4439,14 +4495,26 @@
    +WebKitDOMAttr:local-name, object property in WebKitDOMAttr +
    +
    +
    WebKitDOMAttr:name, object property in WebKitDOMAttr
    +WebKitDOMAttr:namespace-uri, object property in WebKitDOMAttr +
    +
    +
    WebKitDOMAttr:owner-element, object property in WebKitDOMAttr
    +WebKitDOMAttr:prefix, object property in WebKitDOMAttr +
    +
    +
    WebKitDOMAttr:specified, object property in WebKitDOMAttr
    @@ -4619,11 +4687,15 @@
    -WebKitDOMDocument:default-charset, object property in WebKitDOMDocument +WebKitDOMDocument:default-view, object property in WebKitDOMDocument
    -WebKitDOMDocument:default-view, object property in WebKitDOMDocument +WebKitDOMDocument:design-mode, object property in WebKitDOMDocument +
    +
    +
    +WebKitDOMDocument:dir, object property in WebKitDOMDocument
    @@ -4643,6 +4715,10 @@
    +WebKitDOMDocument:embeds, object property in WebKitDOMDocument +
    +
    +
    WebKitDOMDocument:first-element-child, object property in WebKitDOMDocument
    @@ -4687,6 +4763,10 @@
    +WebKitDOMDocument:plugins, object property in WebKitDOMDocument +
    +
    +
    WebKitDOMDocument:pointer-lock-element, object property in WebKitDOMDocument
    @@ -4703,6 +4783,10 @@
    +WebKitDOMDocument:scripts, object property in WebKitDOMDocument +
    +
    +
    WebKitDOMDocument:scrolling-element, object property in WebKitDOMDocument
    @@ -4827,10 +4911,6 @@
    -WebKitDOMDOMWindow:css, object property in WebKitDOMDOMWindow -
    -
    -
    WebKitDOMDOMWindow:default-status, object property in WebKitDOMDOMWindow
    @@ -5051,6 +5131,14 @@
    +WebKitDOMElement:local-name, object property in WebKitDOMElement +
    +
    +
    +WebKitDOMElement:namespace-uri, object property in WebKitDOMElement +
    +
    +
    WebKitDOMElement:next-element-sibling, object property in WebKitDOMElement
    @@ -5079,6 +5167,10 @@
    +WebKitDOMElement:prefix, object property in WebKitDOMElement +
    +
    +
    WebKitDOMElement:previous-element-sibling, object property in WebKitDOMElement
    @@ -5127,6 +5219,10 @@
    +WebKitDOMEvent:composed, object property in WebKitDOMEvent +
    +
    +
    WebKitDOMEvent:current-target, object property in WebKitDOMEvent
    @@ -5171,6 +5267,10 @@
    +WebKitDOMFile:last-modified, object property in WebKitDOMFile +
    +
    +
    WebKitDOMFile:name, object property in WebKitDOMFile
    @@ -5227,6 +5327,10 @@
    +WebKitDOMHTMLAnchorElement:password, object property in WebKitDOMHTMLAnchorElement +
    +
    +
    WebKitDOMHTMLAnchorElement:pathname, object property in WebKitDOMHTMLAnchorElement
    @@ -5275,6 +5379,10 @@
    +WebKitDOMHTMLAnchorElement:username, object property in WebKitDOMHTMLAnchorElement +
    +
    +
    WebKitDOMHTMLAppletElement, struct in WebKitDOMHTMLAppletElement
    @@ -5355,6 +5463,14 @@
    +WebKitDOMHTMLAreaElement:origin, object property in WebKitDOMHTMLAreaElement +
    +
    +
    +WebKitDOMHTMLAreaElement:password, object property in WebKitDOMHTMLAreaElement +
    +
    +
    WebKitDOMHTMLAreaElement:pathname, object property in WebKitDOMHTMLAreaElement
    @@ -5391,6 +5507,10 @@
    +WebKitDOMHTMLAreaElement:username, object property in WebKitDOMHTMLAreaElement +
    +
    +
    WebKitDOMHTMLBaseElement, struct in WebKitDOMHTMLBaseElement
    @@ -5559,22 +5679,10 @@
    -WebKitDOMHTMLDocument:compat-mode, object property in WebKitDOMHTMLDocument -
    -
    -
    -WebKitDOMHTMLDocument:design-mode, object property in WebKitDOMHTMLDocument -
    -
    -
    WebKitDOMHTMLDocument:dir, object property in WebKitDOMHTMLDocument
    -WebKitDOMHTMLDocument:embeds, object property in WebKitDOMHTMLDocument -
    -
    -
    WebKitDOMHTMLDocument:fg-color, object property in WebKitDOMHTMLDocument
    @@ -5587,14 +5695,6 @@
    -WebKitDOMHTMLDocument:plugins, object property in WebKitDOMHTMLDocument -
    -
    -
    -WebKitDOMHTMLDocument:scripts, object property in WebKitDOMHTMLDocument -
    -
    -
    WebKitDOMHTMLDocument:vlink-color, object property in WebKitDOMHTMLDocument
    @@ -6291,10 +6391,18 @@
    +WebKitDOMHTMLLinkElement:as, object property in WebKitDOMHTMLLinkElement +
    +
    +
    WebKitDOMHTMLLinkElement:charset, object property in WebKitDOMHTMLLinkElement
    +WebKitDOMHTMLLinkElement:cross-origin, object property in WebKitDOMHTMLLinkElement +
    +
    +
    WebKitDOMHTMLLinkElement:disabled, object property in WebKitDOMHTMLLinkElement
    @@ -6787,6 +6895,10 @@
    +WebKitDOMHTMLStyleElement:nonce, object property in WebKitDOMHTMLStyleElement +
    +
    +
    WebKitDOMHTMLStyleElement:sheet, object property in WebKitDOMHTMLStyleElement
    @@ -7287,15 +7399,11 @@
    -WebKitDOMNode:last-child, object property in WebKitDOMNode -
    -
    -
    -WebKitDOMNode:local-name, object property in WebKitDOMNode +WebKitDOMNode:is-connected, object property in WebKitDOMNode
    -WebKitDOMNode:namespace-uri, object property in WebKitDOMNode +WebKitDOMNode:last-child, object property in WebKitDOMNode
    @@ -7327,10 +7435,6 @@
    -WebKitDOMNode:prefix, object property in WebKitDOMNode -
    -
    -
    WebKitDOMNode:previous-sibling, object property in WebKitDOMNode
    @@ -7339,10 +7443,6 @@
    -WebKitDOMNode:tree-root, object property in WebKitDOMNode -
    -
    -
    WebKitDOMNodeFilter, struct in WebKitDOMNodeFilter
    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/index.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/index.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/index.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/index.html 2016-11-03 07:31:44.000000000 +0000 @@ -14,7 +14,7 @@
    -

    for WebKitDOMGTK+ 2.12.3

    +

    for WebKitDOMGTK+ 2.14.2


    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMAttr.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMAttr.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMAttr.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMAttr.html 2016-11-03 07:31:44.000000000 +0000 @@ -82,6 +82,30 @@ webkit_dom_attr_get_owner_element () + + +gchar * + + +webkit_dom_attr_get_namespace_uri () + + + + +gchar * + + +webkit_dom_attr_get_prefix () + + + + +gchar * + + +webkit_dom_attr_get_local_name () + + @@ -102,16 +126,34 @@ gchar * +local-name +Read + + + +gchar * name Read +gchar * +namespace-uri +Read + + + WebKitDOMElement * owner-element Read + +gchar * +prefix +Read + + gboolean specified Read @@ -292,6 +334,84 @@

    [transfer none]

    +
    +
    +

    webkit_dom_attr_get_namespace_uri ()

    +
    gchar *
    +webkit_dom_attr_get_namespace_uri (WebKitDOMAttr *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMAttr

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_attr_get_prefix ()

    +
    gchar *
    +webkit_dom_attr_get_prefix (WebKitDOMAttr *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMAttr

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_attr_get_local_name ()

    +
    gchar *
    +webkit_dom_attr_get_local_name (WebKitDOMAttr *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMAttr

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +

    Types and Values

    @@ -311,6 +431,14 @@

    +

    The “local-name” property

    +
      “local-name”               gchar *
    +

    read-only gchar* Attr:local-name.

    +

    Flags: Read

    +

    Default value: ""

    +
    +
    +

    The “name” property

      “name”                     gchar *

    read-only gchar* Attr:name.

    @@ -319,6 +447,14 @@

    +

    The “namespace-uri” property

    +
      “namespace-uri”            gchar *
    +

    read-only gchar* Attr:namespace-uri.

    +

    Flags: Read

    +

    Default value: ""

    +
    +
    +

    The “owner-element” property

      “owner-element”            WebKitDOMElement *

    read-only WebKitDOMElement* Attr:owner-element.

    @@ -326,6 +462,14 @@

    +

    The “prefix” property

    +
      “prefix”                   gchar *
    +

    read-only gchar* Attr:prefix.

    +

    Flags: Read

    +

    Default value: ""

    +
    +
    +

    The “specified” property

      “specified”                gboolean

    read-only gboolean Attr:specified.

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocument.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocument.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocument.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocument.html 2016-11-03 07:31:44.000000000 +0000 @@ -447,6 +447,22 @@ gchar * +webkit_dom_document_get_design_mode () + + + + +void + + +webkit_dom_document_set_design_mode () + + + + +gchar * + + webkit_dom_document_get_referrer () @@ -548,26 +564,26 @@ -gchar * +WebKitDOMHTMLCollection * -webkit_dom_document_get_last_modified () +webkit_dom_document_get_embeds () -gchar * +WebKitDOMHTMLCollection * -webkit_dom_document_get_charset () +webkit_dom_document_get_plugins () -void +WebKitDOMHTMLCollection * -webkit_dom_document_set_charset () +webkit_dom_document_get_scripts () @@ -575,7 +591,23 @@ gchar * -webkit_dom_document_get_default_charset () +webkit_dom_document_get_last_modified () + + + + +gchar * + + +webkit_dom_document_get_charset () + + + + +void + + +webkit_dom_document_set_charset () @@ -628,6 +660,14 @@ +gchar * + + +webkit_dom_document_get_compat_mode () + + + + WebKitDOMNodeList * @@ -658,6 +698,14 @@ webkit_dom_document_create_entity_reference () + + +gchar * + + +webkit_dom_document_get_default_charset () + +
    @@ -743,15 +791,21 @@ -gchar * -default-charset +WebKitDOMDOMWindow * +default-view Read -WebKitDOMDOMWindow * -default-view -Read +gchar * +design-mode +Read / Write + + + +gchar * +dir +Read / Write @@ -779,6 +833,12 @@ +WebKitDOMHTMLCollection * +embeds +Read + + + WebKitDOMElement * first-element-child Read @@ -844,6 +904,12 @@ +WebKitDOMHTMLCollection * +plugins +Read + + + WebKitDOMElement * pointer-lock-element Read @@ -868,6 +934,12 @@ +WebKitDOMHTMLCollection * +scripts +Read + + + WebKitDOMElement * scrolling-element Read @@ -2780,6 +2852,62 @@
    +

    webkit_dom_document_get_design_mode ()

    +
    gchar *
    +webkit_dom_document_get_design_mode (WebKitDOMDocument *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMDocument

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_document_set_design_mode ()

    +
    void
    +webkit_dom_document_set_design_mode (WebKitDOMDocument *self,
    +                                     const gchar *value);
    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + +

    self

    A WebKitDOMDocument

     

    value

    A gchar

     
    +
    +

    Since: 2.14

    +
    +
    +

    webkit_dom_document_get_referrer ()

    gchar *
     webkit_dom_document_get_referrer (WebKitDOMDocument *self);
    @@ -3140,6 +3268,87 @@

    +

    webkit_dom_document_get_embeds ()

    +
    WebKitDOMHTMLCollection *
    +webkit_dom_document_get_embeds (WebKitDOMDocument *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMDocument

     
    +
    +
    +

    Returns

    +

    A WebKitDOMHTMLCollection.

    +

    [transfer full]

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_document_get_plugins ()

    +
    WebKitDOMHTMLCollection *
    +webkit_dom_document_get_plugins (WebKitDOMDocument *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMDocument

     
    +
    +
    +

    Returns

    +

    A WebKitDOMHTMLCollection.

    +

    [transfer full]

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_document_get_scripts ()

    +
    WebKitDOMHTMLCollection *
    +webkit_dom_document_get_scripts (WebKitDOMDocument *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMDocument

     
    +
    +
    +

    Returns

    +

    A WebKitDOMHTMLCollection.

    +

    [transfer full]

    +
    +

    Since: 2.14

    +
    +
    +

    webkit_dom_document_get_last_modified ()

    gchar *
     webkit_dom_document_get_last_modified (WebKitDOMDocument *self);
    @@ -3219,32 +3428,6 @@

    -

    webkit_dom_document_get_default_charset ()

    -
    gchar *
    -webkit_dom_document_get_default_charset
    -                               (WebKitDOMDocument *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMDocument

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -

    webkit_dom_document_get_ready_state ()

    gchar *
     webkit_dom_document_get_ready_state (WebKitDOMDocument *self);
    @@ -3404,6 +3587,32 @@

    +

    webkit_dom_document_get_compat_mode ()

    +
    gchar *
    +webkit_dom_document_get_compat_mode (WebKitDOMDocument *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMDocument

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +

    webkit_dom_document_get_elements_by_class_name ()

    WebKitDOMNodeList *
     webkit_dom_document_get_elements_by_class_name
    @@ -3440,6 +3649,14 @@
                                     GError **error);

    webkit_dom_document_create_entity_reference is deprecated and should not be used in newly-written code.

    +
    +
    +

    webkit_dom_document_get_default_charset ()

    +
    gchar *
    +webkit_dom_document_get_default_charset
    +                               (WebKitDOMDocument *self);
    +

    webkit_dom_document_get_default_charset is deprecated and should not be used in newly-written code.

    +

    Types and Values

    @@ -3540,18 +3757,26 @@

    -

    The “default-charset” property

    -
      “default-charset”          gchar *
    -

    read-only gchar* Document:default-charset.

    +

    The “default-view” property

    +
      “default-view”             WebKitDOMDOMWindow *
    +

    read-only WebKitDOMDOMWindow* Document:default-view.

    Flags: Read

    +
    +
    +
    +

    The “design-mode” property

    +
      “design-mode”              gchar *
    +

    read-write gchar* Document:design-mode.

    +

    Flags: Read / Write

    Default value: ""


    -

    The “default-view” property

    -
      “default-view”             WebKitDOMDOMWindow *
    -

    read-only WebKitDOMDOMWindow* Document:default-view.

    -

    Flags: Read

    +

    The “dir” property

    +
      “dir”                      gchar *
    +

    read-write gchar* Document:dir.

    +

    Flags: Read / Write

    +

    Default value: ""


    @@ -3585,6 +3810,13 @@

    +

    The “embeds” property

    +
      “embeds”                   WebKitDOMHTMLCollection *
    +

    read-only WebKitDOMHTMLCollection* Document:embeds.

    +

    Flags: Read

    +
    +
    +

    The “first-element-child” property

      “first-element-child”      WebKitDOMElement *

    read-only WebKitDOMElement* Document:first-element-child.

    @@ -3666,6 +3898,13 @@

    +

    The “plugins” property

    +
      “plugins”                  WebKitDOMHTMLCollection *
    +

    read-only WebKitDOMHTMLCollection* Document:plugins.

    +

    Flags: Read

    +
    +
    +

    The “pointer-lock-element” property

      “pointer-lock-element”     WebKitDOMElement *

    read-only WebKitDOMElement* Document:pointer-lock-element.

    @@ -3697,6 +3936,13 @@

    +

    The “scripts” property

    +
      “scripts”                  WebKitDOMHTMLCollection *
    +

    read-only WebKitDOMHTMLCollection* Document:scripts.

    +

    Flags: Read

    +
    +
    +

    The “scrolling-element” property

      “scrolling-element”        WebKitDOMElement *

    read-only WebKitDOMElement* Document:scrolling-element.

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocumentType.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocumentType.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocumentType.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMDocumentType.html 2016-11-03 07:31:44.000000000 +0000 @@ -71,7 +71,7 @@ gchar * -webkit_dom_document_type_get_public_id () +webkit_dom_document_type_get_internal_subset () @@ -79,7 +79,7 @@ gchar * -webkit_dom_document_type_get_system_id () +webkit_dom_document_type_get_public_id () @@ -87,7 +87,7 @@ gchar * -webkit_dom_document_type_get_internal_subset () +webkit_dom_document_type_get_system_id () @@ -252,12 +252,12 @@

    -

    webkit_dom_document_type_get_public_id ()

    +

    webkit_dom_document_type_get_internal_subset ()

    gchar *
    -webkit_dom_document_type_get_public_id
    +webkit_dom_document_type_get_internal_subset
                                    (WebKitDOMDocumentType *self);
    -

    Parameters

    +

    Parameters

    @@ -272,18 +272,18 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_document_type_get_system_id ()

    +

    webkit_dom_document_type_get_public_id ()

    gchar *
    -webkit_dom_document_type_get_system_id
    +webkit_dom_document_type_get_public_id
                                    (WebKitDOMDocumentType *self);
    -

    Parameters

    +

    Parameters

    @@ -298,18 +298,18 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_document_type_get_internal_subset ()

    +

    webkit_dom_document_type_get_system_id ()

    gchar *
    -webkit_dom_document_type_get_internal_subset
    +webkit_dom_document_type_get_system_id
                                    (WebKitDOMDocumentType *self);
    -

    Parameters

    +

    Parameters

    @@ -324,7 +324,7 @@
    -

    Returns

    +

    Returns

    A gchar

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMDOMWindow.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMDOMWindow.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMDOMWindow.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMDOMWindow.html 2016-11-03 07:31:44.000000000 +0000 @@ -62,12 +62,6 @@ -WebKitDOMDOMWindowCSS * -css -Read - - - gchar * default-status Read / Write @@ -364,13 +358,6 @@
    -

    The “css” property

    -
      “css”                      WebKitDOMDOMWindowCSS *
    -

    read-only WebKitDOMDOMWindowCSS* DOMWindow:css.

    -

    Flags: Read

    -
    -
    -

    The “default-status” property

      “default-status”           gchar *

    read-write gchar* DOMWindow:default-status.

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -284,6 +284,30 @@ +gchar * + + +webkit_dom_element_get_namespace_uri () + + + + +gchar * + + +webkit_dom_element_get_prefix () + + + + +gchar * + + +webkit_dom_element_get_local_name () + + + + gdouble @@ -609,6 +633,18 @@ +gchar * +local-name +Read + + + +gchar * +namespace-uri +Read + + + WebKitDOMElement * next-element-sibling Read @@ -647,6 +683,12 @@ +gchar * +prefix +Read + + + WebKitDOMElement * previous-element-sibling Read @@ -1729,6 +1771,84 @@

    +

    webkit_dom_element_get_namespace_uri ()

    +
    gchar *
    +webkit_dom_element_get_namespace_uri (WebKitDOMElement *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMElement

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_element_get_prefix ()

    +
    gchar *
    +webkit_dom_element_get_prefix (WebKitDOMElement *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMElement

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_element_get_local_name ()

    +
    gchar *
    +webkit_dom_element_get_local_name (WebKitDOMElement *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMElement

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +

    Since: 2.14

    +
    +
    +

    webkit_dom_element_get_offset_left ()

    gdouble
     webkit_dom_element_get_offset_left (WebKitDOMElement *self);
    @@ -2587,6 +2707,22 @@

    +

    The “local-name” property

    +
      “local-name”               gchar *
    +

    read-only gchar* Element:local-name.

    +

    Flags: Read

    +

    Default value: ""

    +
    +
    +
    +

    The “namespace-uri” property

    +
      “namespace-uri”            gchar *
    +

    read-only gchar* Element:namespace-uri.

    +

    Flags: Read

    +

    Default value: ""

    +
    +
    +

    The “next-element-sibling” property

      “next-element-sibling”     WebKitDOMElement *

    read-only WebKitDOMElement* Element:next-element-sibling.

    @@ -2640,6 +2776,14 @@

    Default value: ""


    +
    +

    The “prefix” property

    +
      “prefix”                   gchar *
    +

    read-only gchar* Element:prefix.

    +

    Flags: Read

    +

    Default value: ""

    +
    +

    The “previous-element-sibling” property

      “previous-element-sibling” WebKitDOMElement *
    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMEvent.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMEvent.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMEvent.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMEvent.html 2016-11-03 07:31:44.000000000 +0000 @@ -189,6 +189,11 @@ Read +gboolean +composed +Read + + WebKitDOMEventTarget * current-target @@ -894,6 +899,14 @@

    Flags: Read

    Default value: FALSE

    +
    +
    +

    The “composed” property

    +
      “composed”                 gboolean
    +

    read-only gboolean Event:composed.

    +

    Flags: Read

    +

    Default value: FALSE

    +

    The “current-target” property

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMFile.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMFile.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMFile.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMFile.html 2016-11-03 07:31:44.000000000 +0000 @@ -58,12 +58,19 @@ - + + +gint64 +last-modified +Read + + gchar * name Read - + +
    @@ -127,6 +134,14 @@

    Property Details

    +

    The “last-modified” property

    +
      “last-modified”            gint64
    +

    read-only gint64 File:last-modified.

    +

    Flags: Read

    +

    Default value: 0

    +
    +
    +

    The “name” property

      “name”                     gchar *

    read-only gchar* File:name.

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/webkitdomgtk-4.0.devhelp2 webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/webkitdomgtk-4.0.devhelp2 --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/webkitdomgtk-4.0.devhelp2 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/webkitdomgtk-4.0.devhelp2 2016-11-03 07:31:43.000000000 +0000 @@ -230,10 +230,16 @@ + + + + + + @@ -307,6 +313,8 @@ + + @@ -320,20 +328,24 @@ + + + - + + @@ -347,12 +359,14 @@ - + + + @@ -364,10 +378,12 @@ + + @@ -390,9 +406,9 @@ + - @@ -430,6 +446,9 @@ + + + @@ -474,6 +493,8 @@ + + @@ -481,6 +502,7 @@ + @@ -528,6 +550,7 @@ + @@ -609,14 +632,14 @@ - + - + @@ -630,14 +653,15 @@ - - - - + + + + + @@ -659,9 +683,8 @@ + - - @@ -669,10 +692,8 @@ - - @@ -717,8 +738,8 @@ - + @@ -744,8 +765,8 @@ - + @@ -804,6 +825,7 @@ + @@ -813,8 +835,6 @@ - - @@ -829,21 +849,23 @@ - - + + + + + - - - - + + - + + @@ -855,6 +877,7 @@ + @@ -867,6 +890,7 @@ + @@ -905,21 +929,21 @@ - - - + + + - - + + @@ -928,6 +952,8 @@ + + @@ -937,6 +963,7 @@ + @@ -972,10 +999,10 @@ - - + + @@ -1023,16 +1050,10 @@ - - - - - - @@ -1043,18 +1064,19 @@ + + + + + + - - - - - @@ -1366,7 +1388,8 @@ - + + @@ -1453,7 +1476,9 @@ + + @@ -1717,6 +1742,7 @@ + @@ -1736,14 +1762,14 @@ + + - - @@ -1942,7 +1968,6 @@ - diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLAnchorElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLAnchorElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLAnchorElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLAnchorElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -79,22 +79,6 @@ gchar * -webkit_dom_html_anchor_element_get_href () - - - - -void - - -webkit_dom_html_anchor_element_set_href () - - - - -gchar * - - webkit_dom_html_anchor_element_get_hreflang () @@ -207,7 +191,15 @@ gchar * -webkit_dom_html_anchor_element_get_hash () +webkit_dom_html_anchor_element_get_text () + + + + +gchar * + + +webkit_dom_html_anchor_element_get_href () @@ -215,7 +207,7 @@ void -webkit_dom_html_anchor_element_set_hash () +webkit_dom_html_anchor_element_set_href () @@ -223,7 +215,7 @@ gchar * -webkit_dom_html_anchor_element_get_host () +webkit_dom_html_anchor_element_get_protocol () @@ -231,7 +223,7 @@ void -webkit_dom_html_anchor_element_set_host () +webkit_dom_html_anchor_element_set_protocol () @@ -239,7 +231,7 @@ gchar * -webkit_dom_html_anchor_element_get_hostname () +webkit_dom_html_anchor_element_get_host () @@ -247,7 +239,7 @@ void -webkit_dom_html_anchor_element_set_hostname () +webkit_dom_html_anchor_element_set_host () @@ -255,7 +247,7 @@ gchar * -webkit_dom_html_anchor_element_get_pathname () +webkit_dom_html_anchor_element_get_hostname () @@ -263,7 +255,7 @@ void -webkit_dom_html_anchor_element_set_pathname () +webkit_dom_html_anchor_element_set_hostname () @@ -287,7 +279,7 @@ gchar * -webkit_dom_html_anchor_element_get_protocol () +webkit_dom_html_anchor_element_get_pathname () @@ -295,7 +287,7 @@ void -webkit_dom_html_anchor_element_set_protocol () +webkit_dom_html_anchor_element_set_pathname () @@ -319,7 +311,15 @@ gchar * -webkit_dom_html_anchor_element_get_text () +webkit_dom_html_anchor_element_get_hash () + + + + +void + + +webkit_dom_html_anchor_element_set_hash () @@ -397,6 +397,12 @@ gchar * +password +Read / Write + + + +gchar * pathname Read / Write @@ -466,6 +472,12 @@ type Read / Write + + +gchar * +username +Read / Write +
    @@ -616,62 +628,6 @@

    -

    webkit_dom_html_anchor_element_get_href ()

    -
    gchar *
    -webkit_dom_html_anchor_element_get_href
    -                               (WebKitDOMHTMLAnchorElement *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMHTMLAnchorElement

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -
    -

    webkit_dom_html_anchor_element_set_href ()

    -
    void
    -webkit_dom_html_anchor_element_set_href
    -                               (WebKitDOMHTMLAnchorElement *self,
    -                                const gchar *value);
    -
    -

    Parameters

    -
    ----- - - - - - - - - - - - - -

    self

    A WebKitDOMHTMLAnchorElement

     

    value

    A gchar

     
    -
    -
    -
    -

    webkit_dom_html_anchor_element_get_hreflang ()

    gchar *
     webkit_dom_html_anchor_element_get_hreflang
    @@ -1064,12 +1020,12 @@
     

    -

    webkit_dom_html_anchor_element_get_hash ()

    +

    webkit_dom_html_anchor_element_get_text ()

    gchar *
    -webkit_dom_html_anchor_element_get_hash
    +webkit_dom_html_anchor_element_get_text
                                    (WebKitDOMHTMLAnchorElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1084,19 +1040,45 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_anchor_element_set_hash ()

    +

    webkit_dom_html_anchor_element_get_href ()

    +
    gchar *
    +webkit_dom_html_anchor_element_get_href
    +                               (WebKitDOMHTMLAnchorElement *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    A WebKitDOMHTMLAnchorElement

     
    +
    +
    +

    Returns

    +

    A gchar

    +
    +
    +
    +
    +

    webkit_dom_html_anchor_element_set_href ()

    void
    -webkit_dom_html_anchor_element_set_hash
    +webkit_dom_html_anchor_element_set_href
                                    (WebKitDOMHTMLAnchorElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -1120,12 +1102,12 @@
    -

    webkit_dom_html_anchor_element_get_host ()

    +

    webkit_dom_html_anchor_element_get_protocol ()

    gchar *
    -webkit_dom_html_anchor_element_get_host
    +webkit_dom_html_anchor_element_get_protocol
                                    (WebKitDOMHTMLAnchorElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1140,19 +1122,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_anchor_element_set_host ()

    +

    webkit_dom_html_anchor_element_set_protocol ()

    void
    -webkit_dom_html_anchor_element_set_host
    +webkit_dom_html_anchor_element_set_protocol
                                    (WebKitDOMHTMLAnchorElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -1176,12 +1158,12 @@
    -

    webkit_dom_html_anchor_element_get_hostname ()

    +

    webkit_dom_html_anchor_element_get_host ()

    gchar *
    -webkit_dom_html_anchor_element_get_hostname
    +webkit_dom_html_anchor_element_get_host
                                    (WebKitDOMHTMLAnchorElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1196,19 +1178,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_anchor_element_set_hostname ()

    +

    webkit_dom_html_anchor_element_set_host ()

    void
    -webkit_dom_html_anchor_element_set_hostname
    +webkit_dom_html_anchor_element_set_host
                                    (WebKitDOMHTMLAnchorElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -1232,12 +1214,12 @@
    -

    webkit_dom_html_anchor_element_get_pathname ()

    +

    webkit_dom_html_anchor_element_get_hostname ()

    gchar *
    -webkit_dom_html_anchor_element_get_pathname
    +webkit_dom_html_anchor_element_get_hostname
                                    (WebKitDOMHTMLAnchorElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1252,19 +1234,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_anchor_element_set_pathname ()

    +

    webkit_dom_html_anchor_element_set_hostname ()

    void
    -webkit_dom_html_anchor_element_set_pathname
    +webkit_dom_html_anchor_element_set_hostname
                                    (WebKitDOMHTMLAnchorElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -1344,12 +1326,12 @@
    -

    webkit_dom_html_anchor_element_get_protocol ()

    +

    webkit_dom_html_anchor_element_get_pathname ()

    gchar *
    -webkit_dom_html_anchor_element_get_protocol
    +webkit_dom_html_anchor_element_get_pathname
                                    (WebKitDOMHTMLAnchorElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1364,19 +1346,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_anchor_element_set_protocol ()

    +

    webkit_dom_html_anchor_element_set_pathname ()

    void
    -webkit_dom_html_anchor_element_set_protocol
    +webkit_dom_html_anchor_element_set_pathname
                                    (WebKitDOMHTMLAnchorElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -1456,12 +1438,12 @@
    -

    webkit_dom_html_anchor_element_get_text ()

    +

    webkit_dom_html_anchor_element_get_hash ()

    gchar *
    -webkit_dom_html_anchor_element_get_text
    +webkit_dom_html_anchor_element_get_hash
                                    (WebKitDOMHTMLAnchorElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1476,10 +1458,40 @@
    -

    Returns

    +

    Returns

    A gchar

    +
    +
    +

    webkit_dom_html_anchor_element_set_hash ()

    +
    void
    +webkit_dom_html_anchor_element_set_hash
    +                               (WebKitDOMHTMLAnchorElement *self,
    +                                const gchar *value);
    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + +

    self

    A WebKitDOMHTMLAnchorElement

     

    value

    A gchar

     
    +
    +

    Types and Values

    @@ -1571,6 +1583,14 @@

    +

    The “password” property

    +
      “password”                 gchar *
    +

    read-write gchar* HTMLAnchorElement:password.

    +

    Flags: Read / Write

    +

    Default value: ""

    +
    +
    +

    The “pathname” property

      “pathname”                 gchar *

    read-write gchar* HTMLAnchorElement:pathname.

    @@ -1664,6 +1684,14 @@

    Flags: Read / Write

    Default value: ""

    +
    +
    +

    The “username” property

    +
      “username”                 gchar *
    +

    read-write gchar* HTMLAnchorElement:username.

    +

    Flags: Read / Write

    +

    Default value: ""

    +
    @@ -449,11 +467,12 @@
    -

    webkit_dom_html_area_element_get_href ()

    -
    gchar *
    -webkit_dom_html_area_element_get_href (WebKitDOMHTMLAreaElement *self);
    +

    webkit_dom_html_area_element_get_no_href ()

    +
    gboolean
    +webkit_dom_html_area_element_get_no_href
    +                               (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -468,18 +487,19 @@
    -

    Returns

    -

    A gchar

    +

    Returns

    +

    A gboolean


    -

    webkit_dom_html_area_element_set_href ()

    +

    webkit_dom_html_area_element_set_no_href ()

    void
    -webkit_dom_html_area_element_set_href (WebKitDOMHTMLAreaElement *self,
    -                                       const gchar *value);
    +webkit_dom_html_area_element_set_no_href + (WebKitDOMHTMLAreaElement *self, + gboolean value);
    -

    Parameters

    +

    Parameters

    @@ -494,7 +514,7 @@ - + @@ -503,12 +523,12 @@
    -

    webkit_dom_html_area_element_get_no_href ()

    -
    gboolean
    -webkit_dom_html_area_element_get_no_href
    +

    webkit_dom_html_area_element_get_shape ()

    +
    gchar *
    +webkit_dom_html_area_element_get_shape
                                    (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    value

    A gchar

    A gboolean

     
    @@ -523,19 +543,19 @@
    -

    Returns

    -

    A gboolean

    +

    Returns

    +

    A gchar


    -

    webkit_dom_html_area_element_set_no_href ()

    +

    webkit_dom_html_area_element_set_shape ()

    void
    -webkit_dom_html_area_element_set_no_href
    +webkit_dom_html_area_element_set_shape
                                    (WebKitDOMHTMLAreaElement *self,
    -                                gboolean value);
    + const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -550,7 +570,7 @@ - + @@ -559,12 +579,12 @@
    -

    webkit_dom_html_area_element_get_shape ()

    +

    webkit_dom_html_area_element_get_target ()

    gchar *
    -webkit_dom_html_area_element_get_shape
    +webkit_dom_html_area_element_get_target
                                    (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    value

    A gboolean

    A gchar

     
    @@ -579,19 +599,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_area_element_set_shape ()

    +

    webkit_dom_html_area_element_set_target ()

    void
    -webkit_dom_html_area_element_set_shape
    +webkit_dom_html_area_element_set_target
                                    (WebKitDOMHTMLAreaElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -615,12 +635,11 @@
    -

    webkit_dom_html_area_element_get_target ()

    +

    webkit_dom_html_area_element_get_href ()

    gchar *
    -webkit_dom_html_area_element_get_target
    -                               (WebKitDOMHTMLAreaElement *self);
    +webkit_dom_html_area_element_get_href (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -635,19 +654,18 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_area_element_set_target ()

    +

    webkit_dom_html_area_element_set_href ()

    void
    -webkit_dom_html_area_element_set_target
    -                               (WebKitDOMHTMLAreaElement *self,
    -                                const gchar *value);
    +webkit_dom_html_area_element_set_href (WebKitDOMHTMLAreaElement *self, + const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -671,11 +689,12 @@
    -

    webkit_dom_html_area_element_get_hash ()

    +

    webkit_dom_html_area_element_get_protocol ()

    gchar *
    -webkit_dom_html_area_element_get_hash (WebKitDOMHTMLAreaElement *self);
    +webkit_dom_html_area_element_get_protocol + (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -690,7 +709,7 @@
    -

    Returns

    +

    Returns

    A gchar

    @@ -747,12 +766,11 @@
    -

    webkit_dom_html_area_element_get_pathname ()

    +

    webkit_dom_html_area_element_get_port ()

    gchar *
    -webkit_dom_html_area_element_get_pathname
    -                               (WebKitDOMHTMLAreaElement *self);
    +webkit_dom_html_area_element_get_port (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -767,17 +785,18 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_area_element_get_port ()

    +

    webkit_dom_html_area_element_get_pathname ()

    gchar *
    -webkit_dom_html_area_element_get_port (WebKitDOMHTMLAreaElement *self);
    +webkit_dom_html_area_element_get_pathname + (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -792,18 +811,18 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_area_element_get_protocol ()

    +

    webkit_dom_html_area_element_get_search ()

    gchar *
    -webkit_dom_html_area_element_get_protocol
    +webkit_dom_html_area_element_get_search
                                    (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -818,18 +837,17 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_area_element_get_search ()

    +

    webkit_dom_html_area_element_get_hash ()

    gchar *
    -webkit_dom_html_area_element_get_search
    -                               (WebKitDOMHTMLAreaElement *self);
    +webkit_dom_html_area_element_get_hash (WebKitDOMHTMLAreaElement *self);
    -

    Parameters

    +

    Parameters

    @@ -844,7 +862,7 @@
    -

    Returns

    +

    Returns

    A gchar

    @@ -877,24 +895,24 @@

    The “hash” property

      “hash”                     gchar *
    -

    read-only gchar* HTMLAreaElement:hash.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:hash.

    +

    Flags: Read / Write

    Default value: ""


    The “host” property

      “host”                     gchar *
    -

    read-only gchar* HTMLAreaElement:host.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:host.

    +

    Flags: Read / Write

    Default value: ""


    The “hostname” property

      “hostname”                 gchar *
    -

    read-only gchar* HTMLAreaElement:hostname.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:hostname.

    +

    Flags: Read / Write

    Default value: ""


    @@ -915,10 +933,26 @@
    +

    The “origin” property

    +
      “origin”                   gchar *
    +

    read-only gchar* HTMLAreaElement:origin.

    +

    Flags: Read

    +

    Default value: ""

    +
    +
    +
    +

    The “password” property

    +
      “password”                 gchar *
    +

    read-write gchar* HTMLAreaElement:password.

    +

    Flags: Read / Write

    +

    Default value: ""

    +
    +
    +

    The “pathname” property

      “pathname”                 gchar *
    -

    read-only gchar* HTMLAreaElement:pathname.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:pathname.

    +

    Flags: Read / Write

    Default value: ""


    @@ -933,16 +967,16 @@

    The “port” property

      “port”                     gchar *
    -

    read-only gchar* HTMLAreaElement:port.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:port.

    +

    Flags: Read / Write

    Default value: ""


    The “protocol” property

      “protocol”                 gchar *
    -

    read-only gchar* HTMLAreaElement:protocol.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:protocol.

    +

    Flags: Read / Write

    Default value: ""


    @@ -964,8 +998,8 @@

    The “search” property

      “search”                   gchar *
    -

    read-only gchar* HTMLAreaElement:search.

    -

    Flags: Read

    +

    read-write gchar* HTMLAreaElement:search.

    +

    Flags: Read / Write

    Default value: ""


    @@ -984,6 +1018,14 @@

    Flags: Read / Write

    Default value: ""

    +
    +
    +

    The “username” property

    +
      “username”                 gchar *
    +

    read-write gchar* HTMLAreaElement:username.

    +

    Flags: Read / Write

    +

    Default value: ""

    +

    -

    webkit_dom_html_button_element_get_name ()

    +

    webkit_dom_html_button_element_get_button_type ()

    gchar *
    -webkit_dom_html_button_element_get_name
    +webkit_dom_html_button_element_get_button_type
                                    (WebKitDOMHTMLButtonElement *self);
    -

    Parameters

    +

    Parameters

    @@ -433,19 +433,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_button_element_set_name ()

    +

    webkit_dom_html_button_element_set_button_type ()

    void
    -webkit_dom_html_button_element_set_name
    +webkit_dom_html_button_element_set_button_type
                                    (WebKitDOMHTMLButtonElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -469,12 +469,12 @@
    -

    webkit_dom_html_button_element_get_button_type ()

    +

    webkit_dom_html_button_element_get_name ()

    gchar *
    -webkit_dom_html_button_element_get_button_type
    +webkit_dom_html_button_element_get_name
                                    (WebKitDOMHTMLButtonElement *self);
    -

    Parameters

    +

    Parameters

    @@ -489,19 +489,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_button_element_set_button_type ()

    +

    webkit_dom_html_button_element_set_name ()

    void
    -webkit_dom_html_button_element_set_button_type
    +webkit_dom_html_button_element_set_name
                                    (WebKitDOMHTMLButtonElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLDocument.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLDocument.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLDocument.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLDocument.html 2016-11-03 07:31:44.000000000 +0000 @@ -76,82 +76,82 @@ @@ -159,7 +159,7 @@ gchar * @@ -167,7 +167,7 @@ void @@ -175,7 +175,7 @@ gchar * @@ -183,23 +183,23 @@ void @@ -207,31 +207,31 @@ gchar * @@ -261,29 +261,11 @@ - - - - - - - - - - - - - - - @@ -301,18 +283,6 @@ - - - - - - - - - - @@ -445,84 +415,6 @@
    -

    webkit_dom_html_document_get_embeds ()

    -
    WebKitDOMHTMLCollection *
    -webkit_dom_html_document_get_embeds (WebKitDOMHTMLDocument *self);
    -
    -

    Parameters

    -
    -WebKitDOMHTMLCollection * +glong -webkit_dom_html_document_get_embeds () +webkit_dom_html_document_get_width ()
    -WebKitDOMHTMLCollection * +glong -webkit_dom_html_document_get_plugins () +webkit_dom_html_document_get_height ()
    -WebKitDOMHTMLCollection * +gchar * -webkit_dom_html_document_get_scripts () +webkit_dom_html_document_get_dir ()
    -glong +void -webkit_dom_html_document_get_width () +webkit_dom_html_document_set_dir ()
    -glong +gchar * -webkit_dom_html_document_get_height () +webkit_dom_html_document_get_bg_color ()
    -gchar * +void -webkit_dom_html_document_get_dir () +webkit_dom_html_document_set_bg_color ()
    -void +gchar * -webkit_dom_html_document_set_dir () +webkit_dom_html_document_get_fg_color ()
    -gchar * +void -webkit_dom_html_document_get_design_mode () +webkit_dom_html_document_set_fg_color ()
    -void +gchar * -webkit_dom_html_document_set_design_mode () +webkit_dom_html_document_get_alink_color ()
    -gchar * +void -webkit_dom_html_document_get_compat_mode () +webkit_dom_html_document_set_alink_color ()
    -webkit_dom_html_document_get_bg_color () +webkit_dom_html_document_get_link_color ()
    -webkit_dom_html_document_set_bg_color () +webkit_dom_html_document_set_link_color ()
    -webkit_dom_html_document_get_fg_color () +webkit_dom_html_document_get_vlink_color ()
    -webkit_dom_html_document_set_fg_color () +webkit_dom_html_document_set_vlink_color ()
    -gchar * +void -webkit_dom_html_document_get_alink_color () +webkit_dom_html_document_set_design_mode ()
    -void +gchar * -webkit_dom_html_document_set_alink_color () +webkit_dom_html_document_get_design_mode ()
    -webkit_dom_html_document_get_link_color () +webkit_dom_html_document_get_compat_mode ()
    -void +WebKitDOMHTMLCollection * -webkit_dom_html_document_set_link_color () +webkit_dom_html_document_get_scripts ()
    -gchar * +WebKitDOMHTMLCollection * -webkit_dom_html_document_get_vlink_color () +webkit_dom_html_document_get_embeds ()
    -void +WebKitDOMHTMLCollection * -webkit_dom_html_document_set_vlink_color () +webkit_dom_html_document_get_plugins ()
    gchar *compat-modeRead
    -gchar *design-modeRead / Write
    -gchar * dir Read / Write
    -WebKitDOMHTMLCollection *embedsRead
    gchar * fg-color Read / Write
    -WebKitDOMHTMLCollection *pluginsRead
    -WebKitDOMHTMLCollection *scriptsRead
    gchar * vlink-color Read / Write
    ----- - - - - - -

    self

    A WebKitDOMHTMLDocument

     
    -
    -
    -

    Returns

    -

    A WebKitDOMHTMLCollection.

    -

    [transfer full]

    -
    -
    -
    -
    -

    webkit_dom_html_document_get_plugins ()

    -
    WebKitDOMHTMLCollection *
    -webkit_dom_html_document_get_plugins (WebKitDOMHTMLDocument *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMHTMLDocument

     
    -
    -
    -

    Returns

    -

    A WebKitDOMHTMLCollection.

    -

    [transfer full]

    -
    -
    -
    -
    -

    webkit_dom_html_document_get_scripts ()

    -
    WebKitDOMHTMLCollection *
    -webkit_dom_html_document_get_scripts (WebKitDOMHTMLDocument *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMHTMLDocument

     
    -
    -
    -

    Returns

    -

    A WebKitDOMHTMLCollection.

    -

    [transfer full]

    -
    -
    -
    -

    webkit_dom_html_document_get_width ()

    glong
     webkit_dom_html_document_get_width (WebKitDOMHTMLDocument *self);
    @@ -627,88 +519,6 @@

    -

    webkit_dom_html_document_get_design_mode ()

    -
    gchar *
    -webkit_dom_html_document_get_design_mode
    -                               (WebKitDOMHTMLDocument *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMHTMLDocument

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -
    -

    webkit_dom_html_document_set_design_mode ()

    -
    void
    -webkit_dom_html_document_set_design_mode
    -                               (WebKitDOMHTMLDocument *self,
    -                                const gchar *value);
    -
    -

    Parameters

    -
    ----- - - - - - - - - - - - - -

    self

    A WebKitDOMHTMLDocument

     

    value

    A gchar

     
    -
    -
    -
    -
    -

    webkit_dom_html_document_get_compat_mode ()

    -
    gchar *
    -webkit_dom_html_document_get_compat_mode
    -                               (WebKitDOMHTMLDocument *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMHTMLDocument

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -

    webkit_dom_html_document_get_bg_color ()

    gchar *
     webkit_dom_html_document_get_bg_color (WebKitDOMHTMLDocument *self);
    @@ -983,6 +793,52 @@
    +
    +
    +

    webkit_dom_html_document_set_design_mode ()

    +
    void
    +webkit_dom_html_document_set_design_mode
    +                               (WebKitDOMHTMLDocument *self,
    +                                const gchar *value);
    +

    webkit_dom_html_document_set_design_mode is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_html_document_get_design_mode ()

    +
    gchar *
    +webkit_dom_html_document_get_design_mode
    +                               (WebKitDOMHTMLDocument *self);
    +

    webkit_dom_html_document_get_design_mode is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_html_document_get_compat_mode ()

    +
    gchar *
    +webkit_dom_html_document_get_compat_mode
    +                               (WebKitDOMHTMLDocument *self);
    +

    webkit_dom_html_document_get_compat_mode is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_html_document_get_scripts ()

    +
    WebKitDOMHTMLCollection *
    +webkit_dom_html_document_get_scripts (WebKitDOMHTMLDocument *self);
    +

    webkit_dom_html_document_get_scripts is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_html_document_get_embeds ()

    +
    WebKitDOMHTMLCollection *
    +webkit_dom_html_document_get_embeds (WebKitDOMHTMLDocument *self);
    +

    webkit_dom_html_document_get_embeds is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_html_document_get_plugins ()

    +
    WebKitDOMHTMLCollection *
    +webkit_dom_html_document_get_plugins (WebKitDOMHTMLDocument *self);
    +

    webkit_dom_html_document_get_plugins is deprecated and should not be used in newly-written code.

    +

    Types and Values

    @@ -1010,22 +866,6 @@

    -

    The “compat-mode” property

    -
      “compat-mode”              gchar *
    -

    read-only gchar* HTMLDocument:compat-mode.

    -

    Flags: Read

    -

    Default value: ""

    -
    -
    -
    -

    The “design-mode” property

    -
      “design-mode”              gchar *
    -

    read-write gchar* HTMLDocument:design-mode.

    -

    Flags: Read / Write

    -

    Default value: ""

    -
    -
    -

    The “dir” property

      “dir”                      gchar *

    read-write gchar* HTMLDocument:dir.

    @@ -1034,13 +874,6 @@

    -

    The “embeds” property

    -
      “embeds”                   WebKitDOMHTMLCollection *
    -

    read-only WebKitDOMHTMLCollection* HTMLDocument:embeds.

    -

    Flags: Read

    -
    -
    -

    The “fg-color” property

      “fg-color”                 gchar *

    read-write gchar* HTMLDocument:fg-color.

    @@ -1065,20 +898,6 @@

    -

    The “plugins” property

    -
      “plugins”                  WebKitDOMHTMLCollection *
    -

    read-only WebKitDOMHTMLCollection* HTMLDocument:plugins.

    -

    Flags: Read

    -
    -
    -
    -

    The “scripts” property

    -
      “scripts”                  WebKitDOMHTMLCollection *
    -

    read-only WebKitDOMHTMLCollection* HTMLDocument:scripts.

    -

    Flags: Read

    -
    -
    -

    The “vlink-color” property

      “vlink-color”              gchar *

    read-write gchar* HTMLDocument:vlink-color.

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLInputElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLInputElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLInputElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLInputElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -388,6 +388,14 @@ +gchar * + + +webkit_dom_html_input_element_get_capture_type () + + + + gboolean @@ -447,7 +455,8 @@ Read / Write -gboolean + +gchar * capture Read / Write @@ -1899,12 +1908,12 @@

    -

    webkit_dom_html_input_element_get_capture ()

    -
    gboolean
    -webkit_dom_html_input_element_get_capture
    +

    webkit_dom_html_input_element_get_capture_type ()

    +
    gchar *
    +webkit_dom_html_input_element_get_capture_type
                                    (WebKitDOMHTMLInputElement *self);
    -

    Parameters

    +

    Parameters

    @@ -1919,9 +1928,18 @@
    -

    Returns

    -

    A gboolean

    +

    Returns

    +

    A gchar

    +

    Since: 2.14

    +
    +
    +
    +

    webkit_dom_html_input_element_get_capture ()

    +
    gboolean
    +webkit_dom_html_input_element_get_capture
    +                               (WebKitDOMHTMLInputElement *self);
    +

    webkit_dom_html_input_element_get_capture is deprecated and should not be used in newly-written code.

    @@ -1991,10 +2009,10 @@

    The “capture” property

    -
      “capture”                  gboolean
    -

    read-write gboolean HTMLInputElement:capture.

    +
      “capture”                  gchar *
    +

    read-write gchar* HTMLInputElement:capture.

    Flags: Read / Write

    -

    Default value: FALSE

    +

    Default value: ""


    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLLinkElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLLinkElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLLinkElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLLinkElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -209,10 +209,22 @@ gchar * +as +Read / Write + + + +gchar * charset Read / Write + +gchar * +cross-origin +Read / Write + + gboolean disabled Read / Write @@ -849,12 +861,28 @@

    Property Details

    +

    The “as” property

    +
      “as”                       gchar *
    +

    read-write gchar* HTMLLinkElement:as.

    +

    Flags: Read / Write

    +

    Default value: ""

    +
    +
    +

    The “charset” property

      “charset”                  gchar *

    read-write gchar* HTMLLinkElement:charset.

    Flags: Read / Write

    Default value: ""

    +
    +
    +

    The “cross-origin” property

    +
      “cross-origin”             gchar *
    +

    read-write gchar* HTMLLinkElement:cross-origin.

    +

    Flags: Read / Write

    +

    Default value: ""

    +

    The “disabled” property

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLMarqueeElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLMarqueeElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLMarqueeElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLMarqueeElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -105,12 +105,12 @@ Read / Write -glong +gulong scroll-amount Read / Write -glong +gulong scroll-delay Read / Write @@ -267,18 +267,16 @@

    The “scroll-amount” property

    -
      “scroll-amount”            glong
    -

    read-write glong HTMLMarqueeElement:scroll-amount.

    +
      “scroll-amount”            gulong
    +

    read-write gulong HTMLMarqueeElement:scroll-amount.

    Flags: Read / Write

    -

    Default value: 0


    The “scroll-delay” property

    -
      “scroll-delay”             glong
    -

    read-write glong HTMLMarqueeElement:scroll-delay.

    +
      “scroll-delay”             gulong
    +

    read-write gulong HTMLMarqueeElement:scroll-delay.

    Flags: Read / Write

    -

    Default value: 0


    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLStyleElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLStyleElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLStyleElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLStyleElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -123,6 +123,12 @@ +gchar * +nonce +Read / Write + + + WebKitDOMStyleSheet * sheet Read @@ -389,6 +395,14 @@

    Flags: Read / Write

    Default value: ""

    +
    +
    +

    The “nonce” property

    +
      “nonce”                    gchar *
    +

    read-write gchar* HTMLStyleElement:nonce.

    +

    Flags: Read / Write

    +

    Default value: ""

    +

    The “sheet” property

    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLTableCellElement.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLTableCellElement.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLTableCellElement.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMHTMLTableCellElement.html 2016-11-03 07:31:44.000000000 +0000 @@ -148,10 +148,10 @@ -gchar * +glong -webkit_dom_html_table_cell_element_get_headers () +webkit_dom_html_table_cell_element_get_row_span () @@ -159,7 +159,7 @@ void -webkit_dom_html_table_cell_element_set_headers () +webkit_dom_html_table_cell_element_set_row_span () @@ -167,7 +167,7 @@ gchar * -webkit_dom_html_table_cell_element_get_height () +webkit_dom_html_table_cell_element_get_headers () @@ -175,15 +175,15 @@ void -webkit_dom_html_table_cell_element_set_height () +webkit_dom_html_table_cell_element_set_headers () -gboolean +gchar * -webkit_dom_html_table_cell_element_get_no_wrap () +webkit_dom_html_table_cell_element_get_height () @@ -191,15 +191,15 @@ void -webkit_dom_html_table_cell_element_set_no_wrap () +webkit_dom_html_table_cell_element_set_height () -glong +gboolean -webkit_dom_html_table_cell_element_get_row_span () +webkit_dom_html_table_cell_element_get_no_wrap () @@ -207,7 +207,7 @@ void -webkit_dom_html_table_cell_element_set_row_span () +webkit_dom_html_table_cell_element_set_no_wrap () @@ -772,12 +772,12 @@

    -

    webkit_dom_html_table_cell_element_get_headers ()

    -
    gchar *
    -webkit_dom_html_table_cell_element_get_headers
    +

    webkit_dom_html_table_cell_element_get_row_span ()

    +
    glong
    +webkit_dom_html_table_cell_element_get_row_span
                                    (WebKitDOMHTMLTableCellElement *self);
    -

    Parameters

    +

    Parameters

    @@ -792,19 +792,19 @@
    -

    Returns

    -

    A gchar

    +

    Returns

    +

    A glong


    -

    webkit_dom_html_table_cell_element_set_headers ()

    +

    webkit_dom_html_table_cell_element_set_row_span ()

    void
    -webkit_dom_html_table_cell_element_set_headers
    +webkit_dom_html_table_cell_element_set_row_span
                                    (WebKitDOMHTMLTableCellElement *self,
    -                                const gchar *value);
    + glong value);
    -

    Parameters

    +

    Parameters

    @@ -819,7 +819,7 @@ - + @@ -828,12 +828,12 @@
    -

    webkit_dom_html_table_cell_element_get_height ()

    +

    webkit_dom_html_table_cell_element_get_headers ()

    gchar *
    -webkit_dom_html_table_cell_element_get_height
    +webkit_dom_html_table_cell_element_get_headers
                                    (WebKitDOMHTMLTableCellElement *self);
    -

    Parameters

    +

    Parameters

    value

    A gchar

    A glong

     
    @@ -848,19 +848,19 @@
    -

    Returns

    +

    Returns

    A gchar


    -

    webkit_dom_html_table_cell_element_set_height ()

    +

    webkit_dom_html_table_cell_element_set_headers ()

    void
    -webkit_dom_html_table_cell_element_set_height
    +webkit_dom_html_table_cell_element_set_headers
                                    (WebKitDOMHTMLTableCellElement *self,
                                     const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -884,12 +884,12 @@
    -

    webkit_dom_html_table_cell_element_get_no_wrap ()

    -
    gboolean
    -webkit_dom_html_table_cell_element_get_no_wrap
    +

    webkit_dom_html_table_cell_element_get_height ()

    +
    gchar *
    +webkit_dom_html_table_cell_element_get_height
                                    (WebKitDOMHTMLTableCellElement *self);
    -

    Parameters

    +

    Parameters

    @@ -904,19 +904,19 @@
    -

    Returns

    -

    A gboolean

    +

    Returns

    +

    A gchar


    -

    webkit_dom_html_table_cell_element_set_no_wrap ()

    +

    webkit_dom_html_table_cell_element_set_height ()

    void
    -webkit_dom_html_table_cell_element_set_no_wrap
    +webkit_dom_html_table_cell_element_set_height
                                    (WebKitDOMHTMLTableCellElement *self,
    -                                gboolean value);
    + const gchar *value);
    -

    Parameters

    +

    Parameters

    @@ -931,7 +931,7 @@ - + @@ -940,12 +940,12 @@
    -

    webkit_dom_html_table_cell_element_get_row_span ()

    -
    glong
    -webkit_dom_html_table_cell_element_get_row_span
    +

    webkit_dom_html_table_cell_element_get_no_wrap ()

    +
    gboolean
    +webkit_dom_html_table_cell_element_get_no_wrap
                                    (WebKitDOMHTMLTableCellElement *self);
    -

    Parameters

    +

    Parameters

    value

    A gboolean

    A gchar

     
    @@ -960,19 +960,19 @@
    -

    Returns

    -

    A glong

    +

    Returns

    +

    A gboolean


    -

    webkit_dom_html_table_cell_element_set_row_span ()

    +

    webkit_dom_html_table_cell_element_set_no_wrap ()

    void
    -webkit_dom_html_table_cell_element_set_row_span
    +webkit_dom_html_table_cell_element_set_no_wrap
                                    (WebKitDOMHTMLTableCellElement *self,
    -                                glong value);
    + gboolean value);
    -

    Parameters

    +

    Parameters

    @@ -987,7 +987,7 @@ - + diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMNode.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMNode.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMNode.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMNode.html 2016-11-03 07:31:44.000000000 +0000 @@ -87,7 +87,7 @@ WebKitDOMNode * @@ -132,18 +132,18 @@ @@ -255,7 +255,7 @@ gchar * @@ -263,7 +263,7 @@ gchar * @@ -271,15 +271,23 @@ void + + + + @@ -287,7 +295,7 @@ gchar * @@ -295,7 +303,7 @@ gchar * @@ -303,15 +311,15 @@ void @@ -345,21 +353,14 @@ - - - - - - - + + - +WebKitDOMNode * + @@ -405,12 +406,6 @@ - - - - - @@ -421,12 +416,6 @@ - - - - -

    value

    A glong

    A gboolean

     
    -webkit_dom_node_clone_node () +webkit_dom_node_clone_node_with_error ()
    -gboolean +gchar * -webkit_dom_node_is_default_namespace () +webkit_dom_node_lookup_namespace_uri ()
    -gchar * +gboolean -webkit_dom_node_lookup_namespace_uri () +webkit_dom_node_is_default_namespace ()
    -webkit_dom_node_get_namespace_uri () +webkit_dom_node_get_base_uri ()
    -webkit_dom_node_get_prefix () +webkit_dom_node_get_text_content ()
    -webkit_dom_node_set_prefix () +webkit_dom_node_set_text_content ()
    -gchar * +WebKitDOMElement * -webkit_dom_node_get_local_name () +webkit_dom_node_get_parent_element () +
    +WebKitDOMNode * + +webkit_dom_node_clone_node ()
    -webkit_dom_node_get_base_uri () +webkit_dom_node_get_namespace_uri ()
    -webkit_dom_node_get_text_content () +webkit_dom_node_get_prefix ()
    -webkit_dom_node_set_text_content () +webkit_dom_node_set_prefix ()
    -WebKitDOMElement * +gchar * -webkit_dom_node_get_parent_element () +webkit_dom_node_get_local_name ()
    Read
    -WebKitDOMNode *last-childRead
    -gchar *local-namegbooleanis-connected Read
    -gchar *namespace-urilast-child Read
    -gchar *prefixRead / Write
    WebKitDOMNode * previous-sibling Readtext-content Read / Write
    -WebKitDOMNode *tree-rootRead
    @@ -735,12 +724,13 @@

    -

    webkit_dom_node_clone_node ()

    +

    webkit_dom_node_clone_node_with_error ()

    WebKitDOMNode *
    -webkit_dom_node_clone_node (WebKitDOMNode *self,
    -                            gboolean deep);
    +webkit_dom_node_clone_node_with_error (WebKitDOMNode *self, + gboolean deep, + GError **error);
    -

    Parameters

    +

    Parameters

    @@ -758,14 +748,20 @@ + + + + +

    A gboolean

     

    error

    GError

     
    -

    Returns

    +

    Returns

    A WebKitDOMNode.

    [transfer none]

    +

    Since: 2.14


    @@ -928,12 +924,12 @@

    -

    webkit_dom_node_is_default_namespace ()

    -
    gboolean
    -webkit_dom_node_is_default_namespace (WebKitDOMNode *self,
    -                                      const gchar *namespaceURI);
    +

    webkit_dom_node_lookup_namespace_uri ()

    +
    gchar *
    +webkit_dom_node_lookup_namespace_uri (WebKitDOMNode *self,
    +                                      const gchar *prefix);
    -

    Parameters

    +

    Parameters

    @@ -947,7 +943,7 @@ - + @@ -955,18 +951,18 @@
     

    namespaceURI

    prefix

    A gchar

     
    -

    Returns

    -

    A gboolean

    +

    Returns

    +

    A gchar


    -

    webkit_dom_node_lookup_namespace_uri ()

    -
    gchar *
    -webkit_dom_node_lookup_namespace_uri (WebKitDOMNode *self,
    -                                      const gchar *prefix);
    +

    webkit_dom_node_is_default_namespace ()

    +
    gboolean
    +webkit_dom_node_is_default_namespace (WebKitDOMNode *self,
    +                                      const gchar *namespaceURI);
    -

    Parameters

    +

    Parameters

    @@ -980,7 +976,7 @@ - + @@ -988,8 +984,8 @@
     

    prefix

    namespaceURI

    A gchar

     
    -

    Returns

    -

    A gchar

    +

    Returns

    +

    A gboolean


    @@ -1353,116 +1349,6 @@

    -

    webkit_dom_node_get_namespace_uri ()

    -
    gchar *
    -webkit_dom_node_get_namespace_uri (WebKitDOMNode *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMNode

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -
    -

    webkit_dom_node_get_prefix ()

    -
    gchar *
    -webkit_dom_node_get_prefix (WebKitDOMNode *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMNode

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -
    -

    webkit_dom_node_set_prefix ()

    -
    void
    -webkit_dom_node_set_prefix (WebKitDOMNode *self,
    -                            const gchar *value,
    -                            GError **error);
    -
    -

    Parameters

    -
    ----- - - - - - - - - - - - - - - - - - -

    self

    A WebKitDOMNode

     

    value

    A gchar

     

    error

    GError

     
    -
    -
    -
    -
    -

    webkit_dom_node_get_local_name ()

    -
    gchar *
    -webkit_dom_node_get_local_name (WebKitDOMNode *self);
    -
    -

    Parameters

    -
    ----- - - - - - -

    self

    A WebKitDOMNode

     
    -
    -
    -

    Returns

    -

    A gchar

    -
    -
    -
    -

    webkit_dom_node_get_base_uri ()

    gchar *
     webkit_dom_node_get_base_uri (WebKitDOMNode *self);
    @@ -1572,6 +1458,45 @@

    [transfer none]

    +
    +
    +

    webkit_dom_node_clone_node ()

    +
    WebKitDOMNode *
    +webkit_dom_node_clone_node (WebKitDOMNode *self,
    +                            gboolean deep,
    +                            GError **error);
    +

    webkit_dom_node_clone_node is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_node_get_namespace_uri ()

    +
    gchar *
    +webkit_dom_node_get_namespace_uri (WebKitDOMNode *self);
    +

    webkit_dom_node_get_namespace_uri is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_node_get_prefix ()

    +
    gchar *
    +webkit_dom_node_get_prefix (WebKitDOMNode *self);
    +

    webkit_dom_node_get_prefix is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_node_set_prefix ()

    +
    void
    +webkit_dom_node_set_prefix (WebKitDOMNode *self,
    +                            const gchar *value,
    +                            GError **error);
    +

    webkit_dom_node_set_prefix is deprecated and should not be used in newly-written code.

    +
    +
    +
    +

    webkit_dom_node_get_local_name ()

    +
    gchar *
    +webkit_dom_node_get_local_name (WebKitDOMNode *self);
    +

    webkit_dom_node_get_local_name is deprecated and should not be used in newly-written code.

    +

    Types and Values

    @@ -1707,26 +1632,18 @@

    -

    The “last-child” property

    -
      “last-child”               WebKitDOMNode *
    -

    read-only WebKitDOMNode* Node:last-child.

    +

    The “is-connected” property

    +
      “is-connected”             gboolean
    +

    read-only gboolean Node:is-connected.

    Flags: Read

    +

    Default value: FALSE


    -

    The “local-name” property

    -
      “local-name”               gchar *
    -

    read-only gchar* Node:local-name.

    -

    Flags: Read

    -

    Default value: ""

    -
    -
    -
    -

    The “namespace-uri” property

    -
      “namespace-uri”            gchar *
    -

    read-only gchar* Node:namespace-uri.

    +

    The “last-child” property

    +
      “last-child”               WebKitDOMNode *
    +

    read-only WebKitDOMNode* Node:last-child.

    Flags: Read

    -

    Default value: ""


    @@ -1782,14 +1699,6 @@

    -

    The “prefix” property

    -
      “prefix”                   gchar *
    -

    read-write gchar* Node:prefix.

    -

    Flags: Read / Write

    -

    Default value: ""

    -
    -
    -

    The “previous-sibling” property

      “previous-sibling”         WebKitDOMNode *

    read-only WebKitDOMNode* Node:previous-sibling.

    @@ -1803,13 +1712,6 @@

    Flags: Read / Write

    Default value: ""

    -
    -
    -

    The “tree-root” property

    -
      “tree-root”                WebKitDOMNode *
    -

    read-only WebKitDOMNode* Node:tree-root.

    -

    Flags: Read

    -

    -

    webkit_dom_range_compare_point ()

    -
    gshort
    -webkit_dom_range_compare_point (WebKitDOMRange *self,
    -                                WebKitDOMNode *refNode,
    -                                glong offset,
    -                                GError **error);
    +

    webkit_dom_range_intersects_node ()

    +
    gboolean
    +webkit_dom_range_intersects_node (WebKitDOMRange *self,
    +                                  WebKitDOMNode *refNode,
    +                                  GError **error);
    -

    Parameters

    +

    Parameters

    @@ -1137,11 +1136,6 @@ - - - - - @@ -1150,19 +1144,20 @@
     

    offset

    A glong

     

    error

    GError

     
    -

    Returns

    -

    A gshort

    +

    Returns

    +

    A gboolean


    -

    webkit_dom_range_intersects_node ()

    -
    gboolean
    -webkit_dom_range_intersects_node (WebKitDOMRange *self,
    -                                  WebKitDOMNode *refNode,
    -                                  GError **error);
    +

    webkit_dom_range_compare_point ()

    +
    gshort
    +webkit_dom_range_compare_point (WebKitDOMRange *self,
    +                                WebKitDOMNode *refNode,
    +                                glong offset,
    +                                GError **error);
    -

    Parameters

    +

    Parameters

    @@ -1181,6 +1176,11 @@ + + + + + @@ -1189,8 +1189,8 @@
     

    offset

    A glong

     

    error

    GError

     
    -

    Returns

    -

    A gboolean

    +

    Returns

    +

    A gshort


    diff -Nru webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMText.html webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMText.html --- webkit2gtk-2.12.3/Documentation/webkitdomgtk-4.0/html/WebKitDOMText.html 2016-05-24 08:27:40.000000000 +0000 +++ webkit2gtk-2.14.2/Documentation/webkitdomgtk-4.0/html/WebKitDOMText.html 2016-11-03 07:31:44.000000000 +0000 @@ -52,18 +52,18 @@ -WebKitDOMText * +gchar * -webkit_dom_text_replace_whole_text () +webkit_dom_text_get_whole_text () -gchar * +WebKitDOMText * -webkit_dom_text_get_whole_text () +webkit_dom_text_replace_whole_text () @@ -160,46 +160,6 @@
    -

    webkit_dom_text_replace_whole_text ()

    -
    WebKitDOMText *
    -webkit_dom_text_replace_whole_text (WebKitDOMText *self,
    -                                    const gchar *content,
    -                                    GError **error);
    -
    -

    Parameters

    -
    ----- - - - - - - - - - - - - - - - - - -

    self

    A WebKitDOMText

     

    content

    A gchar

     

    error

    GError

     
    -
    -
    -

    Returns

    -

    A WebKitDOMText.

    -

    [transfer none]

    -
    -
    -
    -

    webkit_dom_text_get_whole_text ()

    gchar *
     webkit_dom_text_get_whole_text (WebKitDOMText *self);
    @@ -223,6 +183,15 @@

    A gchar

    +
    +
    +

    webkit_dom_text_replace_whole_text ()

    +
    WebKitDOMText *
    +webkit_dom_text_replace_whole_text (WebKitDOMText *self,
    +                                    const gchar *content,
    +                                    GError **error);
    +

    webkit_dom_text_replace_whole_text is deprecated and should not be used in newly-written code.

    +

    Types and Values

    diff -Nru webkit2gtk-2.12.3/NEWS webkit2gtk-2.14.2/NEWS --- webkit2gtk-2.12.3/NEWS 2016-05-24 08:19:12.000000000 +0000 +++ webkit2gtk-2.14.2/NEWS 2016-11-03 07:10:51.000000000 +0000 @@ -1,104 +1,138 @@ ================== -WebKitGTK+ 2.12.3 +WebKitGTK+ 2.14.2 ================== -What's new in WebKitGTK+ 2.12.3? +What's new in WebKitGTK+ 2.14.2? - - Improved the detection of supported MIME types supported by the media player. - - Fix web process crash when playing adaptive streaming media. - - Change the volume while thumb slider is dragged, not only when released. - - Fix leaked thread in network process. + - Expose WebKitDOMHTMLInputElement APIs for form autofill in unstable DOM API. + - Properly update WebKitWebView and WebKitWebPage URI properties when request is modified by + WebKitWebPage:send-request signal. + - Restore user agent quirk for Yahoo. + - Dot not leak the default WebKitWebsiteDataManager in WebKitWebContext. + - Use eglGetPlatformDisplay when available instead of eglGetDisplay. + - Avoid strstr() when checking (E)GL extensions. - Fix several crashes and rendering issues. + - Fix the build with ENABLE_OPENGL=OFF and allow to build on Wayland without OpenGL again. - Translation updates: Hungarian. - - Security fixes: CVE-2016-1857, CVE-2016-1856. ================== -WebKitGTK+ 2.12.2 +WebKitGTK+ 2.14.1 ================== -What's new in WebKitGTK+ 2.12.2? +What's new in WebKitGTK+ 2.14.1? - - Fix rendering of scrollbars with GTK themes using stepper buttons. - - Fix compatibility issue with 2.12.1 regarding local storage access from file URLs. - - Make menu list buttons use the text color from the theme. - - Do not show resize grip in non-resizable text fields. - - Fix accessibility events causing Orca to echo key presses instead of speaking the - inserted characters in password fields. - - Fix an off by one error in hyphenation. + - MiniBrowser and jsc binaries are now installed in pkglibexecdir instead of bindir. + - Improve performance when resizing a window with multiple web views in X11. + - Check whether GDK can use GL before using gdk_cairo_draw_from_gl() in Wayland. + - Updated default UserAgent string or better compatibility. + - Fix a crash on github.com in IntlDateTimeFormat::resolvedOptions when using the C locale. + - Fix BadDamage X errors when closing the web view in X11. + - Fix UIProcess crash when using Japanese input method. + - Fix build with clang due to missing header includes. + - Fix the build with USE_REDIRECTED_XCOMPOSITE_WINDOW disabled. - Fix several crashes and rendering issues. - - Fix the build with libjpeg v9. - - Translation updates: Bulgarian, Finnish, Greek, Italian, Turkish. + - Translation updates: German. ================== -WebKitGTK+ 2.12.1 +WebKitGTK+ 2.14.0 ================== -What's new in WebKitGTK+ 2.12.1? +What's new in WebKitGTK+ 2.14.0? - - Fix spotify player. - - Improve themed control elements rendering to better match GTK+ widgets. - - Make remote web inspector work again. - - Fix several crashes and rendering issues. - - Fix several memory leaks. - - Fix the build in Linux / PowerPC. - - Fix detection of S390X and PPC64 architectures. - - Fix the build in glibc-based BSD systems - - Translation updates: Brazilian Portuguese. + - Use gdk_cairo_draw_from_gl() when possible in Wayland to render directly using the GPU in the UI process. + - Ensure we don't send an empty referrer header after session restore. + - Fix a web process crash in pages using filter animations. + - Fix main frame scrolling jumps when scrolling acclerated subframes. + - Fix the size of the cairo surface created in the UI process on Wayland. + - Fix memory leak in JavaScriptCore. + - Fix the build when '.' is not in @INC by default in perl. + - Translation updates: Ukrainian. ================== -WebKitGTK+ 2.12.0 +WebKitGTK+ 2.13.92 ================== -What's new in WebKitGTK+ 2.12.0? +What's new in WebKitGTK+ 2.13.92? - - Enable GSS-Negotiate support when available in libsoup. - - Fix overlay scrollbar indicator position. - - Fix smooth scrolling behavior that was not fixed in all cases in 2.11.92. - - Fix the build with newer versions of GCC and clang. + - Add clipboard support in Wayland. + - Improve rendering of scrollbars with themes setting a minimum width for the scrollbar CSS gadget. + - Fix another WebProcess crash when the last WebView is destroyed. + - Fix the build with GCC 6. ================== -WebKitGTK+ 2.11.92 +WebKitGTK+ 2.13.91 ================== -What's new in WebKitGTK+ 2.11.92? +What's new in WebKitGTK+ 2.13.91? - - Revert the patch to limit the number of tiles according to the visible area introduced in 2.11.90, - because it caused rendering issues in several popular websites. - - Fix scrollbars rendering again with GTK+ >= 3.19.11. - - Fix rendering of slider input elements. - - Fix rendering artifacts when using a web view background color. - - Make webkit_web_context_clear_cache() work again. - - Fix smooth scrolling behavior that was changed by mistake. - - Don't force ENABLE_INTROSPECTION=OFF on Mac. - - Install WebProcess and NetworkProcess on OSX when not building the Mac port. + - Improve the performance when resizing the WebView with the threaded compositor. + - Do not try to use GL_PACK_ROW_LENGTH when compiling with GLES2, since it's not available. + - Use a different plugins cache file in Wayland and X11. + - Fix UI process crash visiting sites protected with HTTP auth when using GTK+ < 3.14. + - Fix a WebProcess crash when the last WebView is destroyed. + - Fix build configure without Wayland support. + - Fix the build when compiling with Clang. + - Fix several crashes and rendering issues. + - Translation updates: Polish. ================== -WebKitGTK+ 2.11.91 +WebKitGTK+ 2.13.90 ================== -What's new in WebKitGTK+ 2.11.91? +What's new in WebKitGTK+ 2.13.90? - - Do not show stale contents after session restore. - - Fix flickering and rendering artifacts when entering accelerated compositing mode - before the web view is realized. - - Fix several rendering issues and crashes. - - Fix build with FTL enabled in FreeBSD. - - Translation updates: Polish. + - Add initial implementation of accelerating compositing support under Wayland. + - Fix performance with the modesetting intel driver and DRI3 enabled. + - Improved performance when resizing the web view on X11. + - Fix several crashes and rendering issues. + - Translation updates: German, Polish. -================== -WebKitGTK+ 2.11.90 -================== +================= +WebKitGTK+ 2.13.4 +================= + +What's new in WebKitGTK+ 2.13.4? + + - Switched to use the threaded compositor. Accelerated compositing mode is now always enabled by default + and happens in a separate thread in the web process. + - Make web view background colors work in accelerated compositing mode. + - Fix several crashes and rendering issues. + +================= +WebKitGTK+ 2.13.3 +================= + +What's new in WebKitGTK+ 2.13.3? + + - Fix Web Process deadlocks when loading HLS videos. + - Make videos work when painted into a canvas when accelerated compositing is enabled. + - Fix flickering with animated GIFs. + - Fix a Web Process crash when video repaint is requested with GStreamer GL enabled. + - Reduce the amount of file descriptors that the Web Process keeps open. + - Make memory pressure handler work when cgroups are not available. + - Fix several crashes and rendering issues. + +================= +WebKitGTK+ 2.13.2 +================= -What's new in WebKitGTK+ 2.11.90? +What's new in WebKitGTK+ 2.13.2? - - Switch to use overlay scrollbars like all other GTK+ widgets and ensure the behavior - is consistent with GTK+ too. - - Limit the number of tiles according to the visible area. This was causing a huge memory - consumption with some websites. - - Fix toggle buttons rendering with GTK+ 3.19. - - Fix HTTP authentication dialog rendering when accelerated compositing mode is enabled. - - Use G_TYPE_ERROR instead of G_TYPE_POINTER for GError parameters of signals. - - Fix several memory leaks. + - Properly redraw the web view when reparented in force compositing mode. + - Flip the volume control layout in media controls on RTL. + - Add support for video orientation to the GStreamer media backend. + - Fix several crashes and rendering issues. + +================= +WebKitGTK+ 2.13.1 +================= + +What's new in WebKitGTK+ 2.13.1? + + - CSS Grid Layout has been unprefixed and can be enabled as an experimental feature at runtime. + - The HTTP disk cache implements speculative resources revalidation. + - Add a new WebKitSetting to allow universal access from file URLs. + - Fix several crashes and rendering issues. ================= WebKitGTK+ 2.11.5 diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Algorithm.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Algorithm.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Algorithm.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Algorithm.h 2016-09-16 09:56:48.000000000 +0000 @@ -101,6 +101,11 @@ return (numerator + denominator - 1) / denominator; } +template inline T roundUpToMultipleOfNonPowerOfTwo(size_t divisor, T x) +{ + return divideRoundingUp(x, divisor) * divisor; +} + // Version of sizeof that returns 0 for empty classes. template inline constexpr size_t sizeOf() diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Allocator.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Allocator.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Allocator.cpp 2016-04-25 15:52:04.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Allocator.cpp 2016-10-27 10:20:32.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,12 +64,27 @@ void* Allocator::allocate(size_t alignment, size_t size) { + bool crashOnFailure = true; + return allocateImpl(alignment, size, crashOnFailure); +} + +void* Allocator::tryAllocate(size_t alignment, size_t size) +{ + bool crashOnFailure = false; + return allocateImpl(alignment, size, crashOnFailure); +} + +void* Allocator::allocateImpl(size_t alignment, size_t size, bool crashOnFailure) +{ BASSERT(isPowerOfTwo(alignment)); if (!m_isBmallocEnabled) { void* result = nullptr; - if (posix_memalign(&result, alignment, size)) + if (posix_memalign(&result, alignment, size)) { + if (crashOnFailure) + BCRASH(); return nullptr; + } return result; } @@ -80,13 +95,20 @@ return allocate(roundUpToMultipleOf(alignment, size)); std::lock_guard lock(PerProcess::mutex()); - return PerProcess::getFastCase()->allocateLarge(lock, alignment, size); + Heap* heap = PerProcess::getFastCase(); + if (crashOnFailure) + return heap->allocateLarge(lock, alignment, size); + return heap->tryAllocateLarge(lock, alignment, size); } void* Allocator::reallocate(void* object, size_t newSize) { - if (!m_isBmallocEnabled) - return realloc(object, newSize); + if (!m_isBmallocEnabled) { + void* result = realloc(object, newSize); + if (!result) + BCRASH(); + return result; + } size_t oldSize = 0; switch (objectType(object)) { @@ -171,8 +193,12 @@ void* Allocator::allocateSlowCase(size_t size) { - if (!m_isBmallocEnabled) - return malloc(size); + if (!m_isBmallocEnabled) { + void* result = malloc(size); + if (!result) + BCRASH(); + return result; + } if (size <= maskSizeClassMax) { size_t sizeClass = bmalloc::maskSizeClass(size); diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Allocator.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Allocator.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Allocator.h 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Allocator.h 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,12 +43,15 @@ void* tryAllocate(size_t); void* allocate(size_t); + void* tryAllocate(size_t alignment, size_t); void* allocate(size_t alignment, size_t); void* reallocate(void*, size_t); void scavenge(); private: + void* allocateImpl(size_t alignment, size_t, bool crashOnFailure); + bool allocateFastCase(size_t, void*&); void* allocateSlowCase(size_t); diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/AsyncTask.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/AsyncTask.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/AsyncTask.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/AsyncTask.h 2016-08-30 12:24:51.000000000 +0000 @@ -44,9 +44,7 @@ void run(); private: - enum State { Exited, ExitRequested, Sleeping, Running, RunRequested }; - - static const constexpr std::chrono::seconds exitDelay = std::chrono::seconds(1); + enum State { Sleeping, Running, RunRequested }; void runSlowCase(); @@ -64,13 +62,11 @@ Function m_function; }; -template const constexpr std::chrono::seconds AsyncTask::exitDelay; - template AsyncTask::AsyncTask(Object& object, const Function& function) - : m_state(Exited) + : m_state(Running) , m_condition() - , m_thread() + , m_thread(std::thread(&AsyncTask::threadEntryPoint, this)) , m_object(object) , m_function(function) { @@ -79,19 +75,9 @@ template AsyncTask::~AsyncTask() { - // Prevent our thread from entering the running or sleeping state. - State oldState = m_state.exchange(ExitRequested); - - // Wake our thread if it was already in the sleeping state. - if (oldState == Sleeping) { - std::lock_guard lock(m_conditionMutex); - m_condition.notify_all(); - } - - // Wait for our thread to exit because it uses our data members (and it may - // use m_object's data members). - if (m_thread.joinable()) - m_thread.join(); + // We'd like to mark our destructor deleted but C++ won't allow it because + // we are an automatic member of Heap. + RELEASE_BASSERT(0); } template @@ -109,16 +95,9 @@ if (oldState == RunRequested || oldState == Running) return; - if (oldState == Sleeping) { - std::lock_guard lock(m_conditionMutex); - m_condition.notify_all(); - return; - } - - BASSERT(oldState == Exited); - if (m_thread.joinable()) - m_thread.detach(); - m_thread = std::thread(&AsyncTask::threadEntryPoint, this); + BASSERT(oldState == Sleeping); + std::lock_guard lock(m_conditionMutex); + m_condition.notify_all(); } template @@ -130,10 +109,9 @@ template void AsyncTask::threadRunLoop() { - // This loop ratchets downward from most active to least active state, and - // finally exits. While we ratchet downward, any other thread may reset our - // state to RunRequested or ExitRequested. - + // This loop ratchets downward from most active to least active state. While + // we ratchet downward, any other thread may reset our state. + // We require any state change while we are sleeping to signal to our // condition variable and wake us up. @@ -145,16 +123,8 @@ expectedState = Running; if (m_state.compare_exchange_weak(expectedState, Sleeping)) { std::unique_lock lock(m_conditionMutex); - m_condition.wait_for(lock, exitDelay, [=]() { return this->m_state != Sleeping; }); + m_condition.wait(lock, [&]() { return m_state != Sleeping; }); } - - expectedState = Sleeping; - if (m_state.compare_exchange_weak(expectedState, Exited)) - return; - - expectedState = ExitRequested; - if (m_state.compare_exchange_weak(expectedState, Exited)) - return; } } diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/BAssert.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/BAssert.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/BAssert.h 2016-04-13 09:31:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/BAssert.h 2016-08-30 12:24:51.000000000 +0000 @@ -20,13 +20,17 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BAssert_h -#define BAssert_h +#pragma once #include "BPlatform.h" +#include "Logging.h" + +#if BUSE(OS_LOG) +#include +#endif #if defined(NDEBUG) && BOS(DARWIN) @@ -63,10 +67,25 @@ #define RELEASE_BASSERT(x) BASSERT_IMPL(x) -// FIXME: Implement logging: -#define RELEASE_BASSERT_WITH_MESSAGE(x, f, ...) BASSERT_IMPL(x) +#if BUSE(OS_LOG) +#define BMALLOC_LOGGING_PREFIX "bmalloc: " +#define BLOG_ERROR(format, ...) os_log_error(OS_LOG_DEFAULT, BMALLOC_LOGGING_PREFIX format, __VA_ARGS__) +#else +#define BLOG_ERROR(format, ...) bmalloc::reportAssertionFailureWithMessage(__FILE__, __LINE__, __PRETTY_FUNCTION__, format, __VA_ARGS__) +#endif -#define UNUSED(x) (void)x +#if defined(NDEBUG) +#define RELEASE_BASSERT_WITH_MESSAGE(x, format, ...) BASSERT_IMPL(x) +#else +#define RELEASE_BASSERT_WITH_MESSAGE(x, format, ...) do { \ + if (!(x)) { \ + BLOG_ERROR("ASSERTION FAILED: " #x " :: " format, ##__VA_ARGS__); \ + BCRASH(); \ + } \ +} while (0); +#endif + +#define UNUSED(x) ((void)x) // ===== Release build ===== @@ -85,8 +104,6 @@ #define BASSERT(x) BASSERT_IMPL(x) -#define IF_DEBUG(x) x +#define IF_DEBUG(x) (x) #endif // !defined(NDEBUG) - -#endif // BAssert_h diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/bmalloc.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/bmalloc.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/bmalloc.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/bmalloc.h 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,6 +43,12 @@ return Cache::allocate(size); } +// Returns null on failure. +inline void* tryMemalign(size_t alignment, size_t size) +{ + return Cache::tryAllocate(alignment, size); +} + // Crashes on failure. inline void* memalign(size_t alignment, size_t size) { @@ -73,5 +79,11 @@ PerProcess::get()->scavenge(lock, std::chrono::milliseconds(0)); } +inline bool isEnabled() +{ + std::unique_lock lock(PerProcess::mutex()); + return PerProcess::getFastCase()->environment().isBmallocEnabled(); +} + } // namespace api } // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/BPlatform.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/BPlatform.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/BPlatform.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/BPlatform.h 2016-08-30 12:24:51.000000000 +0000 @@ -23,22 +23,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BPlatform_h -#define BPlatform_h +#pragma once #ifdef __APPLE__ +#include +#include #include #endif #define BPLATFORM(PLATFORM) (defined BPLATFORM_##PLATFORM && BPLATFORM_##PLATFORM) #define BOS(OS) (defined BOS_##OS && BOS_##OS) -#if ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) \ - || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \ - || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)) -#define BPLATFORM_IOS 1 -#endif - #ifdef __APPLE__ #define BOS_DARWIN 1 #endif @@ -47,6 +42,19 @@ #define BOS_UNIX 1 #endif +#if BOS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) \ + || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \ + || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)) +#define BPLATFORM_IOS 1 +#elif BOS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC +#define BPLATFORM_MAC 1 +#endif + +/* ==== Policy decision macros: these define policy choices for a particular port. ==== */ + +/* BUSE() - use a particular third-party library or optional OS service */ +#define BUSE(FEATURE) (defined BUSE_##FEATURE && BUSE_##FEATURE) + /* ==== Platform adaptation macros: these describe properties of the target environment. ==== */ /* BCPU() - the target CPU architecture */ @@ -181,4 +189,8 @@ #endif /* ARM */ -#endif // BPlatform_h +#define BATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments))) + +#if (BPLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (BPLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) +#define BUSE_OS_LOG 1 +#endif diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Cache.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Cache.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Cache.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Cache.h 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,6 +41,7 @@ static void* tryAllocate(size_t); static void* allocate(size_t); + static void* tryAllocate(size_t alignment, size_t); static void* allocate(size_t alignment, size_t); static void deallocate(void*); static void* reallocate(void*, size_t); @@ -79,6 +80,14 @@ return cache->allocator().allocate(size); } +inline void* Cache::tryAllocate(size_t alignment, size_t size) +{ + Cache* cache = PerThread::getFastCase(); + if (!cache) + return allocateSlowCaseNullCache(alignment, size); + return cache->allocator().tryAllocate(alignment, size); +} + inline void* Cache::allocate(size_t alignment, size_t size) { Cache* cache = PerThread::getFastCase(); diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Chunk.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Chunk.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Chunk.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Chunk.h 2016-10-14 09:38:09.000000000 +0000 @@ -43,13 +43,13 @@ size_t offset(void*); - char* object(size_t offset); + char* address(size_t offset); SmallPage* page(size_t offset); SmallLine* line(size_t offset); char* bytes() { return reinterpret_cast(this); } - SmallLine* lines() { return m_lines.begin(); } - SmallPage* pages() { return m_pages.begin(); } + SmallLine* lines() { return &m_lines[0]; } + SmallPage* pages() { return &m_pages[0]; } private: std::array m_lines; @@ -68,19 +68,19 @@ { } -inline Chunk* Chunk::get(void* object) +inline Chunk* Chunk::get(void* address) { - return static_cast(mask(object, chunkMask)); + return static_cast(mask(address, chunkMask)); } -inline size_t Chunk::offset(void* object) +inline size_t Chunk::offset(void* address) { - BASSERT(object >= this); - BASSERT(object < bytes() + chunkSize); - return static_cast(object) - bytes(); + BASSERT(address >= this); + BASSERT(address < bytes() + chunkSize); + return static_cast(address) - bytes(); } -inline char* Chunk::object(size_t offset) +inline char* Chunk::address(size_t offset) { return bytes() + offset; } @@ -133,9 +133,9 @@ BASSERT(chunk == Chunk::get(object)); } -inline char* Object::begin() +inline char* Object::address() { - return m_chunk->object(m_offset); + return m_chunk->address(m_offset); } inline SmallLine* Object::line() diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/darwin/BSoftLinking.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/darwin/BSoftLinking.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/darwin/BSoftLinking.h 2016-04-13 09:31:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/darwin/BSoftLinking.h 2016-08-30 16:10:50.000000000 +0000 @@ -29,13 +29,13 @@ #include #include -#define BSOFT_LINK_FRAMEWORK(framework) \ +#define BSOFT_LINK_PRIVATE_FRAMEWORK(framework) \ static void* framework##Library() \ { \ static void* frameworkLibrary; \ static std::once_flag once; \ std::call_once(once, [] { \ - frameworkLibrary = dlopen("/System/Library/Frameworks/" #framework ".framework/" #framework, RTLD_NOW); \ + frameworkLibrary = dlopen("/System/Library/PrivateFrameworks/" #framework ".framework/" #framework, RTLD_NOW); \ RELEASE_BASSERT_WITH_MESSAGE(frameworkLibrary, "%s", dlerror()); \ }); \ return frameworkLibrary; \ diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Environment.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Environment.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Environment.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Environment.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -75,23 +75,31 @@ return true; } -static bool isASanEnabled() +static bool isSanitizerEnabled() { #if BOS(DARWIN) + static const char sanitizerPrefix[] = "/libclang_rt."; + static const char asanName[] = "asan_"; + static const char tsanName[] = "tsan_"; uint32_t imageCount = _dyld_image_count(); for (uint32_t i = 0; i < imageCount; ++i) { const char* imageName = _dyld_get_image_name(i); if (!imageName) continue; - if (strstr(imageName, "/libclang_rt.asan_")) - return true; + if (const char* s = strstr(imageName, sanitizerPrefix)) { + const char* sanitizerName = s + sizeof(sanitizerPrefix) - 1; + if (!strncmp(sanitizerName, asanName, sizeof(asanName) - 1)) + return true; + if (!strncmp(sanitizerName, tsanName, sizeof(tsanName) - 1)) + return true; + } } return false; #elif BOS(UNIX) void* handle = dlopen(nullptr, RTLD_NOW); if (!handle) return false; - bool result = !!dlsym(handle, "__asan_poison_memory_region"); + bool result = !!dlsym(handle, "__asan_init") || !!dlsym(handle, "__tsan_init"); dlclose(handle); return result; #else @@ -110,7 +118,7 @@ return false; if (isLibgmallocEnabled()) return false; - if (isASanEnabled()) + if (isSanitizerEnabled()) return false; return true; } diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/FixedVector.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/FixedVector.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/FixedVector.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/FixedVector.h 2016-10-14 09:38:09.000000000 +0000 @@ -44,7 +44,7 @@ FixedVector(); - const T* begin() const { return m_buffer.begin(); } + const T* begin() const { return &m_buffer[0]; } const T* end() const { return begin() + size(); } size_t size() const { return m_size; } diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Heap.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Heap.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Heap.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Heap.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -131,13 +131,16 @@ void Heap::scavengeLargeObjects(std::unique_lock& lock, std::chrono::milliseconds sleepDuration) { - while (XLargeRange range = m_largeFree.removePhysical()) { + auto& ranges = m_largeFree.ranges(); + for (size_t i = ranges.size(); i-- > 0; i = std::min(i, ranges.size())) { + auto range = ranges.pop(i); + lock.unlock(); vmDeallocatePhysicalPagesSloppy(range.begin(), range.size()); lock.lock(); - + range.setPhysicalSize(0); - m_largeFree.add(range); + ranges.push(range); waitUntilFalse(lock, sleepDuration, m_isAllocatingPages); } @@ -265,7 +268,7 @@ }; auto allocateSmallBumpRange = [&](Object& it, Object& end) -> BumpRange { - char* begin = it.begin(); + char* begin = it.address(); unsigned short objectCount = 0; for ( ; it + size <= end; it = it + size) { if (it.line()->refCount(lock)) @@ -302,21 +305,21 @@ } } -XLargeRange Heap::splitAndAllocate(XLargeRange& range, size_t alignment, size_t size) +LargeRange Heap::splitAndAllocate(LargeRange& range, size_t alignment, size_t size) { - XLargeRange prev; - XLargeRange next; + LargeRange prev; + LargeRange next; size_t alignmentMask = alignment - 1; if (test(range.begin(), alignmentMask)) { size_t prefixSize = roundUpToMultipleOf(alignment, range.begin()) - range.begin(); - std::pair pair = range.split(prefixSize); + std::pair pair = range.split(prefixSize); prev = pair.first; range = pair.second; } if (range.size() - size > size / pageSizeWasteFactor) { - std::pair pair = range.split(size); + std::pair pair = range.split(size); range = pair.first; next = pair.second; } @@ -354,7 +357,7 @@ return nullptr; alignment = roundedAlignment; - XLargeRange range = m_largeFree.remove(alignment, size); + LargeRange range = m_largeFree.remove(alignment, size); if (!range) { range = m_vmHeap.tryAllocateLargeChunk(lock, alignment, size); if (!range) @@ -389,7 +392,7 @@ BASSERT(object.size() > newSize); size_t size = m_largeAllocated.remove(object.begin()); - XLargeRange range = XLargeRange(object, size); + LargeRange range = LargeRange(object, size); splitAndAllocate(range, alignment, newSize); m_scavenger.run(); @@ -398,7 +401,7 @@ void Heap::deallocateLarge(std::lock_guard&, void* object) { size_t size = m_largeAllocated.remove(object); - m_largeFree.add(XLargeRange(object, size, size)); + m_largeFree.add(LargeRange(object, size, size)); m_scavenger.run(); } diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Heap.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Heap.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Heap.h 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Heap.h 2016-09-19 12:18:06.000000000 +0000 @@ -26,8 +26,10 @@ #ifndef Heap_h #define Heap_h +#include "AsyncTask.h" #include "BumpRange.h" #include "Environment.h" +#include "LargeMap.h" #include "LineMetadata.h" #include "List.h" #include "Map.h" @@ -37,7 +39,6 @@ #include "SmallPage.h" #include "VMHeap.h" #include "Vector.h" -#include "XLargeMap.h" #include #include @@ -93,7 +94,7 @@ void mergeLargeLeft(EndTag*&, BeginTag*&, Range&, bool& inVMHeap); void mergeLargeRight(EndTag*&, BeginTag*&, Range&, bool& inVMHeap); - XLargeRange splitAndAllocate(XLargeRange&, size_t alignment, size_t); + LargeRange splitAndAllocate(LargeRange&, size_t alignment, size_t); void concurrentScavenge(); void scavengeSmallPages(std::unique_lock&, std::chrono::milliseconds); @@ -107,7 +108,7 @@ std::array, pageClassCount> m_smallPages; Map m_largeAllocated; - XLargeMap m_largeFree; + LargeMap m_largeFree; Map m_objectTypes; diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/LargeMap.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/LargeMap.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/LargeMap.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/LargeMap.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "LargeMap.h" +#include + +namespace bmalloc { + +LargeRange LargeMap::remove(size_t alignment, size_t size) +{ + size_t alignmentMask = alignment - 1; + + LargeRange* candidate = m_free.end(); + for (LargeRange* it = m_free.begin(); it != m_free.end(); ++it) { + if (it->size() < size) + continue; + + if (candidate != m_free.end() && candidate->begin() < it->begin()) + continue; + + if (test(it->begin(), alignmentMask)) { + char* aligned = roundUpToMultipleOf(alignment, it->begin()); + if (aligned < it->begin()) // Check for overflow. + continue; + + char* alignedEnd = aligned + size; + if (alignedEnd < aligned) // Check for overflow. + continue; + + if (alignedEnd > it->end()) + continue; + } + + candidate = it; + } + + if (candidate == m_free.end()) + return LargeRange(); + + return m_free.pop(candidate); +} + +void LargeMap::add(const LargeRange& range) +{ + LargeRange merged = range; + + for (size_t i = 0; i < m_free.size(); ++i) { + if (!canMerge(merged, m_free[i])) + continue; + + merged = merge(merged, m_free.pop(i--)); + } + + m_free.push(merged); +} + +} // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/LargeMap.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/LargeMap.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/LargeMap.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/LargeMap.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LargeMap_h +#define LargeMap_h + +#include "LargeRange.h" +#include "Vector.h" +#include + +namespace bmalloc { + +class LargeMap { +public: + void add(const LargeRange&); + LargeRange remove(size_t alignment, size_t); + Vector& ranges() { return m_free; } + +private: + Vector m_free; +}; + +} // namespace bmalloc + +#endif // LargeMap_h diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/LargeRange.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/LargeRange.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/LargeRange.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/LargeRange.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LargeRange_h +#define LargeRange_h + +#include "BAssert.h" +#include "Range.h" + +namespace bmalloc { + +class LargeRange : public Range { +public: + LargeRange() + : Range() + , m_physicalSize(0) + { + } + + LargeRange(const Range& other, size_t physicalSize) + : Range(other) + , m_physicalSize(physicalSize) + { + } + + LargeRange(void* begin, size_t size, size_t physicalSize) + : Range(begin, size) + , m_physicalSize(physicalSize) + { + } + + size_t physicalSize() const { return m_physicalSize; } + void setPhysicalSize(size_t physicalSize) { m_physicalSize = physicalSize; } + + std::pair split(size_t) const; + + bool operator<(const void* other) const { return begin() < other; } + bool operator<(const LargeRange& other) const { return begin() < other.begin(); } + +private: + size_t m_physicalSize; +}; + +inline bool canMerge(const LargeRange& a, const LargeRange& b) +{ + if (a.end() == b.begin()) + return true; + + if (b.end() == a.begin()) + return true; + + return false; +} + +inline LargeRange merge(const LargeRange& a, const LargeRange& b) +{ + const LargeRange& left = std::min(a, b); + if (left.size() == left.physicalSize()) { + return LargeRange( + left.begin(), + a.size() + b.size(), + a.physicalSize() + b.physicalSize()); + } + + return LargeRange( + left.begin(), + a.size() + b.size(), + left.physicalSize()); +} + +inline std::pair LargeRange::split(size_t size) const +{ + BASSERT(size <= this->size()); + + if (size <= physicalSize()) { + LargeRange left(begin(), size, size); + LargeRange right(left.end(), this->size() - size, physicalSize() - size); + return std::make_pair(left, right); + } + + LargeRange left(begin(), size, physicalSize()); + LargeRange right(left.end(), this->size() - size, 0); + return std::make_pair(left, right); +} + +} // namespace bmalloc + +#endif // LargeRange_h diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Logging.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Logging.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Logging.cpp 2016-04-13 09:31:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Logging.cpp 2016-08-30 16:10:50.000000000 +0000 @@ -26,13 +26,18 @@ #include "Logging.h" #include "BPlatform.h" +#if !BUSE(OS_LOG) +#include +#include +#endif + #if BPLATFORM(IOS) #include #include #include #include "BSoftLinking.h" -BSOFT_LINK_FRAMEWORK(CrashReporterSupport); +BSOFT_LINK_PRIVATE_FRAMEWORK(CrashReporterSupport); BSOFT_LINK_FUNCTION(CrashReporterSupport, SimulateCrash, BOOL, (pid_t pid, mach_exception_data_type_t exceptionCode, id description), (pid, exceptionCode, description)); #endif @@ -46,4 +51,15 @@ #endif } +#if !BUSE(OS_LOG) +void reportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* format, ...) +{ + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "%s(%d) : %s\n", file, line, function); +} +#endif + } // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Logging.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Logging.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Logging.h 2016-04-13 09:31:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Logging.h 2016-08-30 16:10:50.000000000 +0000 @@ -23,13 +23,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Logging_h -#define Logging_h +#pragma once + +#include "BPlatform.h" namespace bmalloc { void logVMFailure(); -} // namespace bmalloc +#if !BUSE(OS_LOG) +void reportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* format, ...) BATTRIBUTE_PRINTF(4, 5); +#endif -#endif // Logging_h +} // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Object.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Object.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Object.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Object.h 2016-09-16 09:56:48.000000000 +0000 @@ -46,12 +46,13 @@ Chunk* chunk() { return m_chunk; } size_t offset() { return m_offset; } - char* begin(); + char* address(); SmallLine* line(); SmallPage* page(); Object operator+(size_t); + Object operator-(size_t); bool operator<=(const Object&); private: @@ -64,6 +65,11 @@ return Object(m_chunk, m_offset + offset); } +inline Object Object::operator-(size_t offset) +{ + return Object(m_chunk, m_offset - offset); +} + inline bool Object::operator<=(const Object& other) { BASSERT(m_chunk == other.m_chunk); diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/ScopeExit.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/ScopeExit.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/ScopeExit.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/ScopeExit.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace bmalloc { + +template +class ScopeExit { +public: + explicit ScopeExit(ExitFunction&& exitFunction) + : m_exitFunction(exitFunction) + { + } + + ~ScopeExit() + { + m_exitFunction(); + } + +private: + ExitFunction m_exitFunction; +}; + +template +ScopeExit makeScopeExit(ExitFunction&& exitFunction) +{ + return ScopeExit(std::forward(exitFunction)); +} + +} // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/StaticMutex.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/StaticMutex.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/StaticMutex.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/StaticMutex.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -23,6 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "ScopeExit.h" #include "StaticMutex.h" #include @@ -30,6 +31,21 @@ void StaticMutex::lockSlowCase() { + // The longest critical section in bmalloc is much shorter than the + // time it takes to make a system call to yield to the OS scheduler. + // So, we try again a lot before we yield. + static const size_t aLot = 256; + + if (!m_isSpinning.test_and_set()) { + auto clear = makeScopeExit([&] { m_isSpinning.clear(); }); + + for (size_t i = 0; i < aLot; ++i) { + if (try_lock()) + return; + } + } + + // Avoid spinning pathologically. while (!try_lock()) std::this_thread::yield(); } diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/StaticMutex.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/StaticMutex.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/StaticMutex.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/StaticMutex.h 2016-09-19 12:18:06.000000000 +0000 @@ -52,6 +52,7 @@ void lockSlowCase(); std::atomic_flag m_flag; + std::atomic_flag m_isSpinning; }; static inline void sleep( @@ -78,6 +79,7 @@ inline void StaticMutex::init() { m_flag.clear(); + m_isSpinning.clear(); } inline bool StaticMutex::try_lock() diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Vector.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Vector.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Vector.h 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Vector.h 2016-08-30 12:24:51.000000000 +0000 @@ -198,6 +198,8 @@ template void Vector::reallocateBuffer(size_t newCapacity) { + RELEASE_BASSERT(newCapacity < std::numeric_limits::max() / sizeof(T)); + size_t vmSize = bmalloc::vmSize(newCapacity * sizeof(T)); T* newBuffer = vmSize ? static_cast(vmAllocate(vmSize)) : nullptr; if (m_buffer) { diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/VMAllocate.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/VMAllocate.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/VMAllocate.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/VMAllocate.h 2016-09-16 09:56:48.000000000 +0000 @@ -137,6 +137,12 @@ munmap(p, vmSize); } +inline void vmRevokePermissions(void* p, size_t vmSize) +{ + vmValidate(p, vmSize); + mprotect(p, vmSize, PROT_NONE); +} + // Allocates vmSize bytes at a specified power-of-two alignment. // Use this function to create maskable memory regions. diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/VMHeap.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/VMHeap.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/VMHeap.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/VMHeap.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -29,55 +29,67 @@ namespace bmalloc { -XLargeRange VMHeap::tryAllocateLargeChunk(std::lock_guard& lock, size_t alignment, size_t size) +LargeRange VMHeap::tryAllocateLargeChunk(std::lock_guard&, size_t alignment, size_t size) { // We allocate VM in aligned multiples to increase the chances that // the OS will provide contiguous ranges that we can merge. size_t roundedAlignment = roundUpToMultipleOf(alignment); if (roundedAlignment < alignment) // Check for overflow - return XLargeRange(); + return LargeRange(); alignment = roundedAlignment; size_t roundedSize = roundUpToMultipleOf(size); if (roundedSize < size) // Check for overflow - return XLargeRange(); + return LargeRange(); size = roundedSize; void* memory = tryVMAllocate(alignment, size); if (!memory) - return XLargeRange(); + return LargeRange(); - Chunk* chunk = new (memory) Chunk(lock); + Chunk* chunk = static_cast(memory); #if BOS(DARWIN) - m_zone.addChunk(chunk); + m_zone.addRange(Range(chunk->bytes(), size)); #endif - return XLargeRange(chunk->bytes(), size, 0); + return LargeRange(chunk->bytes(), size, 0); } void VMHeap::allocateSmallChunk(std::lock_guard& lock, size_t pageClass) { - Chunk* chunk = - new (vmAllocate(chunkSize, chunkSize)) Chunk(lock); - -#if BOS(DARWIN) - m_zone.addChunk(chunk); -#endif - size_t pageSize = bmalloc::pageSize(pageClass); size_t smallPageCount = pageSize / smallPageSize; - // We align to our page size in order to guarantee that we can service - // aligned allocation requests at equal and smaller powers of two. - size_t metadataSize = divideRoundingUp(sizeof(Chunk), pageSize) * pageSize; + void* memory = vmAllocate(chunkSize, chunkSize); + Chunk* chunk = static_cast(memory); + + // We align to our page size in order to honor OS APIs and in order to + // guarantee that we can service aligned allocation requests at equal + // and smaller powers of two. + size_t vmPageSize = roundUpToMultipleOf(bmalloc::vmPageSize(), pageSize); + size_t metadataSize = roundUpToMultipleOfNonPowerOfTwo(vmPageSize, sizeof(Chunk)); Object begin(chunk, metadataSize); Object end(chunk, chunkSize); + // Establish guard pages before writing to Chunk memory to work around + // an edge case in the Darwin VM system (). + vmRevokePermissions(begin.address(), vmPageSize); + vmRevokePermissions(end.address() - vmPageSize, vmPageSize); + + begin = begin + vmPageSize; + end = end - vmPageSize; + BASSERT(begin <= end && end.offset() - begin.offset() >= pageSize); + + new (chunk) Chunk(lock); + +#if BOS(DARWIN) + m_zone.addRange(Range(begin.address(), end.address() - begin.address())); +#endif + for (Object it = begin; it + pageSize <= end; it = it + pageSize) { SmallPage* page = it.page(); - new (page) SmallPage; for (size_t i = 0; i < smallPageCount; ++i) page[i].setSlide(i); diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/VMHeap.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/VMHeap.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/VMHeap.h 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/VMHeap.h 2016-09-19 12:18:06.000000000 +0000 @@ -26,12 +26,11 @@ #ifndef VMHeap_h #define VMHeap_h -#include "AsyncTask.h" #include "Chunk.h" #include "FixedVector.h" +#include "LargeRange.h" #include "Map.h" #include "Vector.h" -#include "XLargeRange.h" #if BOS(DARWIN) #include "Zone.h" #endif @@ -47,7 +46,7 @@ SmallPage* allocateSmallPage(std::lock_guard&, size_t); void deallocateSmallPage(std::unique_lock&, size_t, SmallPage*); - XLargeRange tryAllocateLargeChunk(std::lock_guard&, size_t alignment, size_t); + LargeRange tryAllocateLargeChunk(std::lock_guard&, size_t alignment, size_t); private: void allocateSmallChunk(std::lock_guard&, size_t); diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/XLargeMap.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/XLargeMap.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/XLargeMap.cpp 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/XLargeMap.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "XLargeMap.h" -#include - -namespace bmalloc { - -XLargeRange XLargeMap::remove(size_t alignment, size_t size) -{ - size_t alignmentMask = alignment - 1; - - XLargeRange* candidate = m_free.end(); - for (XLargeRange* it = m_free.begin(); it != m_free.end(); ++it) { - if (it->size() < size) - continue; - - if (candidate != m_free.end() && candidate->begin() < it->begin()) - continue; - - if (test(it->begin(), alignmentMask)) { - char* aligned = roundUpToMultipleOf(alignment, it->begin()); - if (aligned < it->begin()) // Check for overflow. - continue; - - char* alignedEnd = aligned + size; - if (alignedEnd < aligned) // Check for overflow. - continue; - - if (alignedEnd > it->end()) - continue; - } - - candidate = it; - } - - if (candidate == m_free.end()) - return XLargeRange(); - - return m_free.pop(candidate); -} - -void XLargeMap::add(const XLargeRange& range) -{ - XLargeRange merged = range; - - for (size_t i = 0; i < m_free.size(); ++i) { - if (!canMerge(merged, m_free[i])) - continue; - - merged = merge(merged, m_free.pop(i--)); - } - - m_free.push(merged); -} - -XLargeRange XLargeMap::removePhysical() -{ - auto it = std::find_if(m_free.begin(), m_free.end(), [](const XLargeRange& range) { - return range.physicalSize(); - }); - - if (it == m_free.end()) - return XLargeRange(); - - return m_free.pop(it); -} - -} // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/XLargeMap.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/XLargeMap.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/XLargeMap.h 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/XLargeMap.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef XLargeMap_h -#define XLargeMap_h - -#include "Vector.h" -#include "XLargeRange.h" -#include - -namespace bmalloc { - -class XLargeMap { -public: - void add(const XLargeRange&); - XLargeRange remove(size_t alignment, size_t); - XLargeRange removePhysical(); - -private: - Vector m_free; -}; - -} // namespace bmalloc - -#endif // XLargeMap_h diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/XLargeRange.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/XLargeRange.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/XLargeRange.h 2016-04-25 15:48:49.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/XLargeRange.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef XLargeRange_h -#define XLargeRange_h - -namespace bmalloc { - -class XLargeRange : public Range { -public: - XLargeRange() - : Range() - , m_physicalSize(0) - { - } - - XLargeRange(const Range& other, size_t physicalSize) - : Range(other) - , m_physicalSize(physicalSize) - { - } - - XLargeRange(void* begin, size_t size, size_t physicalSize) - : Range(begin, size) - , m_physicalSize(physicalSize) - { - } - - size_t physicalSize() const { return m_physicalSize; } - void setPhysicalSize(size_t physicalSize) { m_physicalSize = physicalSize; } - - std::pair split(size_t) const; - - bool operator<(const void* other) const { return begin() < other; } - bool operator<(const XLargeRange& other) const { return begin() < other.begin(); } - -private: - size_t m_physicalSize; -}; - -inline bool canMerge(const XLargeRange& a, const XLargeRange& b) -{ - if (a.end() == b.begin()) - return true; - - if (b.end() == a.begin()) - return true; - - return false; -} - -inline XLargeRange merge(const XLargeRange& a, const XLargeRange& b) -{ - const XLargeRange& left = std::min(a, b); - if (left.size() == left.physicalSize()) { - return XLargeRange( - left.begin(), - a.size() + b.size(), - a.physicalSize() + b.physicalSize()); - } - - return XLargeRange( - left.begin(), - a.size() + b.size(), - left.physicalSize()); -} - -inline std::pair XLargeRange::split(size_t size) const -{ - BASSERT(size <= this->size()); - - if (size <= physicalSize()) { - XLargeRange left(begin(), size, size); - XLargeRange right(left.end(), this->size() - size, physicalSize() - size); - return std::make_pair(left, right); - } - - XLargeRange left(begin(), size, physicalSize()); - XLargeRange right(left.end(), this->size() - size, 0); - return std::make_pair(left, right); -} - -} // namespace bmalloc - -#endif // XLargeRange_h diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Zone.cpp webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Zone.cpp --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Zone.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Zone.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -88,14 +88,14 @@ static kern_return_t enumerator(task_t task, void* context, unsigned type_mask, vm_address_t zone_address, memory_reader_t reader, vm_range_recorder_t recorder) { Zone remoteZone(task, reader, zone_address); - for (auto* chunk : remoteZone.chunks()) { - vm_range_t range = { reinterpret_cast(chunk), chunkSize }; + for (auto& range : remoteZone.ranges()) { + vm_range_t vmRange = { reinterpret_cast(range.begin()), range.size() }; if ((type_mask & MALLOC_PTR_REGION_RANGE_TYPE)) - (*recorder)(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &range, 1); + (*recorder)(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &vmRange, 1); if ((type_mask & MALLOC_PTR_IN_USE_RANGE_TYPE)) - (*recorder)(task, context, MALLOC_PTR_IN_USE_RANGE_TYPE, &range, 1); + (*recorder)(task, context, MALLOC_PTR_IN_USE_RANGE_TYPE, &vmRange, 1); } return 0; @@ -104,7 +104,7 @@ // The memory analysis API requires the contents of this struct to be a static // constant in the program binary. The leaks process will load this struct // out of the program binary (and not out of the running process). -static malloc_introspection_t zoneIntrospect = { +static const malloc_introspection_t zoneIntrospect = { .enumerator = bmalloc::enumerator, .good_size = bmalloc::good_size, .check = bmalloc::check, @@ -119,7 +119,7 @@ { malloc_zone_t::size = &bmalloc::zoneSize; malloc_zone_t::zone_name = "WebKit Malloc"; - malloc_zone_t::introspect = &bmalloc::zoneIntrospect; + malloc_zone_t::introspect = const_cast(&bmalloc::zoneIntrospect); malloc_zone_t::version = 4; malloc_zone_register(this); } diff -Nru webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Zone.h webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Zone.h --- webkit2gtk-2.12.3/Source/bmalloc/bmalloc/Zone.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/bmalloc/Zone.h 2016-09-16 09:56:48.000000000 +0000 @@ -27,6 +27,7 @@ #define Zone_h #include "FixedVector.h" +#include "Range.h" #include namespace bmalloc { @@ -41,8 +42,8 @@ Zone(); Zone(task_t, memory_reader_t, vm_address_t); - void addChunk(Chunk*); - FixedVector& chunks() { return m_chunks; } + void addRange(Range); + FixedVector& ranges() { return m_ranges; } private: // This vector has two purposes: @@ -56,15 +57,15 @@ // This prevents the leaks tool from reporting false positive leaks for // objects pointed to from bmalloc memory -- though it also prevents the // leaks tool from finding any leaks in bmalloc memory. - FixedVector m_chunks; + FixedVector m_ranges; }; -inline void Zone::addChunk(Chunk* chunk) +inline void Zone::addRange(Range range) { - if (m_chunks.size() == m_chunks.capacity()) + if (m_ranges.size() == m_ranges.capacity()) return; - m_chunks.push(chunk); + m_ranges.push(range); } } // namespace bmalloc diff -Nru webkit2gtk-2.12.3/Source/bmalloc/CMakeLists.txt webkit2gtk-2.14.2/Source/bmalloc/CMakeLists.txt --- webkit2gtk-2.12.3/Source/bmalloc/CMakeLists.txt 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/CMakeLists.txt 2016-09-19 12:18:06.000000000 +0000 @@ -1,3 +1,5 @@ +set_property(DIRECTORY . PROPERTY FOLDER "bmalloc") + set(bmalloc_INCLUDE_DIRECTORIES "${BMALLOC_DIR}" ) @@ -8,20 +10,24 @@ bmalloc/Deallocator.cpp bmalloc/Environment.cpp bmalloc/Heap.cpp + bmalloc/LargeMap.cpp bmalloc/Logging.cpp bmalloc/ObjectType.cpp bmalloc/StaticMutex.cpp bmalloc/VMHeap.cpp - bmalloc/XLargeMap.cpp bmalloc/mbmalloc.cpp ) +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + list(APPEND bmalloc_SOURCES + bmalloc/Zone.cpp + ) +endif () + set(bmalloc_LIBRARIES ${CMAKE_DL_LIBS} ) -WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() - WEBKIT_WRAP_SOURCELIST(${bmalloc_SOURCES}) include_directories(${bmalloc_INCLUDE_DIRECTORIES}) add_library(bmalloc STATIC ${bmalloc_SOURCES}) diff -Nru webkit2gtk-2.12.3/Source/bmalloc/PlatformGTK.cmake webkit2gtk-2.14.2/Source/bmalloc/PlatformGTK.cmake --- webkit2gtk-2.12.3/Source/bmalloc/PlatformGTK.cmake 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/PlatformGTK.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - list(APPEND bmalloc_SOURCES - bmalloc/Zone.cpp - ) -endif () diff -Nru webkit2gtk-2.12.3/Source/bmalloc/PlatformMac.cmake webkit2gtk-2.14.2/Source/bmalloc/PlatformMac.cmake --- webkit2gtk-2.12.3/Source/bmalloc/PlatformMac.cmake 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/bmalloc/PlatformMac.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -list(APPEND bmalloc_SOURCES - bmalloc/Zone.cpp -) \ No newline at end of file diff -Nru webkit2gtk-2.12.3/Source/cmake/FindGLIB.cmake webkit2gtk-2.14.2/Source/cmake/FindGLIB.cmake --- webkit2gtk-2.12.3/Source/cmake/FindGLIB.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/FindGLIB.cmake 2016-09-16 09:56:48.000000000 +0000 @@ -70,14 +70,16 @@ set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR}) # Version detection -file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) -string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") -set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") -string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") -set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") -string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") -set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") -set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") +if (EXISTS "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h") + file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) + string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") + set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") + set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") + string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") + set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") + set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") +endif () # Additional Glib components. We only look for libraries, as not all of them # have corresponding headers and all headers are installed alongside the main diff -Nru webkit2gtk-2.12.3/Source/cmake/FindGStreamer.cmake webkit2gtk-2.14.2/Source/cmake/FindGStreamer.cmake --- webkit2gtk-2.12.3/Source/cmake/FindGStreamer.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/FindGStreamer.cmake 2016-09-16 09:56:48.000000000 +0000 @@ -85,7 +85,7 @@ FIND_GSTREAMER_COMPONENT(GSTREAMER_APP gstreamer-app-1.0 gstapp-1.0) FIND_GSTREAMER_COMPONENT(GSTREAMER_AUDIO gstreamer-audio-1.0 gstaudio-1.0) FIND_GSTREAMER_COMPONENT(GSTREAMER_FFT gstreamer-fft-1.0 gstfft-1.0) -FIND_GSTREAMER_COMPONENT(GSTREAMER_GL gstreamer-gl-1.0>=1.6.0 gstgl-1.0) +FIND_GSTREAMER_COMPONENT(GSTREAMER_GL gstreamer-gl-1.0>=1.8.0 gstgl-1.0) FIND_GSTREAMER_COMPONENT(GSTREAMER_MPEGTS gstreamer-mpegts-1.0>=1.4.0 gstmpegts-1.0) FIND_GSTREAMER_COMPONENT(GSTREAMER_PBUTILS gstreamer-pbutils-1.0 gstpbutils-1.0) FIND_GSTREAMER_COMPONENT(GSTREAMER_TAG gstreamer-tag-1.0 gsttag-1.0) diff -Nru webkit2gtk-2.12.3/Source/cmake/FindICU.cmake webkit2gtk-2.14.2/Source/cmake/FindICU.cmake --- webkit2gtk-2.12.3/Source/cmake/FindICU.cmake 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/FindICU.cmake 2016-09-19 12:18:06.000000000 +0000 @@ -18,15 +18,17 @@ NAMES unicode/utypes.h HINTS ${PC_ICU_INCLUDE_DIRS} ${PC_ICU_INCLUDEDIR} + ${WEBKIT_LIBRARIES_INCLUDE_DIR} DOC "Include directory for the ICU library") mark_as_advanced(ICU_INCLUDE_DIR) # Look for the library. find_library( ICU_LIBRARY - NAMES icuuc cygicuuc cygicuuc32 + NAMES icuuc libicuuc cygicuuc cygicuuc32 HINTS ${PC_ICU_LIBRARY_DIRS} ${PC_ICU_LIBDIR} + ${WEBKIT_LIBRARIES_LINK_DIR} DOC "Libraries to link against for the common parts of ICU") mark_as_advanced(ICU_LIBRARY) @@ -49,9 +51,10 @@ pkg_check_modules(PC_ICU_I18N icu-i18n) find_library( ICU_I18N_LIBRARY - NAMES icui18n icuin cygicuin cygicuin32 + NAMES icui18n icuin libicui18n libicuin cygicuin cygicuin32 HINTS ${PC_ICU_I18N_LIBRARY_DIRS} ${PC_ICU_I18N_LIBDIR} + ${WEBKIT_LIBRARIES_LINK_DIR} DOC "Libraries to link against for ICU internationalization") mark_as_advanced(ICU_I18N_LIBRARY) if (ICU_I18N_LIBRARY) @@ -61,11 +64,30 @@ set(ICU_I18N_FOUND 0) set(ICU_I18N_LIBRARIES) endif () + + # Look for the ICU data libraries + find_library( + ICU_DATA_LIBRARY + NAMES icudata libicudata cygicudata cygicudata32 + HINTS ${PC_ICU_I18N_LIBRARY_DIRS} + ${PC_ICU_I18N_LIBDIR} + ${WEBKIT_LIBRARIES_LINK_DIR} + DOC "Libraries to link against for ICU data") + mark_as_advanced(ICU_DATA_LIBRARY) + if (ICU_DATA_LIBRARY) + set(ICU_DATA_FOUND 1) + set(ICU_DATA_LIBRARIES ${ICU_DATA_LIBRARY}) + else () + set(ICU_DATA_FOUND 0) + set(ICU_DATA_LIBRARIES) + endif () else () set(ICU_FOUND 0) set(ICU_I18N_FOUND 0) + set(ICU_DATA_FOUND 0) set(ICU_LIBRARIES) set(ICU_I18N_LIBRARIES) + set(ICU_DATA_LIBRARIES) set(ICU_INCLUDE_DIRS) set(ICU_VERSION) set(ICU_MAJOR_VERSION) @@ -76,6 +98,8 @@ if (NOT ICU_FIND_QUIETLY) message(STATUS "Found ICU header files in ${ICU_INCLUDE_DIRS}") message(STATUS "Found ICU libraries: ${ICU_LIBRARIES}") + message(STATUS "Found ICU internationaliation libraries: ${ICU_I18N_LIBRARIES}") + message(STATUS "Found ICU data libraries: ${ICU_DATA_LIBRARIES}") endif () else () if (ICU_FIND_REQUIRED) diff -Nru webkit2gtk-2.12.3/Source/cmake/FindLibSeccomp.cmake webkit2gtk-2.14.2/Source/cmake/FindLibSeccomp.cmake --- webkit2gtk-2.12.3/Source/cmake/FindLibSeccomp.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/FindLibSeccomp.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -# Copyright (c) 2013, Intel Corporation -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of Intel Corporation nor the names of its contributors may -# be used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# Try to find libseccomp include and library directories. -# -# After successful discovery, this will set for inclusion where needed: -# LIBSECCOMP_INCLUDE_DIRS - containg the libseccomp headers -# LIBSECCOMP_LIBRARIES - containg the libseccomp library - -include(FindPkgConfig) - -pkg_check_modules(PC_LIBSECCOMP libseccomp) - -find_path(LIBSECCOMP_INCLUDE_DIRS NAMES seccomp.h - HINTS ${PC_LIBSECCOMP_INCLUDE_DIRS} ${PC_LIBSECCOMP_INCLUDEDIR} -) - -find_library(LIBSECCOMP_LIBRARIES NAMES seccomp - HINTS ${PC_LIBSECCOMP_LIBRARY_DIRS} ${PC_LIBSECCOMP_LIBDIR} -) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(seccomp DEFAULT_MSG LIBSECCOMP_INCLUDE_DIRS LIBSECCOMP_LIBRARIES) diff -Nru webkit2gtk-2.12.3/Source/cmake/FindLLVM.cmake webkit2gtk-2.14.2/Source/cmake/FindLLVM.cmake --- webkit2gtk-2.12.3/Source/cmake/FindLLVM.cmake 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/FindLLVM.cmake 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,49 @@ +# +# Check if the llvm-config gives us the path for the llvm libs. +# +# The following variables are set: +# LLVM_CONFIG_EXE +# LLVM_VERSION +# LLVM_INCLUDE_DIRS - include directories for the llvm headers. +# LLVM_STATIC_LIBRARIES - list of paths for the static llvm libraries. + + +foreach (_program_name llvm-config llvm-config-3.7 llvm-config-3.6 llvm-config-3.5) + find_program(LLVM_CONFIG_EXE NAMES ${_program_name}) + if (LLVM_CONFIG_EXE) + execute_process(COMMAND ${LLVM_CONFIG_EXE} --version OUTPUT_VARIABLE LLVM_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + if ("${LLVM_VERSION}" VERSION_LESS "${LLVM_FIND_VERSION}") + unset(LLVM_CONFIG_EXE CACHE) + else () + break () + endif () + endif () +endforeach () + +execute_process(COMMAND ${LLVM_CONFIG_EXE} --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXE} --libfiles OUTPUT_VARIABLE LLVM_STATIC_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXE} --system-libs OUTPUT_VARIABLE LLVM_SYSTEM_LIBRARIES OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXE} --libdir OUTPUT_VARIABLE LLVM_LIBS_DIRECTORY OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXE} --libs OUTPUT_VARIABLE LLVM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process(COMMAND ${LLVM_CONFIG_EXE} --ldflags OUTPUT_VARIABLE LLVM_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + +# Depending on how llvm was built, we could have either a global .so file when built using autotools, +# or multiple .so files for each static library when built using CMake. So, we set the LLVM_LIBS_DIRECTORY +# variable here accordingly for each case. +# We need to build the soname manually in any case, since there's currently no way to get it from llvm-config. +set(LLVM_SONAME "LLVM-${LLVM_VERSION}") +if (EXISTS "${LLVM_LIBS_DIRECTORY}/lib${LLVM_SONAME}.so") + set(LLVM_LIBRARIES "${LLVM_LDFLAGS} -l${LLVM_SONAME}") +else () + set(LLVM_LIBRARIES "${LLVM_LDFLAGS} ${LLVM_LIBS}") +endif () + +# convert the list of paths into a cmake list +separate_arguments(LLVM_STATIC_LIBRARIES) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LLVM + REQUIRED_VARS LLVM_VERSION LLVM_INCLUDE_DIRS LLVM_LIBRARIES LLVM_STATIC_LIBRARIES + VERSION_VAR LLVM_VERSION) + +mark_as_advanced(LLVM_VERSION LLVM_INCLUDE_DIRS LLVM_LIBRARIES LLVM_STATIC_LIBRARIES) diff -Nru webkit2gtk-2.12.3/Source/cmake/FindWebP.cmake webkit2gtk-2.14.2/Source/cmake/FindWebP.cmake --- webkit2gtk-2.12.3/Source/cmake/FindWebP.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/FindWebP.cmake 2016-09-16 09:56:48.000000000 +0000 @@ -30,19 +30,22 @@ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. find_package(PkgConfig) -pkg_check_modules(WEBP libwebp) +pkg_check_modules(PC_WEBP QUIET libwebp) -if (NOT(WEBP_FOUND)) - # Older installations of libwebp do not install a pkgconfig file, so we fall - # back to a manual search for a libwebp header file. - include(CheckIncludeFiles) - check_include_files("webp/decode.h" WEBP_FOUND_HEADER) - if (WEBP_FOUND_HEADER) - set(WEBP_LIBRARIES "-lwebp") - set(WEBP_FOUND TRUE) - endif () -endif () +# Look for the header file. +find_path(WEBP_INCLUDE_DIRS + NAMES webp/decode.h + HINTS ${PC_WEBP_INCLUDEDIR} ${PC_WEBP_INCLUDE_DIRS} +) +mark_as_advanced(WEBP_INCLUDE_DIRS) + +# Look for the library. +find_library( + WEBP_LIBRARIES + NAMES webp + HINTS ${PC_WEBP_LIBDIR} ${PC_WEBP_LIBRARY_DIRS} +) +mark_as_advanced(WEBP_LIBRARIES) -# WEBP_INCLUDE_DIRS is often empty, so we rely only on WEBP_LIBRARIES. include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(WEBP DEFAULT_MSG WEBP_LIBRARIES) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WEBP DEFAULT_MSG WEBP_INCLUDE_DIRS WEBP_LIBRARIES) diff -Nru webkit2gtk-2.12.3/Source/cmake/OptionsCommon.cmake webkit2gtk-2.14.2/Source/cmake/OptionsCommon.cmake --- webkit2gtk-2.12.3/Source/cmake/OptionsCommon.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/OptionsCommon.cmake 2016-11-03 07:04:21.000000000 +0000 @@ -24,11 +24,12 @@ endif () set_property(GLOBAL PROPERTY USE_FOLDERS ON) +define_property(TARGET PROPERTY FOLDER INHERITED BRIEF_DOCS "folder" FULL_DOCS "IDE folder name") if (CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-exceptions -fno-strict-aliasing") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-strict-aliasing -fno-rtti") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") endif () if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_GENERATOR STREQUAL "Ninja") @@ -36,6 +37,33 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics") endif () +# Ensure that the default include system directories are added to the list of CMake implicit includes. +# This workarounds an issue that happens when using GCC 6 and using system includes (-isystem). +# For more details check: https://bugs.webkit.org/show_bug.cgi?id=161697 +macro(DETERMINE_GCC_SYSTEM_INCLUDE_DIRS _lang _compiler _flags _result) + file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/dummy" "\n") + separate_arguments(_buildFlags UNIX_COMMAND "${_flags}") + execute_process(COMMAND ${_compiler} ${_buildFlags} -v -E -x ${_lang} -dD dummy + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/CMakeFiles OUTPUT_QUIET + ERROR_VARIABLE _gccOutput) + file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/dummy") + if ("${_gccOutput}" MATCHES "> search starts here[^\n]+\n *(.+) *\n *End of (search) list") + set(${_result} ${CMAKE_MATCH_1}) + string(REPLACE "\n" " " ${_result} "${${_result}}") + separate_arguments(${_result}) + endif () +endmacro() + +if (CMAKE_COMPILER_IS_GNUCC) + DETERMINE_GCC_SYSTEM_INCLUDE_DIRS("c" "${CMAKE_C_COMPILER}" "${CMAKE_C_FLAGS}" SYSTEM_INCLUDE_DIRS) + set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES} ${SYSTEM_INCLUDE_DIRS}) +endif () + +if (CMAKE_COMPILER_IS_GNUCXX) + DETERMINE_GCC_SYSTEM_INCLUDE_DIRS("c++" "${CMAKE_CXX_COMPILER}" "${CMAKE_CXX_FLAGS}" SYSTEM_INCLUDE_DIRS) + set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES} ${SYSTEM_INCLUDE_DIRS}) +endif () + # Detect Cortex-A53 core if CPU is ARM64 and OS is Linux. # Query /proc/cpuinfo for each available core and check reported CPU part number: 0xd03 signals Cortex-A53. # (see Main ID Register in ARM Cortex-A53 MPCore Processor Technical Reference Manual) @@ -68,10 +96,29 @@ EXPOSE_VARIABLE_TO_BUILD(WTF_CPU_ARM64_CORTEXA53) +set(ARM_TRADITIONAL_DETECTED FALSE) +if (WTF_CPU_ARM) + set(ARM_THUMB2_TEST_SOURCE + " + #if !defined(thumb2) && !defined(__thumb2__) + #error \"Thumb2 instruction set isn't available\" + #endif + int main() {} + ") + + include(CheckCXXSourceCompiles) + CHECK_CXX_SOURCE_COMPILES("${ARM_THUMB2_TEST_SOURCE}" ARM_THUMB2_DETECTED) + if (NOT ARM_THUMB2_DETECTED) + set(ARM_TRADITIONAL_DETECTED TRUE) + # See https://bugs.webkit.org/show_bug.cgi?id=159880#c4 for details. + message(STATUS "Disabling GNU gold linker, because it doesn't support ARM instruction set properly.") + endif () +endif () + # Use ld.gold if it is available and isn't disabled explicitly include(CMakeDependentOption) CMAKE_DEPENDENT_OPTION(USE_LD_GOLD "Use GNU gold linker" ON - "NOT CXX_ACCEPTS_MFIX_CORTEX_A53_835769" OFF) + "NOT CXX_ACCEPTS_MFIX_CORTEX_A53_835769;NOT ARM_TRADITIONAL_DETECTED" OFF) if (USE_LD_GOLD) execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) if ("${LD_VERSION}" MATCHES "GNU gold") @@ -124,6 +171,11 @@ set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined ${CMAKE_SHARED_LINKER_FLAGS}") endif () +if (USE_ARM_LLVM_DISASSEMBLER) + find_package(LLVM REQUIRED) + SET_AND_EXPOSE_TO_BUILD(HAVE_LLVM TRUE) +endif () + # Enable the usage of OpenMP. # - At this moment, OpenMP is only used as an alternative implementation # to native threads for the parallelization of the SVG filters. diff -Nru webkit2gtk-2.12.3/Source/cmake/OptionsGTK.cmake webkit2gtk-2.14.2/Source/cmake/OptionsGTK.cmake --- webkit2gtk-2.12.3/Source/cmake/OptionsGTK.cmake 2016-05-24 08:06:23.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/OptionsGTK.cmake 2016-11-03 07:04:39.000000000 +0000 @@ -1,8 +1,8 @@ include(GNUInstallDirs) set(PROJECT_VERSION_MAJOR 2) -set(PROJECT_VERSION_MINOR 12) -set(PROJECT_VERSION_MICRO 3) +set(PROJECT_VERSION_MINOR 14) +set(PROJECT_VERSION_MICRO 2) set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_MICRO}) set(WEBKITGTK_API_VERSION 4.0) @@ -15,8 +15,8 @@ # Libtool library version, not to be confused with API version. # See http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html -CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT2 50 9 13) -CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(JAVASCRIPTCORE 21 11 3) +CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT2 51 9 14) +CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(JAVASCRIPTCORE 22 9 4) # These are shared variables, but we special case their definition so that we can use the # CMAKE_INSTALL_* variables that are populated by the GNUInstallDirs macro. @@ -33,6 +33,7 @@ find_package(Cairo 1.10.2 REQUIRED) find_package(Fontconfig 2.8.0 REQUIRED) find_package(Freetype2 2.4.2 REQUIRED) +find_package(GnuTLS 3.0.0 REQUIRED) find_package(GTK3 3.6.0 REQUIRED) find_package(GDK3 3.6.0 REQUIRED) find_package(HarfBuzz 0.9.2 REQUIRED) @@ -55,6 +56,8 @@ WEBKIT_OPTION_BEGIN() +set(USE_WOFF2 ON) + # Set the default value for ENABLE_GLES2 automatically. # We are not enabling or disabling automatically a feature here, because # the feature is by default always on (ENABLE_OPENGL=ON). @@ -107,7 +110,6 @@ WEBKIT_OPTION_DEPEND(USE_GSTREAMER_GL ENABLE_OPENGL) WEBKIT_OPTION_DEPEND(USE_GSTREAMER_GL ENABLE_VIDEO) WEBKIT_OPTION_DEPEND(USE_GSTREAMER_MPEGTS ENABLE_VIDEO) -WEBKIT_OPTION_DEPEND(ENABLE_WAYLAND_TARGET ENABLE_OPENGL) SET_AND_EXPOSE_TO_BUILD(ENABLE_DEVELOPER_MODE ${DEVELOPER_MODE}) if (DEVELOPER_MODE) @@ -138,6 +140,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_JIT PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SAMPLING_PROFILER PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPELLCHECK PUBLIC ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THREADED_COMPOSITOR PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VIDEO PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_AUDIO PUBLIC ON) @@ -149,28 +152,24 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_3D_TRANSFORMS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ACCESSIBILITY PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CANVAS_PATH PRIVATE OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_IMAGE_SET PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_REGIONS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SELECTORS_LEVEL4 PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DATABASE_PROCESS PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTL_JIT PRIVATE ${ENABLE_FTL_DEFAULT}) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FULLSCREEN_API PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INDEXED_DATABASE PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INDEXED_DATABASE_IN_WORKERS PRIVATE OFF) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INDEXED_DATABASE_IN_WORKERS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_COLOR PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_WEB_AUDIO PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_CONTROLS_SCRIPT PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MHTML PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NOTIFICATIONS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PUBLIC_SUFFIX_LIST PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REQUEST_ANIMATION_FRAME PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SMOOTH_SCROLLING PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SVG_OTF_CONVERTER PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_USERSELECT_ALL PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_USER_MESSAGE_HANDLERS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VIDEO_TRACK PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_TIMING PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL PRIVATE ON) # Finalize the value for all options. Do not attempt to use an option before @@ -197,7 +196,7 @@ add_definitions(-DBUILDING_GTK__=1) add_definitions(-DGETTEXT_PACKAGE="WebKit2GTK-${WEBKITGTK_API_VERSION}") add_definitions(-DDATA_DIR="${CMAKE_INSTALL_DATADIR}") -add_definitions(-DUSER_AGENT_GTK_MAJOR_VERSION="602") +add_definitions(-DUSER_AGENT_GTK_MAJOR_VERSION="603") add_definitions(-DUSER_AGENT_GTK_MINOR_VERSION="1") add_definitions(-DWEBKITGTK_API_VERSION_STRING="${WEBKITGTK_API_VERSION}") @@ -262,10 +261,10 @@ endif () endif () -if (ENABLE_MEDIA_STREAM) +if (ENABLE_MEDIA_STREAM OR ENABLE_WEB_RTC) find_package(OpenWebRTC) if (NOT OPENWEBRTC_FOUND) - message(FATAL_ERROR "OpenWebRTC is needed for ENABLE_MEDIA_STREAM.") + message(FATAL_ERROR "OpenWebRTC is needed for ENABLE_MEDIA_STREAM and ENABLE_WEB_RTC.") endif () SET_AND_EXPOSE_TO_BUILD(USE_OPENWEBRTC TRUE) endif () @@ -312,13 +311,6 @@ find_package(GDK2 2.24.10 REQUIRED) endif () -if (ENABLE_SECCOMP_FILTERS) - find_package(LibSeccomp) - if (NOT PC_LIBSECCOMP_FOUND) - message(FATAL_ERROR "libseccomp is required for ENABLE_SECCOMP_FILTERS") - endif () -endif () - if (ENABLE_SPELLCHECK) find_package(Enchant) if (NOT PC_ENCHANT_FOUND) @@ -326,13 +318,6 @@ endif () endif () -if (ENABLE_SUBTLE_CRYPTO) - find_package(GnuTLS 3.0.0) - if (NOT GNUTLS_FOUND) - message(FATAL_ERROR "GnuTLS is needed for ENABLE_SUBTLE_CRYPTO") - endif () -endif () - if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO) set(GSTREAMER_COMPONENTS app pbutils) @@ -403,10 +388,14 @@ message(FATAL_ERROR "Recompile GTK+ with Wayland backend to use ENABLE_WAYLAND_TARGET") endif () - if (ENABLE_WAYLAND_TARGET AND GTK3_VERSION VERSION_LESS 3.12) + if (GTK3_VERSION VERSION_LESS 3.12) message(FATAL_ERROR "GTK+ 3.12 is required to use ENABLE_WAYLAND_TARGET") endif () + if (NOT EGL_FOUND) + message(FATAL_ERROR "EGL is required to use ENABLE_WAYLAND_TARGET") + endif () + find_package(Wayland REQUIRED) endif () diff -Nru webkit2gtk-2.12.3/Source/cmake/OptionsJSCOnly.cmake webkit2gtk-2.14.2/Source/cmake/OptionsJSCOnly.cmake --- webkit2gtk-2.12.3/Source/cmake/OptionsJSCOnly.cmake 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/OptionsJSCOnly.cmake 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,67 @@ +find_package(ICU REQUIRED) +find_package(Threads REQUIRED) + +set(PROJECT_VERSION_MAJOR 1) +set(PROJECT_VERSION_MINOR 0) +set(PROJECT_VERSION_MICRO 0) +set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_MICRO}) + +WEBKIT_OPTION_BEGIN() +WEBKIT_OPTION_DEFINE(ENABLE_STATIC_JSC "Whether to build JavaScriptCore as a static library." PUBLIC OFF) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTL_JIT PUBLIC ON) +WEBKIT_OPTION_END() + +set(ALL_EVENT_LOOP_TYPES + GLib + Generic +) + +set(DEFAULT_EVENT_LOOP_TYPE "Generic") + +set(EVENT_LOOP_TYPE ${DEFAULT_EVENT_LOOP_TYPE} CACHE STRING "Implementation of event loop to be used in JavaScriptCore (one of ${ALL_EVENT_LOOP_TYPES})") + +set(ENABLE_WEBCORE OFF) +set(ENABLE_WEBKIT OFF) +set(ENABLE_WEBKIT2 OFF) +set(ENABLE_API_TESTS ON) + +if (WTF_CPU_X86 OR WTF_CPU_X86_64) + SET_AND_EXPOSE_TO_BUILD(USE_UDIS86 1) +endif () + +if (ENABLE_STATIC_JSC) + set(JavaScriptCore_LIBRARY_TYPE STATIC) +endif () + +string(TOLOWER ${EVENT_LOOP_TYPE} LOWERCASE_EVENT_LOOP_TYPE) +if (LOWERCASE_EVENT_LOOP_TYPE STREQUAL "glib") + find_package(GLIB 2.36 REQUIRED COMPONENTS gio gobject) + SET_AND_EXPOSE_TO_BUILD(USE_GLIB 1) + SET_AND_EXPOSE_TO_BUILD(USE_GLIB_EVENT_LOOP 1) + SET_AND_EXPOSE_TO_BUILD(WTF_DEFAULT_EVENT_LOOP 0) +else () + SET_AND_EXPOSE_TO_BUILD(USE_GENERIC_EVENT_LOOP 1) + SET_AND_EXPOSE_TO_BUILD(WTF_DEFAULT_EVENT_LOOP 0) +endif () + +# From OptionsGTK.cmake +if (CMAKE_MAJOR_VERSION LESS 3) + # Before CMake 3 it was necessary to use a build script instead of using cmake --build directly + # to preserve colors and pretty-printing. + + build_command(COMMAND_LINE_TO_BUILD) + # build_command unconditionally adds -i (ignore errors) for make, and there's + # no reasonable way to turn that off, so we just replace it with -k, which has + # the same effect, except that the return code will indicate that an error occurred. + # See: http://www.cmake.org/cmake/help/v3.0/command/build_command.html + string(REPLACE " -i" " -k" COMMAND_LINE_TO_BUILD ${COMMAND_LINE_TO_BUILD}) + file(WRITE + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build.sh + "#!/bin/sh\n" + "${COMMAND_LINE_TO_BUILD} $@" + ) + file(COPY ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/build.sh + DESTINATION ${CMAKE_BINARY_DIR} + FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE + ) +endif () diff -Nru webkit2gtk-2.12.3/Source/cmake/OptionsMac.cmake webkit2gtk-2.14.2/Source/cmake/OptionsMac.cmake --- webkit2gtk-2.12.3/Source/cmake/OptionsMac.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/OptionsMac.cmake 2016-11-03 07:04:21.000000000 +0000 @@ -1,3 +1,5 @@ +set(WEBKIT_MAC_VERSION 602.1.27) + WEBKIT_OPTION_BEGIN() WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_3D_TRANSFORMS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ACCELERATED_2D_CANVAS PRIVATE OFF) @@ -18,12 +20,10 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_GRID_LAYOUT PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_IMAGE_ORIENTATION PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_IMAGE_RESOLUTION PRIVATE OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_IMAGE_SET PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_REGIONS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SCROLL_SNAP PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SHAPES PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS3_TEXT PRIVATE OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS3_TEXT_LINE_BREAK PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CUSTOM_SCHEME_HANDLER PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DASHBOARD_SUPPORT PRIVATE ON) @@ -39,7 +39,6 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FULLSCREEN_API PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD_DEPRECATED PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GEOLOCATION PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ICONDATABASE PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_WEEK PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SERVICE_CONTROLS PRIVATE ON) @@ -54,11 +53,10 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATETIMELOCAL PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_MONTH PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_TIME PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_IOS_TEXT_AUTOSIZING PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_IOS_TEXT_AUTOSIZING PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_CSS_VENDOR_PREFIXES PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_NOTIFICATIONS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_VENDOR_PREFIXES PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LEGACY_WEB_AUDIO PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LETTERPRESS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_LINK_PREFETCH PRIVATE OFF) @@ -83,7 +81,6 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PUBLIC_SUFFIX_LIST PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_QUOTA PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REMOTE_INSPECTOR PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REQUEST_ANIMATION_FRAME PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_RESOLUTION_MEDIA_QUERY PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_RESOURCE_USAGE PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_RUBBER_BANDING PRIVATE ON) @@ -94,7 +91,6 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TELEPHONE_NUMBER_DETECTION PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TEMPLATE_ELEMENT PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TEXT_AUTOSIZING PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_ICON_LOADING PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_USERSELECT_ALL PRIVATE ON) @@ -116,8 +112,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PRIVATE OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTL_JIT PRIVATE OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_TIMING PRIVATE OFF) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTL_JIT PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_IOS_AIRPLAY PRIVATE OFF) diff -Nru webkit2gtk-2.12.3/Source/cmake/OptionsWin.cmake webkit2gtk-2.14.2/Source/cmake/OptionsWin.cmake --- webkit2gtk-2.12.3/Source/cmake/OptionsWin.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/OptionsWin.cmake 2016-11-03 07:04:21.000000000 +0000 @@ -10,17 +10,16 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CANVAS_PATH PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CANVAS_PROXY PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CHANNEL_MESSAGING PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSP_NEXT PUBLIC ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSP_NEXT PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS3_TEXT PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_BOX_DECORATION_BREAK PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_COMPOSITING PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_GRID_LAYOUT PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_IMAGE_SET PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_REGIONS PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SELECTORS_LEVEL4 PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SHAPES PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CUSTOM_ELEMENTS PRIVATE OFF) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CUSTOM_ELEMENTS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CUSTOM_SCHEME_HANDLER PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DATALIST_ELEMENT PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DATA_TRANSFER_ITEMS PUBLIC OFF) @@ -28,16 +27,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOM4_EVENTS_CONSTRUCTOR PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ES6_GENERATORS PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ES6_MODULES PUBLIC OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FETCH_API PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FULLSCREEN_API PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GEOLOCATION PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ICONDATABASE PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INDEXED_DATABASE PUBLIC OFF) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INDEXED_DATABASE PUBLIC ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INDEXED_DATABASE_IN_WORKERS PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_COLOR PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATE PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATETIME_INCOMPLETE PUBLIC OFF) @@ -60,16 +57,13 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_QUOTA PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NAVIGATOR_CONTENT_UTILS PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REQUEST_ANIMATION_FRAME PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHADOW_DOM PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_STREAMS_API PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SVG_FONTS PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SVG_OTF_CONVERTER PUBLIC OFF) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TEMPLATE_ELEMENT PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TEXT_AUTOSIZING PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VIDEO PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VIDEO_TRACK PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VIEW_MODE_CSS_MEDIA PUBLIC ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_ANIMATIONS PUBLIC OFF) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_ANIMATIONS PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_AUDIO PUBLIC OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_SOCKETS PUBLIC ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_TIMING PUBLIC ON) @@ -99,18 +93,25 @@ endif () endif () -include_directories("${CMAKE_BINARY_DIR}/DerivedSources/ForwardingHeaders" "${CMAKE_BINARY_DIR}/DerivedSources" "${WEBKIT_LIBRARIES_DIR}/include") +set(WEBKIT_LIBRARIES_INCLUDE_DIR "${WEBKIT_LIBRARIES_DIR}/include") + +include_directories("${CMAKE_BINARY_DIR}/DerivedSources/ForwardingHeaders" "${CMAKE_BINARY_DIR}/DerivedSources" "${WEBKIT_LIBRARIES_INCLUDE_DIR}") if (${MSVC_CXX_ARCHITECTURE_ID} STREQUAL "X86") - link_directories("${CMAKE_BINARY_DIR}/lib32" "${WEBKIT_LIBRARIES_DIR}/lib32") + set(WEBKIT_LIBRARIES_LINK_DIR "${WEBKIT_LIBRARIES_DIR}/lib32") + # FIXME: Remove ${WEBKIT_LIBRARIES_LINK_DIR} when find_library is used for everything + link_directories("${CMAKE_BINARY_DIR}/lib32" "${WEBKIT_LIBRARIES_LINK_DIR}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib32) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib32) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin32) else () - link_directories("${CMAKE_BINARY_DIR}/lib64" "${WEBKIT_LIBRARIES_DIR}/lib64") + set(WEBKIT_LIBRARIES_LINK_DIR "${WEBKIT_LIBRARIES_DIR}/lib64") + # FIXME: Remove ${WEBKIT_LIBRARIES_LINK_DIR} when find_library is used for everything + link_directories("${CMAKE_BINARY_DIR}/lib64" "${WEBKIT_LIBRARIES_LINK_DIR}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib64) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib64) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin64) endif () + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") @@ -121,18 +122,18 @@ if (MSVC) add_definitions( /wd4018 /wd4068 /wd4099 /wd4100 /wd4127 /wd4138 /wd4146 /wd4180 /wd4189 - /wd4201 /wd4244 /wd4251 /wd4267 /wd4275 /wd4288 /wd4291 /wd4305 /wd4309 - /wd4344 /wd4355 /wd4389 /wd4396 /wd4456 /wd4457 /wd4458 /wd4459 /wd4481 - /wd4503 /wd4505 /wd4510 /wd4512 /wd4530 /wd4610 /wd4611 /wd4702 /wd4706 - /wd4800 /wd4819 /wd4951 /wd4952 /wd4996 /wd6011 /wd6031 /wd6211 /wd6246 - /wd6255 /wd6387 + /wd4201 /wd4206 /wd4244 /wd4251 /wd4267 /wd4275 /wd4288 /wd4291 /wd4305 + /wd4309 /wd4344 /wd4355 /wd4389 /wd4396 /wd4456 /wd4457 /wd4458 /wd4459 + /wd4481 /wd4503 /wd4505 /wd4510 /wd4512 /wd4530 /wd4610 /wd4611 /wd4646 + /wd4702 /wd4706 /wd4722 /wd4800 /wd4819 /wd4951 /wd4952 /wd4996 /wd6011 + /wd6031 /wd6211 /wd6246 /wd6255 /wd6387 ) # Create pdb files for debugging purposes, also for Release builds add_compile_options(/Zi /GS) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG /OPT:ICF /OPT:REF") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:ICF /OPT:REF") # We do not use exceptions add_definitions(-D_HAS_EXCEPTIONS=0) @@ -187,4 +188,5 @@ set(PORT Win) set(JavaScriptCore_LIBRARY_TYPE SHARED) set(WTF_LIBRARY_TYPE SHARED) -set(ICU_LIBRARIES libicuuc${DEBUG_SUFFIX} libicuin${DEBUG_SUFFIX}) + +find_package(ICU REQUIRED) diff -Nru webkit2gtk-2.12.3/Source/cmake/tools/scripts/version-stamp.pl webkit2gtk-2.14.2/Source/cmake/tools/scripts/version-stamp.pl --- webkit2gtk-2.12.3/Source/cmake/tools/scripts/version-stamp.pl 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/tools/scripts/version-stamp.pl 2016-09-16 09:56:48.000000000 +0000 @@ -1,6 +1,8 @@ #!/usr/bin/perl -w use strict; +use Cwd 'abs_path'; +use File::Basename; use File::Spec; use POSIX; @@ -29,9 +31,11 @@ sub exitStatus($); -my $WEBKIT_LIBRARIES = $ENV{'WEBKIT_LIBRARIES'}; +my $rawPath = $0; -my $VERSION_STAMPER = File::Spec->catfile($WEBKIT_LIBRARIES, 'tools', 'VersionStamper', 'VersionStamper.exe'); +my $thisDirectory = dirname(abs_path($rawPath)); + +my $VERSION_STAMPER = File::Spec->catfile($thisDirectory, '..', 'VersionStamper', 'VersionStamper.exe'); unless (-e $VERSION_STAMPER) { print "No $VERSION_STAMPER executable. Exiting.\n"; @@ -89,6 +93,9 @@ my $TARGET_PATH = File::Spec->canonpath($target); +# Replace forward slashes with backslashes in case we are running Cygwin Perl. +$TARGET_PATH =~ s/\//\\/g; + print "Adjusting RC_PROJECTSOURCEVERSION and RC_ProjectSourceVersion to be safe for VersionStamper.\n"; my $SAFE_PROJECT_VERSION = "$components{'__FULL_BUILD_MAJOR_VERSION__'}.$components{'__VERSION_MINOR__'}.$components{'__VERSION_TINY__'}"; diff -Nru webkit2gtk-2.12.3/Source/cmake/WebKitFeatures.cmake webkit2gtk-2.14.2/Source/cmake/WebKitFeatures.cmake --- webkit2gtk-2.12.3/Source/cmake/WebKitFeatures.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/WebKitFeatures.cmake 2016-11-03 07:04:21.000000000 +0000 @@ -1,3 +1,13 @@ +# The settings in this file are the WebKit project default values, and +# are recommended for most ports. Ports can override these settings in +# Options*.cmake, but should do so only if there is strong reason to +# deviate from the defaults of the WebKit project (e.g. if the feature +# requires platform-specific implementation that does not exist). +# +# Most defaults in this file affect end users but not developers. +# Defaults for development builds are set in FeatureList.pm. Most all +# features enabled here should also be enabled in FeatureList.pm. + set(_WEBKIT_AVAILABLE_OPTIONS "") set(PUBLIC YES) @@ -76,14 +86,12 @@ WEBKIT_OPTION_DEFINE(ENABLE_CREDENTIAL_STORAGE "Toggle Credential Storage support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSP_NEXT "Toggle Content Security Policy 1.1 support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS3_TEXT "Toggle CSS3 Text support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_CSS3_TEXT_LINE_BREAK "Toggle CSS3 Text Line Break support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS_BOX_DECORATION_BREAK "Toggle Box Decoration break (CSS Backgrounds and Borders) support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_CSS_COMPOSITING "Toggle CSS COMPOSITING support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS_DEVICE_ADAPTATION "Toggle CSS Device Adaptation support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_CSS_GRID_LAYOUT "Toggle CSS Grid Layout support" PRIVATE OFF) + WEBKIT_OPTION_DEFINE(ENABLE_CSS_GRID_LAYOUT "Toggle CSS Grid Layout support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_CSS_IMAGE_ORIENTATION "Toggle CSS image-orientation support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS_IMAGE_RESOLUTION "Toggle CSS image-resolution support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_CSS_IMAGE_SET "Toggle CSS image-set support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS_REGIONS "Toggle CSS regions support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS_SCROLL_SNAP "Toggle CSS snap scroll support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_CSS_SELECTORS_LEVEL4 "Toggle CSS Selectors Level 4 support" PRIVATE OFF) @@ -104,11 +112,7 @@ WEBKIT_OPTION_DEFINE(ENABLE_DRAG_SUPPORT "Toggle Drag Support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_ENCRYPTED_MEDIA "Toggle EME support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_ENCRYPTED_MEDIA_V2 "Support EME v2" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_ES6_ARROWFUNCTION_SYNTAX "Toggle ES6 arrow function syntax support" PRIVATE ON) - WEBKIT_OPTION_DEFINE(ENABLE_ES6_CLASS_SYNTAX "Toggle ES6 class syntax support" PRIVATE ON) - WEBKIT_OPTION_DEFINE(ENABLE_ES6_GENERATORS "Toggle ES6 generators support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_ES6_MODULES "Toggle ES6 modules support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_ES6_TEMPLATE_LITERAL_SYNTAX "Toggle ES6 template literal syntax support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_FETCH_API "Toggle Fetch API support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_FILTERS_LEVEL_2 "Toggle Filters Module Level 2" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_FONT_LOAD_EVENTS "Toggle Font Load Events support" PRIVATE OFF) @@ -118,7 +122,6 @@ WEBKIT_OPTION_DEFINE(ENABLE_GAMEPAD "Toggle Gamepad support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_GAMEPAD_DEPRECATED "Toggle deprecated Gamepad support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_GEOLOCATION "Toggle Geolocation support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_HIDDEN_PAGE_DOM_TIMER_THROTTLING "Toggle hidden page DOM timer throttling support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_ICONDATABASE "Toggle Icon database support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_IMAGE_DECODER_DOWN_SAMPLING "Toggle image decoder down sampling support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_INDEXED_DATABASE "Toggle Indexed Database API support" PRIVATE OFF) @@ -139,7 +142,6 @@ WEBKIT_OPTION_DEFINE(ENABLE_LEGACY_CSS_VENDOR_PREFIXES "Toggle legacy css vendor prefix support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_LEGACY_NOTIFICATIONS "Toggle Legacy Desktop Notifications Support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_LEGACY_VENDOR_PREFIXES "Toggle Legacy Vendor Prefix Support" PRIVATE ON) - WEBKIT_OPTION_DEFINE(ENABLE_LEGACY_WEB_AUDIO "Toggle Legacy Web Audio support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_LETTERPRESS "Toggle letterpress support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_LINK_PREFETCH "Toggle pre fetching support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_MAC_LONG_PRESS "Toggle mac long press support" PRIVATE OFF) @@ -147,8 +149,8 @@ WEBKIT_OPTION_DEFINE(ENABLE_MEDIA_CAPTURE "Toggle Media Capture support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_MEDIA_CONTROLS_SCRIPT "Toggle definition of media controls in Javascript" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_MEDIA_SOURCE "Toggle Media Source support" PRIVATE OFF) + WEBKIT_OPTION_DEFINE(ENABLE_MEDIA_STREAM "Toggle Media Stream support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_MEDIA_STATISTICS "Toggle Media Statistics support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_MEDIA_STREAM "Toggle Media Stream API support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_MEMORY_SAMPLER "Toggle Memory Sampler support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_METER_ELEMENT "Toggle Meter Tag support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_MHTML "Toggle MHTML support" PRIVATE OFF) @@ -161,30 +163,25 @@ WEBKIT_OPTION_DEFINE(ENABLE_NOTIFICATIONS "Toggle Desktop Notifications Support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_ORIENTATION_EVENTS "Toggle Orientation Events support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_PDFKIT_PLUGIN "Toggle PDFKit plugin support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_PERFORMANCE_TIMELINE "Toggle Performance Timeline support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_POINTER_LOCK "Toggle pointer lock support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_PROXIMITY_EVENTS "Toggle Proximity Events support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_PUBLIC_SUFFIX_LIST "Toggle public suffix list support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_QUOTA "Toggle Quota support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_REMOTE_INSPECTOR "Toggle remote inspector support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_REQUEST_ANIMATION_FRAME "Toggle requestAnimationFrame support" PRIVATE OFF) + WEBKIT_OPTION_DEFINE(ENABLE_REQUEST_ANIMATION_FRAME "Toggle requestAnimationFrame support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_RESOLUTION_MEDIA_QUERY "Toggle resolution media query support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_RESOURCE_TIMING "Toggle Resource Timing support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_RESOURCE_USAGE "Toggle resource usage support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_RUBBER_BANDING "Toggle rubber banding support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_SAMPLING_PROFILER "Toggle sampling profiler support" PRIVATE ON) - WEBKIT_OPTION_DEFINE(ENABLE_SECCOMP_FILTERS "Toggle Linux seccomp filters for the WebProcess support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_SERVICE_CONTROLS "Toggle service controls support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_SHADOW_DOM "Toggle shadow dom" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_SMOOTH_SCROLLING "Toggle smooth scrolling" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_SPEECH_SYNTHESIS "Toggle Speech Synthesis API support)" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_SPELLCHECK "Toggle Spellchecking support (requires Enchant)" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_STREAMS_API "Toggle Streams API support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_SUBTLE_CRYPTO "Toggle subtle crypto support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_SVG_FONTS "Toggle SVG fonts support (imples SVG support)" PRIVATE ON) - WEBKIT_OPTION_DEFINE(ENABLE_SVG_OTF_CONVERTER "Toggle whether to use the SVG to OTF font converter" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_TELEPHONE_NUMBER_DETECTION "Toggle telephone number detection support" PRIVATE OFF) - WEBKIT_OPTION_DEFINE(ENABLE_TEMPLATE_ELEMENT "Toggle Template support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_TEXT_AUTOSIZING "Toggle Text auto sizing support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_THREADED_COMPOSITOR "Toggle threaded compositor support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_TOUCH_EVENTS "Toggle Touch Events support" PRIVATE OFF) @@ -203,16 +200,19 @@ WEBKIT_OPTION_DEFINE(ENABLE_WEB_ANIMATIONS "Toggle Web Animations support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_WEB_AUDIO "Toggle Web Audio support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_WEB_REPLAY "Toggle Web Replay support" PRIVATE OFF) + WEBKIT_OPTION_DEFINE(ENABLE_WEB_RTC "Toggle WebRTC API support" PRIVATE OFF) WEBKIT_OPTION_DEFINE(ENABLE_WEB_SOCKETS "Toggle Web Sockets support" PRIVATE ON) - WEBKIT_OPTION_DEFINE(ENABLE_WEB_TIMING "Toggle Web Timing support" PRIVATE OFF) + WEBKIT_OPTION_DEFINE(ENABLE_WEB_TIMING "Toggle Web Timing support" PRIVATE ON) WEBKIT_OPTION_DEFINE(ENABLE_XSLT "Toggle XSLT support" PRIVATE ON) WEBKIT_OPTION_DEFINE(USE_SYSTEM_MALLOC "Toggle system allocator instead of WebKit's custom allocator" PRIVATE OFF) + WEBKIT_OPTION_DEPEND(ENABLE_WEB_RTC ENABLE_MEDIA_STREAM) WEBKIT_OPTION_DEPEND(ENABLE_ENCRYPTED_MEDIA_V2 ENABLE_VIDEO) WEBKIT_OPTION_DEPEND(ENABLE_DFG_JIT ENABLE_JIT) WEBKIT_OPTION_DEPEND(ENABLE_FTL_JIT ENABLE_DFG_JIT) WEBKIT_OPTION_DEPEND(ENABLE_SAMPLING_PROFILER ENABLE_JIT) WEBKIT_OPTION_DEPEND(ENABLE_MEDIA_CONTROLS_SCRIPT ENABLE_VIDEO) + WEBKIT_OPTION_DEPEND(ENABLE_MEDIA_SOURCE ENABLE_VIDEO) WEBKIT_OPTION_DEPEND(ENABLE_VIDEO_TRACK ENABLE_VIDEO) WEBKIT_OPTION_DEPEND(ENABLE_TOUCH_SLIDER ENABLE_TOUCH_EVENTS) endmacro() @@ -268,7 +268,7 @@ endif () option(${_name} "${_WEBKIT_AVAILABLE_OPTIONS_DESCRIPTION_${_name}}" ${_WEBKIT_AVAILABLE_OPTIONS_INITIAL_VALUE_${_name}}) - if (NOT _WEBKIT_AVAILABLE_OPTIONS_IS_PUBLIC_${_name}) + if (NOT ${_WEBKIT_AVAILABLE_OPTIONS_IS_PUBLIC_${_name}}) mark_as_advanced(FORCE ${_name}) endif () endforeach () diff -Nru webkit2gtk-2.12.3/Source/cmake/WebKitFS.cmake webkit2gtk-2.14.2/Source/cmake/WebKitFS.cmake --- webkit2gtk-2.12.3/Source/cmake/WebKitFS.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/WebKitFS.cmake 2016-09-16 09:56:48.000000000 +0000 @@ -34,11 +34,14 @@ file(MAKE_DIRECTORY ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}) file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Source/JavaScriptCore/runtime) -file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBCORE_DIR}) file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBINSPECTORUI_DIR}) file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBINSPECTORUI_DIR}/Protocol) file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBINSPECTORUI_DIR}/UserInterface/Protocol) +if (ENABLE_WEBCORE) + file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBCORE_DIR}) +endif () + if (ENABLE_WEBKIT2) file(MAKE_DIRECTORY ${DERIVED_SOURCES_WEBKIT2_DIR}) endif () diff -Nru webkit2gtk-2.12.3/Source/cmake/WebKitHelpers.cmake webkit2gtk-2.14.2/Source/cmake/WebKitHelpers.cmake --- webkit2gtk-2.12.3/Source/cmake/WebKitHelpers.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/WebKitHelpers.cmake 2016-11-03 07:04:21.000000000 +0000 @@ -20,6 +20,11 @@ set(OLD_COMPILE_FLAGS "-Wno-parentheses-equality ${OLD_COMPILE_FLAGS}") endif () + # Suppress -Wmissing-field-initializers due to a GCC bug, see https://bugs.webkit.org/show_bug.cgi?id=157888 for details. + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION MATCHES "4\\.9") + set(OLD_COMPILE_FLAGS "-Wno-missing-field-initializers ${OLD_COMPILE_FLAGS}") + endif () + # Enable warnings by default if (NOT ${OPTION_IGNORECXX_WARNINGS}) set(OLD_COMPILE_FLAGS "-Wall -Wextra -Wcast-align -Wformat-security -Wmissing-format-attribute -Wpointer-arith -Wundef -Wwrite-strings ${OLD_COMPILE_FLAGS}") diff -Nru webkit2gtk-2.12.3/Source/cmake/WebKitMacros.cmake webkit2gtk-2.14.2/Source/cmake/WebKitMacros.cmake --- webkit2gtk-2.12.3/Source/cmake/WebKitMacros.cmake 2016-05-23 13:40:29.000000000 +0000 +++ webkit2gtk-2.14.2/Source/cmake/WebKitMacros.cmake 2016-11-03 07:04:21.000000000 +0000 @@ -25,8 +25,9 @@ macro(ADD_PRECOMPILED_HEADER _header _cpp _source) if (MSVC) - get_filename_component(PrecompiledBasename ${_header} NAME_WE) - set(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${PrecompiledBasename}.pch") + get_filename_component(PrecompiledBasename ${_cpp} NAME_WE) + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_source}") + set(PrecompiledBinary "${CMAKE_CURRENT_BINARY_DIR}/${_source}/${PrecompiledBasename}.pch") set(_sources ${${_source}}) set_source_files_properties(${_cpp} @@ -74,42 +75,21 @@ if (EXISTS ${WEBCORE_DIR}/bindings/scripts/CodeGenerator${_generator}.pm) list(APPEND COMMON_GENERATOR_DEPENDENCIES ${WEBCORE_DIR}/bindings/scripts/CodeGenerator${_generator}.pm) endif () + if (EXISTS ${_base_dir}/CodeGenerator${_generator}.pm) + list(APPEND common_generator_dependencies ${_base_dir}/CodeGenerator${_generator}.pm) + endif () foreach (_file ${_input_files}) get_filename_component(_name ${_file} NAME_WE) - # Not all ObjC bindings generate a .mm file, and not all .mm files generated should be compiled. - if (${_generator} STREQUAL "ObjC") - list(FIND ObjC_BINDINGS_NO_MM ${_name} _no_mm_index) - if (${_no_mm_index} EQUAL -1) - set(_no_mm 0) - else () - set(_no_mm 1) - endif () - else () - set(_no_mm 0) - endif () - - if (${_no_mm}) - add_custom_command( - OUTPUT ${_destination}/${_prefix}${_name}.h - MAIN_DEPENDENCY ${_file} - DEPENDS ${COMMON_GENERATOR_DEPENDENCIES} - COMMAND ${PERL_EXECUTABLE} -I${WEBCORE_DIR}/bindings/scripts ${BINDING_GENERATOR} --defines "${_features}" --generator ${_generator} ${_idl_includes} --outputDir "${_destination}" --preprocessor "${CODE_GENERATOR_PREPROCESSOR}" --idlAttributesFile ${_idl_attributes_file} ${_supplemental_dependency} ${_file} - WORKING_DIRECTORY ${_base_dir} - VERBATIM) - - list(APPEND ${_output_source} ${_destination}/${_prefix}${_name}.h) - else () - add_custom_command( - OUTPUT ${_destination}/${_prefix}${_name}.${_extension} ${_destination}/${_prefix}${_name}.h - MAIN_DEPENDENCY ${_file} - DEPENDS ${COMMON_GENERATOR_DEPENDENCIES} - COMMAND ${PERL_EXECUTABLE} -I${WEBCORE_DIR}/bindings/scripts ${BINDING_GENERATOR} --defines "${_features}" --generator ${_generator} ${_idl_includes} --outputDir "${_destination}" --preprocessor "${CODE_GENERATOR_PREPROCESSOR}" --idlAttributesFile ${_idl_attributes_file} ${_supplemental_dependency} ${_file} - WORKING_DIRECTORY ${_base_dir} - VERBATIM) - list(APPEND ${_output_source} ${_destination}/${_prefix}${_name}.${_extension}) - endif () + add_custom_command( + OUTPUT ${_destination}/${_prefix}${_name}.${_extension} ${_destination}/${_prefix}${_name}.h + MAIN_DEPENDENCY ${_file} + DEPENDS ${COMMON_GENERATOR_DEPENDENCIES} + COMMAND ${PERL_EXECUTABLE} -I${WEBCORE_DIR}/bindings/scripts -I${_base_dir} ${BINDING_GENERATOR} --defines "${_features}" --generator ${_generator} ${_idl_includes} --outputDir "${_destination}" --preprocessor "${CODE_GENERATOR_PREPROCESSOR}" --idlAttributesFile ${_idl_attributes_file} ${_supplemental_dependency} ${_file} + WORKING_DIRECTORY ${_base_dir} + VERBATIM) + list(APPEND ${_output_source} ${_destination}/${_prefix}${_name}.${_extension}) endforeach () endmacro() @@ -243,7 +223,29 @@ endmacro() macro(WEBKIT_FRAMEWORK _target) - if (APPLE AND NOT PORT STREQUAL "GTK") + include_directories(${${_target}_INCLUDE_DIRECTORIES}) + include_directories(SYSTEM ${${_target}_SYSTEM_INCLUDE_DIRECTORIES}) + add_library(${_target} ${${_target}_LIBRARY_TYPE} + ${${_target}_HEADERS} + ${${_target}_SOURCES} + ) + target_link_libraries(${_target} ${${_target}_LIBRARIES}) + set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS "BUILDING_${_target}") + + if (${_target}_OUTPUT_NAME) + set_target_properties(${_target} PROPERTIES OUTPUT_NAME ${${_target}_OUTPUT_NAME}) + endif () + + if (${_target}_PRE_BUILD_COMMAND) + add_custom_target(_${_target}_PreBuild COMMAND ${${_target}_PRE_BUILD_COMMAND} VERBATIM) + add_dependencies(${_target} _${_target}_PreBuild) + endif () + + if (${_target}_POST_BUILD_COMMAND) + add_custom_command(TARGET ${_target} POST_BUILD COMMAND ${${_target}_POST_BUILD_COMMAND} VERBATIM) + endif () + + if (APPLE AND NOT PORT STREQUAL "GTK" AND NOT ${_target} STREQUAL "WTF") set_target_properties(${_target} PROPERTIES FRAMEWORK TRUE) install(TARGETS ${_target} FRAMEWORK DESTINATION ${LIB_INSTALL_DIR}) endif () @@ -328,14 +330,32 @@ endforeach () endmacro() +macro(MAKE_JS_FILE_ARRAYS _output_cpp _output_h _scripts _scripts_dependencies) + if (WIN32) + set(_python_path set "PYTHONPATH=${JavaScriptCore_SCRIPTS_DIR}" COMMAND) + else () + set(_python_path "PYTHONPATH=${JavaScriptCore_SCRIPTS_DIR}") + endif () + + add_custom_command( + OUTPUT ${_output_h} ${_output_cpp} + MAIN_DEPENDENCY ${WEBCORE_DIR}/Scripts/make-js-file-arrays.py + DEPENDS ${${_scripts}} + COMMAND ${_python_path} ${PYTHON_EXECUTABLE} ${WEBCORE_DIR}/Scripts/make-js-file-arrays.py ${_output_h} ${_output_cpp} ${${_scripts}} + VERBATIM) + list(APPEND WebCore_DERIVED_SOURCES ${_output_cpp}) + ADD_SOURCE_DEPENDENCIES(${${_scripts_dependencies}} ${_output_h} ${_output_cpp}) +endmacro() + # Helper macro for using all-in-one builds # This macro removes the sources included in the _all_in_one_file from the input _file_list. # _file_list is a list of source files # _all_in_one_file is an all-in-one cpp file includes other cpp files # _result_file_list is the output file list -macro(PROCESS_ALLINONE_FILE _file_list _all_in_one_file _result_file_list) +macro(PROCESS_ALLINONE_FILE _file_list _all_in_one_file _result_file_list _no_compile) file(STRINGS ${_all_in_one_file} _all_in_one_file_content) set(${_result_file_list} ${_file_list}) + set(_allins "") foreach (_line ${_all_in_one_file_content}) string(REGEX MATCH "^#include [\"<](.*)[\">]" _found ${_line}) if (_found) @@ -344,7 +364,14 @@ endforeach () foreach (_allin ${_allins}) - string(REGEX REPLACE ";[^;]*/${_allin};" ";" _new_result "${${_result_file_list}};") + if (${_no_compile}) + # For DerivedSources.cpp, we still need the derived sources to be generated, but we do not want them to be compiled + # individually. We add the header to the result file list so that CMake knows to keep generating the files. + string(REGEX REPLACE "(.*)\\.cpp" "\\1" _allin_no_ext ${_allin}) + string(REGEX REPLACE ";([^;]*/)${_allin_no_ext}\\.cpp;" ";\\1${_allin_no_ext}.h;" _new_result "${${_result_file_list}};") + else () + string(REGEX REPLACE ";[^;]*/${_allin};" ";" _new_result "${${_result_file_list}};") + endif () set(${_result_file_list} ${_new_result}) endforeach () diff -Nru webkit2gtk-2.12.3/Source/CMakeLists.txt webkit2gtk-2.14.2/Source/CMakeLists.txt --- webkit2gtk-2.12.3/Source/CMakeLists.txt 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/CMakeLists.txt 2016-09-16 09:56:47.000000000 +0000 @@ -9,8 +9,6 @@ add_subdirectory(JavaScriptCore) -add_subdirectory(WebCore) - if (WIN32 AND ENABLE_GRAPHICS_CONTEXT_3D) add_subdirectory(ThirdParty/ANGLE) endif () @@ -19,6 +17,15 @@ add_subdirectory(ThirdParty/gtest) endif () +if (USE_WOFF2) + add_subdirectory(ThirdParty/brotli) + add_subdirectory(ThirdParty/woff2) +endif () + +if (ENABLE_WEBCORE) + add_subdirectory(WebCore) +endif () + if (ENABLE_WEBKIT) add_subdirectory(WebKit) endif () @@ -37,8 +44,12 @@ endif () WEBKIT_SET_EXTRA_COMPILER_FLAGS(WTF ${ADDITIONAL_COMPILER_FLAGS}) WEBKIT_SET_EXTRA_COMPILER_FLAGS(JavaScriptCore ${ADDITIONAL_COMPILER_FLAGS}) -WEBKIT_SET_EXTRA_COMPILER_FLAGS(WebCoreTestSupport ${ADDITIONAL_COMPILER_FLAGS}) -WEBKIT_SET_EXTRA_COMPILER_FLAGS(WebCore ${ADDITIONAL_COMPILER_FLAGS}) + +if (ENABLE_WEBCORE) + WEBKIT_SET_EXTRA_COMPILER_FLAGS(WebCoreTestSupport ${ADDITIONAL_COMPILER_FLAGS}) + WEBKIT_SET_EXTRA_COMPILER_FLAGS(WebCore ${ADDITIONAL_COMPILER_FLAGS}) + WEBKIT_SET_EXTRA_COMPILER_FLAGS(WebCoreDerivedSources ${ADDITIONAL_COMPILER_FLAGS}) +endif () if (ENABLE_WEBKIT) WEBKIT_SET_EXTRA_COMPILER_FLAGS(WebKit ${ADDITIONAL_COMPILER_FLAGS}) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/APICallbackFunction.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/APICallbackFunction.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/APICallbackFunction.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/APICallbackFunction.h 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,6 +44,8 @@ template EncodedJSValue JSC_HOST_CALL APICallbackFunction::call(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); JSContextRef execRef = toRef(exec); JSObjectRef functionRef = toRef(exec->callee()); JSObjectRef thisObjRef = toRef(jsCast(exec->thisValue().toThis(exec, NotStrictMode))); @@ -61,7 +63,7 @@ result = jsCast(toJS(functionRef))->functionCallback()(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); // result must be a valid JSValue. if (!result) @@ -73,6 +75,8 @@ template EncodedJSValue JSC_HOST_CALL APICallbackFunction::construct(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); JSObject* constructor = exec->callee(); JSContextRef ctx = toRef(exec); JSObjectRef constructorRef = toRef(constructor); @@ -92,12 +96,12 @@ result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception); } if (exception) { - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return JSValue::encode(toJS(exec, exception)); } // result must be a valid JSValue. if (!result) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); return JSValue::encode(toJS(result)); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/APIUtils.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/APIUtils.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/APIUtils.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/APIUtils.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef APIUtils_h +#define APIUtils_h + +#include "Exception.h" +#include "JSCJSValue.h" +#include "JSGlobalObjectInspectorController.h" +#include "JSValueRef.h" + +enum class ExceptionStatus { + DidThrow, + DidNotThrow +}; + +inline ExceptionStatus handleExceptionIfNeeded(JSC::ExecState* exec, JSValueRef* returnedExceptionRef) +{ + if (exec->hadException()) { + JSC::Exception* exception = exec->exception(); + if (returnedExceptionRef) + *returnedExceptionRef = toRef(exec, exception->value()); + exec->clearException(); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception); +#endif + return ExceptionStatus::DidThrow; + } + return ExceptionStatus::DidNotThrow; +} + +inline void setException(JSC::ExecState* exec, JSValueRef* returnedExceptionRef, JSC::JSValue exception) +{ + if (returnedExceptionRef) + *returnedExceptionRef = toRef(exec, exception); +#if ENABLE(REMOTE_INSPECTOR) + exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, JSC::Exception::create(exec->vm(), exception)); +#endif +} + +#endif /* APIUtils_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JavaScript.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JavaScript.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JavaScript.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JavaScript.h 2016-09-16 09:56:47.000000000 +0000 @@ -31,6 +31,7 @@ #include #include #include +#include #include #endif /* JavaScript_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSBase.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSBase.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSBase.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSBase.h 2016-09-16 09:56:47.000000000 +0000 @@ -57,6 +57,8 @@ /*! @typedef JSPropertyNameAccumulatorRef An ordered set used to collect the names of a JavaScript object's properties. */ typedef struct OpaqueJSPropertyNameAccumulator* JSPropertyNameAccumulatorRef; +/*! @typedef JSTypedArrayBytesDeallocator A function used to deallocate bytes passed to a Typed Array constructor. The function should take two arguments. The first is a pointer to the bytes that were originally passed to the Typed Array constructor. The second is a pointer to additional information desired at the time the bytes are to be freed. */ +typedef void (*JSTypedArrayBytesDeallocator)(void* bytes, void* deallocatorContext); /* JavaScript data types */ @@ -136,7 +138,7 @@ /* Enable the Objective-C API for platforms with a modern runtime. */ #if !defined(JSC_OBJC_API_ENABLED) -#define JSC_OBJC_API_ENABLED (defined(__clang__) && defined(__APPLE__) && !defined(BUILDING_GTK__) && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && !defined(__i386__)) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE))) +#define JSC_OBJC_API_ENABLED (defined(__clang__) && defined(__APPLE__) && ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && !defined(__i386__)) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE))) #endif #endif /* JSBase_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackConstructor.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackConstructor.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackConstructor.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackConstructor.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -33,7 +33,6 @@ #include "JSLock.h" #include "ObjectPrototype.h" #include "JSCInlines.h" -#include namespace JSC { @@ -68,7 +67,7 @@ ConstructType JSCallbackConstructor::getConstructData(JSCell*, ConstructData& constructData) { constructData.native.function = APICallbackFunction::construct; - return ConstructTypeHost; + return ConstructType::Host; } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackFunction.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackFunction.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackFunction.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackFunction.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,7 +36,6 @@ #include "JSGlobalObject.h" #include "JSLock.h" #include "JSCInlines.h" -#include namespace JSC { @@ -58,7 +57,8 @@ JSCallbackFunction* JSCallbackFunction::create(VM& vm, JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, const String& name) { - JSCallbackFunction* function = new (NotNull, allocateCell(vm.heap)) JSCallbackFunction(vm, globalObject->callbackFunctionStructure(), callback); + Structure* structure = globalObject->callbackFunctionStructure(); + JSCallbackFunction* function = new (NotNull, allocateCell(vm.heap)) JSCallbackFunction(vm, structure, callback); function->finishCreation(vm, name); return function; } @@ -66,7 +66,7 @@ CallType JSCallbackFunction::getCallData(JSCell*, CallData& callData) { callData.native.function = APICallbackFunction::call; - return CallTypeHost; + return CallType::Host; } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2008, 2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * Redistribution and use in source and binary forms, with or without @@ -133,6 +133,9 @@ template bool JSCallbackObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObject = jsCast(object); JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(thisObject); @@ -159,7 +162,7 @@ value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception); } if (exception) { - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); slot.setValue(thisObject, ReadOnly | DontEnum, jsUndefined()); return true; } @@ -200,6 +203,9 @@ template JSValue JSCallbackObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + const JSCallbackObject* thisObject = jsCast(object); JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(thisObject); @@ -210,7 +216,7 @@ JSValueRef exception = 0; JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception); if (exception) { - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return jsUndefined(); } if (result) @@ -222,8 +228,11 @@ } template -void JSCallbackObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSCallbackObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObject = jsCast(cell); JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(thisObject); @@ -242,15 +251,15 @@ result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); if (result || exception) - return; + return result; } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { if (StaticValueEntry* entry = staticValues->get(name)) { if (entry->attributes & kJSPropertyAttributeReadOnly) - return; + return false; if (JSObjectSetPropertyCallback setProperty = entry->setProperty) { JSValueRef exception = 0; bool result; @@ -259,9 +268,9 @@ result = setProperty(ctx, thisRef, entry->propertyNameRef.get(), valueRef, &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); if (result || exception) - return; + return result; } } } @@ -272,9 +281,8 @@ if (Parent::getOwnPropertySlot(thisObject, exec, propertyName, getSlot)) return Parent::put(thisObject, exec, propertyName, value, slot); if (entry->attributes & kJSPropertyAttributeReadOnly) - return; - thisObject->JSCallbackObject::putDirect(exec->vm(), propertyName, value); // put as override property - return; + return false; + return thisObject->JSCallbackObject::putDirect(vm, propertyName, value); // put as override property } } } @@ -284,8 +292,11 @@ } template -void JSCallbackObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyIndex, JSValue value, bool shouldThrow) +bool JSCallbackObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyIndex, JSValue value, bool shouldThrow) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObject = jsCast(cell); JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(thisObject); @@ -304,15 +315,15 @@ result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); if (result || exception) - return; + return result; } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeReadOnly) - return; + return false; if (JSObjectSetPropertyCallback setProperty = entry->setProperty) { JSValueRef exception = 0; bool result; @@ -321,9 +332,9 @@ result = setProperty(ctx, thisRef, entry->propertyNameRef.get(), valueRef, &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); if (result || exception) - return; + return result; } } } @@ -331,7 +342,7 @@ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) { if (entry->attributes & kJSPropertyAttributeReadOnly) - return; + return false; break; } } @@ -343,6 +354,9 @@ template bool JSCallbackObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObject = jsCast(cell); JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(thisObject); @@ -360,7 +374,7 @@ result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); if (result || exception) return true; } @@ -400,15 +414,18 @@ for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (jsClass->callAsConstructor) { constructData.native.function = construct; - return ConstructTypeHost; + return ConstructType::Host; } } - return ConstructTypeNone; + return ConstructType::None; } template EncodedJSValue JSCallbackObject::construct(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSObject* constructor = exec->callee(); JSContextRef execRef = toRef(exec); JSObjectRef constructorRef = toRef(constructor); @@ -427,7 +444,7 @@ result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception)); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return JSValue::encode(result); } } @@ -439,6 +456,9 @@ template bool JSCallbackObject::customHasInstance(JSObject* object, ExecState* exec, JSValue value) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObject = jsCast(object); JSContextRef execRef = toRef(exec); JSObjectRef thisRef = toRef(thisObject); @@ -453,7 +473,7 @@ result = hasInstance(execRef, thisRef, valueRef, &exception); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return result; } } @@ -467,15 +487,18 @@ for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (jsClass->callAsFunction) { callData.native.function = call; - return CallTypeHost; + return CallType::Host; } } - return CallTypeNone; + return CallType::None; } template EncodedJSValue JSCallbackObject::call(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSContextRef execRef = toRef(exec); JSObjectRef functionRef = toRef(exec->callee()); JSObjectRef thisObjRef = toRef(jsCast(exec->thisValue().toThis(exec, NotStrictMode))); @@ -494,7 +517,7 @@ result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception)); } if (exception) - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return JSValue::encode(result); } } @@ -571,6 +594,9 @@ template JSValue JSCallbackObject::getStaticValue(ExecState* exec, PropertyName propertyName) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSObjectRef thisRef = toRef(this); if (StringImpl* name = propertyName.uid()) { @@ -585,7 +611,7 @@ value = getProperty(toRef(exec), thisRef, entry->propertyNameRef.get(), &exception); } if (exception) { - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return jsUndefined(); } if (value) @@ -602,6 +628,9 @@ template EncodedJSValue JSCallbackObject::staticFunctionGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObj = asCallbackObject(thisValue); // Check for cached or override property. @@ -614,7 +643,6 @@ if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) { if (StaticFunctionEntry* entry = staticFunctions->get(name)) { if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) { - VM& vm = exec->vm(); JSObject* o = JSCallbackFunction::create(vm, thisObj->globalObject(), callAsFunction, name); thisObj->putDirect(vm, propertyName, o, entry->attributes); return JSValue::encode(o); @@ -624,12 +652,15 @@ } } - return JSValue::encode(exec->vm().throwException(exec, createReferenceError(exec, ASCIILiteral("Static function property defined with NULL callAsFunction callback.")))); + return JSValue::encode(throwException(exec, scope, createReferenceError(exec, ASCIILiteral("Static function property defined with NULL callAsFunction callback.")))); } template EncodedJSValue JSCallbackObject::callbackGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSCallbackObject* thisObj = asCallbackObject(thisValue); JSObjectRef thisRef = toRef(thisObj); @@ -647,7 +678,7 @@ value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } if (exception) { - exec->vm().throwException(exec, toJS(exec, exception)); + throwException(exec, scope, toJS(exec, exception)); return JSValue::encode(jsUndefined()); } if (value) @@ -656,7 +687,7 @@ } } - return JSValue::encode(exec->vm().throwException(exec, createReferenceError(exec, ASCIILiteral("hasProperty callback returned true for a property that doesn't exist.")))); + return JSValue::encode(throwException(exec, scope, createReferenceError(exec, ASCIILiteral("hasProperty callback returned true for a property that doesn't exist.")))); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackObject.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackObject.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSCallbackObject.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSCallbackObject.h 2016-11-03 07:04:20.000000000 +0000 @@ -181,8 +181,8 @@ static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); - static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool shouldThrow); + static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + static bool putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool shouldThrow); static bool deleteProperty(JSCell*, ExecState*, PropertyName); static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSClassRef.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSClassRef.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSClassRef.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSClassRef.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -204,7 +204,7 @@ JSObject* prototype = JSCallbackObject::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction if (parentClass) { if (JSObject* parentPrototype = parentClass->prototype(exec)) - prototype->setPrototype(exec->vm(), parentPrototype); + prototype->setPrototypeDirect(exec->vm(), parentPrototype); } jsClassData.cachedPrototype = Weak(prototype); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSContextRef.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSContextRef.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSContextRef.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSContextRef.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -255,7 +255,7 @@ { } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { if (m_remainingCapacityForFrameCapture) { // If callee is unknown, but we've not added any frame yet, we should @@ -292,7 +292,7 @@ private: StringBuilder& m_builder; - unsigned m_remainingCapacityForFrameCapture; + mutable unsigned m_remainingCapacityForFrameCapture; }; JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSObjectRef.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSObjectRef.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSObjectRef.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSObjectRef.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -29,6 +29,7 @@ #include "JSObjectRefPrivate.h" #include "APICast.h" +#include "APIUtils.h" #include "ButterflyInlines.h" #include "CodeBlock.h" #include "CopiedSpaceInlines.h" @@ -62,34 +63,14 @@ using namespace JSC; -enum class ExceptionStatus { - DidThrow, - DidNotThrow -}; - -static ExceptionStatus handleExceptionIfNeeded(ExecState* exec, JSValueRef* returnedExceptionRef) -{ - if (exec->hadException()) { - Exception* exception = exec->exception(); - if (returnedExceptionRef) - *returnedExceptionRef = toRef(exec, exception->value()); - exec->clearException(); -#if ENABLE(REMOTE_INSPECTOR) - exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception); -#endif - return ExceptionStatus::DidThrow; - } - return ExceptionStatus::DidNotThrow; -} - JSClassRef JSClassCreate(const JSClassDefinition* definition) { initializeThreading(); - RefPtr jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype) + auto jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype) ? OpaqueJSClass::createNoAutomaticPrototype(definition) : OpaqueJSClass::create(definition); - return jsClass.release().leakRef(); + return &jsClass.leakRef(); } JSClassRef JSClassRetain(JSClassRef jsClass) @@ -117,7 +98,7 @@ JSCallbackObject* object = JSCallbackObject::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data); if (JSObject* prototype = jsClass->prototype(exec)) - object->setPrototype(exec->vm(), prototype); + object->setPrototypeDirect(exec->vm(), prototype); return toRef(object); } @@ -267,8 +248,8 @@ ExecState* exec = toJS(ctx); JSLockHolder locker(exec); - JSObject* jsObject = toJS(object); - return toRef(exec, jsObject->prototype()); + JSObject* jsObject = toJS(object); + return toRef(exec, jsObject->getPrototypeDirect()); } void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value) @@ -291,7 +272,7 @@ // Someday we might use proxies for something other than JSGlobalObjects, but today is not that day. RELEASE_ASSERT_NOT_REACHED(); } - jsObject->setPrototypeWithCycleCheck(exec, jsValue.isObject() ? jsValue : jsNull()); + jsObject->setPrototype(exec->vm(), exec, jsValue.isObject() ? jsValue : jsNull()); } bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) @@ -530,7 +511,7 @@ JSLockHolder locker(toJS(ctx)); CallData callData; JSCell* cell = toJS(object); - return cell->methodTable()->getCallData(cell, callData) != CallTypeNone; + return cell->methodTable()->getCallData(cell, callData) != CallType::None; } JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -553,7 +534,7 @@ CallData callData; CallType callType = jsObject->methodTable()->getCallData(jsObject, callData); - if (callType == CallTypeNone) + if (callType == CallType::None) return 0; JSValueRef result = toRef(exec, profiledCall(exec, ProfilingReason::API, jsObject, callType, callData, jsThisObject, argList)); @@ -568,7 +549,7 @@ return false; JSObject* jsObject = toJS(object); ConstructData constructData; - return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone; + return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructType::None; } JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -583,7 +564,7 @@ ConstructData constructData; ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData); - if (constructType == ConstructTypeNone) + if (constructType == ConstructType::None) return 0; MarkedArgumentBuffer argList; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSProfilerPrivate.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSProfilerPrivate.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSProfilerPrivate.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSProfilerPrivate.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSProfilerPrivate.h" - -#include "APICast.h" -#include "LegacyProfiler.h" -#include "OpaqueJSString.h" - -using namespace JSC; - -void JSStartProfiling(JSContextRef ctx, JSStringRef title) -{ - // Use an independent stopwatch for API-initiated profiling, since the user will expect it - // to be relative to when their command was issued. - RefPtr stopwatch = Stopwatch::create(); - stopwatch->start(); - LegacyProfiler::profiler()->startProfiling(toJS(ctx), title->string(), stopwatch.release()); -} - -void JSEndProfiling(JSContextRef ctx, JSStringRef title) -{ - ExecState* exec = toJS(ctx); - LegacyProfiler* profiler = LegacyProfiler::profiler(); - profiler->stopProfiling(exec, title->string()); -} - diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSProfilerPrivate.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSProfilerPrivate.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSProfilerPrivate.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSProfilerPrivate.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSProfiler_h -#define JSProfiler_h - -#include - -#ifndef __cplusplus -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*! -@function JSStartProfiling -@abstract Enables the profler. -@param ctx The execution context to use. -@param title The title of the profile. -@result The profiler is turned on. -*/ -JS_EXPORT void JSStartProfiling(JSContextRef ctx, JSStringRef title); - -/*! -@function JSEndProfiling -@abstract Disables the profler. -@param ctx The execution context to use. -@param title The title of the profile. -@result The profiler is turned off. If there is no name, the most recently started - profile is stopped. If the name does not match any profile then no profile - is stopped. -*/ -JS_EXPORT void JSEndProfiling(JSContextRef ctx, JSStringRef title); - -#ifdef __cplusplus -} -#endif - -#endif /* JSProfiler_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSScriptRef.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSScriptRef.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSScriptRef.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSScriptRef.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -76,7 +76,7 @@ { return !!JSC::parse( vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin, - JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, + JSParserStrictMode::NotStrict, JSParserCommentMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error); } @@ -93,7 +93,7 @@ startingLineNumber = std::max(1, startingLineNumber); - RefPtr result = OpaqueJSScript::create(vm, url ? url->string() : String(), startingLineNumber, String(StringImpl::createFromLiteral(source, length))); + auto result = OpaqueJSScript::create(vm, url ? url->string() : String(), startingLineNumber, String(StringImpl::createFromLiteral(source, length))); ParserError error; if (!parseScript(vm, SourceCode(result), error)) { @@ -104,7 +104,7 @@ return nullptr; } - return result.release().leakRef(); + return result.leakRef(); } JSScriptRef JSScriptCreateFromString(JSContextGroupRef contextGroup, JSStringRef url, int startingLineNumber, JSStringRef source, JSStringRef* errorMessage, int* errorLine) @@ -114,7 +114,7 @@ startingLineNumber = std::max(1, startingLineNumber); - RefPtr result = OpaqueJSScript::create(vm, url ? url->string() : String(), startingLineNumber, source->string()); + auto result = OpaqueJSScript::create(vm, url ? url->string() : String(), startingLineNumber, source->string()); ParserError error; if (!parseScript(vm, SourceCode(result), error)) { @@ -125,7 +125,7 @@ return nullptr; } - return result.release().leakRef(); + return result.leakRef(); } void JSScriptRetain(JSScriptRef script) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSStringRef.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSStringRef.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSStringRef.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSStringRef.h 2016-11-03 07:04:20.000000000 +0000 @@ -41,7 +41,9 @@ && !((defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__linux__)) /* RVCT */ /*! @typedef JSChar -@abstract A Unicode character. +@abstract A UTF-16 code unit. One, or a sequence of two, can encode any Unicode + character. As with all scalar types, endianness depends on the underlying + architecture. */ typedef unsigned short JSChar; #else diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSTypedArray.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSTypedArray.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSTypedArray.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSTypedArray.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2015 Dominic Szablewski (dominic@phoboslab.org) + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSTypedArray.h" + +#include "APICast.h" +#include "APIUtils.h" +#include "ClassInfo.h" +#include "Error.h" +#include "JSArrayBufferViewInlines.h" +#include "JSCInlines.h" +#include "JSDataView.h" +#include "JSGenericTypedArrayViewInlines.h" +#include "JSTypedArrays.h" +#include + +using namespace JSC; + +// Helper functions. + +inline JSTypedArrayType toJSTypedArrayType(TypedArrayType type) +{ + switch (type) { + case JSC::TypeDataView: + case NotTypedArray: + return kJSTypedArrayTypeNone; + case TypeInt8: + return kJSTypedArrayTypeInt8Array; + case TypeUint8: + return kJSTypedArrayTypeUint8Array; + case TypeUint8Clamped: + return kJSTypedArrayTypeUint8ClampedArray; + case TypeInt16: + return kJSTypedArrayTypeInt16Array; + case TypeUint16: + return kJSTypedArrayTypeUint16Array; + case TypeInt32: + return kJSTypedArrayTypeInt32Array; + case TypeUint32: + return kJSTypedArrayTypeUint32Array; + case TypeFloat32: + return kJSTypedArrayTypeFloat32Array; + case TypeFloat64: + return kJSTypedArrayTypeFloat64Array; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +inline TypedArrayType toTypedArrayType(JSTypedArrayType type) +{ + switch (type) { + case kJSTypedArrayTypeArrayBuffer: + case kJSTypedArrayTypeNone: + return NotTypedArray; + case kJSTypedArrayTypeInt8Array: + return TypeInt8; + case kJSTypedArrayTypeUint8Array: + return TypeUint8; + case kJSTypedArrayTypeUint8ClampedArray: + return TypeUint8Clamped; + case kJSTypedArrayTypeInt16Array: + return TypeInt16; + case kJSTypedArrayTypeUint16Array: + return TypeUint16; + case kJSTypedArrayTypeInt32Array: + return TypeInt32; + case kJSTypedArrayTypeUint32Array: + return TypeUint32; + case kJSTypedArrayTypeFloat32Array: + return TypeFloat32; + case kJSTypedArrayTypeFloat64Array: + return TypeFloat64; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +static JSObject* createTypedArray(ExecState* exec, JSTypedArrayType type, RefPtr&& buffer, size_t offset, size_t length) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSGlobalObject* globalObject = exec->lexicalGlobalObject(); + if (!buffer) { + throwOutOfMemoryError(exec, scope); + return nullptr; + } + switch (type) { + case kJSTypedArrayTypeInt8Array: + return JSInt8Array::create(exec, globalObject->typedArrayStructure(TypeInt8), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeInt16Array: + return JSInt16Array::create(exec, globalObject->typedArrayStructure(TypeInt16), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeInt32Array: + return JSInt32Array::create(exec, globalObject->typedArrayStructure(TypeInt32), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeUint8Array: + return JSUint8Array::create(exec, globalObject->typedArrayStructure(TypeUint8), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeUint8ClampedArray: + return JSUint8ClampedArray::create(exec, globalObject->typedArrayStructure(TypeUint8Clamped), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeUint16Array: + return JSUint16Array::create(exec, globalObject->typedArrayStructure(TypeUint16), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeUint32Array: + return JSUint32Array::create(exec, globalObject->typedArrayStructure(TypeUint32), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeFloat32Array: + return JSFloat32Array::create(exec, globalObject->typedArrayStructure(TypeFloat32), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeFloat64Array: + return JSFloat64Array::create(exec, globalObject->typedArrayStructure(TypeFloat64), WTFMove(buffer), offset, length); + case kJSTypedArrayTypeArrayBuffer: + case kJSTypedArrayTypeNone: + RELEASE_ASSERT_NOT_REACHED(); + } + return nullptr; +} + +// Implementations of the API functions. + +JSTypedArrayType JSValueGetTypedArrayType(JSContextRef ctx, JSValueRef valueRef, JSValueRef*) +{ + + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + + JSValue value = toJS(exec, valueRef); + if (!value.isObject()) + return kJSTypedArrayTypeNone; + JSObject* object = value.getObject(); + + if (jsDynamicCast(object)) + return kJSTypedArrayTypeArrayBuffer; + + return toJSTypedArrayType(object->classInfo()->typedArrayStorageType); +} + +JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t length, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + + if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer) + return nullptr; + + unsigned elementByteSize = elementSize(toTypedArrayType(arrayType)); + + auto buffer = ArrayBuffer::tryCreate(length, elementByteSize); + JSObject* result = createTypedArray(exec, arrayType, WTFMove(buffer), 0, length); + if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) + return nullptr; + return toRef(result); +} + +JSObjectRef JSObjectMakeTypedArrayWithBytesNoCopy(JSContextRef ctx, JSTypedArrayType arrayType, void* bytes, size_t length, JSTypedArrayBytesDeallocator destructor, void* destructorContext, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + + if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer) + return nullptr; + + unsigned elementByteSize = elementSize(toTypedArrayType(arrayType)); + + RefPtr buffer = ArrayBuffer::createFromBytes(bytes, length, [=](void* p) { + if (destructor) + destructor(p, destructorContext); + }); + JSObject* result = createTypedArray(exec, arrayType, WTFMove(buffer), 0, length / elementByteSize); + if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) + return nullptr; + return toRef(result); +} + +JSObjectRef JSObjectMakeTypedArrayWithArrayBuffer(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef jsBufferRef, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + + if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer) + return nullptr; + + JSArrayBuffer* jsBuffer = jsDynamicCast(toJS(jsBufferRef)); + if (!jsBuffer) { + setException(exec, exception, createTypeError(exec, "JSObjectMakeTypedArrayWithArrayBuffer expects buffer to be an Array Buffer object")); + return nullptr; + } + + RefPtr buffer = jsBuffer->impl(); + unsigned elementByteSize = elementSize(toTypedArrayType(arrayType)); + + JSObject* result = createTypedArray(exec, arrayType, WTFMove(buffer), 0, buffer->byteLength() / elementByteSize); + if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) + return nullptr; + return toRef(result); +} + +JSObjectRef JSObjectMakeTypedArrayWithArrayBufferAndOffset(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef jsBufferRef, size_t offset, size_t length, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + + if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer) + return nullptr; + + JSArrayBuffer* jsBuffer = jsDynamicCast(toJS(jsBufferRef)); + if (!jsBuffer) { + setException(exec, exception, createTypeError(exec, "JSObjectMakeTypedArrayWithArrayBuffer expects buffer to be an Array Buffer object")); + return nullptr; + } + + JSObject* result = createTypedArray(exec, arrayType, jsBuffer->impl(), offset, length); + if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) + return nullptr; + return toRef(result); +} + +void* JSObjectGetTypedArrayBytesPtr(JSContextRef ctx, JSObjectRef objectRef, JSValueRef*) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + JSObject* object = toJS(objectRef); + + if (JSArrayBufferView* typedArray = jsDynamicCast(object)) { + ArrayBuffer* buffer = typedArray->buffer(); + buffer->pinAndLock(); + return buffer->data(); + } + return nullptr; +} + +size_t JSObjectGetTypedArrayLength(JSContextRef, JSObjectRef objectRef, JSValueRef*) +{ + JSObject* object = toJS(objectRef); + + if (JSArrayBufferView* typedArray = jsDynamicCast(object)) + return typedArray->length(); + + return 0; +} + +size_t JSObjectGetTypedArrayByteLength(JSContextRef, JSObjectRef objectRef, JSValueRef*) +{ + JSObject* object = toJS(objectRef); + + if (JSArrayBufferView* typedArray = jsDynamicCast(object)) + return typedArray->length() * elementSize(typedArray->classInfo()->typedArrayStorageType); + + return 0; +} + +size_t JSObjectGetTypedArrayByteOffset(JSContextRef, JSObjectRef objectRef, JSValueRef*) +{ + JSObject* object = toJS(objectRef); + + if (JSArrayBufferView* typedArray = jsDynamicCast(object)) + return typedArray->byteOffset(); + + return 0; +} + +JSObjectRef JSObjectGetTypedArrayBuffer(JSContextRef ctx, JSObjectRef objectRef, JSValueRef*) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + JSObject* object = toJS(objectRef); + + if (JSArrayBufferView* typedArray = jsDynamicCast(object)) + return toRef(exec->vm().m_typedArrayController->toJS(exec, typedArray->globalObject(), typedArray->buffer())); + + return nullptr; +} + +JSObjectRef JSObjectMakeArrayBufferWithBytesNoCopy(JSContextRef ctx, void* bytes, size_t byteLength, JSTypedArrayBytesDeallocator bytesDeallocator, void* deallocatorContext, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + + auto buffer = ArrayBuffer::createFromBytes(bytes, byteLength, [=](void* p) { + if (bytesDeallocator) + bytesDeallocator(p, deallocatorContext); + }); + + JSArrayBuffer* jsBuffer = JSArrayBuffer::create(exec->vm(), exec->lexicalGlobalObject()->arrayBufferStructure(), WTFMove(buffer)); + if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) + return nullptr; + + return toRef(jsBuffer); +} + +void* JSObjectGetArrayBufferBytesPtr(JSContextRef ctx, JSObjectRef objectRef, JSValueRef*) +{ + ExecState* exec = toJS(ctx); + JSLockHolder locker(exec); + JSObject* object = toJS(objectRef); + + if (JSArrayBuffer* jsBuffer = jsDynamicCast(object)) { + ArrayBuffer* buffer = jsBuffer->impl(); + buffer->pinAndLock(); + return buffer->data(); + } + return nullptr; +} + +size_t JSObjectGetArrayBufferByteLength(JSContextRef, JSObjectRef objectRef, JSValueRef*) +{ + JSObject* object = toJS(objectRef); + + if (JSArrayBuffer* jsBuffer = jsDynamicCast(object)) + return jsBuffer->impl()->byteLength(); + + return 0; +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSTypedArray.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSTypedArray.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSTypedArray.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSTypedArray.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2015 Dominic Szablewski (dominic@phoboslab.org) + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSTypedArray_h +#define JSTypedArray_h + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------- Typed Array functions -------------- + +/*! + @function + @abstract Creates a JavaScript Typed Array object with the given number of elements. + @param ctx The execution context to use. + @param arrayType A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned. + @param length The number of elements to be in the new Typed Array. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObjectRef that is a Typed Array with all elements set to zero or NULL if there was an error. + */ +JS_EXPORT JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t length, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Creates a JavaScript Typed Array object from an existing pointer. + @param ctx The execution context to use. + @param arrayType A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned. + @param bytes A pointer to the byte buffer to be used as the backing store of the Typed Array object. + @param byteLength The number of bytes pointed to by the parameter bytes. + @param bytesDeallocator The allocator to use to deallocate the external buffer when the JSTypedArrayData object is deallocated. + @param deallocatorContext A pointer to pass back to the deallocator. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObjectRef Typed Array whose backing store is the same as the one pointed to by bytes or NULL if there was an error. + @discussion If an exception is thrown during this function the bytesDeallocator will always be called. + */ +JS_EXPORT JSObjectRef JSObjectMakeTypedArrayWithBytesNoCopy(JSContextRef ctx, JSTypedArrayType arrayType, void* bytes, size_t byteLength, JSTypedArrayBytesDeallocator bytesDeallocator, void* deallocatorContext, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Creates a JavaScript Typed Array object from an existing JavaScript Array Buffer object. + @param ctx The execution context to use. + @param arrayType A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned. + @param buffer An Array Buffer object that should be used as the backing store for the created JavaScript Typed Array object. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObjectRef that is a Typed Array or NULL if there was an error. The backing store of the Typed Array will be buffer. + */ +JS_EXPORT JSObjectRef JSObjectMakeTypedArrayWithArrayBuffer(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef buffer, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Creates a JavaScript Typed Array object from an existing JavaScript Array Buffer object with the given offset and length. + @param ctx The execution context to use. + @param arrayType A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned. + @param buffer An Array Buffer object that should be used as the backing store for the created JavaScript Typed Array object. + @param byteOffset The byte offset for the created Typed Array. byteOffset should aligned with the element size of arrayType. + @param length The number of elements to include in the Typed Array. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObjectRef that is a Typed Array or NULL if there was an error. The backing store of the Typed Array will be buffer. + */ +JS_EXPORT JSObjectRef JSObjectMakeTypedArrayWithArrayBufferAndOffset(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef buffer, size_t byteOffset, size_t length, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns a temporary pointer to the backing store of a JavaScript Typed Array object. + @param ctx The execution context to use. + @param object The Typed Array object whose backing store pointer to return. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A pointer to the raw data buffer that serves as object's backing store or NULL if object is not a Typed Array object. + @discussion The pointer returned by this function is temporary and is not guaranteed to remain valid across JavaScriptCore API calls. + */ +JS_EXPORT void* JSObjectGetTypedArrayBytesPtr(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns the length of a JavaScript Typed Array object. + @param ctx The execution context to use. + @param object The Typed Array object whose length to return. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result The length of the Typed Array object or 0 if the object is not a Typed Array object. + */ +JS_EXPORT size_t JSObjectGetTypedArrayLength(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns the byte length of a JavaScript Typed Array object. + @param ctx The execution context to use. + @param object The Typed Array object whose byte length to return. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result The byte length of the Typed Array object or 0 if the object is not a Typed Array object. + */ +JS_EXPORT size_t JSObjectGetTypedArrayByteLength(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns the byte offset of a JavaScript Typed Array object. + @param ctx The execution context to use. + @param object The Typed Array object whose byte offset to return. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result The byte offset of the Typed Array object or 0 if the object is not a Typed Array object. + */ +JS_EXPORT size_t JSObjectGetTypedArrayByteOffset(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns the JavaScript Array Buffer object that is used as the backing of a JavaScript Typed Array object. + @param ctx The execution context to use. + @param object The JSObjectRef whose Typed Array type data pointer to obtain. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObjectRef with a JSTypedArrayType of kJSTypedArrayTypeArrayBuffer or NULL if object is not a Typed Array. + */ +JS_EXPORT JSObjectRef JSObjectGetTypedArrayBuffer(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +// ------------- Array Buffer functions ------------- + +/*! + @function + @abstract Creates a JavaScript Array Buffer object from an existing pointer. + @param ctx The execution context to use. + @param bytes A pointer to the byte buffer to be used as the backing store of the Typed Array object. + @param byteLength The number of bytes pointed to by the parameter bytes. + @param bytesDeallocator The allocator to use to deallocate the external buffer when the Typed Array data object is deallocated. + @param deallocatorContext A pointer to pass back to the deallocator. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObjectRef Array Buffer whose backing store is the same as the one pointed to by bytes or NULL if there was an error. + @discussion If an exception is thrown during this function the bytesDeallocator will always be called. + */ +JS_EXPORT JSObjectRef JSObjectMakeArrayBufferWithBytesNoCopy(JSContextRef ctx, void* bytes, size_t byteLength, JSTypedArrayBytesDeallocator bytesDeallocator, void* deallocatorContext, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns a pointer to the data buffer that serves as the backing store for a JavaScript Typed Array object. + @param buffer The Array Buffer object whose internal backing store pointer to return. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A pointer to the raw data buffer that serves as object's backing store or NULL if object is not an Array Buffer object. + @discussion The pointer returned by this function is temporary and is not guaranteed to remain valid across JavaScriptCore API calls. + */ +JS_EXPORT void* JSObjectGetArrayBufferBytesPtr(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +/*! + @function + @abstract Returns the number of bytes in a JavaScript data object. + @param ctx The execution context to use. + @param object The JS Arary Buffer object whose length in bytes to return. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result The number of bytes stored in the data object. + */ +JS_EXPORT size_t JSObjectGetArrayBufferByteLength(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + +#ifdef __cplusplus +} +#endif + +#endif /* JSTypedArray_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSValueRef.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSValueRef.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSValueRef.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSValueRef.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,7 @@ #include "JSValueRef.h" #include "APICast.h" +#include "APIUtils.h" #include "DateInstance.h" #include "Exception.h" #include "JSAPIWrapperObject.h" @@ -53,26 +54,6 @@ using namespace JSC; -enum class ExceptionStatus { - DidThrow, - DidNotThrow -}; - -static ExceptionStatus handleExceptionIfNeeded(ExecState* exec, JSValueRef* returnedExceptionRef) -{ - if (exec->hadException()) { - Exception* exception = exec->exception(); - if (returnedExceptionRef) - *returnedExceptionRef = toRef(exec, exception->value()); - exec->clearException(); -#if ENABLE(REMOTE_INSPECTOR) - exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception); -#endif - return ExceptionStatus::DidThrow; - } - return ExceptionStatus::DidNotThrow; -} - #if PLATFORM(MAC) static bool evernoteHackNeeded() { @@ -420,10 +401,10 @@ JSValue jsValue = toJS(exec, value); - RefPtr stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec))); + auto stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec))); if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) stringRef = nullptr; - return stringRef.release().leakRef(); + return stringRef.leakRef(); } JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSValueRef.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSValueRef.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSValueRef.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSValueRef.h 2016-11-03 07:04:20.000000000 +0000 @@ -52,6 +52,36 @@ kJSTypeObject } JSType; +/*! + @enum JSTypedArrayType + @abstract A constant identifying the Typed Array type of a JSObjectRef. + @constant kJSTypedArrayTypeInt8Array Int8Array + @constant kJSTypedArrayTypeInt16Array Int16Array + @constant kJSTypedArrayTypeInt32Array Int32Array + @constant kJSTypedArrayTypeUint8Array Uint8Array + @constant kJSTypedArrayTypeUint8ClampedArray Uint8ClampedArray + @constant kJSTypedArrayTypeUint16Array Uint16Array + @constant kJSTypedArrayTypeUint32Array Uint32Array + @constant kJSTypedArrayTypeFloat32Array Float32Array + @constant kJSTypedArrayTypeFloat64Array Float64Array + @constant kJSTypedArrayTypeArrayBuffer ArrayBuffer + @constant kJSTypedArrayTypeNone Not a Typed Array + + */ +typedef enum { + kJSTypedArrayTypeInt8Array, + kJSTypedArrayTypeInt16Array, + kJSTypedArrayTypeInt32Array, + kJSTypedArrayTypeUint8Array, + kJSTypedArrayTypeUint8ClampedArray, + kJSTypedArrayTypeUint16Array, + kJSTypedArrayTypeUint32Array, + kJSTypedArrayTypeFloat32Array, + kJSTypedArrayTypeFloat64Array, + kJSTypedArrayTypeArrayBuffer, + kJSTypedArrayTypeNone, +} JSTypedArrayType CF_ENUM_AVAILABLE(10_12, 10_0); + #ifdef __cplusplus extern "C" { #endif @@ -147,6 +177,16 @@ */ JS_EXPORT bool JSValueIsDate(JSContextRef ctx, JSValueRef value) CF_AVAILABLE(10_11, 9_0); +/*! +@function +@abstract Returns a JavaScript value's Typed Array type. +@param ctx The execution context to use. +@param value The JSValue whose Typed Array type to return. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result A value of type JSTypedArrayType that identifies value's Typed Array type, or kJSTypedArrayTypeNone if the value is not a Typed Array object. + */ +JS_EXPORT JSTypedArrayType JSValueGetTypedArrayType(JSContextRef ctx, JSValueRef value, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0); + /* Comparing values */ /*! diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -33,8 +33,6 @@ #include "JSCInlines.h" #include "Weak.h" #include "WeakGCMapInlines.h" -#include -#include using namespace WTF; using namespace JSC; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/ObjCCallbackFunction.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/ObjCCallbackFunction.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/ObjCCallbackFunction.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/ObjCCallbackFunction.h 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,7 +62,7 @@ ObjCCallbackFunctionImpl* impl() const { return m_impl.get(); } protected: - ObjCCallbackFunction(VM&, JSGlobalObject*, JSObjectCallAsFunctionCallback, JSObjectCallAsConstructorCallback, std::unique_ptr); + ObjCCallbackFunction(VM&, Structure*, JSObjectCallAsFunctionCallback, JSObjectCallAsConstructorCallback, std::unique_ptr); private: static CallType getCallData(JSCell*, CallData&); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -142,9 +142,9 @@ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; - scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); + scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); - scriptBuilder.append(") break; } } foo();"); + scriptBuilder.appendLiteral(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; @@ -178,16 +178,16 @@ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; - scriptBuilder.append("var startTime = currentCPUTime();" + scriptBuilder.appendLiteral("var startTime = currentCPUTime();" "function recurse(i) {" "'use strict';" "if (i % 1000 === 0) {" "if (currentCPUTime() - startTime >"); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); - scriptBuilder.append(" ) { return; }"); - scriptBuilder.append(" }"); - scriptBuilder.append(" return recurse(i + 1); }"); - scriptBuilder.append("recurse(0);"); + scriptBuilder.appendLiteral(" ) { return; }"); + scriptBuilder.appendLiteral(" }"); + scriptBuilder.appendLiteral(" return recurse(i + 1); }"); + scriptBuilder.appendLiteral("recurse(0);"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; @@ -221,9 +221,9 @@ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; - scriptBuilder.append("function foo() { var startTime = currentCPUTime(); try { while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); + scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); try { while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); - scriptBuilder.append(") break; } } catch(e) { } } foo();"); + scriptBuilder.appendLiteral(") break; } } catch(e) { } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; @@ -258,9 +258,9 @@ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; - scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); + scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); - scriptBuilder.append(") break; } } foo();"); + scriptBuilder.appendLiteral(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; @@ -295,9 +295,9 @@ unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis; StringBuilder scriptBuilder; - scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); + scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(timeAfterWatchdogShouldHaveFired / 1000.0); - scriptBuilder.append(") break; } } foo();"); + scriptBuilder.appendLiteral(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; @@ -332,9 +332,9 @@ unsigned maxBusyLoopTime = 750 + tierAdjustmentMillis; StringBuilder scriptBuilder; - scriptBuilder.append("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); + scriptBuilder.appendLiteral("function foo() { var startTime = currentCPUTime(); while (true) { for (var i = 0; i < 1000; i++); if (currentCPUTime() - startTime > "); scriptBuilder.appendNumber(maxBusyLoopTime / 1000.0); // in seconds. - scriptBuilder.append(") break; } } foo();"); + scriptBuilder.appendLiteral(") break; } } foo();"); JSStringRef script = JSStringCreateWithUTF8CString(scriptBuilder.toString().utf8().data()); exception = nullptr; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/FunctionOverridesTest.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FunctionOverridesTest.h" + +#include "FunctionOverrides.h" +#include "InitializeThreading.h" +#include "JSContextRefPrivate.h" +#include "JavaScriptCore.h" +#include "Options.h" +#include +#include + +using JSC::Options; + +int testFunctionOverrides() +{ + bool failed = false; + + JSC::initializeThreading(); + Options::initialize(); // Ensure options is initialized first. + + const char* oldFunctionOverrides = Options::functionOverrides(); + + Options::functionOverrides() = "testapi-function-overrides.js"; + JSC::FunctionOverrides::reinstallOverrides(); + + JSGlobalContextRef context = JSGlobalContextCreateInGroup(nullptr, nullptr); + + JSObjectRef globalObject = JSContextGetGlobalObject(context); + ASSERT_UNUSED(globalObject, JSValueIsObject(context, globalObject)); + + const char* scriptString = + "var str = '';" "\n" + "function f1() { /* Original f1 */ }" "\n" + "str += f1 + '\\n';" "\n" + "var f2 = function() {" "\n" + " // Original f2" "\n" + "}" "\n" + "str += f2 + '\\n';" "\n" + "str += (function() { /* Original f3 */ }) + '\\n';" "\n" + "var f4Source = '/* Original f4 */'" "\n" + "var f4 = new Function(f4Source);" "\n" + "str += f4 + '\\n';" "\n" + "\n" + "var expectedStr =" "\n" + "'function f1() { /* Overridden f1 */ }\\n" + "function () { /* Overridden f2 */ }\\n" + "function () { /* Overridden f3 */ }\\n" + "function anonymous() { /* Overridden f4 */ }\\n';" + "var result = (str == expectedStr);" "\n" + "result"; + + JSStringRef script = JSStringCreateWithUTF8CString(scriptString); + JSValueRef exception = nullptr; + JSValueRef resultRef = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); + + if (!JSValueIsBoolean(context, resultRef) || !JSValueToBoolean(context, resultRef)) + failed = true; + + JSGlobalContextRelease(context); + + JSC::Options::functionOverrides() = oldFunctionOverrides; + JSC::FunctionOverrides::reinstallOverrides(); + + printf("%s: function override tests.\n", failed ? "FAIL" : "PASS"); + + return failed; +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/FunctionOverridesTest.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Returns 1 if failures were encountered. Else, returns 0. */ +int testFunctionOverrides(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/PingPongStackOverflowTest.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -56,13 +56,13 @@ result = JSObjectCallAsFunction(context, function, constructor, 1, &possibleValue, exception); } else { StringBuilder builder; - builder.append("dummy.valueOf([0]"); + builder.appendLiteral("dummy.valueOf([0]"); for (int i = 1; i < 35000; i++) { - builder.append(", ["); + builder.appendLiteral(", ["); builder.appendNumber(i); - builder.append("]"); + builder.appendLiteral("]"); } - builder.append(");"); + builder.appendLiteral(");"); JSStringRef script = JSStringCreateWithUTF8CString(builder.toString().utf8().data()); result = JSEvaluateScript(context, script, NULL, NULL, 1, exception); @@ -120,13 +120,13 @@ JSC::initializeThreading(); Options::initialize(); // Ensure options is initialized first. + auto origSoftReservedZoneSize = Options::softReservedZoneSize(); auto origReservedZoneSize = Options::reservedZoneSize(); - auto origErrorModeReservedZoneSize = Options::errorModeReservedZoneSize(); auto origUseLLInt = Options::useLLInt(); auto origMaxPerThreadStackUsage = Options::maxPerThreadStackUsage(); - Options::reservedZoneSize() = 128 * KB; - Options::errorModeReservedZoneSize() = 64 * KB; + Options::softReservedZoneSize() = 128 * KB; + Options::reservedZoneSize() = 64 * KB; #if ENABLE(JIT) // Normally, we want to disable the LLINT to force the use of JITted code which is necessary for // reproducing the regression in https://bugs.webkit.org/show_bug.cgi?id=148749. However, we only @@ -158,7 +158,7 @@ JSStringRelease(PingPongStackOverflowObjectString); unsigned stackSize = 32 * KB; - Options::maxPerThreadStackUsage() = stackSize + Options::reservedZoneSize(); + Options::maxPerThreadStackUsage() = stackSize + Options::softReservedZoneSize(); exception = nullptr; scriptResult = JSEvaluateScript(context, script, nullptr, nullptr, 1, &exception); @@ -173,8 +173,8 @@ printf("PASS: PingPongStackOverflow test.\n"); } + Options::softReservedZoneSize() = origSoftReservedZoneSize; Options::reservedZoneSize() = origReservedZoneSize; - Options::errorModeReservedZoneSize() = origErrorModeReservedZoneSize; Options::useLLInt() = origUseLLInt; Options::maxPerThreadStackUsage() = origMaxPerThreadStackUsage; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/testapi.c webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/testapi.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/testapi.c 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/testapi.c 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,15 +42,16 @@ #include "CompareAndSwapTest.h" #include "CustomGlobalObjectClassTest.h" #include "ExecutionTimeLimitTest.h" +#include "FunctionOverridesTest.h" #include "GlobalContextWithFinalizerTest.h" #include "PingPongStackOverflowTest.h" +#include "TypedArrayCTest.h" #if JSC_OBJC_API_ENABLED void testObjectiveCAPI(void); #endif bool assertTrue(bool value, const char* message); -extern void JSSynchronousGarbageCollectForDebugging(JSContextRef); static JSGlobalContextRef context; int failed; @@ -1113,19 +1114,9 @@ val.name = "something"; } - int main(int argc, char* argv[]) { #if OS(WINDOWS) -#if defined(_M_X64) || defined(__x86_64__) - // The VS2013 runtime has a bug where it mis-detects AVX-capable processors - // if the feature has been disabled in firmware. This causes us to crash - // in some of the math functions. For now, we disable those optimizations - // because Microsoft is not going to fix the problem in VS2013. - // FIXME: http://webkit.org/b/141449: Remove this workaround when we switch to VS2015+. - _set_FMA3_enable(0); -#endif - // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the // error mode here to work around Cygwin's behavior. See . @@ -1138,6 +1129,8 @@ testObjectiveCAPI(); #endif + + const char *scriptPath = "testapi.js"; if (argc > 1) { scriptPath = argv[1]; @@ -1891,7 +1884,9 @@ JSGlobalContextRelease(context); } + failed = testTypedArrayCAPI() || failed; failed = testExecutionTimeLimit() || failed; + failed = testFunctionOverrides() || failed; failed = testGlobalContextWithFinalizer() || failed; failed = testPingPongStackOverflow() || failed; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/testapi-function-overrides.js webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/testapi-function-overrides.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/testapi-function-overrides.js 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/testapi-function-overrides.js 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,16 @@ +// testapi function overrides for testing. +override %%%{ /* Original f1 */ }%%% +with %%%{ /* Overridden f1 */ }%%% + +override #$%{ + // Original f2 +}#$% +with $$${ /* Overridden f2 */ }$$$ + +override %%%{ /* Original f3 */ }%%% +with %%%{ /* Overridden f3 */ }%%% + +override %%%{ +/* Original f4 */ +}%%% +with %%%{ /* Overridden f4 */ }%%% diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/TypedArrayCTest.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "TypedArrayCTest.h" + +#include "JavaScriptCore.h" +#include + +extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef); + +static void id(void*, void*) { } +static void freePtr(void* ptr, void*) +{ + free(ptr); +} + +static const unsigned numLengths = 3; + +static const unsigned lengths[numLengths] = +{ + 0, + 1, + 10, +}; + +static const unsigned byteSizes[kJSTypedArrayTypeArrayBuffer] = +{ + 1, // kJSTypedArrayTypeInt8Array + 2, // kJSTypedArrayTypeInt16Array + 4, // kJSTypedArrayTypeInt32Array + 1, // kJSTypedArrayTypeUint8Array + 1, // kJSTypedArrayTypeUint8ClampedArray + 2, // kJSTypedArrayTypeUint16Array + 4, // kJSTypedArrayTypeUint32Array + 4, // kJSTypedArrayTypeFloat32Array + 8, // kJSTypedArrayTypeFloat64Array +}; + +static const char* typeToString[kJSTypedArrayTypeArrayBuffer] = +{ + "kJSTypedArrayTypeInt8Array", + "kJSTypedArrayTypeInt16Array", + "kJSTypedArrayTypeInt32Array", + "kJSTypedArrayTypeUint8Array", + "kJSTypedArrayTypeUint8ClampedArray", + "kJSTypedArrayTypeUint16Array", + "kJSTypedArrayTypeUint32Array", + "kJSTypedArrayTypeFloat32Array", + "kJSTypedArrayTypeFloat64Array", +}; + +inline int unexpectedException(const char* name) +{ + fprintf(stderr, "%s FAILED: unexpected exception\n", name); + return 1; +} + +static int assertEqualsAsNumber(JSGlobalContextRef context, JSValueRef value, double expectedValue) +{ + double number = JSValueToNumber(context, value, nullptr); + if (number != expectedValue && !(isnan(number) && isnan(expectedValue))) { + fprintf(stderr, "assertEqualsAsNumber FAILED: %p, %lf\n", value, expectedValue); + return 1; + } + return 0; +} + +static int testAccess(JSGlobalContextRef context, JSObjectRef typedArray, JSTypedArrayType type, unsigned elementLength, void* expectedPtr = nullptr, JSObjectRef expectedBuffer = nullptr, unsigned expectedOffset = 0) +{ + JSValueRef exception = nullptr; + // Test typedArray basic functions. + JSTypedArrayType actualType = JSValueGetTypedArrayType(context, typedArray, &exception); + if (type != actualType || exception) { + fprintf(stderr, "TypedArray type FAILED: %p, got: %s, expected: %s\n", typedArray, typeToString[actualType], typeToString[type]); + return 1; + } + + unsigned length = JSObjectGetTypedArrayLength(context, typedArray, &exception); + if (elementLength != length || exception) { + fprintf(stderr, "TypedArray length FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], length, elementLength); + return 1; + } + + unsigned byteLength = JSObjectGetTypedArrayByteLength(context, typedArray, &exception); + unsigned expectedLength = byteSizes[type] * elementLength; + if (byteLength != expectedLength || exception) { + fprintf(stderr, "TypedArray byteLength FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], byteLength, expectedLength); + return 1; + } + + unsigned offset = JSObjectGetTypedArrayByteOffset(context, typedArray, &exception); + if (expectedOffset != offset || exception) { + fprintf(stderr, "TypedArray byteOffset FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], offset, expectedOffset); + return 1; + } + + void* ptr = JSObjectGetTypedArrayBytesPtr(context, typedArray, &exception); + if (exception) + return unexpectedException("TypedArray get bytes ptr"); + + JSObjectRef buffer = JSObjectGetTypedArrayBuffer(context, typedArray, &exception); + if (exception) + return unexpectedException("TypedArray get buffer"); + + void* bufferPtr = JSObjectGetArrayBufferBytesPtr(context, buffer, &exception); + if (exception) + return unexpectedException("ArrayBuffer get bytes ptr"); + + if (bufferPtr != ptr) { + fprintf(stderr, "FAIL: TypedArray bytes ptr and ArrayBuffer byte ptr were not the same: %p (%s) TypedArray: %p, ArrayBuffer: %p\n", typedArray, typeToString[type], ptr, bufferPtr); + return 1; + } + + if (expectedPtr && ptr != expectedPtr) { + fprintf(stderr, "FAIL: TypedArray bytes ptr and the ptr used to construct the array were not the same: %p (%s) TypedArray: %p, bytes ptr: %p\n", typedArray, typeToString[type], ptr, expectedPtr); + return 1; + } + + if (expectedBuffer && expectedBuffer != buffer) { + fprintf(stderr, "FAIL: TypedArray buffer and the ArrayBuffer buffer used to construct the array were not the same: %p (%s) TypedArray buffer: %p, data: %p\n", typedArray, typeToString[type], buffer, expectedBuffer); + return 1; + } + + return 0; +} + +static int testConstructors(JSGlobalContextRef context, JSTypedArrayType type, unsigned length) +{ + int failed = 0; + JSValueRef exception = nullptr; + JSObjectRef typedArray; + + // Test create with length. + typedArray = JSObjectMakeTypedArray(context, type, length, &exception); + failed = failed || exception || testAccess(context, typedArray, type, length); + + void* ptr = calloc(length, byteSizes[type]); // This is to be freed by data + JSObjectRef data = JSObjectMakeArrayBufferWithBytesNoCopy(context, ptr, length * byteSizes[type], freePtr, nullptr, &exception); + failed = failed || exception; + + // Test create with existing ptr. + typedArray = JSObjectMakeTypedArrayWithBytesNoCopy(context, type, ptr, length * byteSizes[type], id, nullptr, &exception); + failed = failed || exception || testAccess(context, typedArray, type, length, ptr); + + // Test create with existing ArrayBuffer. + typedArray = JSObjectMakeTypedArrayWithArrayBuffer(context, type, data, &exception); + failed = failed || exception || testAccess(context, typedArray, type, length, ptr, data); + + // Test create with existing ArrayBuffer and offset. + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, 0, length, &exception); + failed = failed || exception || testAccess(context, typedArray, type, length, ptr, data); + + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], length-1, &exception); + if (!length) + failed = failed || !exception; + else + failed = failed || testAccess(context, typedArray, type, length-1, ptr, data, byteSizes[type]) || exception; + + exception = nullptr; + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], 3, &exception); + if (length < 2) + failed = failed || !exception; + else + failed = failed || testAccess(context, typedArray, type, 3, ptr, data, byteSizes[type]) || exception; + + if (byteSizes[type] > 1) { + exception = nullptr; + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, 1, length-1, &exception); + failed = failed || !exception; + } + + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], length, &exception); + failed = failed || !exception; + + exception = nullptr; + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], 0, &exception); + if (!length) + failed = failed || !exception; + else + failed = failed || testAccess(context, typedArray, type, 0, ptr, data, byteSizes[type]) || exception; + + return failed; +} + +template +static int forEachTypedArrayType(const Functor& functor) +{ + int failed = 0; + for (unsigned i = 0; i < kJSTypedArrayTypeArrayBuffer; i++) + failed = failed || functor(static_cast(i)); + return failed; +} + +int testTypedArrayCAPI() +{ + int failed = 0; + JSGlobalContextRef context = JSGlobalContextCreate(nullptr); + + failed = failed || forEachTypedArrayType([&](JSTypedArrayType type) { + int failed = 0; + for (unsigned i = 0; i < numLengths; i++) + failed = failed || testConstructors(context, type, lengths[i]); + return failed; + }); + + // Test making a typedArray from scratch length. + volatile JSObjectRef typedArray = JSObjectMakeTypedArray(context, kJSTypedArrayTypeUint32Array, 10, nullptr); + JSObjectRef data = JSObjectGetTypedArrayBuffer(context, typedArray, nullptr); + unsigned* buffer = static_cast(JSObjectGetArrayBufferBytesPtr(context, data, nullptr)); + + ASSERT(JSObjectGetTypedArrayLength(context, typedArray, nullptr) == 10); + + // Test buffer is connected to typedArray. + buffer[1] = 1; + JSValueRef v = JSObjectGetPropertyAtIndex(context, typedArray, 1, nullptr); + failed = failed || assertEqualsAsNumber(context, v, 1); + + // Test passing a buffer from a new array to an old array + typedArray = JSObjectMakeTypedArrayWithBytesNoCopy(context, kJSTypedArrayTypeUint32Array, buffer, 40, id, nullptr, nullptr); + buffer = static_cast(JSObjectGetTypedArrayBytesPtr(context, typedArray, nullptr)); + ASSERT(buffer[1] == 1); + buffer[1] = 20; + ASSERT(((unsigned*)JSObjectGetArrayBufferBytesPtr(context, data, nullptr))[1] == 20); + + // Test constructing with data and the data returned are the same even with an offset. + typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, kJSTypedArrayTypeUint32Array, data, 4, 9, nullptr); + failed = failed || assertEqualsAsNumber(context, JSObjectGetPropertyAtIndex(context, typedArray, 0, nullptr), 20); + ASSERT(data == JSObjectGetTypedArrayBuffer(context, typedArray, nullptr)); + + // Test attempting to allocate an array too big for memory. + forEachTypedArrayType([&](JSTypedArrayType type) { + JSValueRef exception = nullptr; + JSObjectMakeTypedArray(context, type, UINT_MAX, &exception); + return !exception; + }); + + JSGlobalContextRelease(context); + + if (!failed) + printf("PASS: Typed Array C API Tests.\n"); + else + printf("FAIL: Some Typed Array C API Tests failed.\n"); + + return failed; +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/TypedArrayCTest.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/TypedArrayCTest.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/tests/TypedArrayCTest.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/tests/TypedArrayCTest.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef TypedArrayCTest_h +#define TypedArrayCTest_h + +#ifdef __cplusplus +extern "C" { +#endif + +int testTypedArrayCAPI(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TypedArrayCTest_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/API/WebKitAvailability.h webkit2gtk-2.14.2/Source/JavaScriptCore/API/WebKitAvailability.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/API/WebKitAvailability.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/API/WebKitAvailability.h 2016-09-16 09:56:47.000000000 +0000 @@ -46,6 +46,10 @@ #define __NSi_10_11 introduced=10.0 // Use 10.0 to indicate that everything is available. #endif +#ifndef __NSi_10_12 // Building from trunk rather than SDK. +#define __NSi_10_12 introduced=10.0 // Use 10.0 to indicate that everything is available. +#endif + #ifndef __AVAILABILITY_INTERNAL__MAC_10_9 #define __AVAILABILITY_INTERNAL__MAC_10_9 #endif @@ -67,10 +71,13 @@ #if defined(BUILDING_GTK__) #undef CF_AVAILABLE #define CF_AVAILABLE(_mac, _ios) +#undef CF_ENUM_AVAILABLE +#define CF_ENUM_AVAILABLE(_mac, _ios) #endif #else #define CF_AVAILABLE(_mac, _ios) +#define CF_ENUM_AVAILABLE(_mac, _ios) #endif #endif /* __WebKitAvailability__ */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/AbortReason.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/AbortReason.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/AbortReason.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/AbortReason.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,8 +57,10 @@ DFGNegativeStringLength = 200, DFGSlowPathGeneratorFellThrough = 210, DFGUnreachableBasicBlock = 220, + DFGUnreachableNode = 225, DFGUnreasonableOSREntryJumpDestination = 230, DFGVarargsThrowingPathDidNotThrow = 235, + FTLCrash = 236, JITDidReturnFromTailCall = 237, JITDivOperandsAreNotNumbers = 240, JITGetByValResultIsNotEmpty = 250, diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -27,7 +27,6 @@ #define AbstractMacroAssembler_h #include "AbortReason.h" -#include "AssemblerBuffer.h" #include "CodeLocation.h" #include "MacroAssemblerCodeRef.h" #include "Options.h" @@ -143,7 +142,9 @@ return TimesFour; return TimesEight; } - + + struct BaseIndex; + // Address: // // Describes a simple base-offset address. @@ -159,6 +160,8 @@ return Address(base, offset + additionalOffset); } + BaseIndex indexedBy(RegisterID index, Scale) const; + RegisterID base; int32_t offset; }; @@ -216,7 +219,7 @@ , offset(offset) { } - + RegisterID base; RegisterID index; Scale scale; @@ -711,8 +714,6 @@ // A JumpList is a set of Jump objects. // All jumps in the set will be linked to the same destination. class JumpList { - friend class LinkBuffer; - public: typedef Vector JumpVector; @@ -724,20 +725,18 @@ append(jump); } - void link(AbstractMacroAssemblerType* masm) + void link(AbstractMacroAssemblerType* masm) const { size_t size = m_jumps.size(); for (size_t i = 0; i < size; ++i) m_jumps[i].link(masm); - m_jumps.clear(); } - void linkTo(Label label, AbstractMacroAssemblerType* masm) + void linkTo(Label label, AbstractMacroAssemblerType* masm) const { size_t size = m_jumps.size(); for (size_t i = 0; i < size; ++i) m_jumps[i].linkTo(label, masm); - m_jumps.clear(); } void append(Jump jump) @@ -1038,18 +1037,34 @@ m_linkTasks.append(createSharedTask(functor)); } + void emitNops(size_t memoryToFillWithNopsInBytes) + { + AssemblerBuffer& buffer = m_assembler.buffer(); + size_t startCodeSize = buffer.codeSize(); + size_t targetCodeSize = startCodeSize + memoryToFillWithNopsInBytes; + buffer.ensureSpace(memoryToFillWithNopsInBytes); + bool isCopyingToExecutableMemory = false; + AssemblerType::fillNops(static_cast(buffer.data()) + startCodeSize, memoryToFillWithNopsInBytes, isCopyingToExecutableMemory); + buffer.setCodeSize(targetCodeSize); + } + protected: AbstractMacroAssembler() - : m_randomSource(cryptographicallyRandomNumber()) + : m_randomSource(0) { invalidateAllTempRegisters(); } uint32_t random() { + if (!m_randomSourceIsInitialized) { + m_randomSourceIsInitialized = true; + m_randomSource.setSeed(cryptographicallyRandomNumber()); + } return m_randomSource.getUint32(); } + bool m_randomSourceIsInitialized { false }; WeakRandom m_randomSource; #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) @@ -1141,6 +1156,15 @@ friend class LinkBuffer; }; // class AbstractMacroAssembler +template +inline typename AbstractMacroAssembler::BaseIndex +AbstractMacroAssembler::Address::indexedBy( + typename AbstractMacroAssembler::RegisterID index, + typename AbstractMacroAssembler::Scale scale) const +{ + return BaseIndex(base, index, scale, offset); +} + } // namespace JSC #endif // ENABLE(ASSEMBLER) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARM64Assembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARM64Assembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARM64Assembler.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARM64Assembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -1088,6 +1088,20 @@ } template + ALWAYS_INLINE void ldp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) + { + CHECK_DATASIZE(); + insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, pimm, rn, rt, rt2)); + } + + template + ALWAYS_INLINE void ldnp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) + { + CHECK_DATASIZE(); + insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, pimm, rn, rt, rt2)); + } + + template ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, RegisterID rm) { ldr(rt, rn, rm, UXTX, 0); @@ -1470,12 +1484,17 @@ insn(nopPseudo()); } - static void fillNops(void* base, size_t size) + static void fillNops(void* base, size_t size, bool isCopyingToExecutableMemory) { RELEASE_ASSERT(!(size % sizeof(int32_t))); size_t n = size / sizeof(int32_t); - for (int32_t* ptr = static_cast(base); n--;) - *ptr++ = nopPseudo(); + for (int32_t* ptr = static_cast(base); n--;) { + int insn = nopPseudo(); + if (isCopyingToExecutableMemory) + performJITMemcpy(ptr++, &insn, sizeof(int)); + else + memcpy(ptr++, &insn, sizeof(int)); + } } ALWAYS_INLINE void dmbSY() @@ -1646,6 +1665,20 @@ } template + ALWAYS_INLINE void stp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) + { + CHECK_DATASIZE(); + insn(loadStoreRegisterPairOffset(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, pimm, rn, rt, rt2)); + } + + template + ALWAYS_INLINE void stnp(RegisterID rt, RegisterID rt2, RegisterID rn, unsigned pimm = 0) + { + CHECK_DATASIZE(); + insn(loadStoreRegisterPairNonTemporal(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, pimm, rn, rt, rt2)); + } + + template ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, RegisterID rm) { str(rt, rn, rm, UXTX, 0); @@ -2442,23 +2475,23 @@ m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, type, condition, bitNumber, compareRegister)); } - void linkJump(AssemblerLabel from, AssemblerLabel to) + void linkJump(AssemblerLabel from, void* executableCode, AssemblerLabel to) { ASSERT(from.isSet()); ASSERT(to.isSet()); - relinkJumpOrCall(addressOf(from), addressOf(to)); + relinkJumpOrCall(addressOf(from), addressOf(executableCode, from), addressOf(to)); } static void linkJump(void* code, AssemblerLabel from, void* to) { ASSERT(from.isSet()); - relinkJumpOrCall(addressOf(code, from), to); + relinkJumpOrCall(addressOf(code, from), addressOf(code, from), to); } static void linkCall(void* code, AssemblerLabel from, void* to) { ASSERT(from.isSet()); - linkJumpOrCall(addressOf(code, from) - 1, to); + linkJumpOrCall(addressOf(code, from) - 1, addressOf(code, from) - 1, to); } static void linkPointer(void* code, AssemblerLabel where, void* valuePtr) @@ -2470,7 +2503,8 @@ { intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(where)) >> 2; ASSERT(static_cast(offset) == offset); - *static_cast(where) = unconditionalBranchImmediate(false, static_cast(offset)); + int insn = unconditionalBranchImmediate(false, static_cast(offset)); + performJITMemcpy(where, &insn, sizeof(int)); cacheFlush(where, sizeof(int)); } @@ -2478,6 +2512,11 @@ { return 4; } + + static constexpr ptrdiff_t patchableJumpSize() + { + return 4; + } static void replaceWithLoad(void* where) { @@ -2494,7 +2533,8 @@ ASSERT(!S); ASSERT(!shift); ASSERT(!(imm12 & ~0xff8)); - *static_cast(where) = loadStoreRegisterUnsignedImmediate(MemOpSize_64, false, MemOp_LOAD, encodePositiveImmediate<64>(imm12), rn, rd); + int insn = loadStoreRegisterUnsignedImmediate(MemOpSize_64, false, MemOp_LOAD, encodePositiveImmediate<64>(imm12), rn, rd); + performJITMemcpy(where, &insn, sizeof(int)); cacheFlush(where, sizeof(int)); } #if !ASSERT_DISABLED @@ -2527,7 +2567,8 @@ ASSERT(!V); ASSERT(opc == MemOp_LOAD); ASSERT(!(imm12 & ~0x1ff)); - *static_cast(where) = addSubtractImmediate(Datasize_64, AddOp_ADD, DontSetFlags, 0, imm12 * sizeof(void*), rn, rt); + int insn = addSubtractImmediate(Datasize_64, AddOp_ADD, DontSetFlags, 0, imm12 * sizeof(void*), rn, rt); + performJITMemcpy(where, &insn, sizeof(int)); cacheFlush(where, sizeof(int)); } #if !ASSERT_DISABLED @@ -2557,9 +2598,11 @@ static void setPointer(int* address, void* valuePtr, RegisterID rd, bool flush) { uintptr_t value = reinterpret_cast(valuePtr); - address[0] = moveWideImediate(Datasize_64, MoveWideOp_Z, 0, getHalfword(value, 0), rd); - address[1] = moveWideImediate(Datasize_64, MoveWideOp_K, 1, getHalfword(value, 1), rd); - address[2] = moveWideImediate(Datasize_64, MoveWideOp_K, 2, getHalfword(value, 2), rd); + int buffer[3]; + buffer[0] = moveWideImediate(Datasize_64, MoveWideOp_Z, 0, getHalfword(value, 0), rd); + buffer[1] = moveWideImediate(Datasize_64, MoveWideOp_K, 1, getHalfword(value, 1), rd); + buffer[2] = moveWideImediate(Datasize_64, MoveWideOp_K, 2, getHalfword(value, 2), rd); + performJITMemcpy(address, buffer, sizeof(int) * 3); if (flush) cacheFlush(address, sizeof(int) * 3); @@ -2578,13 +2621,15 @@ ASSERT_UNUSED(expected, expected && !sf && (opc == MoveWideOp_Z || opc == MoveWideOp_N) && !hw); ASSERT(checkMovk(address[1], 1, rd)); + int buffer[2]; if (value >= 0) { - address[0] = moveWideImediate(Datasize_32, MoveWideOp_Z, 0, getHalfword(value, 0), rd); - address[1] = moveWideImediate(Datasize_32, MoveWideOp_K, 1, getHalfword(value, 1), rd); + buffer[0] = moveWideImediate(Datasize_32, MoveWideOp_Z, 0, getHalfword(value, 0), rd); + buffer[1] = moveWideImediate(Datasize_32, MoveWideOp_K, 1, getHalfword(value, 1), rd); } else { - address[0] = moveWideImediate(Datasize_32, MoveWideOp_N, 0, ~getHalfword(value, 0), rd); - address[1] = moveWideImediate(Datasize_32, MoveWideOp_K, 1, getHalfword(value, 1), rd); + buffer[0] = moveWideImediate(Datasize_32, MoveWideOp_N, 0, ~getHalfword(value, 0), rd); + buffer[1] = moveWideImediate(Datasize_32, MoveWideOp_K, 1, getHalfword(value, 1), rd); } + performJITMemcpy(where, &buffer, sizeof(int) * 2); cacheFlush(where, sizeof(int) * 2); } @@ -2619,15 +2664,20 @@ return readPointer(reinterpret_cast(from) - 4); } + // The static relink, repatch, and replace methods can use can + // use |from| for both the write and executable address for call + // and jump patching as they're modifying existing (linked) code, + // so the address being provided is correct for relative address + // computation. static void relinkJump(void* from, void* to) { - relinkJumpOrCall(reinterpret_cast(from), to); + relinkJumpOrCall(reinterpret_cast(from), reinterpret_cast(from), to); cacheFlush(from, sizeof(int)); } static void relinkCall(void* from, void* to) { - relinkJumpOrCall(reinterpret_cast(from) - 1, to); + relinkJumpOrCall(reinterpret_cast(from) - 1, reinterpret_cast(from) - 1, to); cacheFlush(reinterpret_cast(from) - 1, sizeof(int)); } @@ -2648,7 +2698,8 @@ imm12 = encodePositiveImmediate<32>(value); else imm12 = encodePositiveImmediate<64>(value); - *static_cast(where) = loadStoreRegisterUnsignedImmediate(size, V, opc, imm12, rn, rt); + int insn = loadStoreRegisterUnsignedImmediate(size, V, opc, imm12, rn, rt); + performJITMemcpy(where, &insn, sizeof(int)); cacheFlush(where, sizeof(int)); } @@ -2768,29 +2819,30 @@ return m_jumpsToLink; } - static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to) + static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, const uint8_t* fromInstruction8, uint8_t* to) { + const int* fromInstruction = reinterpret_cast(fromInstruction8); switch (record.linkType()) { case LinkJumpNoCondition: - linkJumpOrCall(reinterpret_cast(from), to); + linkJumpOrCall(reinterpret_cast(from), fromInstruction, to); break; case LinkJumpConditionDirect: - linkConditionalBranch(record.condition(), reinterpret_cast(from), to); + linkConditionalBranch(record.condition(), reinterpret_cast(from), fromInstruction, to); break; case LinkJumpCondition: - linkConditionalBranch(record.condition(), reinterpret_cast(from) - 1, to); + linkConditionalBranch(record.condition(), reinterpret_cast(from) - 1, fromInstruction - 1, to); break; case LinkJumpCompareAndBranchDirect: - linkCompareAndBranch(record.condition(), record.is64Bit(), record.compareRegister(), reinterpret_cast(from), to); + linkCompareAndBranch(record.condition(), record.is64Bit(), record.compareRegister(), reinterpret_cast(from), fromInstruction, to); break; case LinkJumpCompareAndBranch: - linkCompareAndBranch(record.condition(), record.is64Bit(), record.compareRegister(), reinterpret_cast(from) - 1, to); + linkCompareAndBranch(record.condition(), record.is64Bit(), record.compareRegister(), reinterpret_cast(from) - 1, fromInstruction - 1, to); break; case LinkJumpTestBitDirect: - linkTestAndBranch(record.condition(), record.bitNumber(), record.compareRegister(), reinterpret_cast(from), to); + linkTestAndBranch(record.condition(), record.bitNumber(), record.compareRegister(), reinterpret_cast(from), fromInstruction, to); break; case LinkJumpTestBit: - linkTestAndBranch(record.condition(), record.bitNumber(), record.compareRegister(), reinterpret_cast(from) - 1, to); + linkTestAndBranch(record.condition(), record.bitNumber(), record.compareRegister(), reinterpret_cast(from) - 1, fromInstruction - 1, to); break; default: ASSERT_NOT_REACHED(); @@ -2832,7 +2884,7 @@ } template - static void linkJumpOrCall(int* from, void* to) + static void linkJumpOrCall(int* from, const int* fromInstruction, void* to) { bool link; int imm26; @@ -2842,60 +2894,69 @@ ASSERT_UNUSED(isCall, (link == isCall) || disassembleNop(from)); ASSERT(!(reinterpret_cast(from) & 3)); ASSERT(!(reinterpret_cast(to) & 3)); - intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(from)) >> 2; + intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(fromInstruction)) >> 2; ASSERT(static_cast(offset) == offset); - *from = unconditionalBranchImmediate(isCall, static_cast(offset)); + int insn = unconditionalBranchImmediate(isCall, static_cast(offset)); + performJITMemcpy(from, &insn, sizeof(int)); } template - static void linkCompareAndBranch(Condition condition, bool is64Bit, RegisterID rt, int* from, void* to) + static void linkCompareAndBranch(Condition condition, bool is64Bit, RegisterID rt, int* from, const int* fromInstruction, void* to) { ASSERT(!(reinterpret_cast(from) & 3)); ASSERT(!(reinterpret_cast(to) & 3)); - intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(from)) >> 2; + intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(fromInstruction)) >> 2; ASSERT(((offset << 38) >> 38) == offset); bool useDirect = ((offset << 45) >> 45) == offset; // Fits in 19 bits ASSERT(!isDirect || useDirect); if (useDirect || isDirect) { - *from = compareAndBranchImmediate(is64Bit ? Datasize_64 : Datasize_32, condition == ConditionNE, static_cast(offset), rt); - if (!isDirect) - *(from + 1) = nopPseudo(); + int insn = compareAndBranchImmediate(is64Bit ? Datasize_64 : Datasize_32, condition == ConditionNE, static_cast(offset), rt); + performJITMemcpy(from, &insn, sizeof(int)); + if (!isDirect) { + insn = nopPseudo(); + performJITMemcpy(from + 1, &insn, sizeof(int)); + } } else { - *from = compareAndBranchImmediate(is64Bit ? Datasize_64 : Datasize_32, invert(condition) == ConditionNE, 2, rt); - linkJumpOrCall(from + 1, to); + int insn = compareAndBranchImmediate(is64Bit ? Datasize_64 : Datasize_32, invert(condition) == ConditionNE, 2, rt); + performJITMemcpy(from, &insn, sizeof(int)); + linkJumpOrCall(from + 1, fromInstruction + 1, to); } } template - static void linkConditionalBranch(Condition condition, int* from, void* to) + static void linkConditionalBranch(Condition condition, int* from, const int* fromInstruction, void* to) { ASSERT(!(reinterpret_cast(from) & 3)); ASSERT(!(reinterpret_cast(to) & 3)); - intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(from)) >> 2; + intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(fromInstruction)) >> 2; ASSERT(((offset << 38) >> 38) == offset); bool useDirect = ((offset << 45) >> 45) == offset; // Fits in 19 bits ASSERT(!isDirect || useDirect); if (useDirect || isDirect) { - *from = conditionalBranchImmediate(static_cast(offset), condition); - if (!isDirect) - *(from + 1) = nopPseudo(); + int insn = conditionalBranchImmediate(static_cast(offset), condition); + performJITMemcpy(from, &insn, sizeof(int)); + if (!isDirect) { + insn = nopPseudo(); + performJITMemcpy(from + 1, &insn, sizeof(int)); + } } else { - *from = conditionalBranchImmediate(2, invert(condition)); - linkJumpOrCall(from + 1, to); + int insn = conditionalBranchImmediate(2, invert(condition)); + performJITMemcpy(from, &insn, sizeof(int)); + linkJumpOrCall(from + 1, fromInstruction + 1, to); } } template - static void linkTestAndBranch(Condition condition, unsigned bitNumber, RegisterID rt, int* from, void* to) + static void linkTestAndBranch(Condition condition, unsigned bitNumber, RegisterID rt, int* from, const int* fromInstruction, void* to) { ASSERT(!(reinterpret_cast(from) & 3)); ASSERT(!(reinterpret_cast(to) & 3)); - intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(from)) >> 2; + intptr_t offset = (reinterpret_cast(to) - reinterpret_cast(fromInstruction)) >> 2; ASSERT(static_cast(offset) == offset); ASSERT(((offset << 38) >> 38) == offset); @@ -2903,17 +2964,21 @@ ASSERT(!isDirect || useDirect); if (useDirect || isDirect) { - *from = testAndBranchImmediate(condition == ConditionNE, static_cast(bitNumber), static_cast(offset), rt); - if (!isDirect) - *(from + 1) = nopPseudo(); + int insn = testAndBranchImmediate(condition == ConditionNE, static_cast(bitNumber), static_cast(offset), rt); + performJITMemcpy(from, &insn, sizeof(int)); + if (!isDirect) { + insn = nopPseudo(); + performJITMemcpy(from + 1, &insn, sizeof(int)); + } } else { - *from = testAndBranchImmediate(invert(condition) == ConditionNE, static_cast(bitNumber), 2, rt); - linkJumpOrCall(from + 1, to); + int insn = testAndBranchImmediate(invert(condition) == ConditionNE, static_cast(bitNumber), 2, rt); + performJITMemcpy(from, &insn, sizeof(int)); + linkJumpOrCall(from + 1, fromInstruction + 1, to); } } template - static void relinkJumpOrCall(int* from, void* to) + static void relinkJumpOrCall(int* from, const int* fromInstruction, void* to) { if (!isCall && disassembleNop(from)) { unsigned op01; @@ -2928,7 +2993,7 @@ if (imm19 == 8) condition = invert(condition); - linkConditionalBranch(condition, from - 1, to); + linkConditionalBranch(condition, from - 1, fromInstruction - 1, to); return; } @@ -2941,7 +3006,7 @@ if (imm19 == 8) op = !op; - linkCompareAndBranch(op ? ConditionNE : ConditionEQ, opSize == Datasize_64, rt, from - 1, to); + linkCompareAndBranch(op ? ConditionNE : ConditionEQ, opSize == Datasize_64, rt, from - 1, fromInstruction - 1, to); return; } @@ -2953,12 +3018,12 @@ if (imm14 == 8) op = !op; - linkTestAndBranch(op ? ConditionNE : ConditionEQ, bitNumber, rt, from - 1, to); + linkTestAndBranch(op ? ConditionNE : ConditionEQ, bitNumber, rt, from - 1, fromInstruction - 1, to); return; } } - linkJumpOrCall(from, to); + linkJumpOrCall(from, fromInstruction, to); } static int* addressOf(void* code, AssemblerLabel label) @@ -3349,6 +3414,40 @@ } // 'V' means vector + ALWAYS_INLINE static int loadStoreRegisterPairOffset(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, FPRegisterID rt, FPRegisterID rt2) + { + ASSERT(size < 3); + ASSERT(opc == (opc & 1)); // Only load or store, load signed 64 is handled via size. + ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed. + unsigned immedShiftAmount = memPairOffsetShift(V, size); + int imm7 = immediate >> immedShiftAmount; + ASSERT((imm7 << immedShiftAmount) == immediate && isInt7(imm7)); + return (0x29000000 | size << 30 | V << 26 | opc << 22 | (imm7 & 0x7f) << 15 | rt2 << 10 | xOrSp(rn) << 5 | rt); + } + + ALWAYS_INLINE static int loadStoreRegisterPairOffset(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, RegisterID rt, RegisterID rt2) + { + return loadStoreRegisterPairOffset(size, V, opc, immediate, rn, xOrZrAsFPR(rt), xOrZrAsFPR(rt2)); + } + + // 'V' means vector + ALWAYS_INLINE static int loadStoreRegisterPairNonTemporal(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, FPRegisterID rt, FPRegisterID rt2) + { + ASSERT(size < 3); + ASSERT(opc == (opc & 1)); // Only load or store, load signed 64 is handled via size. + ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed. + unsigned immedShiftAmount = memPairOffsetShift(V, size); + int imm7 = immediate >> immedShiftAmount; + ASSERT((imm7 << immedShiftAmount) == immediate && isInt7(imm7)); + return (0x28000000 | size << 30 | V << 26 | opc << 22 | (imm7 & 0x7f) << 15 | rt2 << 10 | xOrSp(rn) << 5 | rt); + } + + ALWAYS_INLINE static int loadStoreRegisterPairNonTemporal(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, RegisterID rt, RegisterID rt2) + { + return loadStoreRegisterPairNonTemporal(size, V, opc, immediate, rn, xOrZrAsFPR(rt), xOrZrAsFPR(rt2)); + } + + // 'V' means vector // 'S' means shift rm ALWAYS_INLINE static int loadStoreRegisterRegisterOffset(MemOpSize size, bool V, MemOp opc, RegisterID rm, ExtendType option, bool S, RegisterID rn, FPRegisterID rt) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARMAssembler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARMAssembler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARMAssembler.cpp 2015-07-22 12:37:57.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARMAssembler.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -395,8 +395,6 @@ { // 64-bit alignment is required for next constant pool and JIT code as well m_buffer.flushWithoutBarrier(true); - if (!m_buffer.isAligned(8)) - bkpt(0); char* data = reinterpret_cast(m_buffer.data()); ptrdiff_t delta = reinterpret_cast(to) - data; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARMAssembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARMAssembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARMAssembler.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARMAssembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -706,6 +706,18 @@ m_buffer.putInt(NOP); } + static void fillNops(void* base, size_t size, bool isCopyingToExecutableMemory) + { + UNUSED_PARAM(isCopyingToExecutableMemory); + RELEASE_ASSERT(!(size % sizeof(int32_t))); + + int32_t* ptr = static_cast(base); + const size_t num32s = size / sizeof(int32_t); + const int32_t insn = NOP; + for (size_t i = 0; i < num32s; i++) + *ptr++ = insn; + } + void dmbSY() { m_buffer.putInt(DMB_SY); @@ -990,6 +1002,11 @@ return sizeof(ARMWord) * 2; } + static constexpr ptrdiff_t patchableJumpSize() + { + return sizeof(ARMWord) * 3; + } + static void replaceWithLoad(void* instructionStart) { ARMWord* instruction = reinterpret_cast(instructionStart); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARMv7Assembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARMv7Assembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/ARMv7Assembler.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/ARMv7Assembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -1327,11 +1327,14 @@ uint16_t* address = static_cast(instructionStart); ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast(imm)); ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast(imm >> 16)); - address[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); - address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(right, lo16); - address[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); - address[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(right, hi16); - address[4] = OP_CMP_reg_T2 | left; + uint16_t instruction[] = { + twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16), + twoWordOp5i6Imm4Reg4EncodedImmSecond(right, lo16), + twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16), + twoWordOp5i6Imm4Reg4EncodedImmSecond(right, hi16), + static_cast(OP_CMP_reg_T2 | left) + }; + performJITMemcpy(address, instruction, sizeof(uint16_t) * 5); cacheFlush(address, sizeof(uint16_t) * 5); } #else @@ -1342,8 +1345,11 @@ ASSERT(!BadReg(rd)); uint16_t* address = static_cast(instructionStart); - address[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, imm); - address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, imm); + uint16_t instruction[] = { + twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, imm), + twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, imm) + }; + performJITMemcpy(address, instruction, sizeof(uint16_t) * 2); cacheFlush(address, sizeof(uint16_t) * 2); } #endif @@ -1998,6 +2004,43 @@ m_formatter.twoWordOp16Op16(OP_NOP_T2a, OP_NOP_T2b); } + static constexpr int16_t nopPseudo16() + { + return OP_NOP_T1; + } + + static constexpr int32_t nopPseudo32() + { + return OP_NOP_T2a | (OP_NOP_T2b << 16); + } + + static void fillNops(void* base, size_t size, bool isCopyingToExecutableMemory) + { + RELEASE_ASSERT(!(size % sizeof(int16_t))); + + char* ptr = static_cast(base); + const size_t num32s = size / sizeof(int32_t); + for (size_t i = 0; i < num32s; i++) { + const int32_t insn = nopPseudo32(); + if (isCopyingToExecutableMemory) + performJITMemcpy(ptr, &insn, sizeof(int32_t)); + else + memcpy(ptr, &insn, sizeof(int32_t)); + ptr += sizeof(int32_t); + } + + const size_t num16s = (size % sizeof(int32_t)) / sizeof(int16_t); + ASSERT(num16s == 0 || num16s == 1); + ASSERT(num16s * sizeof(int16_t) + num32s * sizeof(int32_t) == size); + if (num16s) { + const int16_t insn = nopPseudo16(); + if (isCopyingToExecutableMemory) + performJITMemcpy(ptr, &insn, sizeof(int16_t)); + else + memcpy(ptr, &insn, sizeof(int16_t)); + } + } + void dmbSY() { m_formatter.twoWordOp16Op16(OP_DMB_SY_T2a, OP_DMB_SY_T2b); @@ -2125,29 +2168,30 @@ return m_jumpsToLink; } - static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to) + static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, const uint8_t* fromInstruction8, uint8_t* to) { + const uint16_t* fromInstruction = reinterpret_cast_ptr(fromInstruction8); switch (record.linkType()) { case LinkJumpT1: - linkJumpT1(record.condition(), reinterpret_cast_ptr(from), to); + linkJumpT1(record.condition(), reinterpret_cast_ptr(from), fromInstruction, to); break; case LinkJumpT2: - linkJumpT2(reinterpret_cast_ptr(from), to); + linkJumpT2(reinterpret_cast_ptr(from), fromInstruction, to); break; case LinkJumpT3: - linkJumpT3(record.condition(), reinterpret_cast_ptr(from), to); + linkJumpT3(record.condition(), reinterpret_cast_ptr(from), fromInstruction, to); break; case LinkJumpT4: - linkJumpT4(reinterpret_cast_ptr(from), to); + linkJumpT4(reinterpret_cast_ptr(from), fromInstruction, to); break; case LinkConditionalJumpT4: - linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr(from), to); + linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr(from), fromInstruction, to); break; case LinkConditionalBX: - linkConditionalBX(record.condition(), reinterpret_cast_ptr(from), to); + linkConditionalBX(record.condition(), reinterpret_cast_ptr(from), fromInstruction, to); break; case LinkBX: - linkBX(reinterpret_cast_ptr(from), to); + linkBX(reinterpret_cast_ptr(from), fromInstruction, to); break; default: RELEASE_ASSERT_NOT_REACHED(); @@ -2184,7 +2228,7 @@ ASSERT(from.isSet()); uint16_t* location = reinterpret_cast(reinterpret_cast(code) + from.m_offset); - linkJumpAbsolute(location, to); + linkJumpAbsolute(location, location, to); } static void linkCall(void* code, AssemblerLabel from, void* to) @@ -2200,12 +2244,16 @@ setPointer(reinterpret_cast(code) + where.m_offset, value, false); } + // The static relink and replace methods can use can use |from| for both + // the write and executable address for call and jump patching + // as they're modifying existing (linked) code, so the address being + // provided is correct for relative address computation. static void relinkJump(void* from, void* to) { ASSERT(!(reinterpret_cast(from) & 1)); ASSERT(!(reinterpret_cast(to) & 1)); - linkJumpAbsolute(reinterpret_cast(from), to); + linkJumpAbsolute(reinterpret_cast(from), reinterpret_cast(from), to); cacheFlush(reinterpret_cast(from) - 5, 5 * sizeof(uint16_t)); } @@ -2244,8 +2292,9 @@ offset |= (1 << 11); uint16_t* location = reinterpret_cast(where); - location[1] &= ~((1 << 12) - 1); - location[1] |= offset; + uint16_t instruction = location[1] & ~((1 << 12) - 1); + instruction |= offset; + performJITMemcpy(location + 1, &instruction, sizeof(uint16_t)); cacheFlush(location, sizeof(uint16_t) * 2); } @@ -2269,16 +2318,16 @@ #if OS(LINUX) if (canBeJumpT4(reinterpret_cast(instructionStart), to)) { uint16_t* ptr = reinterpret_cast(instructionStart) + 2; - linkJumpT4(ptr, to); + linkJumpT4(ptr, ptr, to); cacheFlush(ptr - 2, sizeof(uint16_t) * 2); } else { uint16_t* ptr = reinterpret_cast(instructionStart) + 5; - linkBX(ptr, to); + linkBX(ptr, ptr, to); cacheFlush(ptr - 5, sizeof(uint16_t) * 5); } #else uint16_t* ptr = reinterpret_cast(instructionStart) + 2; - linkJumpT4(ptr, to); + linkJumpT4(ptr, ptr, to); cacheFlush(ptr - 2, sizeof(uint16_t) * 2); #endif } @@ -2291,6 +2340,11 @@ return 4; #endif } + + static constexpr ptrdiff_t patchableJumpSize() + { + return 10; + } static void replaceWithLoad(void* instructionStart) { @@ -2299,14 +2353,17 @@ switch (ptr[0] & 0xFFF0) { case OP_LDR_imm_T3: break; - case OP_ADD_imm_T3: + case OP_ADD_imm_T3: { ASSERT(!(ptr[1] & 0xF000)); - ptr[0] &= 0x000F; - ptr[0] |= OP_LDR_imm_T3; - ptr[1] |= (ptr[1] & 0x0F00) << 4; - ptr[1] &= 0xF0FF; + uint16_t instructions[2]; + instructions[0] = ptr[0] & 0x000F; + instructions[0] |= OP_LDR_imm_T3; + instructions[1] = ptr[1] | (ptr[1] & 0x0F00) << 4; + instructions[1] &= 0xF0FF; + performJITMemcpy(ptr, instructions, sizeof(uint16_t) * 2); cacheFlush(ptr, sizeof(uint16_t) * 2); break; + } default: RELEASE_ASSERT_NOT_REACHED(); } @@ -2317,14 +2374,17 @@ ASSERT(!(bitwise_cast(instructionStart) & 1)); uint16_t* ptr = reinterpret_cast(instructionStart); switch (ptr[0] & 0xFFF0) { - case OP_LDR_imm_T3: + case OP_LDR_imm_T3: { ASSERT(!(ptr[1] & 0x0F00)); - ptr[0] &= 0x000F; - ptr[0] |= OP_ADD_imm_T3; - ptr[1] |= (ptr[1] & 0xF000) >> 4; - ptr[1] &= 0x0FFF; + uint16_t instructions[2]; + instructions[0] = ptr[0] & 0x000F; + instructions[0] |= OP_ADD_imm_T3; + instructions[1] = ptr[1] | (ptr[1] & 0xF000) >> 4; + instructions[1] &= 0x0FFF; + performJITMemcpy(ptr, instructions, sizeof(uint16_t) * 2); cacheFlush(ptr, sizeof(uint16_t) * 2); break; + } case OP_ADD_imm_T3: break; default: @@ -2452,11 +2512,13 @@ ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast(value)); ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast(value >> 16)); - location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); - location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); - location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); - location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); + uint16_t instructions[4]; + instructions[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + instructions[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); + instructions[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + instructions[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); + performJITMemcpy(location - 4, instructions, 4 * sizeof(uint16_t)); if (flush) cacheFlush(location - 4, 4 * sizeof(uint16_t)); } @@ -2484,8 +2546,10 @@ ASSERT(imm.isValid()); ASSERT(imm.isUInt7()); uint16_t* location = reinterpret_cast(code); - location[0] &= ~((static_cast(0x7f) >> 2) << 6); - location[0] |= (imm.getUInt7() >> 2) << 6; + uint16_t instruction; + instruction = location[0] & ~((static_cast(0x7f) >> 2) << 6); + instruction |= (imm.getUInt7() >> 2) << 6; + performJITMemcpy(location, &instruction, sizeof(uint16_t)); cacheFlush(location, sizeof(uint16_t)); } @@ -2494,39 +2558,39 @@ setInt32(code, reinterpret_cast(value), flush); } - static bool isB(void* address) + static bool isB(const void* address) { - uint16_t* instruction = static_cast(address); + const uint16_t* instruction = static_cast(address); return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b); } - static bool isBX(void* address) + static bool isBX(const void* address) { - uint16_t* instruction = static_cast(address); + const uint16_t* instruction = static_cast(address); return (instruction[0] & 0xff87) == OP_BX; } - static bool isMOV_imm_T3(void* address) + static bool isMOV_imm_T3(const void* address) { - uint16_t* instruction = static_cast(address); + const uint16_t* instruction = static_cast(address); return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0); } - static bool isMOVT(void* address) + static bool isMOVT(const void* address) { - uint16_t* instruction = static_cast(address); + const uint16_t* instruction = static_cast(address); return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0); } - static bool isNOP_T1(void* address) + static bool isNOP_T1(const void* address) { - uint16_t* instruction = static_cast(address); + const uint16_t* instruction = static_cast(address); return instruction[0] == OP_NOP_T1; } - static bool isNOP_T2(void* address) + static bool isNOP_T2(const void* address) { - uint16_t* instruction = static_cast(address); + const uint16_t* instruction = static_cast(address); return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); } @@ -2574,7 +2638,7 @@ return ((relative << 7) >> 7) == relative; } - static void linkJumpT1(Condition cond, uint16_t* instruction, void* target) + static void linkJumpT1(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); @@ -2589,10 +2653,11 @@ // All branch offsets should be an even distance. ASSERT(!(relative & 1)); - instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1); + uint16_t newInstruction = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1); + performJITMemcpy(writeTarget - 1, &newInstruction, sizeof(uint16_t)); } - static void linkJumpT2(uint16_t* instruction, void* target) + static void linkJumpT2(uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); @@ -2607,10 +2672,11 @@ // All branch offsets should be an even distance. ASSERT(!(relative & 1)); - instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1); + uint16_t newInstruction = OP_B_T2 | ((relative & 0xffe) >> 1); + performJITMemcpy(writeTarget - 1, &newInstruction, sizeof(uint16_t)); } - static void linkJumpT3(Condition cond, uint16_t* instruction, void* target) + static void linkJumpT3(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); @@ -2621,11 +2687,13 @@ // All branch offsets should be an even distance. ASSERT(!(relative & 1)); - instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12); - instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1); + uint16_t instructions[2]; + instructions[0] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12); + instructions[1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1); + performJITMemcpy(writeTarget - 2, instructions, 2 * sizeof(uint16_t)); } - static void linkJumpT4(uint16_t* instruction, void* target) + static void linkJumpT4(uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); @@ -2639,47 +2707,55 @@ // All branch offsets should be an even distance. ASSERT(!(relative & 1)); - instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); - instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); + uint16_t instructions[2]; + instructions[0] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); + instructions[1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); + performJITMemcpy(writeTarget - 2, instructions, 2 * sizeof(uint16_t)); } - static void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target) + static void linkConditionalJumpT4(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); ASSERT(!(reinterpret_cast(target) & 1)); - instruction[-3] = ifThenElse(cond) | OP_IT; - linkJumpT4(instruction, target); + uint16_t newInstruction = ifThenElse(cond) | OP_IT; + performJITMemcpy(writeTarget - 3, &newInstruction, sizeof(uint16_t)); + linkJumpT4(writeTarget, instruction, target); } - static void linkBX(uint16_t* instruction, void* target) + static void linkBX(uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( - ASSERT(!(reinterpret_cast(instruction) & 1)); + ASSERT_UNUSED(instruction, !(reinterpret_cast(instruction) & 1)); + ASSERT(!(reinterpret_cast(writeTarget) & 1)); ASSERT(!(reinterpret_cast(target) & 1)); const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast(reinterpret_cast(target) + 1)); ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast(reinterpret_cast(target) >> 16)); - instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); - instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); - instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); - instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); - instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); + uint16_t instructions[5]; + instructions[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + instructions[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); + instructions[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + instructions[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); + instructions[4] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); + + performJITMemcpy(writeTarget - 5, instructions, 5 * sizeof(uint16_t)); } - static void linkConditionalBX(Condition cond, uint16_t* instruction, void* target) + static void linkConditionalBX(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); ASSERT(!(reinterpret_cast(target) & 1)); - linkBX(instruction, target); - instruction[-6] = ifThenElse(cond, true, true) | OP_IT; + linkBX(writeTarget, instruction, target); + uint16_t newInstruction = ifThenElse(cond, true, true) | OP_IT; + performJITMemcpy(writeTarget - 6, &newInstruction, sizeof(uint16_t)); } - static void linkJumpAbsolute(uint16_t* instruction, void* target) + static void linkJumpAbsolute(uint16_t* writeTarget, const uint16_t* instruction, void* target) { // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); @@ -2687,26 +2763,31 @@ ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2))); - + if (canBeJumpT4(instruction, target)) { // There may be a better way to fix this, but right now put the NOPs first, since in the // case of an conditional branch this will be coming after an ITTT predicating *three* // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to // variable wdith encoding - the previous instruction might *look* like an ITTT but // actually be the second half of a 2-word op. - instruction[-5] = OP_NOP_T1; - instruction[-4] = OP_NOP_T2a; - instruction[-3] = OP_NOP_T2b; - linkJumpT4(instruction, target); + uint16_t instructions[3]; + instructions[0] = OP_NOP_T1; + instructions[1] = OP_NOP_T2a; + instructions[2] = OP_NOP_T2b; + performJITMemcpy(writeTarget - 5, instructions, 3 * sizeof(uint16_t)); + linkJumpT4(writeTarget, instruction, target); } else { const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast(reinterpret_cast(target) + 1)); ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast(reinterpret_cast(target) >> 16)); - instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); - instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); - instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); - instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); - instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); + + uint16_t instructions[5]; + instructions[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + instructions[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); + instructions[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + instructions[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); + instructions[4] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); + performJITMemcpy(writeTarget - 5, instructions, 5 * sizeof(uint16_t)); } } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/AssemblerBuffer.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/AssemblerBuffer.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/AssemblerBuffer.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/AssemblerBuffer.h 2016-11-03 07:04:20.000000000 +0000 @@ -62,39 +62,62 @@ }; class AssemblerData { + WTF_MAKE_NONCOPYABLE(AssemblerData); + static const size_t InlineCapacity = 128; public: AssemblerData() - : m_buffer(nullptr) - , m_capacity(0) + : m_buffer(m_inlineBuffer) + , m_capacity(InlineCapacity) { } - AssemblerData(unsigned initialCapacity) + AssemblerData(size_t initialCapacity) { - m_capacity = initialCapacity; - m_buffer = static_cast(fastMalloc(m_capacity)); + if (initialCapacity <= InlineCapacity) { + m_capacity = InlineCapacity; + m_buffer = m_inlineBuffer; + } else { + m_capacity = initialCapacity; + m_buffer = static_cast(fastMalloc(m_capacity)); + } } AssemblerData(AssemblerData&& other) { - m_buffer = other.m_buffer; - other.m_buffer = nullptr; + if (other.isInlineBuffer()) { + ASSERT(other.m_capacity == InlineCapacity); + memcpy(m_inlineBuffer, other.m_inlineBuffer, InlineCapacity); + m_buffer = m_inlineBuffer; + } else + m_buffer = other.m_buffer; m_capacity = other.m_capacity; + + other.m_buffer = nullptr; other.m_capacity = 0; } AssemblerData& operator=(AssemblerData&& other) { - m_buffer = other.m_buffer; - other.m_buffer = nullptr; + if (m_buffer && !isInlineBuffer()) + fastFree(m_buffer); + + if (other.isInlineBuffer()) { + ASSERT(other.m_capacity == InlineCapacity); + memcpy(m_inlineBuffer, other.m_inlineBuffer, InlineCapacity); + m_buffer = m_inlineBuffer; + } else + m_buffer = other.m_buffer; m_capacity = other.m_capacity; + + other.m_buffer = nullptr; other.m_capacity = 0; return *this; } ~AssemblerData() { - fastFree(m_buffer); + if (m_buffer && !isInlineBuffer()) + fastFree(m_buffer); } char* buffer() const { return m_buffer; } @@ -104,32 +127,37 @@ void grow(unsigned extraCapacity = 0) { m_capacity = m_capacity + m_capacity / 2 + extraCapacity; - m_buffer = static_cast(fastRealloc(m_buffer, m_capacity)); + if (isInlineBuffer()) { + m_buffer = static_cast(fastMalloc(m_capacity)); + memcpy(m_buffer, m_inlineBuffer, InlineCapacity); + } else + m_buffer = static_cast(fastRealloc(m_buffer, m_capacity)); } private: + bool isInlineBuffer() const { return m_buffer == m_inlineBuffer; } char* m_buffer; + char m_inlineBuffer[InlineCapacity]; unsigned m_capacity; }; class AssemblerBuffer { - static const int initialCapacity = 128; public: AssemblerBuffer() - : m_storage(initialCapacity) + : m_storage() , m_index(0) { } - bool isAvailable(int space) + bool isAvailable(unsigned space) { return m_index + space <= m_storage.capacity(); } - void ensureSpace(int space) + void ensureSpace(unsigned space) { - if (!isAvailable(space)) - grow(); + while (!isAvailable(space)) + outOfLineGrow(); } bool isAligned(int alignment) const @@ -156,6 +184,15 @@ return m_index; } + void setCodeSize(size_t index) + { + // Warning: Only use this if you know exactly what you are doing. + // For example, say you want 40 bytes of nops, it's ok to grow + // and then fill 40 bytes of nops using bigger instructions. + m_index = index; + ASSERT(m_index <= m_storage.capacity()); + } + AssemblerLabel label() const { return AssemblerLabel(m_index); @@ -163,7 +200,57 @@ unsigned debugOffset() { return m_index; } - AssemblerData releaseAssemblerData() { return WTFMove(m_storage); } + AssemblerData&& releaseAssemblerData() { return WTFMove(m_storage); } + + // LocalWriter is a trick to keep the storage buffer and the index + // in memory while issuing multiple Stores. + // It is created in a block scope and its attribute can stay live + // between writes. + // + // LocalWriter *CANNOT* be mixed with other types of access to AssemblerBuffer. + // AssemblerBuffer cannot be used until its LocalWriter goes out of scope. + class LocalWriter { + public: + LocalWriter(AssemblerBuffer& buffer, unsigned requiredSpace) + : m_buffer(buffer) + { + buffer.ensureSpace(requiredSpace); + m_storageBuffer = buffer.m_storage.buffer(); + m_index = buffer.m_index; +#if !defined(NDEBUG) + m_initialIndex = m_index; + m_requiredSpace = requiredSpace; +#endif + } + + ~LocalWriter() + { + ASSERT(m_index - m_initialIndex <= m_requiredSpace); + ASSERT(m_buffer.m_index == m_initialIndex); + ASSERT(m_storageBuffer == m_buffer.m_storage.buffer()); + m_buffer.m_index = m_index; + } + + void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); } + void putShortUnchecked(int16_t value) { putIntegralUnchecked(value); } + void putIntUnchecked(int32_t value) { putIntegralUnchecked(value); } + void putInt64Unchecked(int64_t value) { putIntegralUnchecked(value); } + private: + template + void putIntegralUnchecked(IntegralType value) + { + ASSERT(m_index + sizeof(IntegralType) <= m_buffer.m_storage.capacity()); + *reinterpret_cast_ptr(m_storageBuffer + m_index) = value; + m_index += sizeof(IntegralType); + } + AssemblerBuffer& m_buffer; + char* m_storageBuffer; + unsigned m_index; +#if !defined(NDEBUG) + unsigned m_initialIndex; + unsigned m_requiredSpace; +#endif + }; protected: template @@ -171,7 +258,7 @@ { unsigned nextIndex = m_index + sizeof(IntegralType); if (UNLIKELY(nextIndex > m_storage.capacity())) - grow(); + outOfLineGrow(); ASSERT(isAvailable(sizeof(IntegralType))); *reinterpret_cast_ptr(m_storage.buffer() + m_index) = value; m_index = nextIndex; @@ -200,6 +287,13 @@ } private: + NEVER_INLINE void outOfLineGrow() + { + m_storage.grow(); + } + + friend LocalWriter; + AssemblerData m_storage; unsigned m_index; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/LinkBuffer.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/LinkBuffer.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/LinkBuffer.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/LinkBuffer.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -90,7 +90,7 @@ { int32_t ptr = regionStart / sizeof(int32_t); const int32_t end = regionEnd / sizeof(int32_t); - int32_t* offsets = reinterpret_cast(assemblerData.buffer()); + int32_t* offsets = reinterpret_cast_ptr(assemblerData.buffer()); while (ptr < end) offsets[ptr++] = offset; } @@ -98,70 +98,94 @@ template void LinkBuffer::copyCompactAndLinkCode(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort) { - m_initialSize = macroAssembler.m_assembler.codeSize(); - allocate(m_initialSize, ownerUID, effort); + allocate(macroAssembler, ownerUID, effort); + const size_t initialSize = macroAssembler.m_assembler.codeSize(); if (didFailToAllocate()) return; + Vector& jumpsToLink = macroAssembler.jumpsToLink(); m_assemblerStorage = macroAssembler.m_assembler.buffer().releaseAssemblerData(); uint8_t* inData = reinterpret_cast(m_assemblerStorage.buffer()); - uint8_t* outData = reinterpret_cast(m_code); + + AssemblerData outBuffer(m_size); + + uint8_t* outData = reinterpret_cast(outBuffer.buffer()); + uint8_t* codeOutData = reinterpret_cast(m_code); + int readPtr = 0; int writePtr = 0; unsigned jumpCount = jumpsToLink.size(); - for (unsigned i = 0; i < jumpCount; ++i) { - int offset = readPtr - writePtr; - ASSERT(!(offset & 1)); - - // Copy the instructions from the last jump to the current one. - size_t regionSize = jumpsToLink[i].from() - readPtr; - InstructionType* copySource = reinterpret_cast_ptr(inData + readPtr); - InstructionType* copyEnd = reinterpret_cast_ptr(inData + readPtr + regionSize); - InstructionType* copyDst = reinterpret_cast_ptr(outData + writePtr); - ASSERT(!(regionSize % 2)); - ASSERT(!(readPtr % 2)); - ASSERT(!(writePtr % 2)); - while (copySource != copyEnd) - *copyDst++ = *copySource++; - recordLinkOffsets(m_assemblerStorage, readPtr, jumpsToLink[i].from(), offset); - readPtr += regionSize; - writePtr += regionSize; - - // Calculate absolute address of the jump target, in the case of backwards - // branches we need to be precise, forward branches we are pessimistic - const uint8_t* target; - if (jumpsToLink[i].to() >= jumpsToLink[i].from()) - target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far - else - target = outData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to()); - - JumpLinkType jumpLinkType = MacroAssembler::computeJumpType(jumpsToLink[i], outData + writePtr, target); - // Compact branch if we can... - if (MacroAssembler::canCompact(jumpsToLink[i].type())) { - // Step back in the write stream - int32_t delta = MacroAssembler::jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType); - if (delta) { - writePtr -= delta; - recordLinkOffsets(m_assemblerStorage, jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); + if (m_shouldPerformBranchCompaction) { + for (unsigned i = 0; i < jumpCount; ++i) { + int offset = readPtr - writePtr; + ASSERT(!(offset & 1)); + + // Copy the instructions from the last jump to the current one. + size_t regionSize = jumpsToLink[i].from() - readPtr; + InstructionType* copySource = reinterpret_cast_ptr(inData + readPtr); + InstructionType* copyEnd = reinterpret_cast_ptr(inData + readPtr + regionSize); + InstructionType* copyDst = reinterpret_cast_ptr(outData + writePtr); + ASSERT(!(regionSize % 2)); + ASSERT(!(readPtr % 2)); + ASSERT(!(writePtr % 2)); + while (copySource != copyEnd) + *copyDst++ = *copySource++; + recordLinkOffsets(m_assemblerStorage, readPtr, jumpsToLink[i].from(), offset); + readPtr += regionSize; + writePtr += regionSize; + + // Calculate absolute address of the jump target, in the case of backwards + // branches we need to be precise, forward branches we are pessimistic + const uint8_t* target; + if (jumpsToLink[i].to() >= jumpsToLink[i].from()) + target = codeOutData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far + else + target = codeOutData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to()); + + JumpLinkType jumpLinkType = MacroAssembler::computeJumpType(jumpsToLink[i], codeOutData + writePtr, target); + // Compact branch if we can... + if (MacroAssembler::canCompact(jumpsToLink[i].type())) { + // Step back in the write stream + int32_t delta = MacroAssembler::jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType); + if (delta) { + writePtr -= delta; + recordLinkOffsets(m_assemblerStorage, jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr); + } } + jumpsToLink[i].setFrom(writePtr); + } + } else { + if (!ASSERT_DISABLED) { + for (unsigned i = 0; i < jumpCount; ++i) + ASSERT(!MacroAssembler::canCompact(jumpsToLink[i].type())); } - jumpsToLink[i].setFrom(writePtr); } // Copy everything after the last jump - memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr); - recordLinkOffsets(m_assemblerStorage, readPtr, m_initialSize, readPtr - writePtr); + memcpy(outData + writePtr, inData + readPtr, initialSize - readPtr); + recordLinkOffsets(m_assemblerStorage, readPtr, initialSize, readPtr - writePtr); for (unsigned i = 0; i < jumpCount; ++i) { - uint8_t* location = outData + jumpsToLink[i].from(); - uint8_t* target = outData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to()); - MacroAssembler::link(jumpsToLink[i], location, target); + uint8_t* location = codeOutData + jumpsToLink[i].from(); + uint8_t* target = codeOutData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to()); + MacroAssembler::link(jumpsToLink[i], outData + jumpsToLink[i].from(), location, target); } jumpsToLink.clear(); - shrink(writePtr + m_initialSize - readPtr); + + size_t compactSize = writePtr + initialSize - readPtr; + if (m_executableMemory) { + m_size = compactSize; + m_executableMemory->shrink(m_size); + } else { + size_t nopSizeInBytes = initialSize - compactSize; + bool isCopyingToExecutableMemory = false; + MacroAssembler::AssemblerType_T::fillNops(outData + compactSize, nopSizeInBytes, isCopyingToExecutableMemory); + } + + performJITMemcpy(m_code, outData, m_size); #if DUMP_LINK_STATISTICS - dumpLinkStatistics(m_code, m_initialSize, m_size); + dumpLinkStatistics(m_code, initialSize, m_size); #endif #if DUMP_CODE dumpCode(m_code, m_size); @@ -176,15 +200,15 @@ #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL macroAssembler.m_assembler.buffer().flushConstantPool(false); #endif - AssemblerBuffer& buffer = macroAssembler.m_assembler.buffer(); - allocate(buffer.codeSize(), ownerUID, effort); + allocate(macroAssembler, ownerUID, effort); if (!m_didAllocate) return; ASSERT(m_code); + AssemblerBuffer& buffer = macroAssembler.m_assembler.buffer(); #if CPU(ARM_TRADITIONAL) macroAssembler.m_assembler.prepareExecutableCopy(m_code); #endif - memcpy(m_code, buffer.data(), buffer.codeSize()); + performJITMemcpy(m_code, buffer.data(), buffer.codeSize()); #if CPU(MIPS) macroAssembler.m_assembler.relocateJumps(buffer.data(), m_code); #endif @@ -192,22 +216,25 @@ copyCompactAndLinkCode(macroAssembler, ownerUID, effort); #elif CPU(ARM64) copyCompactAndLinkCode(macroAssembler, ownerUID, effort); -#endif +#endif // !ENABLE(BRANCH_COMPACTION) m_linkTasks = WTFMove(macroAssembler.m_linkTasks); } -void LinkBuffer::allocate(size_t initialSize, void* ownerUID, JITCompilationEffort effort) +void LinkBuffer::allocate(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort) { + size_t initialSize = macroAssembler.m_assembler.codeSize(); if (m_code) { if (initialSize > m_size) return; + size_t nopsToFillInBytes = m_size - initialSize; + macroAssembler.emitNops(nopsToFillInBytes); m_didAllocate = true; - m_size = initialSize; return; } + ASSERT(m_vm != nullptr); m_executableMemory = m_vm->executableAllocator.allocate(*m_vm, initialSize, ownerUID, effort); if (!m_executableMemory) return; @@ -216,14 +243,6 @@ m_didAllocate = true; } -void LinkBuffer::shrink(size_t newSize) -{ - if (!m_executableMemory) - return; - m_size = newSize; - m_executableMemory->shrink(m_size); -} - void LinkBuffer::performFinalization() { for (auto& task : m_linkTasks) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/LinkBuffer.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/LinkBuffer.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/LinkBuffer.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/LinkBuffer.h 2016-11-03 07:04:20.000000000 +0000 @@ -82,9 +82,6 @@ public: LinkBuffer(VM& vm, MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed) : m_size(0) -#if ENABLE(BRANCH_COMPACTION) - , m_initialSize(0) -#endif , m_didAllocate(false) , m_code(0) , m_vm(&vm) @@ -95,19 +92,21 @@ linkCode(macroAssembler, ownerUID, effort); } - LinkBuffer(VM& vm, MacroAssembler& macroAssembler, void* code, size_t size) + LinkBuffer(MacroAssembler& macroAssembler, void* code, size_t size, JITCompilationEffort effort = JITCompilationMustSucceed, bool shouldPerformBranchCompaction = true) : m_size(size) -#if ENABLE(BRANCH_COMPACTION) - , m_initialSize(0) -#endif , m_didAllocate(false) , m_code(code) - , m_vm(&vm) + , m_vm(0) #ifndef NDEBUG , m_completed(false) #endif { - linkCode(macroAssembler, 0, JITCompilationCanFail); +#if ENABLE(BRANCH_COMPACTION) + m_shouldPerformBranchCompaction = shouldPerformBranchCompaction; +#else + UNUSED_PARAM(shouldPerformBranchCompaction); +#endif + linkCode(macroAssembler, 0, effort); } ~LinkBuffer() @@ -144,10 +143,10 @@ MacroAssembler::linkJump(code(), jump, label); } - void link(JumpList list, CodeLocationLabel label) + void link(const JumpList& list, CodeLocationLabel label) { - for (unsigned i = 0; i < list.m_jumps.size(); ++i) - link(list.m_jumps[i], label); + for (const Jump& jump : list.jumps()) + link(jump, label); } void patch(DataLabelPtr label, void* value) @@ -250,11 +249,7 @@ return m_code; } - // FIXME: this does not account for the AssemblerData size! - size_t size() - { - return m_size; - } + size_t size() const { return m_size; } bool wasAlreadyDisassembled() const { return m_alreadyDisassembled; } void didAlreadyDisassemble() { m_alreadyDisassembled = true; } @@ -278,15 +273,14 @@ #endif return src; } - + // Keep this private! - the underlying code should only be obtained externally via finalizeCode(). void* code() { return m_code; } - void allocate(size_t initialSize, void* ownerUID, JITCompilationEffort); - void shrink(size_t newSize); + void allocate(MacroAssembler&, void* ownerUID, JITCompilationEffort); JS_EXPORT_PRIVATE void linkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort); #if ENABLE(BRANCH_COMPACTION) @@ -307,8 +301,8 @@ RefPtr m_executableMemory; size_t m_size; #if ENABLE(BRANCH_COMPACTION) - size_t m_initialSize; AssemblerData m_assemblerStorage; + bool m_shouldPerformBranchCompaction { true }; #endif bool m_didAllocate; void* m_code; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,9 @@ class MacroAssemblerARM64 : public AbstractMacroAssembler { public: + static const unsigned numGPRs = 32; + static const unsigned numFPRs = 32; + static const RegisterID dataTempRegister = ARM64Registers::ip0; static const RegisterID memoryTempRegister = ARM64Registers::ip1; @@ -78,7 +81,7 @@ static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return ARM64Assembler::computeJumpType(jumpType, from, to); } static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return ARM64Assembler::computeJumpType(record, from, to); } static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return ARM64Assembler::jumpSizeDelta(jumpType, jumpLinkType); } - static void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return ARM64Assembler::link(record, from, to); } + static void link(LinkRecord& record, uint8_t* from, const uint8_t* fromInstruction, uint8_t* to) { return ARM64Assembler::link(record, from, fromInstruction, to); } static const Scale ScalePtr = TimesEight; @@ -163,7 +166,10 @@ m_assembler.add<32>(dest, src, UInt12(imm.m_value)); else if (isUInt12(-imm.m_value)) m_assembler.sub<32>(dest, src, UInt12(-imm.m_value)); - else { + else if (src != dest) { + move(imm, dest); + add32(src, dest); + } else { move(imm, getCachedDataTempRegisterIDAndInvalidate()); m_assembler.add<32>(dest, src, dataTempRegister); } @@ -699,6 +705,11 @@ m_assembler.sub<32>(dest, dest, src); } + void sub32(RegisterID left, RegisterID right, RegisterID dest) + { + m_assembler.sub<32>(dest, left, right); + } + void sub32(TrustedImm32 imm, RegisterID dest) { if (isUInt12(imm.m_value)) { @@ -761,6 +772,11 @@ { m_assembler.sub<64>(dest, dest, src); } + + void sub64(RegisterID a, RegisterID b, RegisterID dest) + { + m_assembler.sub<64>(dest, a, b); + } void sub64(TrustedImm32 imm, RegisterID dest) { @@ -932,6 +948,11 @@ m_assembler.mvn<64>(dest, src); } + void not64(RegisterID srcDst) + { + m_assembler.mvn<64>(srcDst, srcDst); + } + // Memory access operations: void load64(ImplicitAddress address, RegisterID dest) @@ -960,6 +981,11 @@ load<64>(address, dest); } + void load64(RegisterID src, PostIndex simm, RegisterID dest) + { + m_assembler.ldr<64>(dest, src, simm); + } + DataLabel32 load64WithAddressOffsetPatch(Address address, RegisterID dest) { DataLabel32 label(this); @@ -976,6 +1002,26 @@ return label; } + void loadPair64(RegisterID src, RegisterID dest1, RegisterID dest2) + { + loadPair64(src, TrustedImm32(0), dest1, dest2); + } + + void loadPair64(RegisterID src, TrustedImm32 offset, RegisterID dest1, RegisterID dest2) + { + m_assembler.ldp<64>(dest1, dest2, src, offset.m_value); + } + + void loadPair64WithNonTemporalAccess(RegisterID src, RegisterID dest1, RegisterID dest2) + { + loadPair64WithNonTemporalAccess(src, TrustedImm32(0), dest1, dest2); + } + + void loadPair64WithNonTemporalAccess(RegisterID src, TrustedImm32 offset, RegisterID dest1, RegisterID dest2) + { + m_assembler.ldnp<64>(dest1, dest2, src, offset.m_value); + } + void abortWithReason(AbortReason reason) { move(TrustedImm32(reason), dataTempRegister); @@ -1092,12 +1138,12 @@ void zeroExtend16To32(RegisterID src, RegisterID dest) { - m_assembler.uxth<64>(dest, src); + m_assembler.uxth<32>(dest, src); } void signExtend16To32(RegisterID src, RegisterID dest) { - m_assembler.sxth<64>(dest, src); + m_assembler.sxth<32>(dest, src); } void load8(ImplicitAddress address, RegisterID dest) @@ -1129,6 +1175,11 @@ cachedMemoryTempRegister().invalidate(); } + void load8(RegisterID src, PostIndex simm, RegisterID dest) + { + m_assembler.ldrb(dest, src, simm); + } + void load8SignedExtendTo32(ImplicitAddress address, RegisterID dest) { if (tryLoadSignedWithOffset<8>(dest, address.base, address.offset)) @@ -1152,12 +1203,12 @@ void zeroExtend8To32(RegisterID src, RegisterID dest) { - m_assembler.uxtb<64>(dest, src); + m_assembler.uxtb<32>(dest, src); } void signExtend8To32(RegisterID src, RegisterID dest) { - m_assembler.sxtb<64>(dest, src); + m_assembler.sxtb<32>(dest, src); } void store64(RegisterID src, ImplicitAddress address) @@ -1212,6 +1263,11 @@ moveToCachedReg(imm, dataMemoryTempRegister()); store64(dataTempRegister, address); } + + void store64(RegisterID src, RegisterID dest, PostIndex simm) + { + m_assembler.str<64>(src, dest, simm); + } DataLabel32 store64WithAddressOffsetPatch(RegisterID src, Address address) { @@ -1221,6 +1277,26 @@ return label; } + void storePair64(RegisterID src1, RegisterID src2, RegisterID dest) + { + storePair64(src1, src2, dest, TrustedImm32(0)); + } + + void storePair64(RegisterID src1, RegisterID src2, RegisterID dest, TrustedImm32 offset) + { + m_assembler.stp<64>(src1, src2, dest, offset.m_value); + } + + void storePair64WithNonTemporalAccess(RegisterID src1, RegisterID src2, RegisterID dest) + { + storePair64WithNonTemporalAccess(src1, src2, dest, TrustedImm32(0)); + } + + void storePair64WithNonTemporalAccess(RegisterID src1, RegisterID src2, RegisterID dest, TrustedImm32 offset) + { + m_assembler.stnp<64>(src1, src2, dest, offset.m_value); + } + void store32(RegisterID src, ImplicitAddress address) { if (tryStoreWithOffset<32>(src, address.base, address.offset)) @@ -1304,7 +1380,7 @@ return; signExtend32ToPtr(TrustedImm32(address.offset), getCachedMemoryTempRegisterIDAndInvalidate()); - m_assembler.str<16>(src, address.base, memoryTempRegister); + m_assembler.strh(src, address.base, memoryTempRegister); } void store16(RegisterID src, BaseIndex address) @@ -1343,31 +1419,38 @@ return; signExtend32ToPtr(TrustedImm32(address.offset), getCachedMemoryTempRegisterIDAndInvalidate()); - m_assembler.str<8>(src, address.base, memoryTempRegister); + m_assembler.strb(src, address.base, memoryTempRegister); } void store8(TrustedImm32 imm, void* address) { - if (!imm.m_value) { + TrustedImm32 imm8(static_cast(imm.m_value)); + if (!imm8.m_value) { store8(ARM64Registers::zr, address); return; } - move(imm, getCachedDataTempRegisterIDAndInvalidate()); + move(imm8, getCachedDataTempRegisterIDAndInvalidate()); store8(dataTempRegister, address); } void store8(TrustedImm32 imm, ImplicitAddress address) { - if (!imm.m_value) { + TrustedImm32 imm8(static_cast(imm.m_value)); + if (!imm8.m_value) { store8(ARM64Registers::zr, address); return; } - move(imm, getCachedDataTempRegisterIDAndInvalidate()); + move(imm8, getCachedDataTempRegisterIDAndInvalidate()); store8(dataTempRegister, address); } + void store8(RegisterID src, RegisterID dest, PostIndex simm) + { + m_assembler.strb(src, dest, simm); + } + // Floating-point operations: static bool supportsFloatingPoint() { return true; } @@ -1435,6 +1518,16 @@ m_assembler.frintm<32>(dest, src); } + void roundTowardZeroDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.frintz<64>(dest, src); + } + + void roundTowardZeroFloat(FPRegisterID src, FPRegisterID dest) + { + m_assembler.frintz<32>(dest, src); + } + // Convert 'src' to an integer, and places the resulting 'dest'. // If the result is not representable as a 32 bit value, branch. // May also branch for some values that are representable in 32 bits @@ -1532,11 +1625,21 @@ load32(address.m_ptr, getCachedDataTempRegisterIDAndInvalidate()); convertInt32ToDouble(dataTempRegister, dest); } + + void convertInt32ToFloat(RegisterID src, FPRegisterID dest) + { + m_assembler.scvtf<32, 32>(dest, src); + } void convertInt64ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.scvtf<64, 64>(dest, src); } + + void convertInt64ToFloat(RegisterID src, FPRegisterID dest) + { + m_assembler.scvtf<32, 64>(dest, src); + } void divDouble(FPRegisterID src, FPRegisterID dest) { @@ -1766,6 +1869,11 @@ m_assembler.fneg<64>(dest, src); } + void negateFloat(FPRegisterID src, FPRegisterID dest) + { + m_assembler.fneg<32>(dest, src); + } + void sqrtDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.fsqrt<64>(dest, src); @@ -2317,23 +2425,23 @@ Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) { - ASSERT(!(0xffffff00 & right.m_value)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, getCachedMemoryTempRegisterIDAndInvalidate()); - return branch32(cond, memoryTempRegister, right); + return branch32(cond, memoryTempRegister, right8); } Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { - ASSERT(!(0xffffff00 & right.m_value)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, getCachedMemoryTempRegisterIDAndInvalidate()); - return branch32(cond, memoryTempRegister, right); + return branch32(cond, memoryTempRegister, right8); } Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { - ASSERT(!(0xffffff00 & right.m_value)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left.m_ptr, getCachedMemoryTempRegisterIDAndInvalidate()); - return branch32(cond, memoryTempRegister, right); + return branch32(cond, memoryTempRegister, right8); } Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) @@ -2430,8 +2538,24 @@ Jump branchTest64(ResultCondition cond, RegisterID reg, TrustedImm64 mask) { - move(mask, getCachedDataTempRegisterIDAndInvalidate()); - return branchTest64(cond, reg, dataTempRegister); + if (mask.m_value == -1) { + if ((cond == Zero) || (cond == NonZero)) + return Jump(makeCompareAndBranch<64>(static_cast(cond), reg)); + m_assembler.tst<64>(reg, reg); + } else if (hasOneBitSet(mask.m_value) && ((cond == Zero) || (cond == NonZero))) + return Jump(makeTestBitAndBranch(reg, getLSBSet(mask.m_value), static_cast(cond))); + else { + LogicalImmediate logicalImm = LogicalImmediate::create64(mask.m_value); + + if (logicalImm.isValid()) { + m_assembler.tst<64>(reg, logicalImm); + return Jump(makeBranch(cond)); + } + + move(mask, getCachedDataTempRegisterIDAndInvalidate()); + m_assembler.tst<64>(reg, dataTempRegister); + } + return Jump(makeBranch(cond)); } Jump branchTest64(ResultCondition cond, Address address, RegisterID mask) @@ -2460,27 +2584,31 @@ Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, getCachedDataTempRegisterIDAndInvalidate()); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address.m_ptr, getCachedDataTempRegisterIDAndInvalidate()); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); move(TrustedImmPtr(reinterpret_cast(address.offset)), getCachedDataTempRegisterIDAndInvalidate()); m_assembler.ldrb(dataTempRegister, address.base, dataTempRegister); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, getCachedDataTempRegisterIDAndInvalidate()); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right) @@ -2586,6 +2714,13 @@ return branchAdd64(cond, dest, imm, dest); } + Jump branchAdd64(RelationalCondition cond, TrustedImm32 imm, RegisterID dest) + { + ASSERT(isUInt12(imm.m_value)); + m_assembler.add<64, S>(dest, dest, UInt12(imm.m_value)); + return Jump(makeBranch(cond)); + } + Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID scratch1, RegisterID scratch2, RegisterID dest) { ASSERT(cond != Signed); @@ -2731,6 +2866,13 @@ return branchSub64(cond, dest, imm, dest); } + Jump branchSub64(RelationalCondition cond, TrustedImm32 imm, RegisterID dest) + { + ASSERT(isUInt12(imm.m_value)); + m_assembler.sub<64, S>(dest, dest, UInt12(imm.m_value)); + return Jump(makeBranch(cond)); + } + // Jumps, calls, returns @@ -2775,6 +2917,12 @@ load64(address, getCachedDataTempRegisterIDAndInvalidate()); m_assembler.br(dataTempRegister); } + + void jump(BaseIndex address) + { + load64(address, getCachedDataTempRegisterIDAndInvalidate()); + m_assembler.br(dataTempRegister); + } void jump(AbsoluteAddress address) { @@ -2876,8 +3024,9 @@ void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { + TrustedImm32 right8(static_cast(right.m_value)); load8(left, getCachedMemoryTempRegisterIDAndInvalidate()); - move(right, getCachedDataTempRegisterIDAndInvalidate()); + move(right8, getCachedDataTempRegisterIDAndInvalidate()); compare32(cond, memoryTempRegister, dataTempRegister, dest); } @@ -2901,8 +3050,9 @@ void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, getCachedMemoryTempRegisterIDAndInvalidate()); - test32(cond, memoryTempRegister, mask, dest); + test32(cond, memoryTempRegister, mask8, dest); } void test64(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) @@ -2988,6 +3138,14 @@ return PatchableJump(result); } + PatchableJump patchableBranch32(RelationalCondition cond, Address left, TrustedImm32 imm) + { + m_makeJumpPatchable = true; + Jump result = branch32(cond, left, imm); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + PatchableJump patchableBranch64(RelationalCondition cond, RegisterID reg, TrustedImm64 imm) { m_makeJumpPatchable = true; @@ -3104,6 +3262,11 @@ return ARM64Assembler::maxJumpReplacementSize(); } + static ptrdiff_t patchableJumpSize() + { + return ARM64Assembler::patchableJumpSize(); + } + RegisterID scratchRegisterForBlinding() { // We *do not* have a scratch register for blinding. diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARM.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARM.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARM.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARM.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2013-2015 Apple Inc. + * Copyright (C) 2008, 2013-2016 Apple Inc. * Copyright (C) 2009, 2010 University of Szeged * All rights reserved. * @@ -40,6 +40,9 @@ static const int DoubleConditionBitSpecial = 0x10; COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes); public: + static const unsigned numGPRs = 16; + static const unsigned numFPRs = 16; + typedef ARMRegisters::FPRegisterID FPRegisterID; enum RelationalCondition { @@ -311,6 +314,11 @@ m_assembler.subs(dest, dest, src); } + void sub32(RegisterID left, RegisterID right, RegisterID dest) + { + m_assembler.subs(dest, left, right); + } + void sub32(TrustedImm32 imm, RegisterID dest) { m_assembler.subs(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); @@ -501,14 +509,16 @@ void store8(TrustedImm32 imm, ImplicitAddress address) { - move(imm, ARMRegisters::S1); + TrustedImm32 imm8(static_cast(imm.m_value)); + move(imm8, ARMRegisters::S1); store8(ARMRegisters::S1, address); } void store8(TrustedImm32 imm, const void* address) { + TrustedImm32 imm8(static_cast(imm.m_value)); move(TrustedImm32(reinterpret_cast(address)), ARMRegisters::S0); - move(imm, ARMRegisters::S1); + move(imm8, ARMRegisters::S1); m_assembler.dtrUp(ARMAssembler::StoreUint8, ARMRegisters::S1, ARMRegisters::S0, 0); } @@ -623,22 +633,24 @@ Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) { + TrustedImm32 right8(static_cast(right.m_value)); load8(left, ARMRegisters::S1); - return branch32(cond, ARMRegisters::S1, right); + return branch32(cond, ARMRegisters::S1, right8); } Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { - ASSERT(!(right.m_value & 0xFFFFFF00)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, ARMRegisters::S1); - return branch32(cond, ARMRegisters::S1, right); + return branch32(cond, ARMRegisters::S1, right8); } Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { + TrustedImm32 right8(static_cast(right.m_value)); move(TrustedImmPtr(left.m_ptr), ARMRegisters::S1); load8(Address(ARMRegisters::S1), ARMRegisters::S1); - return branch32(cond, ARMRegisters::S1, right); + return branch32(cond, ARMRegisters::S1, right8); } Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right, int useConstantPool = 0) @@ -685,33 +697,36 @@ Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, ARMRegisters::S1); - return branchTest32(cond, ARMRegisters::S1, mask); + return branchTest32(cond, ARMRegisters::S1, mask8); } Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, ARMRegisters::S1); - return branchTest32(cond, ARMRegisters::S1, mask); + return branchTest32(cond, ARMRegisters::S1, mask8); } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1); load8(Address(ARMRegisters::S1), ARMRegisters::S1); - return branchTest32(cond, ARMRegisters::S1, mask); + return branchTest32(cond, ARMRegisters::S1, mask8); } Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == PositiveOrZero); m_assembler.tst(reg, mask); return Jump(m_assembler.jmp(ARMCondition(cond))); } Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == PositiveOrZero); ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true); if (w & ARMAssembler::Op2InvertedImmediate) m_assembler.bics(ARMRegisters::S0, reg, w & ~ARMAssembler::Op2InvertedImmediate); @@ -910,6 +925,14 @@ return PatchableJump(jump); } + PatchableJump patchableBranch32(RelationalCondition cond, Address address, TrustedImm32 imm) + { + internalCompare32(address, imm); + Jump jump(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMCondition(cond), false)); + m_assembler.bx(ARMRegisters::S1, ARMCondition(cond)); + return PatchableJump(jump); + } + void breakpoint() { m_assembler.bkpt(0); @@ -957,8 +980,9 @@ void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { + TrustedImm32 right8(static_cast(right.m_value)); load8(left, ARMRegisters::S1); - compare32(cond, ARMRegisters::S1, right, dest); + compare32(cond, ARMRegisters::S1, right8, dest); } void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) @@ -979,8 +1003,9 @@ void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, ARMRegisters::S1); - test32(cond, ARMRegisters::S1, mask, dest); + test32(cond, ARMRegisters::S1, mask8, dest); } void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) @@ -1174,6 +1199,12 @@ CRASH(); } + NO_RETURN_DUE_TO_CRASH void roundTowardZeroDouble(FPRegisterID, FPRegisterID) + { + ASSERT(!supportsFloatingPointRounding()); + CRASH(); + } + void storeFloat(FPRegisterID src, BaseIndex address) { m_assembler.baseIndexTransferFloat(ARMAssembler::StoreFloat, src, address.base, address.index, static_cast(address.scale), address.offset); @@ -1434,8 +1465,12 @@ static ptrdiff_t maxJumpReplacementSize() { - ARMAssembler::maxJumpReplacementSize(); - return 0; + return ARMAssembler::maxJumpReplacementSize(); + } + + static ptrdiff_t patchableJumpSize() + { + return ARMAssembler::patchableJumpSize(); } static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } @@ -1526,6 +1561,16 @@ m_assembler.cmp(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); } + void internalCompare32(Address left, TrustedImm32 right) + { + ARMWord tmp = (static_cast(right.m_value) == 0x80000000) ? ARMAssembler::InvalidImmediate : m_assembler.getOp2(-right.m_value); + load32(left, ARMRegisters::S1); + if (tmp != ARMAssembler::InvalidImmediate) + m_assembler.cmn(ARMRegisters::S1, tmp); + else + m_assembler.cmp(ARMRegisters::S1, m_assembler.getImm(right.m_value, ARMRegisters::S0)); + } + static void linkCall(void* code, Call call, FunctionPtr function) { if (call.isFlagSet(Call::Tail)) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -224,7 +224,8 @@ "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" "add ip, sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_D0_OFFSET) "\n" - "vstmia.64 ip, { d0-d31 }" "\n" + "vstmia.64 ip!, { d0-d15 }" "\n" + "vstmia.64 ip!, { d16-d31 }" "\n" "mov fp, sp" "\n" // Save the ProbeContext*. @@ -238,7 +239,9 @@ // out of the ProbeContext before returning. "add ip, sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_D31_OFFSET + FPREG_SIZE) "\n" - "vldmdb.64 ip!, { d0-d31 }" "\n" + "vldmdb.64 ip!, { d16-d31 }" "\n" + "vldmdb.64 ip!, { d0-d15 }" "\n" + "add ip, sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_R11_OFFSET + GPREG_SIZE) "\n" "ldmdb ip, { r0-r11 }" "\n" "ldr ip, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_FPSCR_OFFSET) "]" "\n" diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010, 2014-2015 Apple Inc. All rights reserved. + * Copyright (C) 2009-2010, 2014-2016 Apple Inc. All rights reserved. * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,9 @@ inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); } public: + static const unsigned numGPRs = 16; + static const unsigned numFPRs = 16; + MacroAssemblerARMv7() : m_makeJumpPatchable(false) { @@ -66,7 +69,7 @@ static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return ARMv7Assembler::computeJumpType(jumpType, from, to); } static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return ARMv7Assembler::computeJumpType(record, from, to); } static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return ARMv7Assembler::jumpSizeDelta(jumpType, jumpLinkType); } - static void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return ARMv7Assembler::link(record, from, to); } + static void link(LinkRecord& record, uint8_t* from, const uint8_t* fromInstruction, uint8_t* to) { return ARMv7Assembler::link(record, from, fromInstruction, to); } struct ArmAddress { enum AddressType { @@ -322,6 +325,11 @@ m_assembler.smull(dest, dataTempRegister, dest, src); } + void mul32(RegisterID left, RegisterID right, RegisterID dest) + { + m_assembler.smull(dest, dataTempRegister, left, right); + } + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { move(imm, dataTempRegister); @@ -454,6 +462,11 @@ m_assembler.sub(dest, dest, src); } + void sub32(RegisterID left, RegisterID right, RegisterID dest) + { + m_assembler.sub(dest, left, right); + } + void sub32(TrustedImm32 imm, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value); @@ -824,13 +837,15 @@ void store8(TrustedImm32 imm, void* address) { - move(imm, dataTempRegister); + TrustedImm32 imm8(static_cast(imm.m_value)); + move(imm8, dataTempRegister); store8(dataTempRegister, address); } void store8(TrustedImm32 imm, Address address) { - move(imm, dataTempRegister); + TrustedImm32 imm8(static_cast(imm.m_value)); + move(imm8, dataTempRegister); store8(dataTempRegister, address); } @@ -1084,6 +1099,12 @@ CRASH(); } + NO_RETURN_DUE_TO_CRASH void roundTowardZeroDouble(FPRegisterID, FPRegisterID) + { + ASSERT(!supportsFloatingPointRounding()); + CRASH(); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.vmov(fpTempRegister, src, src); @@ -1334,6 +1355,11 @@ return ARMv7Assembler::maxJumpReplacementSize(); } + static ptrdiff_t patchableJumpSize() + { + return ARMv7Assembler::patchableJumpSize(); + } + // Forwards / external control flow operations: // // This set of jump and conditional branch operations return a Jump @@ -1465,42 +1491,46 @@ Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right) { - compare32AndSetFlags(left, right); + TrustedImm32 right8(static_cast(right.m_value)); + compare32AndSetFlags(left, right8); return Jump(makeBranch(cond)); } Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) { - ASSERT(!(0xffffff00 & right.m_value)); // use addressTempRegister incase the branch8 we call uses dataTempRegister. :-/ + TrustedImm32 right8(static_cast(right.m_value)); load8(left, addressTempRegister); - return branch8(cond, addressTempRegister, right); + return branch8(cond, addressTempRegister, right8); } Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { - ASSERT(!(0xffffff00 & right.m_value)); // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/ + TrustedImm32 right8(static_cast(right.m_value)); load8(left, addressTempRegister); - return branch32(cond, addressTempRegister, right); + return branch32(cond, addressTempRegister, right8); } Jump branch8(RelationalCondition cond, AbsoluteAddress address, TrustedImm32 right) { // Use addressTempRegister instead of dataTempRegister, since branch32 uses dataTempRegister. + TrustedImm32 right8(static_cast(right.m_value)); move(TrustedImmPtr(address.m_ptr), addressTempRegister); load8(Address(addressTempRegister), addressTempRegister); - return branch32(cond, addressTempRegister, right); + return branch32(cond, addressTempRegister, right8); } Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) { + ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == PositiveOrZero); m_assembler.tst(reg, mask); return Jump(makeBranch(cond)); } Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { + ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == PositiveOrZero); test32(reg, mask); return Jump(makeBranch(cond)); } @@ -1522,23 +1552,26 @@ Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, addressTempRegister); - return branchTest32(cond, addressTempRegister, mask); + return branchTest32(cond, addressTempRegister, mask8); } Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, addressTempRegister); - return branchTest32(cond, addressTempRegister, mask); + return branchTest32(cond, addressTempRegister, mask8); } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ + TrustedImm32 mask8(static_cast(mask.m_value)); move(TrustedImmPtr(address.m_ptr), addressTempRegister); load8(Address(addressTempRegister), addressTempRegister); - return branchTest32(cond, addressTempRegister, mask); + return branchTest32(cond, addressTempRegister, mask8); } void jump(RegisterID target) @@ -1765,8 +1798,9 @@ void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { + TrustedImm32 right8(static_cast(right.m_value)); load8(left, addressTempRegister); - compare32(cond, addressTempRegister, right, dest); + compare32(cond, addressTempRegister, right8, dest); } void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) @@ -1792,8 +1826,9 @@ void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, dataTempRegister); - test32(dataTempRegister, mask); + test32(dataTempRegister, mask8); m_assembler.it(armV7Condition(cond), false); m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1)); m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0)); @@ -1856,6 +1891,14 @@ m_makeJumpPatchable = false; return PatchableJump(result); } + + PatchableJump patchableBranch32(RelationalCondition cond, Address left, TrustedImm32 imm) + { + m_makeJumpPatchable = true; + Jump result = branch32(cond, left, imm); + m_makeJumpPatchable = false; + return PatchableJump(result); + } PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MacroAssemblerCodeRef.h" + +#include "JSCInlines.h" +#include "LLIntData.h" + +namespace JSC { + +MacroAssemblerCodePtr MacroAssemblerCodePtr::createLLIntCodePtr(OpcodeID codeId) +{ + return createFromExecutableAddress(LLInt::getCodePtr(codeId)); +} + +void MacroAssemblerCodePtr::dumpWithName(const char* name, PrintStream& out) const +{ + if (!m_value) { + out.print(name, "(null)"); + return; + } + if (executableAddress() == dataLocation()) { + out.print(name, "(", RawPointer(executableAddress()), ")"); + return; + } + out.print(name, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")"); +} + +void MacroAssemblerCodePtr::dump(PrintStream& out) const +{ + dumpWithName("CodePtr", out); +} + +MacroAssemblerCodeRef MacroAssemblerCodeRef::createLLIntCodeRef(OpcodeID codeId) +{ + return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId))); +} + +void MacroAssemblerCodeRef::dump(PrintStream& out) const +{ + m_codePtr.dumpWithName("CodeRef", out); +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,7 +28,6 @@ #include "Disassembler.h" #include "ExecutableAllocator.h" -#include "LLIntData.h" #include #include #include @@ -51,34 +50,10 @@ #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes! #endif -#if CPU(X86) && OS(WINDOWS) -#define CALLING_CONVENTION_IS_STDCALL 1 -#ifndef CDECL -#if COMPILER(MSVC) -#define CDECL __cdecl -#else -#define CDECL __attribute__ ((__cdecl)) -#endif // COMPILER(MSVC) -#endif // CDECL -#else -#define CALLING_CONVENTION_IS_STDCALL 0 -#endif - -#if CPU(X86) -#define HAS_FASTCALL_CALLING_CONVENTION 1 -#ifndef FASTCALL -#if COMPILER(MSVC) -#define FASTCALL __fastcall -#else -#define FASTCALL __attribute__ ((fastcall)) -#endif // COMPILER(MSVC) -#endif // FASTCALL -#else -#define HAS_FASTCALL_CALLING_CONVENTION 0 -#endif // CPU(X86) - namespace JSC { +enum OpcodeID : unsigned; + // FunctionPtr: // // FunctionPtr should be used to wrap pointers to C/C++ functions in JSC @@ -178,7 +153,7 @@ } #endif -#if HAS_FASTCALL_CALLING_CONVENTION +#if COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION) template FunctionPtr(returnType (FASTCALL *value)()) @@ -299,10 +274,7 @@ return result; } - static MacroAssemblerCodePtr createLLIntCodePtr(OpcodeID codeId) - { - return createFromExecutableAddress(LLInt::getCodePtr(codeId)); - } + static MacroAssemblerCodePtr createLLIntCodePtr(OpcodeID codeId); explicit MacroAssemblerCodePtr(ReturnAddressPtr ra) : m_value(ra.value()) @@ -325,23 +297,9 @@ return m_value == other.m_value; } - void dumpWithName(const char* name, PrintStream& out) const - { - if (!m_value) { - out.print(name, "(null)"); - return; - } - if (executableAddress() == dataLocation()) { - out.print(name, "(", RawPointer(executableAddress()), ")"); - return; - } - out.print(name, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")"); - } + void dumpWithName(const char* name, PrintStream& out) const; - void dump(PrintStream& out) const - { - dumpWithName("CodePtr", out); - } + void dump(PrintStream& out) const; enum EmptyValueTag { EmptyValue }; enum DeletedValueTag { DeletedValue }; @@ -415,10 +373,7 @@ } // Helper for creating self-managed code refs from LLInt. - static MacroAssemblerCodeRef createLLIntCodeRef(OpcodeID codeId) - { - return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId))); - } + static MacroAssemblerCodeRef createLLIntCodeRef(OpcodeID codeId); ExecutableMemoryHandle* executableMemory() const { @@ -444,10 +399,7 @@ explicit operator bool() const { return !!m_codePtr; } - void dump(PrintStream& out) const - { - m_codePtr.dumpWithName("CodeRef", out); - } + void dump(PrintStream& out) const; private: MacroAssemblerCodePtr m_codePtr; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssembler.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,6 +28,8 @@ #if ENABLE(ASSEMBLER) +#include "JSCJSValue.h" + #if CPU(ARM_THUMB2) #include "MacroAssemblerARMv7.h" namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; }; @@ -271,7 +273,7 @@ } #endif - // Platform agnostic onvenience functions, + // Platform agnostic convenience functions, // described in terms of other macro assembly methods. void pop() { @@ -492,6 +494,7 @@ // B3 has additional pseudo-opcodes for returning, when it wants to signal that the return // consumes some register in some way. + void retVoid() { ret(); } void ret32(RegisterID) { ret(); } void ret64(RegisterID) { ret(); } void retFloat(FPRegisterID) { ret(); } @@ -790,7 +793,8 @@ using MacroAssemblerBase::branchTest8; Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1)) { - return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask); + TrustedImm32 mask8(static_cast(mask.m_value)); + return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask8); } #else // !CPU(X86_64) @@ -1694,16 +1698,20 @@ Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest) { - if (src == dest) - ASSERT(haveScratchRegisterForBlinding()); - if (shouldBlind(imm)) { - if (src == dest) { - move(src, scratchRegisterForBlinding()); - src = scratchRegisterForBlinding(); + if (src != dest || haveScratchRegisterForBlinding()) { + if (src == dest) { + move(src, scratchRegisterForBlinding()); + src = scratchRegisterForBlinding(); + } + loadXorBlindedConstant(xorBlindConstant(imm), dest); + return branchAdd32(cond, src, dest); } - loadXorBlindedConstant(xorBlindConstant(imm), dest); - return branchAdd32(cond, src, dest); + // If we don't have a scratch register available for use, we'll just + // place a random number of nops. + uint32_t nopCount = random() & 3; + while (nopCount--) + nop(); } return branchAdd32(cond, src, imm.asTrustedImm32(), dest); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h 2016-11-03 07:04:20.000000000 +0000 @@ -641,10 +641,10 @@ { m_assembler.sqrtd(dst, src); } - - void absDouble(FPRegisterID, FPRegisterID) + + void absDouble(FPRegisterID src, FPRegisterID dst) { - RELEASE_ASSERT_NOT_REACHED(); + m_assembler.absd(dst, src); } NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID) @@ -659,6 +659,12 @@ CRASH(); } + NO_RETURN_DUE_TO_CRASH void roundTowardZeroDouble(FPRegisterID, FPRegisterID) + { + ASSERT(!supportsFloatingPointRounding()); + CRASH(); + } + ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) { ConvertibleLoadLabel result(this); @@ -816,7 +822,53 @@ void load16Unaligned(BaseIndex address, RegisterID dest) { - load16(address, dest); + if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { + /* + sll addrtemp, address.index, address.scale + addu addrtemp, addrtemp, address.base + lbu immTemp, address.offset+x(addrtemp) (x=0 for LE, x=1 for BE) + lbu dest, address.offset+x(addrtemp) (x=1 for LE, x=0 for BE) + sll dest, dest, 8 + or dest, dest, immTemp + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); +#if CPU(BIG_ENDIAN) + m_assembler.lbu(immTempRegister, addrTempRegister, address.offset + 1); + m_assembler.lbu(dest, addrTempRegister, address.offset); +#else + m_assembler.lbu(immTempRegister, addrTempRegister, address.offset); + m_assembler.lbu(dest, addrTempRegister, address.offset + 1); +#endif + m_assembler.sll(dest, dest, 8); + m_assembler.orInsn(dest, dest, immTempRegister); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, address.offset >> 16 + ori immTemp, immTemp, address.offset & 0xffff + addu addrTemp, addrTemp, immTemp + lbu immTemp, x(addrtemp) (x=0 for LE, x=1 for BE) + lbu dest, x(addrtemp) (x=1 for LE, x=0 for BE) + sll dest, dest, 8 + or dest, dest, immTemp + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, address.offset >> 16); + m_assembler.ori(immTempRegister, immTempRegister, address.offset); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); +#if CPU(BIG_ENDIAN) + m_assembler.lbu(immTempRegister, addrTempRegister, 1); + m_assembler.lbu(dest, addrTempRegister, 0); +#else + m_assembler.lbu(immTempRegister, addrTempRegister, 0); + m_assembler.lbu(dest, addrTempRegister, 1); +#endif + m_assembler.sll(dest, dest, 8); + m_assembler.orInsn(dest, dest, immTempRegister); + } } void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) @@ -1039,16 +1091,45 @@ li addrTemp, address sb src, 0(addrTemp) */ - if (!imm.m_value && !m_fixedWidth) { + TrustedImm32 imm8(static_cast(imm.m_value)); + if (!imm8.m_value && !m_fixedWidth) { move(TrustedImmPtr(address), addrTempRegister); m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0); } else { - move(imm, immTempRegister); + move(imm8, immTempRegister); move(TrustedImmPtr(address), addrTempRegister); m_assembler.sb(immTempRegister, addrTempRegister, 0); } } + void store8(TrustedImm32 imm, ImplicitAddress address) + { + TrustedImm32 imm8(static_cast(imm.m_value)); + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + if (!imm8.m_value) + m_assembler.sb(MIPSRegisters::zero, address.base, address.offset); + else { + move(imm8, immTempRegister); + m_assembler.sb(immTempRegister, address.base, address.offset); + } + } else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + sb immTemp, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + if (!imm8.m_value && !m_fixedWidth) + m_assembler.sb(MIPSRegisters::zero, addrTempRegister, address.offset); + else { + move(imm8, immTempRegister); + m_assembler.sb(immTempRegister, addrTempRegister, address.offset); + } + } + } + void store16(RegisterID src, BaseIndex address) { if (address.offset >= -32768 && address.offset <= 32767 @@ -1242,7 +1323,16 @@ return false; #endif } - static bool supportsFloatingPointAbs() { return false; } + + static bool supportsFloatingPointAbs() + { +#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) + return true; +#else + return false; +#endif + } + static bool supportsFloatingPointRounding() { return false; } // Stack manipulation operations: @@ -1356,38 +1446,35 @@ Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) { - // Make sure the immediate value is unsigned 8 bits. - ASSERT(!(right.m_value & 0xFFFFFF00)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, dataTempRegister); - move(right, immTempRegister); + move(right8, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { - // Make sure the immediate value is unsigned 8 bits. - ASSERT(!(right.m_value & 0xFFFFFF00)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, dataTempRegister); - move(right, immTempRegister); + move(right8, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { - // Make sure the immediate value is unsigned 8 bits. - ASSERT(!(right.m_value & 0xFFFFFF00)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, dataTempRegister); - move(right, immTempRegister); + move(right8, immTempRegister); compare32(cond, dataTempRegister, immTempRegister, dest); } Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { - ASSERT(!(right.m_value & 0xFFFFFF00)); + TrustedImm32 right8(static_cast(right.m_value)); load8(left, dataTempRegister); // Be careful that the previous load8() uses immTempRegister. // So, we need to put move() after load8(). - move(right, immTempRegister); + move(right8, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } @@ -1493,20 +1580,36 @@ Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); m_assembler.andInsn(cmpTempRegister, reg, mask); - if (cond == Zero) + switch (cond) { + case Zero: return branchEqual(cmpTempRegister, MIPSRegisters::zero); - return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + case NonZero: + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + case Signed: + m_assembler.slt(cmpTempRegister, cmpTempRegister, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + default: + RELEASE_ASSERT_NOT_REACHED(); + } } Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); if (mask.m_value == -1 && !m_fixedWidth) { - if (cond == Zero) + switch (cond) { + case Zero: return branchEqual(reg, MIPSRegisters::zero); - return branchNotEqual(reg, MIPSRegisters::zero); + case NonZero: + return branchNotEqual(reg, MIPSRegisters::zero); + case Signed: + m_assembler.slt(cmpTempRegister, reg, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + default: + RELEASE_ASSERT_NOT_REACHED(); + } } move(mask, immTempRegister); return branchTest32(cond, reg, immTempRegister); @@ -1526,21 +1629,24 @@ Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, dataTempRegister); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, dataTempRegister); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); move(TrustedImmPtr(address.m_ptr), dataTempRegister); load8(Address(dataTempRegister), dataTempRegister); - return branchTest32(cond, dataTempRegister, mask); + return branchTest32(cond, dataTempRegister, mask8); } Jump jump() @@ -2113,14 +2219,15 @@ void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { ASSERT((cond == Zero) || (cond == NonZero)); + TrustedImm32 mask8(static_cast(mask.m_value)); load8(address, dataTempRegister); - if (mask.m_value == -1 && !m_fixedWidth) { + if (mask8.m_value == -1 && !m_fixedWidth) { if (cond == Zero) m_assembler.sltiu(dest, dataTempRegister, 1); else m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); } else { - move(mask, immTempRegister); + move(mask8, immTempRegister); m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister); if (cond == Zero) m_assembler.sltiu(dest, cmpTempRegister, 1); @@ -2499,6 +2606,11 @@ m_assembler.movd(dest, src); } + void moveZeroToDouble(FPRegisterID reg) + { + convertInt32ToDouble(MIPSRegisters::zero, reg); + } + void swapDouble(FPRegisterID fr1, FPRegisterID fr2) { moveDouble(fr1, fpTempRegister); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved. * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. - * Copyright (C) 2008, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -419,6 +419,17 @@ m_assembler.sublRegReg(src, dest); } + void sub32(RegisterID left, RegisterID right, RegisterID dest) + { + if (dest == right) { + neg32(dest); + add32(left, dest); + return; + } + move(left, dest); + sub32(right, dest); + } + void sub32(TrustedImm32 imm, AbsoluteAddress address) { if (!imm.m_value) @@ -921,11 +932,11 @@ void store8(TrustedImm32 imm, void* address) { - ASSERT((imm.m_value >= -128) && (imm.m_value <= 127)); + TrustedImm32 imm8(static_cast(imm.m_value)); RegisterID dstptr = claimScratch(); move(TrustedImmPtr(address), dstptr); RegisterID srcval = claimScratch(); - move(imm, srcval); + move(imm8, srcval); m_assembler.movbRegMem(srcval, dstptr); releaseScratch(dstptr); releaseScratch(srcval); @@ -933,12 +944,12 @@ void store8(TrustedImm32 imm, Address address) { - ASSERT((imm.m_value >= -128) && (imm.m_value <= 127)); + TrustedImm32 imm8(static_cast(imm.m_value)); RegisterID dstptr = claimScratch(); move(address.base, dstptr); add32(TrustedImm32(address.offset), dstptr); RegisterID srcval = claimScratch(); - move(imm, srcval); + move(imm8, srcval); m_assembler.movbRegMem(srcval, dstptr); releaseScratch(dstptr); releaseScratch(srcval); @@ -1587,30 +1598,39 @@ CRASH(); } + NO_RETURN_DUE_TO_CRASH void roundTowardZeroDouble(FPRegisterID, FPRegisterID) + { + ASSERT(!supportsFloatingPointRounding()); + CRASH(); + } + Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); RegisterID addressTempRegister = claimScratch(); load8(address, addressTempRegister); - Jump jmp = branchTest32(cond, addressTempRegister, mask); + Jump jmp = branchTest32(cond, addressTempRegister, mask8); releaseScratch(addressTempRegister); return jmp; } Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); RegisterID addressTempRegister = claimScratch(); load8(address, addressTempRegister); - Jump jmp = branchTest32(cond, addressTempRegister, mask); + Jump jmp = branchTest32(cond, addressTempRegister, mask8); releaseScratch(addressTempRegister); return jmp; } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); RegisterID addressTempRegister = claimScratch(); move(TrustedImmPtr(address.m_ptr), addressTempRegister); load8(Address(addressTempRegister), addressTempRegister); - Jump jmp = branchTest32(cond, addressTempRegister, mask); + Jump jmp = branchTest32(cond, addressTempRegister, mask8); releaseScratch(addressTempRegister); return jmp; } @@ -1627,27 +1647,30 @@ Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) { + TrustedImm32 right8(static_cast(right.m_value)); RegisterID addressTempRegister = claimScratch(); load8(left, addressTempRegister); - Jump jmp = branch32(cond, addressTempRegister, right); + Jump jmp = branch32(cond, addressTempRegister, right8); releaseScratch(addressTempRegister); return jmp; } Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { + TrustedImm32 right8(static_cast(right.m_value)); RegisterID addressTempRegister = claimScratch(); load8(left, addressTempRegister); - Jump jmp = branch32(cond, addressTempRegister, right); + Jump jmp = branch32(cond, addressTempRegister, right8); releaseScratch(addressTempRegister); return jmp; } void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { + TrustedImm32 right8(static_cast(right.m_value)); RegisterID addressTempRegister = claimScratch(); load8(left, addressTempRegister); - compare32(cond, addressTempRegister, right, dest); + compare32(cond, addressTempRegister, right8, dest); releaseScratch(addressTempRegister); } @@ -1819,11 +1842,13 @@ { ASSERT((cond == Zero) || (cond == NonZero)); + TrustedImm32 mask8(static_cast(mask.m_value)); + load8(address, dest); - if (mask.m_value == -1) + if (mask8.m_value == -1) compare32(0, dest, static_cast(cond)); else - testlImm(mask.m_value, dest); + testlImm(mask8.m_value, dest); if (cond != NonZero) { m_assembler.movt(dest); return; @@ -1941,14 +1966,14 @@ Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { - ASSERT(!(right.m_value & 0xFFFFFF00)); + TrustedImm32 right8(static_cast(right.m_value)); RegisterID lefttmp = claimScratch(); loadEffectiveAddress(left, lefttmp); load8(lefttmp, lefttmp); RegisterID righttmp = claimScratch(); - m_assembler.loadConstant(right.m_value, righttmp); + m_assembler.loadConstant(right8.m_value, righttmp); Jump result = branch32(cond, lefttmp, righttmp); releaseScratch(lefttmp); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h 2016-11-03 07:04:20.000000000 +0000 @@ -38,6 +38,9 @@ class MacroAssemblerX86_64 : public MacroAssemblerX86Common { public: + static const unsigned numGPRs = 16; + static const unsigned numFPRs = 16; + static const Scale ScalePtr = TimesEight; using MacroAssemblerX86Common::add32; @@ -137,8 +140,9 @@ void store8(TrustedImm32 imm, void* address) { + TrustedImm32 imm8(static_cast(imm.m_value)); move(TrustedImmPtr(address), scratchRegister()); - store8(imm, Address(scratchRegister())); + store8(imm8, Address(scratchRegister())); } void store8(RegisterID reg, void* address) @@ -922,16 +926,21 @@ return branchAdd64(cond, src1, dest); } - Jump branchAdd64(ResultCondition cond, Address src1, RegisterID src2, RegisterID dest) + Jump branchAdd64(ResultCondition cond, Address op1, RegisterID op2, RegisterID dest) { - move(src2, dest); - return branchAdd64(cond, src1, dest); + if (op2 == dest) + return branchAdd64(cond, op1, dest); + if (op1.base == dest) { + load32(op1, dest); + return branchAdd64(cond, op2, dest); + } + move(op2, dest); + return branchAdd64(cond, op1, dest); } Jump branchAdd64(ResultCondition cond, RegisterID src1, Address src2, RegisterID dest) { - move(src1, dest); - return branchAdd64(cond, src2, dest); + return branchAdd64(cond, src2, src1, dest); } Jump branchAdd64(ResultCondition cond, RegisterID src, RegisterID dest) @@ -1205,22 +1214,25 @@ using MacroAssemblerX86Common::branch8; Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { + TrustedImm32 right8(static_cast(right.m_value)); MacroAssemblerX86Common::move(TrustedImmPtr(left.m_ptr), scratchRegister()); - return MacroAssemblerX86Common::branch8(cond, Address(scratchRegister()), right); + return MacroAssemblerX86Common::branch8(cond, Address(scratchRegister()), right8); } using MacroAssemblerX86Common::branchTest8; Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); TrustedImmPtr addr(reinterpret_cast(address.offset)); MacroAssemblerX86Common::move(addr, scratchRegister()); - return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister(), address.base, TimesOne), mask); + return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister(), address.base, TimesOne), mask8); } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { + TrustedImm32 mask8(static_cast(mask.m_value)); MacroAssemblerX86Common::move(TrustedImmPtr(address.m_ptr), scratchRegister()); - return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister()), mask); + return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister()), mask8); } void convertInt64ToDouble(RegisterID src, FPRegisterID dest) @@ -1228,6 +1240,21 @@ m_assembler.cvtsi2sdq_rr(src, dest); } + void convertInt64ToDouble(Address src, FPRegisterID dest) + { + m_assembler.cvtsi2sdq_mr(src.offset, src.base, dest); + } + + void convertInt64ToFloat(RegisterID src, FPRegisterID dest) + { + m_assembler.cvtsi2ssq_rr(src, dest); + } + + void convertInt64ToFloat(Address src, FPRegisterID dest) + { + m_assembler.cvtsi2ssq_mr(src.offset, src.base, dest); + } + static bool supportsFloatingPoint() { return true; } static bool supportsFloatingPointTruncate() { return true; } static bool supportsFloatingPointSqrt() { return true; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -553,6 +553,7 @@ #endif MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_sse4_1CheckState = CPUIDCheckState::NotChecked; +MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_avxCheckState = CPUIDCheckState::NotChecked; MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_lzcntCheckState = CPUIDCheckState::NotChecked; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h 2016-11-03 07:04:20.000000000 +0000 @@ -48,7 +48,7 @@ return s_scratchRegister; } #endif - + protected: static const int DoubleConditionBitInvert = 0x10; static const int DoubleConditionBitSpecial = 0x20; @@ -135,12 +135,14 @@ void add8(TrustedImm32 imm, Address address) { - m_assembler.addb_im(imm.m_value, address.offset, address.base); + TrustedImm32 imm8(static_cast(imm.m_value)); + m_assembler.addb_im(imm8.m_value, address.offset, address.base); } void add8(TrustedImm32 imm, BaseIndex address) { - m_assembler.addb_im(imm.m_value, address.offset, address.base, address.index, address.scale); + TrustedImm32 imm8(static_cast(imm.m_value)); + m_assembler.addb_im(imm8.m_value, address.offset, address.base, address.index, address.scale); } void add16(TrustedImm32 imm, Address address) @@ -230,7 +232,7 @@ } m_assembler.leal_mr(index.offset, index.base, index.index, index.scale, dest); } - + void and32(RegisterID src, RegisterID dest) { m_assembler.andl_rr(src, dest); @@ -270,14 +272,20 @@ void and32(Address op1, RegisterID op2, RegisterID dest) { - move32IfNeeded(op2, dest); - and32(op1, dest); + if (op2 == dest) + and32(op1, dest); + else if (op1.base == dest) { + load32(op1, dest); + and32(op2, dest); + } else { + zeroExtend32ToPtr(op2, dest); + and32(op1, dest); + } } void and32(RegisterID op1, Address op2, RegisterID dest) { - move32IfNeeded(op1, dest); - and32(op2, dest); + and32(op2, op1, dest); } void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) @@ -360,16 +368,22 @@ m_assembler.imull_mr(src.offset, src.base, dest); } - void mul32(Address src1, RegisterID src2, RegisterID dest) + void mul32(Address op1, RegisterID op2, RegisterID dest) { - move32IfNeeded(src2, dest); - mul32(src1, dest); + if (op2 == dest) + mul32(op1, dest); + else if (op1.base == dest) { + load32(op1, dest); + mul32(op2, dest); + } else { + zeroExtend32ToPtr(op2, dest); + mul32(op1, dest); + } } void mul32(RegisterID src1, Address src2, RegisterID dest) { - move32IfNeeded(src1, dest); - mul32(src2, dest); + mul32(src2, src1, dest); } void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) @@ -450,14 +464,20 @@ void or32(Address op1, RegisterID op2, RegisterID dest) { - move32IfNeeded(op2, dest); - or32(op1, dest); + if (op2 == dest) + or32(op1, dest); + else if (op1.base == dest) { + load32(op1, dest); + or32(op2, dest); + } else { + zeroExtend32ToPtr(op2, dest); + or32(op1, dest); + } } void or32(RegisterID op1, Address op2, RegisterID dest) { - move32IfNeeded(op1, dest); - or32(op2, dest); + or32(op2, op1, dest); } void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) @@ -540,7 +560,18 @@ { m_assembler.subl_rr(src, dest); } - + + void sub32(RegisterID left, RegisterID right, RegisterID dest) + { + if (dest == right) { + neg32(dest); + add32(left, dest); + return; + } + move(left, dest); + sub32(right, dest); + } + void sub32(TrustedImm32 imm, RegisterID dest) { if (imm.m_value == 1) @@ -609,14 +640,20 @@ void xor32(Address op1, RegisterID op2, RegisterID dest) { - move32IfNeeded(op2, dest); - xor32(op1, dest); + if (op2 == dest) + xor32(op1, dest); + else if (op1.base == dest) { + load32(op1, dest); + xor32(op2, dest); + } else { + zeroExtend32ToPtr(op2, dest); + xor32(op1, dest); + } } void xor32(RegisterID op1, Address op2, RegisterID dest) { - move32IfNeeded(op1, dest); - xor32(op2, dest); + xor32(op2, op1, dest); } void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) @@ -711,6 +748,26 @@ m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardNegativeInfiniti); } + void roundTowardZeroDouble(FPRegisterID src, FPRegisterID dst) + { + m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardZero); + } + + void roundTowardZeroDouble(Address src, FPRegisterID dst) + { + m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardZero); + } + + void roundTowardZeroFloat(FPRegisterID src, FPRegisterID dst) + { + m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardZero); + } + + void roundTowardZeroFloat(Address src, FPRegisterID dst) + { + m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardZero); + } + // Memory access operations: // // Loads are of the form load(address, destination) and stores of the form @@ -864,12 +921,14 @@ void store8(TrustedImm32 imm, Address address) { - m_assembler.movb_i8m(static_cast(imm.m_value), address.offset, address.base); + TrustedImm32 imm8(static_cast(imm.m_value)); + m_assembler.movb_i8m(imm8.m_value, address.offset, address.base); } void store8(TrustedImm32 imm, BaseIndex address) { - m_assembler.movb_i8m(static_cast(imm.m_value), address.offset, address.base, address.index, address.scale); + TrustedImm32 imm8(static_cast(imm.m_value)); + m_assembler.movb_i8m(imm8.m_value, address.offset, address.base, address.index, address.scale); } static ALWAYS_INLINE RegisterID getUnusedRegister(BaseIndex address) @@ -1066,96 +1125,124 @@ void addDouble(FPRegisterID src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.addsd_rr(src, dest); + addDouble(src, dest, dest); } void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) - addDouble(op2, dest); + if (supportsAVX()) + m_assembler.vaddsd_rr(op1, op2, dest); else { - moveDouble(op2, dest); - addDouble(op1, dest); + ASSERT(isSSE2Present()); + if (op1 == dest) + m_assembler.addsd_rr(op2, dest); + else { + moveDouble(op2, dest); + m_assembler.addsd_rr(op1, dest); + } } } void addDouble(Address src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.addsd_mr(src.offset, src.base, dest); + addDouble(src, dest, dest); } void addDouble(Address op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op2 == dest) { - addDouble(op1, dest); - return; - } + if (supportsAVX()) + m_assembler.vaddsd_mr(op1.offset, op1.base, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.addsd_mr(op1.offset, op1.base, dest); + return; + } - loadDouble(op1, dest); - addDouble(op2, dest); + loadDouble(op1, dest); + addDouble(op2, dest); + } } void addDouble(FPRegisterID op1, Address op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) { + addDouble(op2, op1, dest); + } + + void addDouble(BaseIndex op1, FPRegisterID op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vaddsd_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.addsd_mr(op1.offset, op1.base, op1.index, op1.scale, dest); + return; + } + loadDouble(op1, dest); addDouble(op2, dest); - return; } - - loadDouble(op2, dest); - addDouble(op1, dest); } void addFloat(FPRegisterID src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.addss_rr(src, dest); + addFloat(src, dest, dest); } void addFloat(Address src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.addss_mr(src.offset, src.base, dest); + addFloat(src, dest, dest); } void addFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) - addFloat(op2, dest); + if (supportsAVX()) + m_assembler.vaddss_rr(op1, op2, dest); else { - moveDouble(op2, dest); - addFloat(op1, dest); + ASSERT(isSSE2Present()); + if (op1 == dest) + m_assembler.addss_rr(op2, dest); + else { + moveDouble(op2, dest); + m_assembler.addss_rr(op1, dest); + } } } void addFloat(Address op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op2 == dest) { - addFloat(op1, dest); - return; - } + if (supportsAVX()) + m_assembler.vaddss_mr(op1.offset, op1.base, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.addss_mr(op1.offset, op1.base, dest); + return; + } - loadFloat(op1, dest); - addFloat(op2, dest); + loadFloat(op1, dest); + addFloat(op2, dest); + } } void addFloat(FPRegisterID op1, Address op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) { + addFloat(op2, op1, dest); + } + + void addFloat(BaseIndex op1, FPRegisterID op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vaddss_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.addss_mr(op1.offset, op1.base, op1.index, op1.scale, dest); + return; + } + loadFloat(op1, dest); addFloat(op2, dest); - return; } - - loadFloat(op2, dest); - addFloat(op1, dest); } void divDouble(FPRegisterID src, FPRegisterID dest) @@ -1193,125 +1280,209 @@ void subDouble(FPRegisterID src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.subsd_rr(src, dest); + subDouble(dest, src, dest); } void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) { - // B := A - B is invalid. - ASSERT(op1 == dest || op2 != dest); + if (supportsAVX()) + m_assembler.vsubsd_rr(op1, op2, dest); + else { + ASSERT(isSSE2Present()); - moveDouble(op1, dest); - subDouble(op2, dest); + // B := A - B is invalid. + ASSERT(op1 == dest || op2 != dest); + moveDouble(op1, dest); + m_assembler.subsd_rr(op2, dest); + } + } + + void subDouble(FPRegisterID op1, Address op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vsubsd_mr(op1, op2.offset, op2.base, dest); + else { + moveDouble(op1, dest); + m_assembler.subsd_mr(op2.offset, op2.base, dest); + } + } + + void subDouble(FPRegisterID op1, BaseIndex op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vsubsd_mr(op1, op2.offset, op2.base, op2.index, op2.scale, dest); + else { + moveDouble(op1, dest); + m_assembler.subsd_mr(op2.offset, op2.base, op2.index, op2.scale, dest); + } } void subDouble(Address src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.subsd_mr(src.offset, src.base, dest); + subDouble(dest, src, dest); } void subFloat(FPRegisterID src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.subss_rr(src, dest); + subFloat(dest, src, dest); + } + + void subFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vsubss_rr(op1, op2, dest); + else { + ASSERT(isSSE2Present()); + // B := A - B is invalid. + ASSERT(op1 == dest || op2 != dest); + moveDouble(op1, dest); + m_assembler.subss_rr(op2, dest); + } + } + + void subFloat(FPRegisterID op1, Address op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vsubss_mr(op1, op2.offset, op2.base, dest); + else { + moveDouble(op1, dest); + m_assembler.subss_mr(op2.offset, op2.base, dest); + } + } + + void subFloat(FPRegisterID op1, BaseIndex op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vsubss_mr(op1, op2.offset, op2.base, op2.index, op2.scale, dest); + else { + moveDouble(op1, dest); + m_assembler.subss_mr(op2.offset, op2.base, op2.index, op2.scale, dest); + } } void subFloat(Address src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.subss_mr(src.offset, src.base, dest); + subFloat(dest, src, dest); } void mulDouble(FPRegisterID src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.mulsd_rr(src, dest); + mulDouble(src, dest, dest); } void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) - mulDouble(op2, dest); + if (supportsAVX()) + m_assembler.vmulsd_rr(op1, op2, dest); else { - moveDouble(op2, dest); - mulDouble(op1, dest); + ASSERT(isSSE2Present()); + if (op1 == dest) + m_assembler.mulsd_rr(op2, dest); + else { + moveDouble(op2, dest); + m_assembler.mulsd_rr(op1, dest); + } } } void mulDouble(Address src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.mulsd_mr(src.offset, src.base, dest); + mulDouble(src, dest, dest); } void mulDouble(Address op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op2 == dest) { - mulDouble(op1, dest); - return; + if (supportsAVX()) + m_assembler.vmulsd_mr(op1.offset, op1.base, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.mulsd_mr(op1.offset, op1.base, dest); + return; + } + loadDouble(op1, dest); + mulDouble(op2, dest); } - loadDouble(op1, dest); - mulDouble(op2, dest); } void mulDouble(FPRegisterID op1, Address op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) { + return mulDouble(op2, op1, dest); + } + + void mulDouble(BaseIndex op1, FPRegisterID op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vmulsd_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.mulsd_mr(op1.offset, op1.base, op1.index, op1.scale, dest); + return; + } + loadDouble(op1, dest); mulDouble(op2, dest); - return; } - loadDouble(op2, dest); - mulDouble(op1, dest); } void mulFloat(FPRegisterID src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.mulss_rr(src, dest); + mulFloat(src, dest, dest); } void mulFloat(Address src, FPRegisterID dest) { - ASSERT(isSSE2Present()); - m_assembler.mulss_mr(src.offset, src.base, dest); + mulFloat(src, dest, dest); } void mulFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) - mulFloat(op2, dest); + if (supportsAVX()) + m_assembler.vmulss_rr(op1, op2, dest); else { - moveDouble(op2, dest); - mulFloat(op1, dest); + ASSERT(isSSE2Present()); + if (op1 == dest) + m_assembler.mulss_rr(op2, dest); + else { + moveDouble(op2, dest); + m_assembler.mulss_rr(op1, dest); + } } } void mulFloat(Address op1, FPRegisterID op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op2 == dest) { - mulFloat(op1, dest); - return; + if (supportsAVX()) + m_assembler.vmulss_mr(op1.offset, op1.base, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.mulss_mr(op1.offset, op1.base, dest); + return; + } + loadFloat(op1, dest); + mulFloat(op2, dest); } - loadFloat(op1, dest); - mulFloat(op2, dest); } void mulFloat(FPRegisterID op1, Address op2, FPRegisterID dest) { - ASSERT(isSSE2Present()); - if (op1 == dest) { + mulFloat(op2, op1, dest); + } + + void mulFloat(BaseIndex op1, FPRegisterID op2, FPRegisterID dest) + { + if (supportsAVX()) + m_assembler.vmulss_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest); + else { + ASSERT(isSSE2Present()); + if (op2 == dest) { + m_assembler.mulss_mr(op1.offset, op1.base, op1.index, op1.scale, dest); + return; + } + loadFloat(op1, dest); mulFloat(op2, dest); - return; } - loadFloat(op2, dest); - mulFloat(op1, dest); } void andDouble(FPRegisterID src, FPRegisterID dst) @@ -1387,6 +1558,18 @@ m_assembler.cvtsi2sd_mr(src.offset, src.base, dest); } + void convertInt32ToFloat(RegisterID src, FPRegisterID dest) + { + ASSERT(isSSE2Present()); + m_assembler.cvtsi2ss_rr(src, dest); + } + + void convertInt32ToFloat(Address src, FPRegisterID dest) + { + ASSERT(isSSE2Present()); + m_assembler.cvtsi2ss_mr(src.offset, src.base, dest); + } + Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) { ASSERT(isSSE2Present()); @@ -1953,7 +2136,8 @@ public: Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) { - m_assembler.cmpb_im(right.m_value, left.offset, left.base); + TrustedImm32 right8(static_cast(right.m_value)); + m_assembler.cmpb_im(right8.m_value, left.offset, left.base); return Jump(m_assembler.jCC(x86Condition(cond))); } @@ -2050,31 +2234,28 @@ Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { - // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values. - ASSERT(mask.m_value >= -128 && mask.m_value <= 255); - if (mask.m_value == -1) + TrustedImm32 mask8(static_cast(mask.m_value)); + if (mask8.m_value == -1) m_assembler.cmpb_im(0, address.offset, address.base); else - m_assembler.testb_im(mask.m_value, address.offset, address.base); + m_assembler.testb_im(mask8.m_value, address.offset, address.base); return Jump(m_assembler.jCC(x86Condition(cond))); } Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { - // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values. - ASSERT(mask.m_value >= -128 && mask.m_value <= 255); - if (mask.m_value == -1) + TrustedImm32 mask8(static_cast(mask.m_value)); + if (mask8.m_value == -1) m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale); else - m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale); + m_assembler.testb_im(mask8.m_value, address.offset, address.base, address.index, address.scale); return Jump(m_assembler.jCC(x86Condition(cond))); } Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { - ASSERT(std::numeric_limits::min() <= right.m_value && right.m_value <= std::numeric_limits::max()); - - m_assembler.cmpb_im(right.m_value, left.offset, left.base, left.index, left.scale); + TrustedImm32 right8(static_cast(right.m_value)); + m_assembler.cmpb_im(right8.m_value, left.offset, left.base, left.index, left.scale); return Jump(m_assembler.jCC(x86Condition(cond))); } @@ -2094,6 +2275,12 @@ m_assembler.jmp_m(address.offset, address.base); } + // Address is a memory location containing the address to jump to + void jump(BaseIndex address) + { + m_assembler.jmp_m(address.offset, address.base, address.index, address.scale); + } + // Arithmetic control flow operations: // @@ -2143,16 +2330,21 @@ return branchAdd32(cond, src1, dest); } - Jump branchAdd32(ResultCondition cond, Address src1, RegisterID src2, RegisterID dest) + Jump branchAdd32(ResultCondition cond, Address op1, RegisterID op2, RegisterID dest) { - move32IfNeeded(src2, dest); - return branchAdd32(cond, src1, dest); + if (op2 == dest) + return branchAdd32(cond, op1, dest); + if (op1.base == dest) { + load32(op1, dest); + return branchAdd32(cond, op2, dest); + } + zeroExtend32ToPtr(op2, dest); + return branchAdd32(cond, op1, dest); } Jump branchAdd32(ResultCondition cond, RegisterID src1, Address src2, RegisterID dest) { - move32IfNeeded(src1, dest); - return branchAdd32(cond, src2, dest); + return branchAdd32(cond, src2, src1, dest); } Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) @@ -2285,7 +2477,8 @@ void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) { - m_assembler.cmpb_im(right.m_value, left.offset, left.base); + TrustedImm32 right8(static_cast(right.m_value)); + m_assembler.cmpb_im(right8.m_value, left.offset, left.base); set32(x86Condition(cond), dest); } @@ -2315,10 +2508,11 @@ void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) { - if (mask.m_value == -1) + TrustedImm32 mask8(static_cast(mask.m_value)); + if (mask8.m_value == -1) m_assembler.cmpb_im(0, address.offset, address.base); else - m_assembler.testb_im(mask.m_value, address.offset, address.base); + m_assembler.testb_im(mask8.m_value, address.offset, address.base); set32(x86Condition(cond), dest); } @@ -2450,40 +2644,56 @@ return X86Assembler::maxJumpReplacementSize(); } + static ptrdiff_t patchableJumpSize() + { + return X86Assembler::patchableJumpSize(); + } + static bool supportsFloatingPointRounding() { - if (s_sse4_1CheckState == CPUIDCheckState::NotChecked) { - int flags = 0; + if (s_sse4_1CheckState == CPUIDCheckState::NotChecked) + updateEax1EcxFlags(); + return s_sse4_1CheckState == CPUIDCheckState::Set; + } + + static bool supportsAVX() + { + // AVX still causes mysterious regressions and those regressions can be massive. + return false; + } + + static void updateEax1EcxFlags() + { + int flags = 0; #if COMPILER(MSVC) - int cpuInfo[4]; - __cpuid(cpuInfo, 0x1); - flags = cpuInfo[2]; + int cpuInfo[4]; + __cpuid(cpuInfo, 0x1); + flags = cpuInfo[2]; #elif COMPILER(GCC_OR_CLANG) #if CPU(X86_64) - asm ( - "movl $0x1, %%eax;" - "cpuid;" - "movl %%ecx, %0;" - : "=g" (flags) - : - : "%eax", "%ebx", "%ecx", "%edx" - ); + asm ( + "movl $0x1, %%eax;" + "cpuid;" + "movl %%ecx, %0;" + : "=g" (flags) + : + : "%eax", "%ebx", "%ecx", "%edx" + ); #else - asm ( - "movl $0x1, %%eax;" - "pushl %%ebx;" - "cpuid;" - "popl %%ebx;" - "movl %%ecx, %0;" - : "=g" (flags) - : - : "%eax", "%ecx", "%edx" - ); + asm ( + "movl $0x1, %%eax;" + "pushl %%ebx;" + "cpuid;" + "popl %%ebx;" + "movl %%ecx, %0;" + : "=g" (flags) + : + : "%eax", "%ecx", "%edx" + ); #endif #endif // COMPILER(GCC_OR_CLANG) - s_sse4_1CheckState = (flags & (1 << 19)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear; - } - return s_sse4_1CheckState == CPUIDCheckState::Set; + s_sse4_1CheckState = (flags & (1 << 19)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear; + s_avxCheckState = (flags & (1 << 28)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear; } #if ENABLE(MASM_PROBE) @@ -2731,7 +2941,8 @@ Clear, Set }; - static CPUIDCheckState s_sse4_1CheckState; + JS_EXPORT_PRIVATE static CPUIDCheckState s_sse4_1CheckState; + JS_EXPORT_PRIVATE static CPUIDCheckState s_avxCheckState; static CPUIDCheckState s_lzcntCheckState; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MacroAssemblerX86.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MacroAssemblerX86.h 2016-11-03 07:04:20.000000000 +0000 @@ -34,6 +34,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Common { public: + static const unsigned numGPRs = 8; + static const unsigned numFPRs = 8; + static const Scale ScalePtr = TimesFour; using MacroAssemblerX86Common::add32; @@ -160,8 +163,8 @@ void store8(TrustedImm32 imm, void* address) { - ASSERT(-128 <= imm.m_value && imm.m_value < 128); - m_assembler.movb_i8m(imm.m_value, address); + TrustedImm32 imm8(static_cast(imm.m_value)); + m_assembler.movb_i8m(imm8.m_value, address); } void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) @@ -237,17 +240,18 @@ Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) { - m_assembler.cmpb_im(right.m_value, left.m_ptr); + TrustedImm32 right8(static_cast(right.m_value)); + m_assembler.cmpb_im(right8.m_value, left.m_ptr); return Jump(m_assembler.jCC(x86Condition(cond))); } Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT(mask.m_value >= -128 && mask.m_value <= 255); - if (mask.m_value == -1) + TrustedImm32 mask8(static_cast(mask.m_value)); + if (mask8.m_value == -1) m_assembler.cmpb_im(0, address.m_ptr); else - m_assembler.testb_im(mask.m_value, address.m_ptr); + m_assembler.testb_im(mask8.m_value, address.m_ptr); return Jump(m_assembler.jCC(x86Condition(cond))); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,6 @@ #ifndef MaxFrameExtentForSlowPathCall_h #define MaxFrameExtentForSlowPathCall_h -#include "JSStack.h" #include "Register.h" #include "StackAlignment.h" #include diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MIPSAssembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MIPSAssembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/MIPSAssembler.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/MIPSAssembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -547,6 +547,11 @@ emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); } + void absd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200005 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + void movd(FPRegisterID fd, FPRegisterID fs) { emitInst(0x46200006 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/X86Assembler.h webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/X86Assembler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/assembler/X86Assembler.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/assembler/X86Assembler.h 2016-11-03 07:04:20.000000000 +0000 @@ -305,6 +305,17 @@ OP3_MFENCE = 0xF0, } ThreeByteOpcodeID; + struct VexPrefix { + enum : uint8_t { + TwoBytes = 0xC5, + ThreeBytes = 0xC4 + }; + }; + enum class VexImpliedBytes : uint8_t { + TwoBytesOp = 1, + ThreeBytesOp38 = 2, + ThreeBytesOp3A = 3 + }; TwoByteOpcodeID cmovcc(Condition cond) { @@ -1972,6 +1983,11 @@ m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset); } + void jmp_m(int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, index, scale, offset); + } + #if !CPU(X86_64) void jmp_m(const void* address) { @@ -2087,24 +2103,66 @@ m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src); } + void vaddsd_rr(XMMRegisterID a, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigCommutativeTwoByteOp(PRE_SSE_F2, OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)a, (RegisterID)b); + } + void addsd_mr(int offset, RegisterID base, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset); } + void addsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, dst, base, index, scale, offset); + } + + void vaddsd_mr(int offset, RegisterID base, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)b, base, offset); + } + + void vaddsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)b, offset, base, index, scale); + } + void addss_rr(XMMRegisterID src, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F3); m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src); } + void vaddss_rr(XMMRegisterID a, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigCommutativeTwoByteOp(PRE_SSE_F3, OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)a, (RegisterID)b); + } + void addss_mr(int offset, RegisterID base, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F3); m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset); } + void addss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, dst, base, index, scale, offset); + } + + void vaddss_mr(int offset, RegisterID base, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)b, base, offset); + } + + void vaddss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)b, offset, base, index, scale); + } + #if !CPU(X86_64) void addsd_mr(const void* address, XMMRegisterID dst) { @@ -2119,12 +2177,36 @@ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); } + void cvtsi2ss_rr(RegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); + } + #if CPU(X86_64) void cvtsi2sdq_rr(RegisterID src, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); } + + void cvtsi2ssq_rr(RegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); + } + + void cvtsi2sdq_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset); + } + + void cvtsi2ssq_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset); + } #endif void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst) @@ -2133,6 +2215,12 @@ m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset); } + void cvtsi2ss_mr(int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset); + } + #if !CPU(X86_64) void cvtsi2sd_mr(const void* address, XMMRegisterID dst) { @@ -2295,24 +2383,66 @@ m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src); } + void vmulsd_rr(XMMRegisterID a, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigCommutativeTwoByteOp(PRE_SSE_F2, OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)a, (RegisterID)b); + } + void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset); } + void mulsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_MULSD_VsdWsd, dst, base, index, scale, offset); + } + + void vmulsd_mr(int offset, RegisterID base, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)b, base, offset); + } + + void vmulsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)b, offset, base, index, scale); + } + void mulss_rr(XMMRegisterID src, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F3); m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src); } + void vmulss_rr(XMMRegisterID a, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigCommutativeTwoByteOp(PRE_SSE_F3, OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)a, (RegisterID)b); + } + void mulss_mr(int offset, RegisterID base, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F3); m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset); } + void mulss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp(OP2_MULSD_VsdWsd, dst, base, index, scale, offset); + } + + void vmulss_mr(int offset, RegisterID base, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)b, base, offset); + } + + void vmulss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)b, offset, base, index, scale); + } + void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst) { m_formatter.prefix(PRE_SSE_66); @@ -2346,24 +2476,66 @@ m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src); } + void vsubsd_rr(XMMRegisterID a, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)a, (RegisterID)b); + } + void subsd_mr(int offset, RegisterID base, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset); } + void subsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, dst, base, index, scale, offset); + } + + void vsubsd_mr(XMMRegisterID b, int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)b, base, offset); + } + + void vsubsd_mr(XMMRegisterID b, int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F2, OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)b, offset, base, index, scale); + } + void subss_rr(XMMRegisterID src, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F3); m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src); } + void vsubss_rr(XMMRegisterID a, XMMRegisterID b, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)a, (RegisterID)b); + } + void subss_mr(int offset, RegisterID base, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F3); m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset); } + void subss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F3); + m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, dst, base, index, scale, offset); + } + + void vsubss_mr(XMMRegisterID b, int offset, RegisterID base, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)b, base, offset); + } + + void vsubss_mr(XMMRegisterID b, int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst) + { + m_formatter.vexNdsLigWigTwoByteOp(PRE_SSE_F3, OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)b, offset, base, index, scale); + } + void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_66); @@ -2641,6 +2813,11 @@ { return 5; } + + static constexpr ptrdiff_t patchableJumpSize() + { + return 5; + } #if CPU(X86_64) static void revertJumpTo_movq_i64r(void* instructionStart, int64_t imm, RegisterID dst) @@ -2779,8 +2956,9 @@ m_formatter.oneByteOp(OP_NOP); } - static void fillNops(void* base, size_t size) + static void fillNops(void* base, size_t size, bool isCopyingToExecutableMemory) { + UNUSED_PARAM(isCopyingToExecutableMemory); #if CPU(X86_64) static const uint8_t nops[10][10] = { // nop @@ -2852,16 +3030,14 @@ } class X86InstructionFormatter { - static const int maxInstructionSize = 16; public: - enum ModRmMode { - ModRmMemoryNoDisp, - ModRmMemoryDisp8, - ModRmMemoryDisp32, - ModRmRegister, + ModRmMemoryNoDisp = 0, + ModRmMemoryDisp8 = 1 << 6, + ModRmMemoryDisp32 = 2 << 6, + ModRmRegister = 3 << 6, }; // Legacy prefix bytes: @@ -2873,6 +3049,260 @@ m_buffer.putByte(pre); } +#if CPU(X86_64) + // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed). + static bool byteRegRequiresRex(int reg) + { + static_assert(X86Registers::esp == 4, "Necessary condition for OR-masking"); + return (reg >= X86Registers::esp); + } + static bool byteRegRequiresRex(int a, int b) + { + return byteRegRequiresRex(a | b); + } + + // Registers r8 & above require a REX prefixe. + static bool regRequiresRex(int reg) + { + static_assert(X86Registers::r8 == 8, "Necessary condition for OR-masking"); + return (reg >= X86Registers::r8); + } + static bool regRequiresRex(int a, int b) + { + return regRequiresRex(a | b); + } + static bool regRequiresRex(int a, int b, int c) + { + return regRequiresRex(a | b | c); + } +#else + static bool byteRegRequiresRex(int) { return false; } + static bool byteRegRequiresRex(int, int) { return false; } + static bool regRequiresRex(int) { return false; } + static bool regRequiresRex(int, int) { return false; } + static bool regRequiresRex(int, int, int) { return false; } +#endif + + class SingleInstructionBufferWriter : public AssemblerBuffer::LocalWriter { + public: + SingleInstructionBufferWriter(AssemblerBuffer& buffer) + : AssemblerBuffer::LocalWriter(buffer, maxInstructionSize) + { + } + + // Internals; ModRm and REX formatters. + + static constexpr RegisterID noBase = X86Registers::ebp; + static constexpr RegisterID hasSib = X86Registers::esp; + static constexpr RegisterID noIndex = X86Registers::esp; + +#if CPU(X86_64) + static constexpr RegisterID noBase2 = X86Registers::r13; + static constexpr RegisterID hasSib2 = X86Registers::r12; + + // Format a REX prefix byte. + ALWAYS_INLINE void emitRex(bool w, int r, int x, int b) + { + ASSERT(r >= 0); + ASSERT(x >= 0); + ASSERT(b >= 0); + putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3)); + } + + // Used to plant a REX byte with REX.w set (for 64-bit operations). + ALWAYS_INLINE void emitRexW(int r, int x, int b) + { + emitRex(true, r, x, b); + } + + // Used for operations with byte operands - use byteRegRequiresRex() to check register operands, + // regRequiresRex() to check other registers (i.e. address base & index). + ALWAYS_INLINE void emitRexIf(bool condition, int r, int x, int b) + { + if (condition) + emitRex(false, r, x, b); + } + + // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above). + ALWAYS_INLINE void emitRexIfNeeded(int r, int x, int b) + { + emitRexIf(regRequiresRex(r, x, b), r, x, b); + } +#else + // No REX prefix bytes on 32-bit x86. + ALWAYS_INLINE void emitRexIf(bool, int, int, int) { } + ALWAYS_INLINE void emitRexIfNeeded(int, int, int) { } +#endif + + ALWAYS_INLINE void putModRm(ModRmMode mode, int reg, RegisterID rm) + { + putByteUnchecked(mode | ((reg & 7) << 3) | (rm & 7)); + } + + ALWAYS_INLINE void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale) + { + ASSERT(mode != ModRmRegister); + + putModRm(mode, reg, hasSib); + putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7)); + } + + ALWAYS_INLINE void registerModRM(int reg, RegisterID rm) + { + putModRm(ModRmRegister, reg, rm); + } + + ALWAYS_INLINE void memoryModRM(int reg, RegisterID base, int offset) + { + // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. +#if CPU(X86_64) + if ((base == hasSib) || (base == hasSib2)) { +#else + if (base == hasSib) { +#endif + if (!offset) // No need to check if the base is noBase, since we know it is hasSib! + putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0); + else if (CAN_SIGN_EXTEND_8_32(offset)) { + putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0); + putByteUnchecked(offset); + } else { + putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0); + putIntUnchecked(offset); + } + } else { +#if CPU(X86_64) + if (!offset && (base != noBase) && (base != noBase2)) +#else + if (!offset && (base != noBase)) +#endif + putModRm(ModRmMemoryNoDisp, reg, base); + else if (CAN_SIGN_EXTEND_8_32(offset)) { + putModRm(ModRmMemoryDisp8, reg, base); + putByteUnchecked(offset); + } else { + putModRm(ModRmMemoryDisp32, reg, base); + putIntUnchecked(offset); + } + } + } + + ALWAYS_INLINE void memoryModRM_disp8(int reg, RegisterID base, int offset) + { + // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. + ASSERT(CAN_SIGN_EXTEND_8_32(offset)); +#if CPU(X86_64) + if ((base == hasSib) || (base == hasSib2)) { +#else + if (base == hasSib) { +#endif + putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0); + putByteUnchecked(offset); + } else { + putModRm(ModRmMemoryDisp8, reg, base); + putByteUnchecked(offset); + } + } + + ALWAYS_INLINE void memoryModRM_disp32(int reg, RegisterID base, int offset) + { + // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. +#if CPU(X86_64) + if ((base == hasSib) || (base == hasSib2)) { +#else + if (base == hasSib) { +#endif + putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0); + putIntUnchecked(offset); + } else { + putModRm(ModRmMemoryDisp32, reg, base); + putIntUnchecked(offset); + } + } + + ALWAYS_INLINE void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset) + { + ASSERT(index != noIndex); + +#if CPU(X86_64) + if (!offset && (base != noBase) && (base != noBase2)) +#else + if (!offset && (base != noBase)) +#endif + putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale); + else if (CAN_SIGN_EXTEND_8_32(offset)) { + putModRmSib(ModRmMemoryDisp8, reg, base, index, scale); + putByteUnchecked(offset); + } else { + putModRmSib(ModRmMemoryDisp32, reg, base, index, scale); + putIntUnchecked(offset); + } + } + +#if !CPU(X86_64) + ALWAYS_INLINE void memoryModRM(int reg, const void* address) + { + // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32! + putModRm(ModRmMemoryNoDisp, reg, noBase); + putIntUnchecked(reinterpret_cast(address)); + } +#endif + ALWAYS_INLINE void twoBytesVex(OneByteOpcodeID simdPrefix, RegisterID inOpReg, RegisterID r) + { + putByteUnchecked(VexPrefix::TwoBytes); + + uint8_t secondByte = vexEncodeSimdPrefix(simdPrefix); + secondByte |= (~inOpReg & 0xf) << 3; + secondByte |= !regRequiresRex(r) << 7; + putByteUnchecked(secondByte); + } + + ALWAYS_INLINE void threeBytesVexNds(OneByteOpcodeID simdPrefix, VexImpliedBytes impliedBytes, RegisterID r, RegisterID inOpReg, RegisterID x, RegisterID b) + { + putByteUnchecked(VexPrefix::ThreeBytes); + + uint8_t secondByte = static_cast(impliedBytes); + secondByte |= !regRequiresRex(r) << 7; + secondByte |= !regRequiresRex(x) << 6; + secondByte |= !regRequiresRex(b) << 5; + putByteUnchecked(secondByte); + + uint8_t thirdByte = vexEncodeSimdPrefix(simdPrefix); + thirdByte |= (~inOpReg & 0xf) << 3; + putByteUnchecked(thirdByte); + } + + ALWAYS_INLINE void threeBytesVexNds(OneByteOpcodeID simdPrefix, VexImpliedBytes impliedBytes, RegisterID r, RegisterID inOpReg, RegisterID b) + { + putByteUnchecked(VexPrefix::ThreeBytes); + + uint8_t secondByte = static_cast(impliedBytes); + secondByte |= !regRequiresRex(r) << 7; + secondByte |= 1 << 6; // REX.X + secondByte |= !regRequiresRex(b) << 5; + putByteUnchecked(secondByte); + + uint8_t thirdByte = vexEncodeSimdPrefix(simdPrefix); + thirdByte |= (~inOpReg & 0xf) << 3; + putByteUnchecked(thirdByte); + } + private: + uint8_t vexEncodeSimdPrefix(OneByteOpcodeID simdPrefix) + { + switch (simdPrefix) { + case 0x66: + return 1; + case 0xF3: + return 2; + case 0xF2: + return 3; + default: + RELEASE_ASSERT_NOT_REACHED(); + } + return 0; + } + + }; + // Word-sized operands / no operand instruction formatters. // // In addition to the opcode, the following operand permutations are supported: @@ -2889,136 +3319,176 @@ void oneByteOp(OneByteOpcodeID opcode) { - m_buffer.ensureSpace(maxInstructionSize); - m_buffer.putByteUnchecked(opcode); + SingleInstructionBufferWriter writer(m_buffer); + writer.putByteUnchecked(opcode); } void oneByteOp(OneByteOpcodeID opcode, RegisterID reg) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(0, 0, reg); - m_buffer.putByteUnchecked(opcode + (reg & 7)); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(0, 0, reg); + writer.putByteUnchecked(opcode + (reg & 7)); } void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, rm); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, rm); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, offset); } void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM_disp32(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM_disp32(reg, base, offset); } void oneByteOp_disp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM_disp8(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM_disp8(reg, base, offset); } void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, index, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, index, scale, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, index, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, index, scale, offset); } #if !CPU(X86_64) void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address) { - m_buffer.ensureSpace(maxInstructionSize); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, address); + SingleInstructionBufferWriter writer(m_buffer); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, address); } #endif void twoByteOp(TwoByteOpcodeID opcode) { - m_buffer.ensureSpace(maxInstructionSize); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); + SingleInstructionBufferWriter writer(m_buffer); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); } void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, rm); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, rm); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, base); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, base); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, offset); } void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, index, base); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, index, scale, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, index, base); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, index, scale, offset); } #if !CPU(X86_64) void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address) { - m_buffer.ensureSpace(maxInstructionSize); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, address); + SingleInstructionBufferWriter writer(m_buffer); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, address); } #endif + void vexNdsLigWigTwoByteOp(OneByteOpcodeID simdPrefix, TwoByteOpcodeID opcode, RegisterID dest, RegisterID a, RegisterID b) + { + SingleInstructionBufferWriter writer(m_buffer); + if (regRequiresRex(b)) + writer.threeBytesVexNds(simdPrefix, VexImpliedBytes::TwoBytesOp, dest, a, b); + else + writer.twoBytesVex(simdPrefix, a, dest); + writer.putByteUnchecked(opcode); + writer.registerModRM(dest, b); + } + + void vexNdsLigWigCommutativeTwoByteOp(OneByteOpcodeID simdPrefix, TwoByteOpcodeID opcode, RegisterID dest, RegisterID a, RegisterID b) + { + // Since this is a commutative operation, we can try switching the arguments. + if (regRequiresRex(b)) + std::swap(a, b); + vexNdsLigWigTwoByteOp(simdPrefix, opcode, dest, a, b); + } + + void vexNdsLigWigTwoByteOp(OneByteOpcodeID simdPrefix, TwoByteOpcodeID opcode, RegisterID dest, RegisterID a, RegisterID base, int offset) + { + SingleInstructionBufferWriter writer(m_buffer); + if (regRequiresRex(base)) + writer.threeBytesVexNds(simdPrefix, VexImpliedBytes::TwoBytesOp, dest, a, base); + else + writer.twoBytesVex(simdPrefix, a, dest); + writer.putByteUnchecked(opcode); + writer.memoryModRM(dest, base, offset); + } + + void vexNdsLigWigTwoByteOp(OneByteOpcodeID simdPrefix, TwoByteOpcodeID opcode, RegisterID dest, RegisterID a, int offset, RegisterID base, RegisterID index, int scale) + { + SingleInstructionBufferWriter writer(m_buffer); + if (regRequiresRex(base, index)) + writer.threeBytesVexNds(simdPrefix, VexImpliedBytes::TwoBytesOp, dest, a, index, base); + else + writer.twoBytesVex(simdPrefix, a, dest); + writer.putByteUnchecked(opcode); + writer.memoryModRM(dest, base, index, scale, offset); + } void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode) { - m_buffer.ensureSpace(maxInstructionSize); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(twoBytePrefix); - m_buffer.putByteUnchecked(opcode); + SingleInstructionBufferWriter writer(m_buffer); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(twoBytePrefix); + writer.putByteUnchecked(opcode); } void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode, int reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, rm); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(twoBytePrefix); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, rm); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(twoBytePrefix); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode, int reg, RegisterID base, int displacement) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIfNeeded(reg, 0, base); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(twoBytePrefix); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, displacement); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIfNeeded(reg, 0, base); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(twoBytePrefix); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, displacement); } #if CPU(X86_64) @@ -3030,83 +3500,83 @@ void oneByteOp64(OneByteOpcodeID opcode) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(0, 0, 0); - m_buffer.putByteUnchecked(opcode); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(0, 0, 0); + writer.putByteUnchecked(opcode); } void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(0, 0, reg); - m_buffer.putByteUnchecked(opcode + (reg & 7)); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(0, 0, reg); + writer.putByteUnchecked(opcode + (reg & 7)); } void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, 0, rm); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, 0, rm); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, offset); } void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM_disp32(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM_disp32(reg, base, offset); } void oneByteOp64_disp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM_disp8(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM_disp8(reg, base, offset); } void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, index, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, index, scale, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, index, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, index, scale, offset); } void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, 0, rm); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, 0, rm); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, 0, base); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, 0, base); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, offset); } void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexW(reg, index, base); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, index, scale, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexW(reg, index, base); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, index, scale, offset); } #endif @@ -3137,52 +3607,52 @@ void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); - m_buffer.putByteUnchecked(opcode); - registerModRM(groupOp, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); + writer.putByteUnchecked(opcode); + writer.registerModRM(groupOp, rm); } void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIf(byteRegRequiresRex(reg) || byteRegRequiresRex(rm), reg, 0, rm); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIf(byteRegRequiresRex(reg, rm), reg, 0, rm); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIf(byteRegRequiresRex(reg) || byteRegRequiresRex(base), reg, 0, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIf(byteRegRequiresRex(reg, base), reg, 0, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, offset); } void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIf(byteRegRequiresRex(reg) || regRequiresRex(index) || regRequiresRex(base), reg, index, base); - m_buffer.putByteUnchecked(opcode); - memoryModRM(reg, base, index, scale, offset); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIf(byteRegRequiresRex(reg) || regRequiresRex(index, base), reg, index, base); + writer.putByteUnchecked(opcode); + writer.memoryModRM(reg, base, index, scale, offset); } void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - registerModRM(reg, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIf(byteRegRequiresRex(reg, rm), reg, 0, rm); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.registerModRM(reg, rm); } void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm) { - m_buffer.ensureSpace(maxInstructionSize); - emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); - m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); - m_buffer.putByteUnchecked(opcode); - registerModRM(groupOp, rm); + SingleInstructionBufferWriter writer(m_buffer); + writer.emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); + writer.putByteUnchecked(OP_2BYTE_ESCAPE); + writer.putByteUnchecked(opcode); + writer.registerModRM(groupOp, rm); } // Immediates: @@ -3225,177 +3695,6 @@ unsigned debugOffset() { return m_buffer.debugOffset(); } - private: - - // Internals; ModRm and REX formatters. - - static const RegisterID noBase = X86Registers::ebp; - static const RegisterID hasSib = X86Registers::esp; - static const RegisterID noIndex = X86Registers::esp; -#if CPU(X86_64) - static const RegisterID noBase2 = X86Registers::r13; - static const RegisterID hasSib2 = X86Registers::r12; - - // Registers r8 & above require a REX prefixe. - inline bool regRequiresRex(int reg) - { - return (reg >= X86Registers::r8); - } - - // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed). - inline bool byteRegRequiresRex(int reg) - { - return (reg >= X86Registers::esp); - } - - // Format a REX prefix byte. - inline void emitRex(bool w, int r, int x, int b) - { - ASSERT(r >= 0); - ASSERT(x >= 0); - ASSERT(b >= 0); - m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3)); - } - - // Used to plant a REX byte with REX.w set (for 64-bit operations). - inline void emitRexW(int r, int x, int b) - { - emitRex(true, r, x, b); - } - - // Used for operations with byte operands - use byteRegRequiresRex() to check register operands, - // regRequiresRex() to check other registers (i.e. address base & index). - inline void emitRexIf(bool condition, int r, int x, int b) - { - if (condition) emitRex(false, r, x, b); - } - - // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above). - inline void emitRexIfNeeded(int r, int x, int b) - { - emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b); - } -#else - // No REX prefix bytes on 32-bit x86. - inline bool regRequiresRex(int) { return false; } - inline bool byteRegRequiresRex(int) { return false; } - inline void emitRexIf(bool, int, int, int) {} - inline void emitRexIfNeeded(int, int, int) {} -#endif - - void putModRm(ModRmMode mode, int reg, RegisterID rm) - { - m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7)); - } - - void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale) - { - ASSERT(mode != ModRmRegister); - - putModRm(mode, reg, hasSib); - m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7)); - } - - void registerModRM(int reg, RegisterID rm) - { - putModRm(ModRmRegister, reg, rm); - } - - void memoryModRM(int reg, RegisterID base, int offset) - { - // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. -#if CPU(X86_64) - if ((base == hasSib) || (base == hasSib2)) { -#else - if (base == hasSib) { -#endif - if (!offset) // No need to check if the base is noBase, since we know it is hasSib! - putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0); - else if (CAN_SIGN_EXTEND_8_32(offset)) { - putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0); - m_buffer.putByteUnchecked(offset); - } else { - putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0); - m_buffer.putIntUnchecked(offset); - } - } else { -#if CPU(X86_64) - if (!offset && (base != noBase) && (base != noBase2)) -#else - if (!offset && (base != noBase)) -#endif - putModRm(ModRmMemoryNoDisp, reg, base); - else if (CAN_SIGN_EXTEND_8_32(offset)) { - putModRm(ModRmMemoryDisp8, reg, base); - m_buffer.putByteUnchecked(offset); - } else { - putModRm(ModRmMemoryDisp32, reg, base); - m_buffer.putIntUnchecked(offset); - } - } - } - - void memoryModRM_disp8(int reg, RegisterID base, int offset) - { - // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. - ASSERT(CAN_SIGN_EXTEND_8_32(offset)); -#if CPU(X86_64) - if ((base == hasSib) || (base == hasSib2)) { -#else - if (base == hasSib) { -#endif - putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0); - m_buffer.putByteUnchecked(offset); - } else { - putModRm(ModRmMemoryDisp8, reg, base); - m_buffer.putByteUnchecked(offset); - } - } - - void memoryModRM_disp32(int reg, RegisterID base, int offset) - { - // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. -#if CPU(X86_64) - if ((base == hasSib) || (base == hasSib2)) { -#else - if (base == hasSib) { -#endif - putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0); - m_buffer.putIntUnchecked(offset); - } else { - putModRm(ModRmMemoryDisp32, reg, base); - m_buffer.putIntUnchecked(offset); - } - } - - void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset) - { - ASSERT(index != noIndex); - -#if CPU(X86_64) - if (!offset && (base != noBase) && (base != noBase2)) -#else - if (!offset && (base != noBase)) -#endif - putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale); - else if (CAN_SIGN_EXTEND_8_32(offset)) { - putModRmSib(ModRmMemoryDisp8, reg, base, index, scale); - m_buffer.putByteUnchecked(offset); - } else { - putModRmSib(ModRmMemoryDisp32, reg, base, index, scale); - m_buffer.putIntUnchecked(offset); - } - } - -#if !CPU(X86_64) - void memoryModRM(int reg, const void* address) - { - // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32! - putModRm(ModRmMemoryNoDisp, reg, noBase); - m_buffer.putIntUnchecked(reinterpret_cast(address)); - } -#endif - public: AssemblerBuffer m_buffer; } m_formatter; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirAllocateStack.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -28,6 +28,7 @@ #if ENABLE(B3_JIT) +#include "AirArgInlines.h" #include "AirCode.h" #include "AirInsertionSet.h" #include "AirInstInlines.h" diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirArg.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirArg.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirArg.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirArg.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -57,31 +57,7 @@ bool Arg::isRepresentableAs(Width width, Signedness signedness) const { - switch (signedness) { - case Signed: - switch (width) { - case Width8: - return isRepresentableAs(); - case Width16: - return isRepresentableAs(); - case Width32: - return isRepresentableAs(); - case Width64: - return isRepresentableAs(); - } - case Unsigned: - switch (width) { - case Width8: - return isRepresentableAs(); - case Width16: - return isRepresentableAs(); - case Width32: - return isRepresentableAs(); - case Width64: - return isRepresentableAs(); - } - } - ASSERT_NOT_REACHED(); + return isRepresentableAs(width, signedness, value()); } bool Arg::usesTmp(Air::Tmp tmp) const @@ -109,6 +85,50 @@ return true; } +unsigned Arg::jsHash() const +{ + unsigned result = static_cast(m_kind); + + switch (m_kind) { + case Invalid: + case Special: + break; + case Tmp: + result += m_base.internalValue(); + break; + case Imm: + case BitImm: + case CallArg: + case RelCond: + case ResCond: + case DoubleCond: + case WidthArg: + result += static_cast(m_offset); + break; + case BigImm: + case BitImm64: + result += static_cast(m_offset); + result += static_cast(m_offset >> 32); + break; + case Addr: + result += m_offset; + result += m_base.internalValue(); + break; + case Index: + result += static_cast(m_offset); + result += m_scale; + result += m_base.internalValue(); + result += m_index.internalValue(); + break; + case Stack: + result += static_cast(m_scale); + result += stackSlot()->index(); + break; + } + + return result; +} + void Arg::dump(PrintStream& out) const { switch (m_kind) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirArg.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirArg.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirArg.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirArg.h 2016-11-03 07:04:20.000000000 +0000 @@ -688,7 +688,15 @@ bool isSomeImm() const { - return isImm() || isBigImm() || isBitImm() || isBitImm64(); + switch (kind()) { + case Imm: + case BigImm: + case BitImm: + case BitImm64: + return true; + default: + return false; + } } bool isAddr() const @@ -785,8 +793,66 @@ { return B3::isRepresentableAs(value()); } + + static bool isRepresentableAs(Width width, Signedness signedness, int64_t value) + { + switch (signedness) { + case Signed: + switch (width) { + case Width8: + return B3::isRepresentableAs(value); + case Width16: + return B3::isRepresentableAs(value); + case Width32: + return B3::isRepresentableAs(value); + case Width64: + return B3::isRepresentableAs(value); + } + case Unsigned: + switch (width) { + case Width8: + return B3::isRepresentableAs(value); + case Width16: + return B3::isRepresentableAs(value); + case Width32: + return B3::isRepresentableAs(value); + case Width64: + return B3::isRepresentableAs(value); + } + } + ASSERT_NOT_REACHED(); + } bool isRepresentableAs(Width, Signedness) const; + + static int64_t castToType(Width width, Signedness signedness, int64_t value) + { + switch (signedness) { + case Signed: + switch (width) { + case Width8: + return static_cast(value); + case Width16: + return static_cast(value); + case Width32: + return static_cast(value); + case Width64: + return static_cast(value); + } + case Unsigned: + switch (width) { + case Width8: + return static_cast(value); + case Width16: + return static_cast(value); + case Width32: + return static_cast(value); + case Width64: + return static_cast(value); + } + } + ASSERT_NOT_REACHED(); + } template T asNumber() const @@ -993,33 +1059,6 @@ return tmp().tmpIndex(); } - // If 'this' is an address Arg, then it returns a new address Arg with the additional offset applied. - // Note that this does not consider whether doing so produces a valid Arg or not. Unless you really - // know what you're doing, you should call Arg::isValidForm() on the result. Some code won't do that, - // like if you're applying a very small offset to a Arg::stack() that you know has no offset to begin - // with. It's safe to assume that all targets allow small offsets (like, 0..7) for Addr, Stack, and - // CallArg. - Arg withOffset(int64_t additionalOffset) const - { - if (!hasOffset()) - return Arg(); - if (sumOverflows(offset(), additionalOffset)) - return Arg(); - switch (kind()) { - case Addr: - return addr(base(), offset() + additionalOffset); - case Stack: - return stack(stackSlot(), offset() + additionalOffset); - case CallArg: - return callArg(offset() + additionalOffset); - case Index: - return index(base(), index(), scale(), offset() + additionalOffset); - default: - RELEASE_ASSERT_NOT_REACHED(); - return Arg(); - } - } - static bool isValidImmForm(int64_t value) { if (isX86()) @@ -1228,7 +1267,7 @@ ASSERT(isDoubleCond()); return static_cast(m_offset); } - + // Tells you if the Arg is invertible. Only condition arguments are invertible, and even for those, there // are a few exceptions - notably Overflow and Signed. bool isInvertible() const @@ -1279,6 +1318,9 @@ return isRelCond() && MacroAssembler::isUnsigned(asRelationalCondition()); } + // This computes a hash for comparing this to JSAir's Arg. + unsigned jsHash() const; + void dump(PrintStream&) const; Arg(WTF::HashTableDeletedValueType) @@ -1316,11 +1358,11 @@ namespace WTF { -void printInternal(PrintStream&, JSC::B3::Air::Arg::Kind); -void printInternal(PrintStream&, JSC::B3::Air::Arg::Role); -void printInternal(PrintStream&, JSC::B3::Air::Arg::Type); -void printInternal(PrintStream&, JSC::B3::Air::Arg::Width); -void printInternal(PrintStream&, JSC::B3::Air::Arg::Signedness); +JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Air::Arg::Kind); +JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Air::Arg::Role); +JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Air::Arg::Type); +JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Air::Arg::Width); +JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Air::Arg::Signedness); template struct DefaultHash; template<> struct DefaultHash { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirArgInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirArgInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirArgInlines.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirArgInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -84,6 +84,88 @@ } }; +template<> struct ArgThingHelper { + static bool is(const Arg& arg) + { + return arg.isStack(); + } + + static StackSlot* as(const Arg& arg) + { + return arg.stackSlot(); + } + + template + static void forEachFast(Arg& arg, const Functor& functor) + { + if (!arg.isStack()) + return; + + StackSlot* stackSlot = arg.stackSlot(); + functor(stackSlot); + arg = Arg::stack(stackSlot, arg.offset()); + } + + template + static void forEach(Arg& arg, Arg::Role role, Arg::Type type, Arg::Width width, const Functor& functor) + { + if (!arg.isStack()) + return; + + StackSlot* stackSlot = arg.stackSlot(); + + // FIXME: This is way too optimistic about the meaning of "Def". It gets lucky for + // now because our only use of "Anonymous" stack slots happens to want the optimistic + // semantics. We could fix this by just changing the comments that describe the + // semantics of "Anonymous". + // https://bugs.webkit.org/show_bug.cgi?id=151128 + + functor(stackSlot, role, type, width); + arg = Arg::stack(stackSlot, arg.offset()); + } +}; + +template<> struct ArgThingHelper { + static bool is(const Arg& arg) + { + return arg.isReg(); + } + + static Reg as(const Arg& arg) + { + return arg.reg(); + } + + template + static void forEachFast(Arg& arg, const Functor& functor) + { + arg.forEachTmpFast( + [&] (Tmp& tmp) { + if (!tmp.isReg()) + return; + + Reg reg = tmp.reg(); + functor(reg); + tmp = Tmp(reg); + }); + } + + template + static void forEach(Arg& arg, Arg::Role argRole, Arg::Type argType, Arg::Width argWidth, const Functor& functor) + { + arg.forEachTmp( + argRole, argType, argWidth, + [&] (Tmp& tmp, Arg::Role role, Arg::Type type, Arg::Width width) { + if (!tmp.isReg()) + return; + + Reg reg = tmp.reg(); + functor(reg, role, type, width); + tmp = Tmp(reg); + }); + } +}; + template bool Arg::is() const { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirCode.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirCode.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirCode.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirCode.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -30,7 +30,9 @@ #include "AirCCallSpecial.h" #include "B3BasicBlockUtils.h" +#include "B3Procedure.h" #include "B3StackSlot.h" +#include namespace JSC { namespace B3 { namespace Air { @@ -78,17 +80,38 @@ return m_cCallSpecial; } +bool Code::isEntrypoint(BasicBlock* block) const +{ + if (m_entrypoints.isEmpty()) + return !block->index(); + + for (const FrequentedBlock& entrypoint : m_entrypoints) { + if (entrypoint.block() == block) + return true; + } + return false; +} + void Code::resetReachability() { - B3::resetReachability( - m_blocks, - [&] (BasicBlock*) { - // We don't have to do anything special for deleted blocks. - }); + clearPredecessors(m_blocks); + if (m_entrypoints.isEmpty()) + updatePredecessorsAfter(m_blocks[0].get()); + else { + for (const FrequentedBlock& entrypoint : m_entrypoints) + updatePredecessorsAfter(entrypoint.block()); + } + + for (auto& block : m_blocks) { + if (isBlockDead(block.get()) && !isEntrypoint(block.get())) + block = nullptr; + } } void Code::dump(PrintStream& out) const { + if (!m_entrypoints.isEmpty()) + out.print("Entrypoints: ", listDump(m_entrypoints), "\n"); for (BasicBlock* block : *this) out.print(deepDump(block)); if (stackSlots().size()) { @@ -134,6 +157,34 @@ m_fastTmps.add(tmp); } +void* Code::addDataSection(size_t size) +{ + return m_proc.addDataSection(size); +} + +unsigned Code::jsHash() const +{ + unsigned result = 0; + + for (BasicBlock* block : *this) { + result *= 1000001; + for (Inst& inst : *block) { + result *= 97; + result += inst.jsHash(); + } + for (BasicBlock* successor : block->successorBlocks()) { + result *= 7; + result += successor->index(); + } + } + for (StackSlot* slot : stackSlots()) { + result *= 101; + result += slot->jsHash(); + } + + return result; +} + } } } // namespace JSC::B3::Air #endif // ENABLE(B3_JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirCode.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirCode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirCode.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirCode.h 2016-11-03 07:04:20.000000000 +0000 @@ -34,8 +34,10 @@ #include "AirStackSlot.h" #include "AirTmp.h" #include "B3SparseCollection.h" +#include "CCallHelpers.h" #include "RegisterAtOffsetList.h" #include "StackAlignment.h" +#include namespace JSC { namespace B3 { @@ -118,13 +120,39 @@ m_frameSize = frameSize; } + // Note that this is not the same thing as proc().numEntrypoints(). This value here may be zero + // until we lower EntrySwitch. + unsigned numEntrypoints() const { return m_entrypoints.size(); } + const Vector& entrypoints() const { return m_entrypoints; } + const FrequentedBlock& entrypoint(unsigned index) const { return m_entrypoints[index]; } + bool isEntrypoint(BasicBlock*) const; + + // This is used by lowerEntrySwitch(). + template + void setEntrypoints(Vector&& vector) + { + m_entrypoints = std::forward(vector); + } + + CCallHelpers::Label entrypointLabel(unsigned index) const + { + return m_entrypointLabels[index]; + } + + // This is used by generate(). + template + void setEntrypointLabels(Vector&& vector) + { + m_entrypointLabels = std::forward(vector); + } + const RegisterAtOffsetList& calleeSaveRegisters() const { return m_calleeSaveRegisters; } RegisterAtOffsetList& calleeSaveRegisters() { return m_calleeSaveRegisters; } // Recomputes predecessors and deletes unreachable blocks. void resetReachability(); - void dump(PrintStream&) const; + JS_EXPORT_PRIVATE void dump(PrintStream&) const; unsigned size() const { return m_blocks.size(); } BasicBlock* at(unsigned index) const { return m_blocks[index].get(); } @@ -203,6 +231,8 @@ void addFastTmp(Tmp); bool isFastTmp(Tmp tmp) const { return m_fastTmps.contains(tmp); } + void* addDataSection(size_t); + // The name has to be a string literal, since we don't do any memory management for the string. void setLastPhaseName(const char* name) { @@ -211,6 +241,10 @@ const char* lastPhaseName() const { return m_lastPhaseName; } + // This is a hash of the code. You can use this if you want to put code into a hashtable, but + // it's mainly for validating the results from JSAir. + unsigned jsHash() const; + private: friend class ::JSC::B3::Procedure; friend class BlockInsertionSet; @@ -228,6 +262,8 @@ unsigned m_frameSize { 0 }; unsigned m_callArgAreaSize { 0 }; RegisterAtOffsetList m_calleeSaveRegisters; + Vector m_entrypoints; // This is empty until after lowerEntrySwitch(). + Vector m_entrypointLabels; // This is empty until code generation. const char* m_lastPhaseName; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirCustom.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirCustom.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirCustom.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirCustom.h 2016-11-03 07:04:20.000000000 +0000 @@ -84,10 +84,20 @@ { return inst.args[0].special()->shouldTryAliasingDef(inst); } + + static bool isTerminal(Inst& inst) + { + return inst.args[0].special()->isTerminal(inst); + } + + static bool hasNonArgEffects(Inst& inst) + { + return inst.args[0].special()->hasNonArgEffects(inst); + } static bool hasNonArgNonControlEffects(Inst& inst) { - return inst.args[0].special()->hasNonArgNonControlEffects(); + return inst.args[0].special()->hasNonArgNonControlEffects(inst); } static CCallHelpers::Jump generate( @@ -97,10 +107,18 @@ } }; +template +struct CommonCustomBase { + static bool hasNonArgEffects(Inst& inst) + { + return Subtype::isTerminal(inst) || Subtype::hasNonArgNonControlEffects(inst); + } +}; + // Definition of CCall instruction. CCall is used for hot path C function calls. It's lowered to a // Patch with an Air CCallSpecial along with code to marshal instructions. The lowering happens // before register allocation, so that the register allocator sees the clobbers. -struct CCallCustom { +struct CCallCustom : public CommonCustomBase { template static void forEachArg(Inst& inst, const Functor& functor) { @@ -138,6 +156,11 @@ { return true; } + + static bool isTerminal(Inst&) + { + return false; + } static bool hasNonArgNonControlEffects(Inst&) { @@ -161,7 +184,7 @@ } }; -struct ShuffleCustom { +struct ShuffleCustom : public CommonCustomBase { template static void forEachArg(Inst& inst, const Functor& functor) { @@ -197,6 +220,11 @@ } } + static bool isTerminal(Inst&) + { + return false; + } + static bool hasNonArgNonControlEffects(Inst&) { return false; @@ -205,6 +233,47 @@ static CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&); }; +struct EntrySwitchCustom : public CommonCustomBase { + template + static void forEachArg(Inst&, const Func&) + { + } + + template + static bool isValidFormStatic(Arguments...) + { + return !sizeof...(Arguments); + } + + static bool isValidForm(Inst& inst) + { + return inst.args.isEmpty(); + } + + static bool admitsStack(Inst&, unsigned) + { + return false; + } + + static bool isTerminal(Inst&) + { + return true; + } + + static bool hasNonArgNonControlEffects(Inst&) + { + return false; + } + + static CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&) + { + // This should never be reached because we should have lowered EntrySwitch before + // generation. + UNREACHABLE_FOR_PLATFORM(); + return CCallHelpers::Jump(); + } +}; + } } } // namespace JSC::B3::Air #endif // ENABLE(B3_JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirDumpAsJS.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirDumpAsJS.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirDumpAsJS.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirDumpAsJS.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AirDumpAsJS.h" + +#if ENABLE(B3_JIT) + +#include "AirCode.h" +#include "AirInstInlines.h" + +namespace JSC { namespace B3 { namespace Air { + +namespace { + +CString varNameForBlockAtIndex(unsigned index) +{ + return toCString("bb", index); +} + +CString varName(BasicBlock* block) +{ + return varNameForBlockAtIndex(block->index()); +} + +CString varNameForStackSlotAtIndex(unsigned index) +{ + return toCString("slot", index); +} + +CString varName(StackSlot* slot) +{ + return varNameForStackSlotAtIndex(slot->index()); +} + +CString varName(Reg reg) +{ + return toCString("Reg.", reg.debugName()); +} + +CString varNameForTmpWithTypeAndIndex(Arg::Type type, unsigned index) +{ + return toCString(type == Arg::FP ? "f" : "", "tmp", index); +} + +CString varName(Tmp tmp) +{ + if (tmp.isReg()) + return varName(tmp.reg()); + return varNameForTmpWithTypeAndIndex(Arg(tmp).type(), tmp.tmpIndex()); +} + +} // anonymous namespace + +void dumpAsJS(Code& code, PrintStream& out) +{ + out.println("let code = new Code();"); + + for (unsigned i = 0; i < code.size(); ++i) + out.println("let ", varNameForBlockAtIndex(i), " = code.addBlock();"); + + out.println("let hash;"); + + for (unsigned i = 0; i < code.stackSlots().size(); ++i) { + StackSlot* slot = code.stackSlots()[i]; + if (slot) { + out.println("let ", varName(slot), " = code.addStackSlot(", slot->byteSize(), ", ", slot->kind(), ");"); + if (slot->offsetFromFP()) + out.println(varName(slot), ".setOffsetFromFP(", slot->offsetFromFP(), ");"); + out.println("hash = ", varName(slot), ".hash();"); + out.println("if (hash != ", slot->jsHash(), ")"); + out.println(" throw new Error(\"Bad hash: \" + hash);"); + } else + out.println("code.addStackSlot(1, Spill);"); + } + + Arg::forEachType( + [&] (Arg::Type type) { + for (unsigned i = code.numTmps(type); i--;) { + out.println( + "let ", varNameForTmpWithTypeAndIndex(type, i), " = code.newTmp(", type, ");"); + } + }); + + out.println("let inst;"); + out.println("let arg;"); + + for (BasicBlock* block : code) { + for (FrequentedBlock successor : block->successors()) { + out.println( + varName(block), ".successors.push(new FrequentedBlock(", + varName(successor.block()), ", ", successor.frequency(), "));"); + } + + for (BasicBlock* predecessor : block->predecessors()) + out.println(varName(block), ".predecessors.push(", varName(predecessor), ");"); + + for (Inst& inst : *block) { + out.println("inst = new Inst(", inst.opcode, ");"); + + inst.forEachArg( + [&] (Arg& arg, Arg::Role, Arg::Type, Arg::Width) { + switch (arg.kind()) { + case Arg::Invalid: + RELEASE_ASSERT_NOT_REACHED(); + break; + + case Arg::Tmp: + out.println("arg = Arg.createTmp(", varName(arg.tmp()), ");"); + break; + + case Arg::Imm: + out.println("arg = Arg.createImm(", arg.value(), ");"); + break; + + case Arg::BigImm: + out.println( + "arg = Arg.createBigImm(", + static_cast(arg.value()), ", ", + static_cast(arg.value() >> 32), ");"); + break; + + case Arg::BitImm: + out.println("arg = Arg.createBitImm(", arg.value(), ");"); + break; + + case Arg::BitImm64: + out.println( + "arg = Arg.createBitImm64(", + static_cast(arg.value()), ", ", + static_cast(arg.value() >> 32), ");"); + break; + + case Arg::Addr: + out.println( + "arg = Arg.createAddr(", varName(arg.base()), ", ", arg.offset(), ");"); + break; + + case Arg::Stack: + out.println( + "arg = Arg.createStack(", varName(arg.stackSlot()), ", ", arg.offset(), ");"); + break; + + case Arg::CallArg: + out.println("arg = Arg.createCallArg(", arg.offset(), ");"); + break; + + case Arg::Index: + out.println( + "arg = Arg.createIndex(", varName(arg.base()), ", ", + varName(arg.index()), ", ", arg.scale(), ", ", arg.offset(), ");"); + break; + + case Arg::RelCond: + out.println("arg = Arg.createRelCond(", arg.asRelationalCondition(), ");"); + break; + + case Arg::ResCond: + out.println("arg = Arg.createResCond(", arg.asResultCondition(), ");"); + break; + + case Arg::DoubleCond: + out.println("arg = Arg.createDoubleCond(", arg.asDoubleCondition(), ");"); + break; + + case Arg::Special: + out.println("arg = Arg.createSpecial();"); + break; + + case Arg::WidthArg: + out.println("arg = Arg.createWidthArg(", arg.width(), ");"); + break; + } + + out.println("inst.args.push(arg);"); + }); + + if (inst.opcode == Patch) { + if (inst.hasNonArgEffects()) + out.println("inst.patchHasNonArgEffects = true;"); + + out.println("inst.extraEarlyClobberedRegs = new Set();"); + out.println("inst.extraClobberedRegs = new Set();"); + inst.extraEarlyClobberedRegs().forEach( + [&] (Reg reg) { + out.println("inst.extraEarlyClobberedRegs.add(", varName(reg), ");"); + }); + inst.extraClobberedRegs().forEach( + [&] (Reg reg) { + out.println("inst.extraClobberedRegs.add(", varName(reg), ");"); + }); + + out.println("inst.patchArgData = [];"); + inst.forEachArg( + [&] (Arg&, Arg::Role role, Arg::Type type, Arg::Width width) { + out.println( + "inst.patchArgData.push({role: Arg.", role, ", type: ", type, + ", width: ", width, "});"); + }); + } + + if (inst.opcode == CCall || inst.opcode == ColdCCall) { + out.println("inst.cCallType = ", inst.origin->type()); + out.println("inst.cCallArgTypes = [];"); + for (unsigned i = 1; i < inst.origin->numChildren(); ++i) + out.println("inst.cCallArgTypes.push(", inst.origin->child(i)->type(), ");"); + } + + out.println("hash = inst.hash();"); + out.println("if (hash != ", inst.jsHash(), ")"); + out.println(" throw new Error(\"Bad hash: \" + hash);"); + + out.println(varName(block), ".append(inst);"); + } + } +} + +} } } // namespace JSC::B3::Air + +#endif // ENABLE(B3_JIT) + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirDumpAsJS.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirDumpAsJS.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirDumpAsJS.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirDumpAsJS.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AirDumpAsJS_h +#define AirDumpAsJS_h + +#if ENABLE(B3_JIT) + +#include + +namespace JSC { namespace B3 { namespace Air { + +class Code; + +// This is used for benchmarking. Various operations on Air are interesting from a benchmarking +// standpoint. We can write some Air phases in JS and then use that to benchmark JS. The benchmark +// is called JSAir, and it's in PerformanceTests/JSAir. +void dumpAsJS(Code&, PrintStream&); + +} } } // namespace JSC::B3::Air + +#endif // ENABLE(B3_JIT) + +#endif // AirDumpAsJS_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirEliminateDeadCode.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -31,7 +31,7 @@ #include "AirCode.h" #include "AirInstInlines.h" #include "AirPhaseScope.h" -#include "B3IndexSet.h" +#include namespace JSC { namespace B3 { namespace Air { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirFixObviousSpills.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -28,10 +28,11 @@ #if ENABLE(B3_JIT) +#include "AirArgInlines.h" #include "AirCode.h" #include "AirInstInlines.h" #include "AirPhaseScope.h" -#include "B3IndexMap.h" +#include #include namespace JSC { namespace B3 { namespace Air { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirFixPartialRegisterStalls.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -34,9 +34,9 @@ #include "AirInst.h" #include "AirInstInlines.h" #include "AirPhaseScope.h" -#include "B3IndexMap.h" -#include "B3IndexSet.h" #include "MacroAssembler.h" +#include +#include #include namespace JSC { namespace B3 { namespace Air { @@ -50,6 +50,8 @@ case ConvertFloatToDouble: case ConvertInt32ToDouble: case ConvertInt64ToDouble: + case ConvertInt32ToFloat: + case ConvertInt64ToFloat: case SqrtDouble: case SqrtFloat: case CeilDouble: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirGenerate.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirGenerate.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirGenerate.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirGenerate.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -30,6 +30,7 @@ #include "AirAllocateStack.h" #include "AirCode.h" +#include "AirDumpAsJS.h" #include "AirEliminateDeadCode.h" #include "AirFixObviousSpills.h" #include "AirFixPartialRegisterStalls.h" @@ -38,6 +39,7 @@ #include "AirIteratedRegisterCoalescing.h" #include "AirLogRegisterPressure.h" #include "AirLowerAfterRegAlloc.h" +#include "AirLowerEntrySwitch.h" #include "AirLowerMacros.h" #include "AirOpcodeUtils.h" #include "AirOptimizeBlockOrder.h" @@ -46,11 +48,13 @@ #include "AirSpillEverything.h" #include "AirValidate.h" #include "B3Common.h" -#include "B3IndexMap.h" #include "B3Procedure.h" #include "B3TimingScope.h" +#include "B3ValueInlines.h" #include "CCallHelpers.h" #include "DisallowMacroScratchRegisterUsage.h" +#include "LinkBuffer.h" +#include namespace JSC { namespace B3 { namespace Air { @@ -102,20 +106,28 @@ // Prior to this point the prologue and epilogue is implicit. This makes it explicit. It also // does things like identify which callee-saves we're using and saves them. handleCalleeSaves(code); + + if (Options::dumpAirAsJSBeforeAllocateStack()) { + dataLog("Dumping Air as JS before allocateStack:\n"); + dumpAsJS(code, WTF::dataFile()); + dataLog("Air hash: ", code.jsHash(), "\n"); + } // This turns all Stack and CallArg Args into Addr args that use the frame pointer. It does // this by first-fit allocating stack slots. It should be pretty darn close to optimal, so we // shouldn't have to worry about this very much. allocateStack(code); + + if (Options::dumpAirAfterAllocateStack()) { + dataLog("Dumping Air after allocateStack:\n"); + dataLog(code); + dataLog("Air hash: ", code.jsHash(), "\n"); + } // If we coalesced moves then we can unbreak critical edges. This is the main reason for this // phase. simplifyCFG(code); - // This sorts the basic blocks in Code to achieve an ordering that maximizes the likelihood that a high - // frequency successor is also the fall-through target. - optimizeBlockOrder(code); - // This is needed to satisfy a requirement of B3::StackmapValue. reportUsedRegisters(code); @@ -124,6 +136,16 @@ // use. We _must_ run this after reportUsedRegisters(), since that kills variable assignments // that seem dead. Luckily, this phase does not change register liveness, so that's OK. fixPartialRegisterStalls(code); + + // Actually create entrypoints. + lowerEntrySwitch(code); + + // The control flow graph can be simplified further after we have lowered EntrySwitch. + simplifyCFG(code); + + // This sorts the basic blocks in Code to achieve an ordering that maximizes the likelihood that a high + // frequency successor is also the fall-through target. + optimizeBlockOrder(code); if (shouldValidateIR()) validate(code); @@ -142,30 +164,23 @@ DisallowMacroScratchRegisterUsage disallowScratch(jit); - // And now, we generate code. - jit.emitFunctionPrologue(); - if (code.frameSize()) - jit.addPtr(CCallHelpers::TrustedImm32(-code.frameSize()), MacroAssembler::stackPointerRegister); - auto argFor = [&] (const RegisterAtOffset& entry) -> CCallHelpers::Address { return CCallHelpers::Address(GPRInfo::callFrameRegister, entry.offset()); }; - for (const RegisterAtOffset& entry : code.calleeSaveRegisters()) { - if (entry.reg().isGPR()) - jit.storePtr(entry.reg().gpr(), argFor(entry)); - else - jit.storeDouble(entry.reg().fpr(), argFor(entry)); - } - + // And now, we generate code. GenerationContext context; context.code = &code; - IndexMap blockLabels(code.size()); + context.blockLabels.resize(code.size()); + for (BasicBlock* block : code) { + if (block) + context.blockLabels[block] = Box::create(); + } IndexMap blockJumps(code.size()); auto link = [&] (CCallHelpers::Jump jump, BasicBlock* target) { - if (blockLabels[target].isSet()) { - jump.linkTo(blockLabels[target], &jit); + if (context.blockLabels[target]->isSet()) { + jump.linkTo(*context.blockLabels[target], &jit); return; } @@ -182,16 +197,36 @@ }; for (BasicBlock* block : code) { + context.currentBlock = block; + context.indexInBlock = UINT_MAX; blockJumps[block].link(&jit); - blockLabels[block] = jit.label(); + CCallHelpers::Label label = jit.label(); + *context.blockLabels[block] = label; + + if (code.isEntrypoint(block)) { + jit.emitFunctionPrologue(); + if (code.frameSize()) + jit.addPtr(CCallHelpers::TrustedImm32(-code.frameSize()), MacroAssembler::stackPointerRegister); + + for (const RegisterAtOffset& entry : code.calleeSaveRegisters()) { + if (entry.reg().isGPR()) + jit.storePtr(entry.reg().gpr(), argFor(entry)); + else + jit.storeDouble(entry.reg().fpr(), argFor(entry)); + } + } + ASSERT(block->size() >= 1); for (unsigned i = 0; i < block->size() - 1; ++i) { + context.indexInBlock = i; Inst& inst = block->at(i); addItem(inst); CCallHelpers::Jump jump = inst.generate(jit, context); ASSERT_UNUSED(jump, !jump.isSet()); } + context.indexInBlock = block->size() - 1; + if (block->last().opcode == Jump && block->successorBlock(0) == code.findNextBlock(block)) continue; @@ -217,24 +252,33 @@ } CCallHelpers::Jump jump = block->last().generate(jit, context); - switch (block->numSuccessors()) { - case 0: - ASSERT(!jump.isSet()); - break; - case 1: - link(jump, block->successorBlock(0)); - break; - case 2: - link(jump, block->successorBlock(0)); - if (block->successorBlock(1) != code.findNextBlock(block)) - link(jit.jump(), block->successorBlock(1)); - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; + // The jump won't be set for patchpoints. It won't be set for Oops because then it won't have + // any successors. + if (jump.isSet()) { + switch (block->numSuccessors()) { + case 1: + link(jump, block->successorBlock(0)); + break; + case 2: + link(jump, block->successorBlock(0)); + if (block->successorBlock(1) != code.findNextBlock(block)) + link(jit.jump(), block->successorBlock(1)); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); + break; + } } addItem(block->last()); } + + context.currentBlock = nullptr; + context.indexInBlock = UINT_MAX; + + Vector entrypointLabels(code.numEntrypoints()); + for (unsigned i = code.numEntrypoints(); i--;) + entrypointLabels[i] = *context.blockLabels[code.entrypoint(i).block()]; + code.setEntrypointLabels(WTFMove(entrypointLabels)); pcToOriginMap.appendItem(jit.label(), Origin()); // FIXME: Make late paths have Origins: https://bugs.webkit.org/show_bug.cgi?id=153689 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirGenerationContext.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirGenerationContext.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirGenerationContext.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirGenerationContext.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,14 +28,14 @@ #if ENABLE(B3_JIT) +#include "AirBasicBlock.h" +#include "CCallHelpers.h" +#include +#include #include #include -namespace JSC { - -class CCallHelpers; - -namespace B3 { namespace Air { +namespace JSC { namespace B3 { namespace Air { class Code; @@ -44,7 +44,10 @@ typedef SharedTask LatePath; Vector> latePaths; - Code* code; + IndexMap> blockLabels; + BasicBlock* currentBlock { nullptr }; + unsigned indexInBlock { UINT_MAX }; + Code* code { nullptr }; }; } } } // namespace JSC::B3::Air diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirInst.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirInst.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirInst.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirInst.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -45,6 +45,16 @@ return result; } +unsigned Inst::jsHash() const +{ + unsigned result = static_cast(opcode); + + for (const Arg& arg : args) + result += arg.jsHash(); + + return result; +} + void Inst::dump(PrintStream& out) const { out.print(opcode, " ", listDump(args)); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirInst.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirInst.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirInst.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirInst.h 2016-11-03 07:04:20.000000000 +0000 @@ -163,6 +163,9 @@ // This function is auto-generated by opcode_generator.rb. bool admitsStack(unsigned argIndex); bool admitsStack(Arg&); + + // Defined by opcode_generator.rb. + bool isTerminal(); // Returns true if this instruction can have any effects other than control flow or arguments. bool hasNonArgNonControlEffects(); @@ -174,6 +177,9 @@ // Tells you if this operation has arg effects. bool hasArgEffects(); + + // Tells you if this operation has non-control effects. + bool hasNonControlEffects() { return hasNonArgNonControlEffects() || hasArgEffects(); } // Generate some code for this instruction. This is, like, literally our backend. If this is the // terminal, it returns the jump that needs to be linked for the "then" case, with the "else" @@ -187,6 +193,9 @@ // Add Tmp1, Tmp2, Tmp3 // returns 2 if 0 and 1 benefit from aliasing to Tmp3. Optional shouldTryAliasingDef(); + + // This computes a hash for comparing this to JSAir's Inst. + unsigned jsHash() const; void dump(PrintStream&) const; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirInstInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirInstInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirInstInlines.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirInstInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -36,65 +36,13 @@ namespace JSC { namespace B3 { namespace Air { -template struct ForEach; -template<> struct ForEach { - template - static void forEach(Inst& inst, const Functor& functor) - { - inst.forEachTmp(functor); - } -}; - -template<> struct ForEach { - template - static void forEach(Inst& inst, const Functor& functor) - { - inst.forEachArg(functor); - } -}; - -template<> struct ForEach { - template - static void forEach(Inst& inst, const Functor& functor) - { - inst.forEachArg( - [&] (Arg& arg, Arg::Role role, Arg::Type type, Arg::Width width) { - if (!arg.isStack()) - return; - StackSlot* stackSlot = arg.stackSlot(); - - // FIXME: This is way too optimistic about the meaning of "Def". It gets lucky for - // now because our only use of "Anonymous" stack slots happens to want the optimistic - // semantics. We could fix this by just changing the comments that describe the - // semantics of "Anonymous". - // https://bugs.webkit.org/show_bug.cgi?id=151128 - - functor(stackSlot, role, type, width); - arg = Arg::stack(stackSlot, arg.offset()); - }); - } -}; - -template<> struct ForEach { - template - static void forEach(Inst& inst, const Functor& functor) - { - inst.forEachTmp( - [&] (Tmp& tmp, Arg::Role role, Arg::Type type, Arg::Width width) { - if (!tmp.isReg()) - return; - - Reg reg = tmp.reg(); - functor(reg, role, type, width); - tmp = Tmp(reg); - }); - } -}; - template void Inst::forEach(const Functor& functor) { - ForEach::forEach(*this, functor); + forEachArg( + [&] (Arg& arg, Arg::Role role, Arg::Type type, Arg::Width width) { + arg.forEach(role, type, width, functor); + }); } inline const RegisterSet& Inst::extraClobberedRegs() @@ -180,17 +128,24 @@ case Or64: case Xor32: case Xor64: - case AddDouble: - case AddFloat: case AndFloat: case AndDouble: - case MulDouble: - case MulFloat: case XorDouble: case XorFloat: if (args.size() == 3) return 2; break; + case AddDouble: + case AddFloat: + case MulDouble: + case MulFloat: +#if CPU(X86) || CPU(X86_64) + if (MacroAssembler::supportsAVX()) + return Nullopt; +#endif + if (args.size() == 3) + return 2; + break; case BranchAdd32: case BranchAdd64: if (args.size() == 4) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -38,7 +38,6 @@ #include "AirTmpWidth.h" #include "AirUseCounts.h" #include -#include namespace JSC { namespace B3 { namespace Air { @@ -1122,7 +1121,7 @@ // If it's a constant, then it's not as bad to spill. We can rematerialize it in many // cases. - if (counts->numConstDefs == counts->numDefs) + if (counts->numConstDefs == 1 && counts->numDefs == 1) uses /= 2; return degree / uses; @@ -1419,6 +1418,11 @@ } } + static unsigned stackSlotMinimumWidth(Arg::Width width) + { + return width <= Arg::Width32 ? 4 : 8; + } + template void addSpillAndFill(const ColoringAllocator& allocator, HashSet& unspillableTmps) { @@ -1429,7 +1433,7 @@ // Allocate stack slot for each spilled value. StackSlot* stackSlot = m_code.addStackSlot( - m_tmpWidth.width(tmp) <= Arg::Width32 ? 4 : 8, StackSlotKind::Spill); + stackSlotMinimumWidth(m_tmpWidth.requiredWidth(tmp)), StackSlotKind::Spill); bool isNewTmp = stackSlots.add(tmp, stackSlot).isNewEntry; ASSERT_UNUSED(isNewTmp, isNewTmp); } @@ -1447,30 +1451,55 @@ // only claim to read 32 bits from the source if only 32 bits of the destination are // read. Note that we only apply this logic if this turns into a load or store, since // Move is the canonical way to move data between GPRs. - bool forceMove32IfDidSpill = false; + bool canUseMove32IfDidSpill = false; bool didSpill = false; if (type == Arg::GP && inst.opcode == Move) { if ((inst.args[0].isTmp() && m_tmpWidth.width(inst.args[0].tmp()) <= Arg::Width32) || (inst.args[1].isTmp() && m_tmpWidth.width(inst.args[1].tmp()) <= Arg::Width32)) - forceMove32IfDidSpill = true; + canUseMove32IfDidSpill = true; } // Try to replace the register use by memory use when possible. inst.forEachArg( - [&] (Arg& arg, Arg::Role, Arg::Type argType, Arg::Width width) { - if (arg.isTmp() && argType == type && !arg.isReg()) { - auto stackSlotEntry = stackSlots.find(arg.tmp()); - if (stackSlotEntry != stackSlots.end() - && inst.admitsStack(arg)) { - stackSlotEntry->value->ensureSize( - forceMove32IfDidSpill ? 4 : Arg::bytes(width)); - arg = Arg::stack(stackSlotEntry->value); - didSpill = true; - } + [&] (Arg& arg, Arg::Role role, Arg::Type argType, Arg::Width width) { + if (!arg.isTmp()) + return; + if (argType != type) + return; + if (arg.isReg()) + return; + + auto stackSlotEntry = stackSlots.find(arg.tmp()); + if (stackSlotEntry == stackSlots.end()) + return; + if (!inst.admitsStack(arg)) + return; + + // If the Tmp holds a constant then we want to rematerialize its + // value rather than loading it from the stack. In order for that + // optimization to kick in, we need to avoid placing the Tmp's stack + // address into the instruction. + if (!Arg::isColdUse(role)) { + const UseCounts::Counts* counts = m_useCounts[arg.tmp()]; + if (counts && counts->numConstDefs == 1 && counts->numDefs == 1) + return; } + + Arg::Width spillWidth = m_tmpWidth.requiredWidth(arg.tmp()); + if (Arg::isAnyDef(role) && width < spillWidth) + return; + ASSERT(inst.opcode == Move || !(Arg::isAnyUse(role) && width > spillWidth)); + + if (spillWidth != Arg::Width32) + canUseMove32IfDidSpill = false; + + stackSlotEntry->value->ensureSize( + canUseMove32IfDidSpill ? 4 : Arg::bytes(width)); + arg = Arg::stack(stackSlotEntry->value); + didSpill = true; }); - if (didSpill && forceMove32IfDidSpill) + if (didSpill && canUseMove32IfDidSpill) inst.opcode = Move32; // For every other case, add Load/Store as needed. @@ -1488,9 +1517,9 @@ return; } - Arg arg = Arg::stack(stackSlotEntry->value); + Arg::Width spillWidth = m_tmpWidth.requiredWidth(tmp); Opcode move = Oops; - switch (stackSlotEntry->value->byteSize()) { + switch (stackSlotMinimumWidth(spillWidth)) { case 4: move = type == Arg::GP ? Move32 : MoveFloat; break; @@ -1505,6 +1534,7 @@ tmp = m_code.newTmp(type); unspillableTmps.add(AbsoluteTmpMapper::absoluteIndex(tmp)); + Arg arg = Arg::stack(stackSlotEntry->value); if (Arg::isAnyUse(role) && role != Arg::Scratch) insertionSet.insert(instIndex, move, inst.origin, arg, tmp); if (Arg::isAnyDef(role)) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLiveness.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLiveness.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLiveness.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLiveness.h 2016-11-03 07:04:20.000000000 +0000 @@ -33,8 +33,8 @@ #include "AirInstInlines.h" #include "AirStackSlot.h" #include "AirTmpInlines.h" -#include "B3IndexMap.h" -#include "B3IndexSet.h" +#include +#include #include #include diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -28,6 +28,7 @@ #if ENABLE(B3_JIT) +#include "AirArgInlines.h" #include "AirCode.h" #include "AirInstInlines.h" #include "AirLiveness.h" diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -28,6 +28,7 @@ #if ENABLE(B3_JIT) +#include "AirArgInlines.h" #include "AirCCallingConvention.h" #include "AirCode.h" #include "AirEmitShuffle.h" diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AirLowerEntrySwitch.h" + +#if ENABLE(B3_JIT) + +#include "AirBlockWorklist.h" +#include "AirCode.h" +#include "AirInstInlines.h" +#include "AirPhaseScope.h" +#include "B3Procedure.h" + +namespace JSC { namespace B3 { namespace Air { + +void lowerEntrySwitch(Code& code) +{ + PhaseScope phaseScope(code, "lowerEntrySwitch"); + + // Figure out the set of blocks that should be duplicated. + BlockWorklist worklist; + for (BasicBlock* block : code) { + if (block->last().opcode == EntrySwitch) + worklist.push(block); + } + + // It's possible that we don't have any EntrySwitches. That's fine. + if (worklist.seen().isEmpty()) { + Vector entrypoints(code.proc().numEntrypoints(), FrequentedBlock(code[0])); + code.setEntrypoints(WTFMove(entrypoints)); + return; + } + + while (BasicBlock* block = worklist.pop()) + worklist.pushAll(block->predecessors()); + + RELEASE_ASSERT(worklist.saw(code[0])); + + Vector entrypointFrequencies(code.proc().numEntrypoints(), FrequencyClass::Rare); + for (BasicBlock* block : code) { + if (block->last().opcode != EntrySwitch) + continue; + for (unsigned entrypointIndex = code.proc().numEntrypoints(); entrypointIndex--;) { + entrypointFrequencies[entrypointIndex] = maxFrequency( + entrypointFrequencies[entrypointIndex], + block->successor(entrypointIndex).frequency()); + } + } + + auto fixEntrySwitch = [&] (BasicBlock* block, unsigned entrypointIndex) { + if (block->last().opcode != EntrySwitch) + return; + FrequentedBlock target = block->successor(entrypointIndex); + block->last().opcode = Jump; + block->successors().resize(1); + block->successor(0) = target; + }; + + // Now duplicate them. + Vector entrypoints; + entrypoints.append(FrequentedBlock(code[0], entrypointFrequencies[0])); + IndexMap map(code.size()); + for (unsigned entrypointIndex = 1; entrypointIndex < code.proc().numEntrypoints(); ++entrypointIndex) { + map.clear(); + for (BasicBlock* block : worklist.seen().values(code)) + map[block] = code.addBlock(block->frequency()); + entrypoints.append(FrequentedBlock(map[code[0]], entrypointFrequencies[entrypointIndex])); + for (BasicBlock* block : worklist.seen().values(code)) { + BasicBlock* newBlock = map[block]; + for (const Inst& inst : *block) + newBlock->appendInst(inst); + newBlock->successors() = block->successors(); + for (BasicBlock*& successor : newBlock->successorBlocks()) { + if (BasicBlock* replacement = map[successor]) + successor = replacement; + } + fixEntrySwitch(newBlock, entrypointIndex); + } + } + for (BasicBlock* block : worklist.seen().values(code)) + fixEntrySwitch(block, 0); + + code.setEntrypoints(WTFMove(entrypoints)); + code.resetReachability(); +} + +} } } // namespace JSC::B3::Air + +#endif // ENABLE(B3_JIT) + + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirLowerEntrySwitch.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AirLowerEntrySwitch_h +#define AirLowerEntrySwitch_h + +#if ENABLE(B3_JIT) + +namespace JSC { namespace B3 { namespace Air { + +class Code; + +// Converts code that seems to have one entrypoint and emulates multiple entrypoints with +// EntrySwitch into code that really has multiple entrypoints. This is accomplished by duplicating +// the backwards transitive closure from all EntrySwitches. +void lowerEntrySwitch(Code&); + +} } } // namespace JSC::B3::Air + +#endif // ENABLE(B3_JIT) + +#endif // AirLowerEntrySwitch_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirOpcode.opcodes webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirOpcode.opcodes --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirOpcode.opcodes 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirOpcode.opcodes 2016-11-03 07:04:20.000000000 +0000 @@ -147,6 +147,7 @@ Tmp, Tmp, Tmp x86: Addr, Tmp, Tmp x86: Tmp, Addr, Tmp + x86: Index, Tmp, Tmp x86: AddDouble U:F:64, UD:F:64 Tmp, Tmp @@ -156,6 +157,7 @@ Tmp, Tmp, Tmp x86: Addr, Tmp, Tmp x86: Tmp, Addr, Tmp + x86: Index, Tmp, Tmp x86: AddFloat U:F:32, UD:F:32 Tmp, Tmp @@ -168,6 +170,9 @@ x86: Addr, Tmp x86: Tmp, Addr +arm64: Sub32 U:G:32, U:G:32, D:G:32 + Tmp, Tmp, Tmp + 64: Sub64 U:G:64, UD:G:64 Tmp, Tmp x86: Imm, Addr @@ -175,15 +180,22 @@ x86: Addr, Tmp x86: Tmp, Addr -arm64: SubDouble U:F:64, U:F:64, D:F:64 +arm64: Sub64 U:G:64, U:G:64, D:G:64 Tmp, Tmp, Tmp +SubDouble U:F:64, U:F:64, D:F:64 + arm64: Tmp, Tmp, Tmp + x86: Tmp, Addr, Tmp + x86: Tmp, Index, Tmp + x86: SubDouble U:F:64, UD:F:64 Tmp, Tmp Addr, Tmp -arm64: SubFloat U:F:32, U:F:32, D:F:32 - Tmp, Tmp, Tmp +SubFloat U:F:32, U:F:32, D:F:32 + arm64: Tmp, Tmp, Tmp + x86: Tmp, Addr, Tmp + x86: Tmp, Index, Tmp x86: SubFloat U:F:32, UD:F:32 Tmp, Tmp @@ -199,6 +211,9 @@ arm64: NegateDouble U:F:64, D:F:64 Tmp, Tmp +arm64: NegateFloat U:F:32, D:F:32 + Tmp, Tmp + Mul32 U:G:32, UZD:G:32 Tmp, Tmp x86: Addr, Tmp @@ -243,6 +258,7 @@ Tmp, Tmp, Tmp x86: Addr, Tmp, Tmp x86: Tmp, Addr, Tmp + x86: Index, Tmp, Tmp x86: MulDouble U:F:64, UD:F:64 Tmp, Tmp @@ -252,6 +268,7 @@ Tmp, Tmp, Tmp x86: Addr, Tmp, Tmp x86: Tmp, Addr, Tmp + x86: Index, Tmp, Tmp x86: MulFloat U:F:32, UD:F:32 Tmp, Tmp @@ -472,6 +489,15 @@ 64: ConvertInt64ToDouble U:G:64, D:F:64 Tmp, Tmp + x86_64: Addr, Tmp + +ConvertInt32ToFloat U:G:32, D:F:32 + Tmp, Tmp + x86: Addr, Tmp + +64: ConvertInt64ToFloat U:G:64, D:F:32 + Tmp, Tmp + x86_64: Addr, Tmp CountLeadingZeros32 U:G:32, ZD:G:32 Tmp, Tmp @@ -658,23 +684,24 @@ x86: RelCond, Index, Tmp BranchTest8 U:G:32, U:G:8, U:G:8 /branch - x86: ResCond, Addr, Imm - x86: ResCond, Index, Imm + x86: ResCond, Addr, BitImm + x86: ResCond, Index, BitImm BranchTest32 U:G:32, U:G:32, U:G:32 /branch ResCond, Tmp, Tmp ResCond, Tmp, BitImm - x86: ResCond, Addr, Imm - x86: ResCond, Index, Imm + x86: ResCond, Addr, BitImm + x86: ResCond, Index, BitImm # Warning: forms that take an immediate will sign-extend their immediate. You probably want # BranchTest32 in most cases where you use an immediate. 64: BranchTest64 U:G:32, U:G:64, U:G:64 /branch ResCond, Tmp, Tmp - ResCond, Tmp, BitImm64 - x86: ResCond, Addr, Imm + arm64: ResCond, Tmp, BitImm64 + x86: ResCond, Tmp, BitImm + x86: ResCond, Addr, BitImm x86: ResCond, Addr, Tmp - x86: ResCond, Index, Imm + x86: ResCond, Index, BitImm BranchDouble U:G:32, U:F:64, U:F:64 /branch DoubleCond, Tmp, Tmp @@ -818,6 +845,8 @@ Jump /branch +RetVoid /return + Ret32 U:G:32 /return Tmp @@ -832,6 +861,10 @@ Oops /terminal +# This is a terminal but we express it as a Custom because we don't want it to have a code +# generator. +custom EntrySwitch + # A Shuffle is a multi-source, multi-destination move. It simultaneously does multiple moves at once. # The moves are specified as triplets of src, dst, and width. For example you can request a swap this # way: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirOptimizeBlockOrder.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -81,16 +81,28 @@ SortedSuccessors sortedSuccessors; SortedSuccessors sortedSlowSuccessors; - fastWorklist.push(code[0]); + // We expect entrypoint lowering to have already happened. + RELEASE_ASSERT(code.numEntrypoints()); + + auto appendSuccessor = [&] (const FrequentedBlock& block) { + if (block.isRare()) + sortedSlowSuccessors.append(block.block()); + else + sortedSuccessors.append(block.block()); + }; + + // For everything but the first entrypoint, we push them in order of frequency and frequency + // class. + for (unsigned i = 1; i < code.numEntrypoints(); ++i) + appendSuccessor(code.entrypoint(i)); + + // Always push the primary successor last so that it gets highest priority. + fastWorklist.push(code.entrypoint(0).block()); while (BasicBlock* block = fastWorklist.pop()) { blocksInOrder.append(block); - for (FrequentedBlock& successor : block->successors()) { - if (successor.isRare()) - sortedSlowSuccessors.append(successor.block()); - else - sortedSuccessors.append(successor.block()); - } + for (FrequentedBlock& successor : block->successors()) + appendSuccessor(successor); sortedSuccessors.process(fastWorklist); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -28,6 +28,7 @@ #if ENABLE(B3_JIT) +#include "AirArgInlines.h" #include "AirCode.h" #include "AirInstInlines.h" #include "AirLiveness.h" diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSimplifyCFG.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -95,33 +95,32 @@ } } - // Now check if the block's terminal can be replaced with a jump. - if (block->numSuccessors() > 1) { - // The terminal must not have weird effects. - if (!block->last().hasArgEffects() - && !block->last().hasNonArgNonControlEffects()) { - // All of the successors must be the same. - bool allSame = true; - BasicBlock* firstSuccessor = block->successorBlock(0); - for (unsigned i = 1; i < block->numSuccessors(); ++i) { - if (block->successorBlock(i) != firstSuccessor) { - allSame = false; - break; - } - } - if (allSame) { - if (verbose) - dataLog("Changing ", pointerDump(block), "'s terminal to a Jump.\n"); - block->last() = Inst(Jump, block->last().origin); - block->successors().resize(1); - block->successors()[0].frequency() = FrequencyClass::Normal; - changed = true; + // Now check if the block's terminal can be replaced with a jump. The terminal must not + // have weird effects. + if (block->numSuccessors() > 1 + && !block->last().hasNonControlEffects()) { + // All of the successors must be the same. + bool allSame = true; + BasicBlock* firstSuccessor = block->successorBlock(0); + for (unsigned i = 1; i < block->numSuccessors(); ++i) { + if (block->successorBlock(i) != firstSuccessor) { + allSame = false; + break; } } + if (allSame) { + if (verbose) + dataLog("Changing ", pointerDump(block), "'s terminal to a Jump.\n"); + block->last() = Inst(Jump, block->last().origin); + block->successors().resize(1); + block->successors()[0].frequency() = FrequencyClass::Normal; + changed = true; + } } // Finally handle jumps to a block with one predecessor. - if (block->numSuccessors() == 1) { + if (block->numSuccessors() == 1 + && !block->last().hasNonControlEffects()) { BasicBlock* successor = block->successorBlock(0); if (successor != block && successor->numPredecessors() == 1) { RELEASE_ASSERT(successor->predecessor(0) == block); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSpecial.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSpecial.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSpecial.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSpecial.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,7 +55,17 @@ return Nullopt; } -bool Special::hasNonArgNonControlEffects() +bool Special::isTerminal(Inst&) +{ + return false; +} + +bool Special::hasNonArgEffects(Inst&) +{ + return true; +} + +bool Special::hasNonArgNonControlEffects(Inst&) { return true; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSpecial.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSpecial.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSpecial.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSpecial.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -87,9 +87,15 @@ virtual const RegisterSet& extraEarlyClobberedRegs(Inst&) = 0; virtual const RegisterSet& extraClobberedRegs(Inst&) = 0; + + // By default, this returns false. + virtual bool isTerminal(Inst&); + + // By default, this returns true. + virtual bool hasNonArgEffects(Inst&); // By default, this returns true. - virtual bool hasNonArgNonControlEffects(); + virtual bool hasNonArgNonControlEffects(Inst&); void dump(PrintStream&) const; void deepDump(PrintStream&) const; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirSpillEverything.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -28,13 +28,14 @@ #if ENABLE(B3_JIT) +#include "AirArgInlines.h" #include "AirCode.h" #include "AirInsertionSet.h" #include "AirInstInlines.h" #include "AirLiveness.h" #include "AirPhaseScope.h" #include "AirRegisterPriority.h" -#include "B3IndexMap.h" +#include namespace JSC { namespace B3 { namespace Air { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirStackSlot.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirStackSlot.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirStackSlot.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirStackSlot.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -39,6 +39,11 @@ m_b3Slot->m_offsetFromFP = value; } +unsigned StackSlot::jsHash() const +{ + return static_cast(m_kind) + m_byteSize * 3 + m_offsetFromFP * 7; +} + void StackSlot::dump(PrintStream& out) const { if (isSpill()) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirStackSlot.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirStackSlot.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirStackSlot.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirStackSlot.h 2016-11-03 07:04:20.000000000 +0000 @@ -76,6 +76,9 @@ // This should usually just be called from phases that do stack allocation. But you can // totally force a stack slot to land at some offset. void setOffsetFromFP(intptr_t); + + // This computes a hash for comparing this to JSAir's StackSlot. + unsigned jsHash() const; void dump(PrintStream&) const; void deepDump(PrintStream&) const; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirTmpWidth.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirTmpWidth.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirTmpWidth.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirTmpWidth.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,7 +29,6 @@ #if ENABLE(B3_JIT) #include "AirArg.h" -#include namespace JSC { namespace B3 { namespace Air { @@ -60,6 +59,15 @@ return std::min(iter->value.use, iter->value.def); } + // Return the minimum required width for all defs/uses of this Tmp. + Arg::Width requiredWidth(Tmp tmp) + { + auto iter = m_width.find(tmp); + if (iter == m_width.end()) + return Arg::minimumWidth(Arg(tmp).type()); + return std::max(iter->value.use, iter->value.def); + } + // This indirectly tells you how much of the tmp's high bits are guaranteed to be zero. The number of // high bits that are zero are: // diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirValidate.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirValidate.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirValidate.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirValidate.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,7 @@ #include "AirCode.h" #include "AirInstInlines.h" +#include "B3Procedure.h" namespace JSC { namespace B3 { namespace Air { @@ -54,7 +55,7 @@ HashSet validSlots; HashSet validBlocks; HashSet validSpecials; - + for (BasicBlock* block : m_code) validBlocks.add(block); for (StackSlot* slot : m_code.stackSlots()) @@ -63,6 +64,10 @@ validSpecials.add(special); for (BasicBlock* block : m_code) { + // Blocks that are entrypoints must not have predecessors. + if (m_code.isEntrypoint(block)) + VALIDATE(!block->numPredecessors(), ("At entrypoint ", *block)); + for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) { Inst& inst = block->at(instIndex); for (Arg& arg : inst.args) { @@ -79,9 +84,9 @@ } VALIDATE(inst.isValidForm(), ("At ", inst, " in ", *block)); if (instIndex == block->size() - 1) - VALIDATE(isTerminal(inst.opcode), ("At ", inst, " in ", *block)); + VALIDATE(inst.isTerminal(), ("At ", inst, " in ", *block)); else - VALIDATE(!isTerminal(inst.opcode), ("At ", inst, " in ", *block)); + VALIDATE(!inst.isTerminal(), ("At ", inst, " in ", *block)); // forEachArg must return Arg&'s that point into the args array. inst.forEachArg( @@ -89,6 +94,14 @@ VALIDATE(&arg >= &inst.args[0], ("At ", arg, " in ", inst, " in ", *block)); VALIDATE(&arg <= &inst.args.last(), ("At ", arg, " in ", inst, " in ", *block)); }); + + switch (inst.opcode) { + case EntrySwitch: + VALIDATE(block->numSuccessors() == m_code.proc().numEntrypoints(), ("At ", inst, " in ", *block)); + break; + default: + break; + } } for (BasicBlock* successor : block->successorBlocks()) VALIDATE(validBlocks.contains(successor), ("In ", *block)); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirValidate.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirValidate.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/AirValidate.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/AirValidate.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,7 +32,7 @@ class Code; -void validate(Code&, const char* dumpBefore = nullptr); +JS_EXPORT_PRIVATE void validate(Code&, const char* dumpBefore = nullptr); } } } // namespace JSC::B3::Air diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/opcode_generator.rb webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/opcode_generator.rb --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/opcode_generator.rb 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/opcode_generator.rb 2016-11-03 07:04:20.000000000 +0000 @@ -490,7 +490,7 @@ outp.puts "namespace WTF {" outp.puts "class PrintStream;" - outp.puts "void printInternal(PrintStream&, JSC::B3::Air::Opcode);" + outp.puts "JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Air::Opcode);" outp.puts "} // namespace WTF" } @@ -714,7 +714,7 @@ outp.puts "return false; " outp.puts "}" - outp.puts "inline bool isTerminal(Opcode opcode)" + outp.puts "inline bool isDefinitelyTerminal(Opcode opcode)" outp.puts "{" outp.puts "switch (opcode) {" didFindTerminals = false @@ -976,6 +976,32 @@ outp.puts "return false;" outp.puts "}" + outp.puts "bool Inst::isTerminal()" + outp.puts "{" + outp.puts "switch (opcode) {" + foundTrue = false + $opcodes.values.each { + | opcode | + if opcode.attributes[:terminal] + outp.puts "case #{opcode.name}:" + foundTrue = true + end + } + if foundTrue + outp.puts "return true;" + end + $opcodes.values.each { + | opcode | + if opcode.custom + outp.puts "case #{opcode.name}:" + outp.puts "return #{opcode.name}Custom::isTerminal(*this);" + end + } + outp.puts "default:" + outp.puts "return false;" + outp.puts "}" + outp.puts "}" + outp.puts "bool Inst::hasNonArgNonControlEffects()" outp.puts "{" outp.puts "switch (opcode) {" @@ -1020,7 +1046,7 @@ | opcode | if opcode.custom outp.puts "case #{opcode.name}:" - outp.puts "return #{opcode.name}Custom::hasNonArgNonControlEffects(*this);" + outp.puts "return #{opcode.name}Custom::hasNonArgEffects(*this);" end } outp.puts "default:" @@ -1090,3 +1116,109 @@ outp.puts "} } } // namespace JSC::B3::Air" } +# This is a hack for JSAir. It's a joke. +File.open("JSAir_opcode.js", "w") { + | outp | + outp.puts "\"use strict\";" + outp.puts "// Generated by opcode_generator.rb from #{$fileName} -- do not edit!" + + $opcodes.values.each { + | opcode | + outp.puts "const #{opcode.name} = Symbol(#{opcode.name.inspect});" + } + + outp.puts "function Inst_forEachArg(inst, func)" + outp.puts "{" + outp.puts "let replacement;" + outp.puts "switch (inst.opcode) {" + $opcodes.values.each { + | opcode | + outp.puts "case #{opcode.name}:" + if opcode.custom + outp.puts "#{opcode.name}Custom.forEachArg(inst, func);" + else + needOverloadSwitch = opcode.overloads.size != 1 + outp.puts "switch (inst.args.length) {" if needOverloadSwitch + opcode.overloads.each { + | overload | + outp.puts "case #{overload.signature.length}:" if needOverloadSwitch + overload.signature.each_with_index { + | arg, index | + role = nil + case arg.role + when "U" + role = "Use" + when "D" + role = "Def" + when "ZD" + role = "ZDef" + when "UD" + role = "UseDef" + when "UZD" + role = "UseZDef" + when "UA" + role = "UseAddr" + when "S" + role = "Scratch" + else + raise + end + + outp.puts "inst.visitArg(#{index}, func, Arg.#{role}, #{arg.type}P, #{arg.width});" + } + outp.puts "break;" + } + if needOverloadSwitch + outp.puts "default:" + outp.puts "throw new Error(\"Bad overload\");" + outp.puts "break;" + outp.puts "}" + end + end + outp.puts "break;" + } + outp.puts "default:" + outp.puts "throw \"Bad opcode\";" + outp.puts "}" + outp.puts "}" + + outp.puts "function Inst_hasNonArgEffects(inst)" + outp.puts "{" + outp.puts "switch (inst.opcode) {" + foundTrue = false + $opcodes.values.each { + | opcode | + if opcode.attributes[:terminal] or opcode.attributes[:effects] + outp.puts "case #{opcode.name}:" + foundTrue = true + end + } + if foundTrue + outp.puts "return true;" + end + $opcodes.values.each { + | opcode | + if opcode.custom + outp.puts "case #{opcode.name}:" + outp.puts "return #{opcode.name}Custom.hasNonArgNonControlEffects(inst);" + end + } + outp.puts "default:" + outp.puts "return false;" + outp.puts "}" + outp.puts "}" + + outp.puts "function opcodeCode(opcode)" + outp.puts "{" + outp.puts "switch (opcode) {" + $opcodes.keys.sort.each_with_index { + | opcode, index | + outp.puts "case #{opcode}:" + outp.puts "return #{index}" + } + outp.puts "default:" + outp.puts "throw new Error(\"bad opcode\");" + outp.puts "}" + outp.puts "}" +} + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/testair.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/testair.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/air/testair.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/air/testair.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1633,6 +1633,200 @@ CHECK(things[3] == 3); } +#if CPU(X86) || CPU(X86_64) +void testX86VMULSD() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Tmp(FPRInfo::argumentFPR1), Tmp(FPRInfo::argumentFPR2)); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR2), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + CHECK(compileAndRun(proc, 2.4, 4.2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDDestRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Tmp(FPRInfo::argumentFPR1), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + CHECK(compileAndRun(proc, 2.4, 4.2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDOp1DestRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm14)); + root->append(MulDouble, nullptr, Tmp(X86Registers::xmm14), Tmp(FPRInfo::argumentFPR1), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + CHECK(compileAndRun(proc, 2.4, 4.2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDOp2DestRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR1), Tmp(X86Registers::xmm14)); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm14), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + CHECK(compileAndRun(proc, 2.4, 4.2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDOpsDestRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm14)); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR1), Tmp(X86Registers::xmm13)); + root->append(MulDouble, nullptr, Tmp(X86Registers::xmm14), Tmp(X86Registers::xmm13), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + CHECK(compileAndRun(proc, 2.4, 4.2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDAddr() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Arg::addr(Tmp(GPRInfo::argumentGPR0), - 16), Tmp(FPRInfo::argumentFPR2)); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR2), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + CHECK(compileAndRun(proc, 2.4, &secondArg + 2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDAddrOpRexAddr() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(Move, nullptr, Tmp(GPRInfo::argumentGPR0), Tmp(X86Registers::r13)); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Arg::addr(Tmp(X86Registers::r13), - 16), Tmp(FPRInfo::argumentFPR2)); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR2), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + CHECK(compileAndRun(proc, 2.4, &secondArg + 2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDDestRexAddr() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Arg::addr(Tmp(GPRInfo::argumentGPR0), 16), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + CHECK(compileAndRun(proc, 2.4, &secondArg - 2, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDRegOpDestRexAddr() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(MoveDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm14)); + root->append(MulDouble, nullptr, Arg::addr(Tmp(GPRInfo::argumentGPR0)), Tmp(X86Registers::xmm14), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + CHECK(compileAndRun(proc, 2.4, &secondArg, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDAddrOpDestRexAddr() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(Move, nullptr, Tmp(GPRInfo::argumentGPR0), Tmp(X86Registers::r13)); + root->append(MulDouble, nullptr, Tmp(FPRInfo::argumentFPR0), Arg::addr(Tmp(X86Registers::r13), 8), Tmp(X86Registers::xmm15)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm15), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + CHECK(compileAndRun(proc, 2.4, &secondArg - 1, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDBaseNeedsRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(Move, nullptr, Tmp(GPRInfo::argumentGPR0), Tmp(X86Registers::r13)); + root->append(MulDouble, nullptr, Arg::index(Tmp(X86Registers::r13), Tmp(GPRInfo::argumentGPR1)), Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm0)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm0), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + uint64_t index = 8; + CHECK(compileAndRun(proc, 2.4, &secondArg - 1, index, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDIndexNeedsRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(Move, nullptr, Tmp(GPRInfo::argumentGPR1), Tmp(X86Registers::r13)); + root->append(MulDouble, nullptr, Arg::index(Tmp(GPRInfo::argumentGPR0), Tmp(X86Registers::r13)), Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm0)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm0), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + uint64_t index = - 8; + CHECK(compileAndRun(proc, 2.4, &secondArg + 1, index, pureNaN()) == 2.4 * 4.2); +} + +void testX86VMULSDBaseIndexNeedRex() +{ + B3::Procedure proc; + Code& code = proc.code(); + + BasicBlock* root = code.addBlock(); + root->append(Move, nullptr, Tmp(GPRInfo::argumentGPR0), Tmp(X86Registers::r12)); + root->append(Move, nullptr, Tmp(GPRInfo::argumentGPR1), Tmp(X86Registers::r13)); + root->append(MulDouble, nullptr, Arg::index(Tmp(X86Registers::r12), Tmp(X86Registers::r13)), Tmp(FPRInfo::argumentFPR0), Tmp(X86Registers::xmm0)); + root->append(MoveDouble, nullptr, Tmp(X86Registers::xmm0), Tmp(FPRInfo::returnValueFPR)); + root->append(RetDouble, nullptr, Tmp(FPRInfo::returnValueFPR)); + + double secondArg = 4.2; + uint64_t index = 16; + CHECK(compileAndRun(proc, 2.4, &secondArg - 2, index, pureNaN()) == 2.4 * 4.2); +} + +#endif + #define RUN(test) do { \ if (!shouldRun(#test)) \ break; \ @@ -1693,6 +1887,24 @@ RUN(testShuffleSwapDouble()); RUN(testShuffleShiftDouble()); +#if CPU(X86) || CPU(X86_64) + RUN(testX86VMULSD()); + RUN(testX86VMULSDDestRex()); + RUN(testX86VMULSDOp1DestRex()); + RUN(testX86VMULSDOp2DestRex()); + RUN(testX86VMULSDOpsDestRex()); + + RUN(testX86VMULSDAddr()); + RUN(testX86VMULSDAddrOpRexAddr()); + RUN(testX86VMULSDDestRexAddr()); + RUN(testX86VMULSDRegOpDestRexAddr()); + RUN(testX86VMULSDAddrOpDestRexAddr()); + + RUN(testX86VMULSDBaseNeedsRex()); + RUN(testX86VMULSDIndexNeedsRex()); + RUN(testX86VMULSDBaseIndexNeedRex()); +#endif + if (tasks.isEmpty()) usage(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlock.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlock.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlock.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlock.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -30,7 +30,6 @@ #include "B3BasicBlockInlines.h" #include "B3BasicBlockUtils.h" -#include "B3ControlValue.h" #include "B3Procedure.h" #include "B3ValueInlines.h" #include @@ -52,12 +51,14 @@ void BasicBlock::append(Value* value) { m_values.append(value); + value->owner = this; } void BasicBlock::appendNonTerminal(Value* value) { m_values.append(m_values.last()); m_values[m_values.size() - 1] = value; + value->owner = this; } void BasicBlock::removeLast(Procedure& proc) @@ -84,9 +85,46 @@ return appendIntConstant(proc, likeValue->origin(), likeValue->type(), value); } +Value* BasicBlock::appendBoolConstant(Procedure& proc, Origin origin, bool value) +{ + return appendIntConstant(proc, origin, Int32, value ? 1 : 0); +} + +void BasicBlock::clearSuccessors() +{ + m_successors.clear(); +} + +void BasicBlock::appendSuccessor(FrequentedBlock target) +{ + m_successors.append(target); +} + +void BasicBlock::setSuccessors(FrequentedBlock target) +{ + m_successors.resize(1); + m_successors[0] = target; +} + +void BasicBlock::setSuccessors(FrequentedBlock taken, FrequentedBlock notTaken) +{ + m_successors.resize(2); + m_successors[0] = taken; + m_successors[1] = notTaken; +} + bool BasicBlock::replaceSuccessor(BasicBlock* from, BasicBlock* to) { - return last()->as()->replaceSuccessor(from, to); + bool result = false; + for (BasicBlock*& successor : successorBlocks()) { + if (successor == from) { + successor = to; + result = true; + + // Keep looping because a successor may be mentioned multiple times, like in a Switch. + } + } + return result; } bool BasicBlock::addPredecessor(BasicBlock* block) @@ -121,6 +159,42 @@ out.print(" Predecessors: ", pointerListDump(predecessors()), "\n"); for (Value* value : *this) out.print(" ", B3::deepDump(proc, value), "\n"); + if (!successors().isEmpty()) { + out.print(" Successors: "); + if (size()) + last()->dumpSuccessors(this, out); + else + out.print(listDump(successors())); + out.print("\n"); + } +} + +Value* BasicBlock::appendNewControlValue(Procedure& proc, Opcode opcode, Origin origin) +{ + RELEASE_ASSERT(opcode == Oops || opcode == Return); + clearSuccessors(); + return appendNew(proc, opcode, origin); +} + +Value* BasicBlock::appendNewControlValue(Procedure& proc, Opcode opcode, Origin origin, Value* value) +{ + RELEASE_ASSERT(opcode == Return); + clearSuccessors(); + return appendNew(proc, opcode, origin, value); +} + +Value* BasicBlock::appendNewControlValue(Procedure& proc, Opcode opcode, Origin origin, const FrequentedBlock& target) +{ + RELEASE_ASSERT(opcode == Jump); + setSuccessors(target); + return appendNew(proc, opcode, origin); +} + +Value* BasicBlock::appendNewControlValue(Procedure& proc, Opcode opcode, Origin origin, Value* predicate, const FrequentedBlock& taken, const FrequentedBlock& notTaken) +{ + RELEASE_ASSERT(opcode == Branch); + setSuccessors(taken, notTaken); + return appendNew(proc, opcode, origin, predicate); } } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlock.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,6 +29,7 @@ #if ENABLE(B3_JIT) #include "B3FrequentedBlock.h" +#include "B3Opcode.h" #include "B3Origin.h" #include "B3SuccessorCollection.h" #include "B3Type.h" @@ -47,7 +48,7 @@ public: typedef Vector ValueList; typedef Vector PredecessorList; - typedef Vector SuccessorList; // This matches ControlValue::SuccessorList + typedef Vector SuccessorList; static const char* const dumpPrefix; @@ -81,24 +82,46 @@ JS_EXPORT_PRIVATE Value* appendIntConstant(Procedure&, Origin, Type, int64_t value); Value* appendIntConstant(Procedure&, Value* likeValue, int64_t value); + Value* appendBoolConstant(Procedure&, Origin, bool); void removeLast(Procedure&); template ValueType* replaceLastWithNew(Procedure&, Arguments...); - unsigned numSuccessors() const; - const FrequentedBlock& successor(unsigned index) const; - FrequentedBlock& successor(unsigned index); - const SuccessorList& successors() const; - SuccessorList& successors(); - - BasicBlock* successorBlock(unsigned index) const; - BasicBlock*& successorBlock(unsigned index); - SuccessorCollection successorBlocks(); - SuccessorCollection successorBlocks() const; + unsigned numSuccessors() const { return m_successors.size(); } + const FrequentedBlock& successor(unsigned index) const { return m_successors[index]; } + FrequentedBlock& successor(unsigned index) { return m_successors[index]; } + const SuccessorList& successors() const { return m_successors; } + SuccessorList& successors() { return m_successors; } + + void clearSuccessors(); + JS_EXPORT_PRIVATE void appendSuccessor(FrequentedBlock); + JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock); + JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock, FrequentedBlock); + + BasicBlock* successorBlock(unsigned index) const { return successor(index).block(); } + BasicBlock*& successorBlock(unsigned index) { return successor(index).block(); } + SuccessorCollection successorBlocks() + { + return SuccessorCollection(successors()); + } + SuccessorCollection successorBlocks() const + { + return SuccessorCollection(successors()); + } bool replaceSuccessor(BasicBlock* from, BasicBlock* to); + + // This is only valid for Jump and Branch. + const FrequentedBlock& taken() const; + FrequentedBlock& taken(); + // This is only valid for Branch. + const FrequentedBlock& notTaken() const; + FrequentedBlock& notTaken(); + // This is only valid for Branch and Switch. + const FrequentedBlock& fallThrough() const; + FrequentedBlock& fallThrough(); unsigned numPredecessors() const { return m_predecessors.size(); } BasicBlock* predecessor(unsigned index) const { return m_predecessors[index]; } @@ -119,6 +142,19 @@ void dump(PrintStream&) const; void deepDump(const Procedure&, PrintStream&) const; + // These are deprecated method for compatibility with the old ControlValue class. Don't use them + // in new code. + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=159440 + + // Use this for Oops. + JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin); + // Use this for Return. + JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*); + // Use this for Jump. + JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, const FrequentedBlock&); + // Use this for Branch. + JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*, const FrequentedBlock&, const FrequentedBlock&); + private: friend class BlockInsertionSet; friend class InsertionSet; @@ -130,6 +166,7 @@ unsigned m_index; ValueList m_values; PredecessorList m_predecessors; + SuccessorList m_successors; double m_frequency; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlockInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlockInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlockInlines.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlockInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,8 +29,8 @@ #if ENABLE(B3_JIT) #include "B3BasicBlock.h" -#include "B3ControlValue.h" #include "B3ProcedureInlines.h" +#include "B3Value.h" namespace JSC { namespace B3 { @@ -58,49 +58,40 @@ return result; } -inline unsigned BasicBlock::numSuccessors() const +inline const FrequentedBlock& BasicBlock::taken() const { - return last()->as()->numSuccessors(); + ASSERT(last()->opcode() == Jump || last()->opcode() == Branch); + return m_successors[0]; } -inline const FrequentedBlock& BasicBlock::successor(unsigned index) const +inline FrequentedBlock& BasicBlock::taken() { - return last()->as()->successor(index); + ASSERT(last()->opcode() == Jump || last()->opcode() == Branch); + return m_successors[0]; } -inline FrequentedBlock& BasicBlock::successor(unsigned index) +inline const FrequentedBlock& BasicBlock::notTaken() const { - return last()->as()->successor(index); + ASSERT(last()->opcode() == Branch); + return m_successors[1]; } -inline const BasicBlock::SuccessorList& BasicBlock::successors() const +inline FrequentedBlock& BasicBlock::notTaken() { - return last()->as()->successors(); + ASSERT(last()->opcode() == Branch); + return m_successors[1]; } -inline BasicBlock::SuccessorList& BasicBlock::successors() +inline const FrequentedBlock& BasicBlock::fallThrough() const { - return last()->as()->successors(); + ASSERT(last()->opcode() == Branch || last()->opcode() == Switch); + return m_successors.last(); } -inline BasicBlock* BasicBlock::successorBlock(unsigned index) const +inline FrequentedBlock& BasicBlock::fallThrough() { - return successor(index).block(); -} - -inline BasicBlock*& BasicBlock::successorBlock(unsigned index) -{ - return successor(index).block(); -} - -inline SuccessorCollection BasicBlock::successorBlocks() -{ - return SuccessorCollection(successors()); -} - -inline SuccessorCollection BasicBlock::successorBlocks() const -{ - return SuccessorCollection(successors()); + ASSERT(last()->opcode() == Branch || last()->opcode() == Switch); + return m_successors.last(); } } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlockUtils.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlockUtils.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BasicBlockUtils.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BasicBlockUtils.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,8 +28,8 @@ #if ENABLE(B3_JIT) -#include "B3IndexSet.h" #include +#include #include namespace JSC { namespace B3 { @@ -85,27 +85,30 @@ } } -// This recomputes predecessors and removes blocks that aren't reachable. -template -void resetReachability( - Vector>& blocks, const DeleteFunctor& deleteFunctor) +template +void clearPredecessors(Vector>& blocks) { - // Clear all predecessor lists first. for (auto& block : blocks) { if (block) block->predecessors().resize(0); } +} +template +void recomputePredecessors(Vector>& blocks) +{ + clearPredecessors(blocks); updatePredecessorsAfter(blocks[0].get()); +} - for (unsigned i = 1; i < blocks.size(); ++i) { - if (!blocks[i]) - continue; - if (blocks[i]->predecessors().isEmpty()) { - deleteFunctor(blocks[i].get()); - blocks[i] = nullptr; - } - } +template +bool isBlockDead(BasicBlock* block) +{ + if (!block) + return false; + if (!block->index()) + return false; + return block->predecessors().isEmpty(); } template diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BlockInsertionSet.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BlockInsertionSet.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BlockInsertionSet.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BlockInsertionSet.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -78,8 +78,8 @@ result->m_values[i] = block->m_values[i]; // Make the new block jump to 'block'. - result->m_values[valueIndex] = - m_proc.add(Jump, value->origin(), FrequentedBlock(block)); + result->m_values[valueIndex] = m_proc.add(Jump, value->origin()); + result->setSuccessors(FrequentedBlock(block)); // If we had inserted things into 'block' before this, execute those insertions now. if (insertionSet) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BlockWorklist.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BlockWorklist.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BlockWorklist.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BlockWorklist.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,13 +28,14 @@ #if ENABLE(B3_JIT) -#include "B3BasicBlock.h" -#include "B3IndexSet.h" #include +#include #include namespace JSC { namespace B3 { +class BasicBlock; + typedef GraphNodeWorklist> BlockWorklist; // When you say BlockWith you should read it as "block with an int". diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BottomProvider.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BottomProvider.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BottomProvider.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BottomProvider.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef B3BottomProvider_h +#define B3BottomProvider_h + +#if ENABLE(B3_JIT) + +#include "B3InsertionSet.h" + +namespace JSC { namespace B3 { + +// This exists because we cannot convert values to constants in-place. +// FIXME: https://bugs.webkit.org/show_bug.cgi?id=159119 + +class BottomProvider { +public: + BottomProvider(InsertionSet& insertionSet, size_t index) + : m_insertionSet(&insertionSet) + , m_index(index) + { + } + + Value* operator()(Origin origin, Type type) const + { + return m_insertionSet->insertBottom(m_index, origin, type); + } + +private: + InsertionSet* m_insertionSet; + size_t m_index; +}; + +} } // namespace JSC::B3 + +#endif // ENABLE(B3_JIT) + +#endif // B3BottomProvider_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BreakCriticalEdges.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BreakCriticalEdges.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3BreakCriticalEdges.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3BreakCriticalEdges.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -30,7 +30,6 @@ #include "B3BasicBlockInlines.h" #include "B3BlockInsertionSet.h" -#include "B3ControlValue.h" #include "B3ProcedureInlines.h" #include "B3ValueInlines.h" @@ -50,8 +49,8 @@ BasicBlock* pad = insertionSet.insertBefore(successor, successor->frequency()); - pad->appendNew( - proc, Jump, successor->at(0)->origin(), FrequentedBlock(successor)); + pad->appendNew(proc, Jump, successor->at(0)->origin()); + pad->setSuccessors(FrequentedBlock(successor)); pad->addPredecessor(block); successor->replacePredecessor(block, pad); successor = pad; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CaseCollection.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CaseCollection.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CaseCollection.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CaseCollection.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "B3CaseCollection.h" + +#if ENABLE(B3_JIT) + +#include "B3BasicBlockInlines.h" +#include "B3CaseCollectionInlines.h" +#include + +namespace JSC { namespace B3 { + +void CaseCollection::dump(PrintStream& out) const +{ + CommaPrinter comma; + for (SwitchCase switchCase : *this) + out.print(comma, switchCase); + out.print(comma, "default->", fallThrough()); +} + +} } // namespace JSC::B3 + +#endif // ENABLE(B3_JIT) + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CaseCollection.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CaseCollection.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CaseCollection.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CaseCollection.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef B3CaseCollection_h +#define B3CaseCollection_h + +#if ENABLE(B3_JIT) + +#include "B3SwitchCase.h" + +namespace JSC { namespace B3 { + +class BasicBlock; +class SwitchValue; + +// NOTE: You'll always want to include B3CaseCollectionInlines.h when you use this. + +class CaseCollection { +public: + CaseCollection() + { + } + + CaseCollection(const SwitchValue* terminal, const BasicBlock* owner) + : m_switch(terminal) + , m_owner(owner) + { + } + + const FrequentedBlock& fallThrough() const; + + unsigned size() const; + SwitchCase at(unsigned index) const; + + SwitchCase operator[](unsigned index) const + { + return at(index); + } + + class iterator { + public: + iterator() + : m_collection(nullptr) + , m_index(0) + { + } + + iterator(const CaseCollection& collection, unsigned index) + : m_collection(&collection) + , m_index(index) + { + } + + SwitchCase operator*() + { + return m_collection->at(m_index); + } + + iterator& operator++() + { + m_index++; + return *this; + } + + bool operator==(const iterator& other) const + { + ASSERT(m_collection == other.m_collection); + return m_index == other.m_index; + } + + bool operator!=(const iterator& other) const + { + return !(*this == other); + } + + private: + const CaseCollection* m_collection; + unsigned m_index; + }; + + typedef iterator const_iterator; + + iterator begin() const { return iterator(*this, 0); } + iterator end() const { return iterator(*this, size()); } + + void dump(PrintStream&) const; + +private: + const SwitchValue* m_switch { nullptr }; + const BasicBlock* m_owner { nullptr }; +}; + +} } // namespace JSC::B3 + +#endif // ENABLE(B3_JIT) + +#endif // B3CaseCollection_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CaseCollectionInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CaseCollectionInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CaseCollectionInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CaseCollectionInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef B3CaseCollectionInlines_h +#define B3CaseCollectionInlines_h + +#if ENABLE(B3_JIT) + +#include "B3CaseCollection.h" +#include "B3SwitchValue.h" +#include "B3BasicBlock.h" + +namespace JSC { namespace B3 { + +inline const FrequentedBlock& CaseCollection::fallThrough() const +{ + return m_owner->fallThrough(); +} + +inline unsigned CaseCollection::size() const +{ + return m_switch->numCaseValues(); +} + +inline SwitchCase CaseCollection::at(unsigned index) const +{ + return SwitchCase(m_switch->caseValue(index), m_owner->successor(index)); +} + +} } // namespace JSC::B3 + +#endif // ENABLE(B3_JIT) + +#endif // B3CaseCollectionInlines_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CCallValue.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CCallValue.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CCallValue.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CCallValue.h 2016-11-03 07:04:20.000000000 +0000 @@ -39,7 +39,7 @@ ~CCallValue(); - Effects effects { Effects::forCall() }; + Effects effects; protected: Value* cloneImpl() const override; @@ -50,6 +50,7 @@ template CCallValue(Type type, Origin origin, Arguments... arguments) : Value(CheckedOpcode, CCall, type, origin, arguments...) + , effects(Effects::forCall()) { RELEASE_ASSERT(numChildren() >= 1); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CFG.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CFG.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CFG.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CFG.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,9 +29,9 @@ #if ENABLE(B3_JIT) #include "B3BasicBlock.h" -#include "B3IndexMap.h" -#include "B3IndexSet.h" #include "B3Procedure.h" +#include +#include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CheckSpecial.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CheckSpecial.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3CheckSpecial.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3CheckSpecial.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -84,7 +84,7 @@ , m_stackmapRole(stackmapRole) , m_numCheckArgs(numArgs) { - ASSERT(isTerminal(opcode)); + ASSERT(isDefinitelyTerminal(opcode)); } CheckSpecial::CheckSpecial(const CheckSpecial::Key& key) @@ -102,6 +102,7 @@ hiddenBranch.args.reserveInitialCapacity(m_numCheckArgs); for (unsigned i = 0; i < m_numCheckArgs; ++i) hiddenBranch.args.append(inst.args[i + 1]); + ASSERT(hiddenBranch.isTerminal()); return hiddenBranch; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Common.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Common.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Common.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Common.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -36,7 +36,11 @@ bool shouldDumpIR(B3ComplitationMode mode) { +#if ENABLE(FTL_JIT) return FTL::verboseCompilationEnabled() || FTL::shouldDumpDisassembly() || shouldDumpIRAtEachPhase(mode); +#else + return shouldDumpIRAtEachPhase(mode); +#endif } bool shouldDumpIRAtEachPhase(B3ComplitationMode mode) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Common.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Common.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Common.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Common.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,8 @@ #if ENABLE(B3_JIT) +#include "JSExportMacros.h" + namespace JSC { namespace B3 { inline bool is64Bit() { return sizeof(void*) == 8; } @@ -38,7 +40,7 @@ AirMode }; -bool shouldDumpIR(B3ComplitationMode); +JS_EXPORT_PRIVATE bool shouldDumpIR(B3ComplitationMode); bool shouldDumpIRAtEachPhase(B3ComplitationMode); bool shouldValidateIR(); bool shouldValidateIRAtEachPhase(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const32Value.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const32Value.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const32Value.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const32Value.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -166,6 +166,16 @@ return proc.add(origin(), bitwise_cast(m_value)); } +Value* Const32Value::iToDConstant(Procedure& proc) const +{ + return proc.add(origin(), static_cast(m_value)); +} + +Value* Const32Value::iToFConstant(Procedure& proc) const +{ + return proc.add(origin(), static_cast(m_value)); +} + TriState Const32Value::equalConstant(const Value* other) const { if (!other->hasInt32()) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const32Value.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const32Value.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const32Value.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const32Value.h 2016-11-03 07:04:20.000000000 +0000 @@ -58,6 +58,8 @@ Value* sShrConstant(Procedure&, const Value* other) const override; Value* zShrConstant(Procedure&, const Value* other) const override; Value* bitwiseCastConstant(Procedure&) const override; + Value* iToDConstant(Procedure&) const override; + Value* iToFConstant(Procedure&) const override; TriState equalConstant(const Value* other) const override; TriState notEqualConstant(const Value* other) const override; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const64Value.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const64Value.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const64Value.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const64Value.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -166,6 +166,16 @@ return proc.add(origin(), bitwise_cast(m_value)); } +Value* Const64Value::iToDConstant(Procedure& proc) const +{ + return proc.add(origin(), static_cast(m_value)); +} + +Value* Const64Value::iToFConstant(Procedure& proc) const +{ + return proc.add(origin(), static_cast(m_value)); +} + TriState Const64Value::equalConstant(const Value* other) const { if (!other->hasInt64()) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const64Value.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const64Value.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Const64Value.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Const64Value.h 2016-11-03 07:04:20.000000000 +0000 @@ -58,6 +58,8 @@ Value* sShrConstant(Procedure&, const Value* other) const override; Value* zShrConstant(Procedure&, const Value* other) const override; Value* bitwiseCastConstant(Procedure&) const override; + Value* iToDConstant(Procedure&) const override; + Value* iToFConstant(Procedure&) const override; TriState equalConstant(const Value* other) const override; TriState notEqualConstant(const Value* other) const override; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ControlValue.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ControlValue.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ControlValue.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ControlValue.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2015-2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "B3ControlValue.h" - -#if ENABLE(B3_JIT) - -#include "B3BasicBlock.h" - -namespace JSC { namespace B3 { - -ControlValue::~ControlValue() -{ -} - -bool ControlValue::replaceSuccessor(BasicBlock* from, BasicBlock* to) -{ - bool result = false; - for (FrequentedBlock& successor : m_successors) { - if (successor.block() == from) { - successor.block() = to; - result = true; - - // Keep looping because it's valid for a successor to be mentioned multiple times, - // like if multiple switch cases have the same target. - } - } - return result; -} - -void ControlValue::convertToJump(BasicBlock* destination) -{ - unsigned index = this->index(); - Origin origin = this->origin(); - BasicBlock* owner = this->owner; - - this->~ControlValue(); - - new (this) ControlValue(Jump, origin, FrequentedBlock(destination)); - - this->owner = owner; - this->m_index = index; -} - -void ControlValue::convertToOops() -{ - unsigned index = this->index(); - Origin origin = this->origin(); - BasicBlock* owner = this->owner; - - this->~ControlValue(); - - new (this) ControlValue(Oops, origin); - - this->owner = owner; - this->m_index = index; -} - -void ControlValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const -{ - for (FrequentedBlock successor : m_successors) - out.print(comma, successor); -} - -Value* ControlValue::cloneImpl() const -{ - return new ControlValue(*this); -} - -} } // namespace JSC::B3 - -#endif // ENABLE(B3_JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ControlValue.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ControlValue.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ControlValue.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ControlValue.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2015-2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef B3ControlValue_h -#define B3ControlValue_h - -#if ENABLE(B3_JIT) - -#include "B3FrequentedBlock.h" -#include "B3SuccessorCollection.h" -#include "B3Value.h" - -namespace JSC { namespace B3 { - -class BasicBlock; - -class JS_EXPORT_PRIVATE ControlValue : public Value { -public: - static bool accepts(Opcode opcode) - { - switch (opcode) { - case Jump: - case Branch: - case Return: - case Oops: - return true; - case Switch: - // This is here because SwitchValue is a subclass of ControlValue, so we want - // switchValue->as() to return non-null. - return true; - default: - return false; - } - } - - typedef Vector SuccessorList; - - ~ControlValue(); - - unsigned numSuccessors() const { return m_successors.size(); } - const FrequentedBlock& successor(unsigned index) const { return m_successors[index]; } - FrequentedBlock& successor(unsigned index) { return m_successors[index]; } - const SuccessorList& successors() const { return m_successors; } - SuccessorList& successors() { return m_successors; } - - BasicBlock* successorBlock(unsigned index) const { return successor(index).block(); } - BasicBlock*& successorBlock(unsigned index) { return successor(index).block(); } - SuccessorCollection successorBlocks() - { - return SuccessorCollection(successors()); - } - SuccessorCollection successorBlocks() const - { - return SuccessorCollection(successors()); - } - - bool replaceSuccessor(BasicBlock* from, BasicBlock* to); - - const FrequentedBlock& taken() const - { - ASSERT(opcode() == Jump || opcode() == Branch); - return successor(0); - } - FrequentedBlock& taken() - { - ASSERT(opcode() == Jump || opcode() == Branch); - return successor(0); - } - const FrequentedBlock& notTaken() const - { - ASSERT(opcode() == Branch); - return successor(1); - } - FrequentedBlock& notTaken() - { - ASSERT(opcode() == Branch); - return successor(1); - } - - void convertToJump(BasicBlock* destination); - void convertToOops(); - -protected: - void dumpMeta(CommaPrinter&, PrintStream&) const override; - - Value* cloneImpl() const override; - - // Use this for subclasses. - template - ControlValue(Opcode opcode, Type type, Origin origin, Arguments... arguments) - : Value(CheckedOpcode, opcode, type, origin, arguments...) - { - ASSERT(accepts(opcode)); - } - - // Subclasses will populate this. - SuccessorList m_successors; - -private: - friend class Procedure; - - // Use this for Oops. - ControlValue(Opcode opcode, Origin origin) - : Value(CheckedOpcode, opcode, Void, origin) - { - ASSERT(opcode == Oops); - } - - // Use this for Return. - ControlValue(Opcode opcode, Origin origin, Value* result) - : Value(CheckedOpcode, opcode, Void, origin, result) - { - ASSERT(opcode == Return); - } - - // Use this for Jump. - ControlValue(Opcode opcode, Origin origin, const FrequentedBlock& target) - : Value(CheckedOpcode, opcode, Void, origin) - { - ASSERT(opcode == Jump); - m_successors.append(target); - } - - // Use this for Branch. - ControlValue( - Opcode opcode, Origin origin, Value* predicate, - const FrequentedBlock& yes, const FrequentedBlock& no) - : Value(CheckedOpcode, opcode, Void, origin, predicate) - { - ASSERT(opcode == Branch); - m_successors.append(yes); - m_successors.append(no); - } -}; - -} } // namespace JSC::B3 - -#endif // ENABLE(B3_JIT) - -#endif // B3ControlValue_h - diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3DataSection.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3DataSection.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3DataSection.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3DataSection.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,7 +31,7 @@ namespace JSC { namespace B3 { DataSection::DataSection(size_t size) - : m_data(fastMalloc(size)) + : m_data(fastZeroedMalloc(size)) , m_size(size) { } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3DuplicateTails.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3DuplicateTails.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3DuplicateTails.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3DuplicateTails.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -30,16 +30,15 @@ #include "B3BasicBlockInlines.h" #include "B3BreakCriticalEdges.h" -#include "B3ControlValue.h" #include "B3Dominators.h" #include "B3FixSSA.h" -#include "B3IndexSet.h" #include "B3InsertionSetInlines.h" #include "B3PhaseScope.h" #include "B3ProcedureInlines.h" #include "B3SwitchValue.h" #include "B3UpsilonValue.h" #include "B3ValueInlines.h" +#include namespace JSC { namespace B3 { @@ -72,7 +71,11 @@ IndexSet candidates; for (BasicBlock* block : m_proc) { - if (block->size() > m_maxSize || block->numSuccessors() > m_maxSuccessors) + if (block->size() > m_maxSize) + continue; + if (block->numSuccessors() > m_maxSuccessors) + continue; + if (block->last()->type() != Void) // Demoting doesn't handle terminals with values. continue; candidates.add(block); @@ -97,11 +100,10 @@ } for (BasicBlock* block : m_proc) { - ControlValue* jump = block->last()->as(); - if (jump->opcode() != Jump) + if (block->last()->opcode() != Jump) continue; - BasicBlock* tail = jump->successorBlock(0); + BasicBlock* tail = block->successorBlock(0); if (!candidates.contains(tail)) continue; @@ -130,6 +132,7 @@ map.add(value, clone); block->append(clone); } + block->successors() = tail->successors(); } m_proc.resetReachability(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Effects.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Effects.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Effects.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Effects.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,7 +45,11 @@ // terminates abruptly. bool exitsSideways { false }; - // True if the instruction may change semantics if hoisted above some control flow. + // True if the instruction may change semantics if hoisted above some control flow. For example, + // loads are usually control-dependent because we must assume that any control construct (either + // a terminal like Branch or anything that exits sideways, like Check) validates whether the + // pointer is valid. Hoisting the load above control may cause the load to trap even though it + // would not have otherwise trapped. bool controlDependent { false }; // True if this writes to the local state. Operations that write local state don't write to anything diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FixSSA.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FixSSA.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FixSSA.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FixSSA.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -30,9 +30,7 @@ #include "B3BasicBlockInlines.h" #include "B3BreakCriticalEdges.h" -#include "B3ControlValue.h" #include "B3Dominators.h" -#include "B3IndexSet.h" #include "B3InsertionSetInlines.h" #include "B3PhaseScope.h" #include "B3ProcedureInlines.h" @@ -42,6 +40,7 @@ #include "B3Variable.h" #include "B3VariableValue.h" #include +#include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FixSSA.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FixSSA.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FixSSA.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FixSSA.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,8 +28,8 @@ #if ENABLE(B3_JIT) -#include "B3IndexSet.h" #include "B3Value.h" +#include #include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FoldPathConstants.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FoldPathConstants.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FoldPathConstants.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FoldPathConstants.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -29,7 +29,7 @@ #if ENABLE(B3_JIT) #include "B3BasicBlockInlines.h" -#include "B3ControlValue.h" +#include "B3CaseCollectionInlines.h" #include "B3Dominators.h" #include "B3InsertionSetInlines.h" #include "B3PhaseScope.h" @@ -87,24 +87,24 @@ }; for (BasicBlock* block : m_proc) { - ControlValue* branch = block->last()->as(); + Value* branch = block->last(); switch (branch->opcode()) { case Branch: - if (branch->successorBlock(0) == branch->successorBlock(1)) + if (block->successorBlock(0) == block->successorBlock(1)) continue; addOverride( block, branch->child(0), - Override::nonZero(branch->successorBlock(0))); + Override::nonZero(block->successorBlock(0))); addOverride( block, branch->child(0), - Override::constant(branch->successorBlock(1), 0)); + Override::constant(block->successorBlock(1), 0)); break; case Switch: { HashMap targetUses; - for (const SwitchCase& switchCase : *branch->as()) + for (const SwitchCase& switchCase : branch->as()->cases(block)) targetUses.add(switchCase.targetBlock(), 0).iterator->value++; - for (const SwitchCase& switchCase : *branch->as()) { + for (const SwitchCase& switchCase : branch->as()->cases(block)) { if (targetUses.find(switchCase.targetBlock())->value != 1) continue; @@ -158,9 +158,8 @@ switch (value->opcode()) { case Branch: { - ControlValue* branch = value->as(); - if (getOverride(block, branch->child(0)).isNonZero) { - branch->convertToJump(branch->taken().block()); + if (getOverride(block, value->child(0)).isNonZero) { + value->replaceWithJump(block, block->taken()); changed = true; } break; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FrequencyClass.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FrequencyClass.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3FrequencyClass.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3FrequencyClass.h 2016-11-03 07:04:20.000000000 +0000 @@ -43,6 +43,13 @@ Rare }; +inline FrequencyClass maxFrequency(FrequencyClass a, FrequencyClass b) +{ + if (a == FrequencyClass::Normal) + return FrequencyClass::Normal; + return b; +} + } } // namespace JSC::B3 namespace WTF { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Generate.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Generate.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Generate.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Generate.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -36,6 +36,7 @@ #include "B3EliminateCommonSubexpressions.h" #include "B3FixSSA.h" #include "B3FoldPathConstants.h" +#include "B3InferSwitches.h" #include "B3LegalizeMemoryOffsets.h" #include "B3LowerMacros.h" #include "B3LowerMacrosAfterOptimizations.h" @@ -82,6 +83,7 @@ reduceDoubleToFloat(procedure); reduceStrength(procedure); eliminateCommonSubexpressions(procedure); + inferSwitches(procedure); duplicateTails(procedure); fixSSA(procedure); foldPathConstants(procedure); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Generate.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Generate.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Generate.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Generate.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,12 +39,12 @@ // This takes a B3::Procedure, optimizes it in-place, lowers it to Air, and prepares the Air for // generation. -void prepareForGeneration(Procedure&, unsigned optLevel = 1); +JS_EXPORT_PRIVATE void prepareForGeneration(Procedure&, unsigned optLevel = 1); // This takes a B3::Procedure that has been prepared for generation (i.e. it has been lowered to Air and // the Air has been prepared for generation) and generates it. This is the equivalent of calling // Air::generate() on the Procedure::code(). -void generate(Procedure&, CCallHelpers&); +JS_EXPORT_PRIVATE void generate(Procedure&, CCallHelpers&); // This takes a B3::Procedure, optimizes it in-place, and lowers it to Air. You can then generate // the Air to machine code using Air::prepareForGeneration() and Air::generate() on the Procedure's diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3GenericFrequentedBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3GenericFrequentedBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3GenericFrequentedBlock.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3GenericFrequentedBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -39,7 +39,7 @@ template class GenericFrequentedBlock { public: - explicit GenericFrequentedBlock( + GenericFrequentedBlock( BasicBlock* block = nullptr, FrequencyClass frequency = FrequencyClass::Normal) : m_block(block) , m_frequency(frequency) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3IndexMap.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3IndexMap.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3IndexMap.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3IndexMap.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef B3IndexMap_h -#define B3IndexMap_h - -#if ENABLE(B3_JIT) - -#include - -namespace JSC { namespace B3 { - -// This is a map for keys that have an index(). It's super efficient for BasicBlocks. It's only -// efficient for Values if you don't create too many of these maps, since Values can have very -// sparse indices and there are a lot of Values. - -template -class IndexMap { -public: - explicit IndexMap(size_t size = 0) - { - m_vector.fill(Value(), size); - } - - void resize(size_t size) - { - m_vector.fill(Value(), size); - } - - void clear() - { - m_vector.fill(Value(), m_vector.size()); - } - - size_t size() const { return m_vector.size(); } - - Value& operator[](size_t index) - { - return m_vector[index]; - } - - const Value& operator[](size_t index) const - { - return m_vector[index]; - } - - Value& operator[](Key* key) - { - return m_vector[key->index()]; - } - - const Value& operator[](Key* key) const - { - return m_vector[key->index()]; - } - -private: - Vector m_vector; -}; - -} } // namespace JSC::B3 - -#endif // ENABLE(B3_JIT) - -#endif // B3IndexMap_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3IndexSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3IndexSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3IndexSet.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3IndexSet.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2015-2016 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef B3IndexSet_h -#define B3IndexSet_h - -#include -#include - -namespace JSC { namespace B3 { - -// This is a set for things that have an index(). It's super efficient for BasicBlocks. It's only -// efficient for Values if you don't create too many of these sets, since Values can have very sparse -// indices and there are a lot of Values. - -// If you want a set of BasicBlocks, you do IndexSet. So, T = BasicBlock. -template -class IndexSet { -public: - IndexSet() - { - } - - bool add(T* value) - { - return !m_set.set(value->index()); - } - - template - bool addAll(const Iterable& iterable) - { - bool result = false; - for (T* value : iterable) - result |= add(value); - return result; - } - - bool remove(T* value) - { - return m_set.clear(value->index()); - } - - bool contains(T* value) const - { - if (!value) - return false; - return m_set.get(value->index()); - } - - size_t size() const - { - return m_set.bitCount(); - } - - bool isEmpty() const - { - return !size(); - } - - template - class Iterable { - public: - Iterable(const CollectionType& collection, const BitVector& set) - : m_collection(collection) - , m_set(set) - { - } - - class iterator { - public: - iterator() - : m_collection(nullptr) - { - } - - iterator(const CollectionType& collection, BitVector::iterator iter) - : m_collection(&collection) - , m_iter(iter) - { - } - - T* operator*() - { - return m_collection->at(*m_iter); - } - - iterator& operator++() - { - ++m_iter; - return *this; - } - - bool operator==(const iterator& other) const - { - return m_iter == other.m_iter; - } - - bool operator!=(const iterator& other) const - { - return !(*this == other); - } - - private: - const CollectionType* m_collection; - BitVector::iterator m_iter; - }; - - iterator begin() const { return iterator(m_collection, m_set.begin()); } - iterator end() const { return iterator(m_collection, m_set.end()); } - - private: - const CollectionType& m_collection; - const BitVector& m_set; - }; - - // For basic blocks, you do: - // indexSet.values(procedure); - // - // For values, you do: - // indexSet.values(procedure.values()); - template - Iterable values(const CollectionType& collection) const - { - return Iterable(collection, indices()); - } - - const BitVector& indices() const { return m_set; } - - void dump(PrintStream& out) const - { - CommaPrinter comma; - for (size_t index : indices()) - out.print(comma, T::dumpPrefix, index); - } - -private: - BitVector m_set; -}; - -} } // namespace JSC::B3 - -#endif // B3IndexSet_h - diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InferSwitches.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InferSwitches.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InferSwitches.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InferSwitches.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "B3InferSwitches.h" + +#if ENABLE(B3_JIT) + +#include "B3BasicBlockInlines.h" +#include "B3CaseCollectionInlines.h" +#include "B3InsertionSetInlines.h" +#include "B3PhaseScope.h" +#include "B3ProcedureInlines.h" +#include "B3SwitchValue.h" +#include "B3UseCounts.h" +#include "B3ValueInlines.h" +#include + +namespace JSC { namespace B3 { + +namespace { + +const bool verbose = false; + +class InferSwitches { +public: + InferSwitches(Procedure& proc) + : m_proc(proc) + , m_insertionSet(proc) + , m_useCounts(proc) + { + } + + bool run() + { + if (verbose) + dataLog("B3 before inferSwitches:\n", m_proc); + + bool changed = true; + bool everChanged = false; + while (changed) { + changed = false; + + if (verbose) + dataLog("Performing fixpoint iteration:\n"); + + for (BasicBlock* block : m_proc) + changed |= attemptToMergeWithPredecessor(block); + + everChanged |= changed; + } + + if (everChanged) { + m_proc.resetReachability(); + m_proc.invalidateCFG(); + + m_proc.deleteOrphans(); + + if (verbose) + dataLog("B3 after inferSwitches:\n", m_proc); + return true; + } + + return false; + } + +private: + bool attemptToMergeWithPredecessor(BasicBlock* block) + { + // No point in considering the root block. We also don't consider blocks with multiple + // predecessors, but we could handle this if we made this code a bit more general and we were + // not afraid of code bloat. + if (block->numPredecessors() != 1) + return false; + + SwitchDescription description = describe(block); + if (verbose) + dataLog("Description of primary block ", *block, ": ", description, "\n"); + if (!description) { + if (verbose) + dataLog(" Bailing because not switch-like.\n"); + return false; + } + + // We know that this block behaves like a switch. But we need to verify that it doesn't also + // perform any effects or do expensive things. We don't want to create a switch if that will + // make expensive things execute unconditionally. We're very conservative about how we define + // "expensive". + for (Value* value : *block) { + if (value->isFree()) + continue; + if (value == description.extra) + continue; + if (value == description.branch) + continue; + if (verbose) + dataLog(" Bailing because of ", deepDump(m_proc, value), "\n"); + return false; + } + + BasicBlock* predecessor = block->predecessor(0); + SwitchDescription predecessorDescription = describe(predecessor); + if (verbose) + dataLog(" Description of predecessor block ", *predecessor, ": ", predecessorDescription, "\n"); + if (!predecessorDescription) { + if (verbose) + dataLog(" Bailing because not switch-like.\n"); + return false; + } + + // Both us and the predecessor are switch-like, but that doesn't mean that we're compatible. + // We may be switching on different values! + if (description.source != predecessorDescription.source) { + if (verbose) + dataLog(" Bailing because sources don't match.\n"); + return false; + } + + // We expect that we are the fall-through destination of the predecessor. This is a bit of a + // goofy condition. If we were not the fall-through destination then our switch is probably + // just totally redundant and we should be getting rid of it. But we don't handle that here, + // yet. + if (predecessorDescription.fallThrough.block() != block) { + if (verbose) + dataLog(" Bailing because fall-through of predecessor is not the primary block.\n"); + return false; + } + + // Make sure that there ain't no loops. + if (description.fallThrough.block() == block + || description.fallThrough.block() == predecessor) { + if (verbose) + dataLog(" Bailing because of fall-through loop.\n"); + return false; + } + for (SwitchCase switchCase : description.cases) { + if (switchCase.targetBlock() == block + || switchCase.targetBlock() == predecessor) { + if (verbose) + dataLog(" Bailing because of loop in primary cases.\n"); + return false; + } + } + for (SwitchCase switchCase : predecessorDescription.cases) { + if (switchCase.targetBlock() == block + || switchCase.targetBlock() == predecessor) { + if (verbose) + dataLog(" Bailing because of loop in predecessor cases.\n"); + return false; + } + } + + if (verbose) + dataLog(" Doing it!\n"); + // We're committed to doing the thing. + + // Delete the extra value from the predecessor, since that would break downstream inference + // on the next fixpoint iteration. We would think that this block is too expensive to merge + // because of the Equal or NotEqual value even though that value is dead! We know it's dead + // so we kill it ourselves. + for (Value* value : *predecessor) { + if (value == predecessorDescription.extra) + value->replaceWithNopIgnoringType(); + } + + // Insert all non-terminal values from our block into our predecessor. We definitely need to + // do this for constants. We must not do it for the extra value, since that would break + // downstream inference on the next fixpoint iteration. As a bonus, we don't do it for nops, + // so that we limit how big blocks get in this phase. + for (unsigned i = 0; i < block->size() - 1; ++i) { + Value* value = block->at(i); + if (value != description.extra && value->opcode() != Nop) + m_insertionSet.insertValue(predecessor->size() - 1, value); + } + m_insertionSet.execute(predecessor); + block->values().resize(0); + block->appendNew(m_proc, Oops, description.branch->origin()); + block->removePredecessor(predecessor); + + for (BasicBlock* successorBlock : description.block->successorBlocks()) + successorBlock->replacePredecessor(block, predecessor); + + block->clearSuccessors(); + + SwitchValue* switchValue = predecessor->replaceLastWithNew( + m_proc, predecessor->last()->origin(), description.source); + predecessor->clearSuccessors(); + switchValue->setFallThrough(description.fallThrough); + + Vector predecessorCases; + for (SwitchCase switchCase : predecessorDescription.cases) { + switchValue->appendCase(switchCase); + predecessorCases.append(switchCase.caseValue()); + } + std::sort(predecessorCases.begin(), predecessorCases.end()); + auto isPredecessorCase = [&] (int64_t value) -> bool { + return !!tryBinarySearch( + predecessorCases, predecessorCases.size(), value, + [] (int64_t* element) -> int64_t { return *element; }); + }; + + for (SwitchCase switchCase : description.cases) { + if (!isPredecessorCase(switchCase.caseValue())) + switchValue->appendCase(switchCase); + } + return true; + } + + struct SwitchDescription { + SwitchDescription() + { + } + + explicit operator bool() { return !!block; } + + void dump(PrintStream& out) const + { + out.print( + "{block = ", pointerDump(block), + ", branch = ", pointerDump(branch), + ", extra = ", pointerDump(extra), + ", source = ", pointerDump(source), + ", cases = ", listDump(cases), + ", fallThrough = ", fallThrough, "}"); + } + + BasicBlock* block { nullptr }; + Value* branch { nullptr }; + Value* extra { nullptr }; // This is the Equal or NotEqual value, if applicable. + Value* source { nullptr }; + Vector cases; + FrequentedBlock fallThrough; + }; + + SwitchDescription describe(BasicBlock* block) + { + SwitchDescription result; + result.block = block; + result.branch = block->last(); + + switch (result.branch->opcode()) { + case Branch: { + Value* predicate = result.branch->child(0); + FrequentedBlock taken = result.block->taken(); + FrequentedBlock notTaken = result.block->notTaken(); + bool handled = false; + // NOTE: This uses UseCounts that we computed before any transformation. This is fine + // because although we may have mutated the IR, we would not have added any new + // predicates. + if (predicate->numChildren() == 2 + && predicate->child(1)->hasInt() + && m_useCounts.numUses(predicate) == 1) { + switch (predicate->opcode()) { + case Equal: + result.source = predicate->child(0); + result.extra = predicate; + result.cases.append(SwitchCase(predicate->child(1)->asInt(), taken)); + result.fallThrough = notTaken; + handled = true; + break; + case NotEqual: + result.source = predicate->child(0); + result.extra = predicate; + result.cases.append(SwitchCase(predicate->child(1)->asInt(), notTaken)); + result.fallThrough = taken; + handled = true; + break; + default: + break; + } + } + if (handled) + break; + result.source = predicate; + result.cases.append(SwitchCase(0, notTaken)); + result.fallThrough = taken; + break; + } + + case Switch: { + SwitchValue* switchValue = result.branch->as(); + result.source = switchValue->child(0); + for (SwitchCase switchCase : switchValue->cases(result.block)) + result.cases.append(switchCase); + result.fallThrough = result.block->fallThrough(); + break; + } + + default: + result.block = nullptr; + result.branch = nullptr; + break; + } + + return result; + } + + Procedure& m_proc; + InsertionSet m_insertionSet; + UseCounts m_useCounts; +}; + +} // anonymous namespace + +bool inferSwitches(Procedure& proc) +{ + PhaseScope phaseScope(proc, "inferSwitches"); + InferSwitches inferSwitches(proc); + return inferSwitches.run(); +} + +} } // namespace JSC::B3 + +#endif // ENABLE(B3_JIT) + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InferSwitches.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InferSwitches.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InferSwitches.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InferSwitches.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef B3InferSwitches_h +#define B3InferSwitches_h + +#if ENABLE(B3_JIT) + +namespace JSC { namespace B3 { + +class Procedure; + +// Fixpoints to convert chains of branches into switches. + +bool inferSwitches(Procedure&); + +} } // namespace JSC::B3 + +#endif // ENABE(B3_JIT) + +#endif // B3InferSwitches_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InsertionSet.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InsertionSet.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InsertionSet.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InsertionSet.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -47,7 +47,10 @@ Value* InsertionSet::insertBottom(size_t index, Origin origin, Type type) { - return insertValue(index, m_procedure.addBottom(origin, type)); + Value*& bottom = m_bottomForType[type]; + if (!bottom) + bottom = insertValue(index, m_procedure.addBottom(origin, type)); + return bottom; } Value* InsertionSet::insertBottom(size_t index, Value* likeValue) @@ -59,6 +62,7 @@ { bubbleSort(m_insertions.begin(), m_insertions.end()); executeInsertions(block->m_values, m_insertions); + m_bottomForType = TypeMap(); } } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InsertionSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InsertionSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3InsertionSet.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3InsertionSet.h 2016-11-03 07:04:20.000000000 +0000 @@ -30,6 +30,7 @@ #include "B3Origin.h" #include "B3Type.h" +#include "B3TypeMap.h" #include #include @@ -77,6 +78,8 @@ private: Procedure& m_procedure; Vector m_insertions; + + TypeMap m_bottomForType; }; } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3LowerMacros.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3LowerMacros.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3LowerMacros.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3LowerMacros.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,18 +28,25 @@ #if ENABLE(B3_JIT) +#include "AllowMacroScratchRegisterUsage.h" #include "B3BasicBlockInlines.h" #include "B3BlockInsertionSet.h" #include "B3CCallValue.h" +#include "B3CaseCollectionInlines.h" #include "B3ConstPtrValue.h" -#include "B3ControlValue.h" #include "B3InsertionSetInlines.h" +#include "B3MemoryValue.h" +#include "B3PatchpointValue.h" #include "B3PhaseScope.h" #include "B3ProcedureInlines.h" +#include "B3StackmapGenerationParams.h" #include "B3SwitchValue.h" #include "B3UpsilonValue.h" #include "B3ValueInlines.h" +#include "CCallHelpers.h" +#include "LinkBuffer.h" #include +#include namespace JSC { namespace B3 { @@ -118,8 +125,8 @@ BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block); BasicBlock* normalModCase = m_blockInsertionSet.insertBefore(m_block); - before->replaceLastWithNew( - m_proc, Branch, m_origin, m_value->child(1), + before->replaceLastWithNew(m_proc, Branch, m_origin, m_value->child(1)); + before->setSuccessors( FrequentedBlock(normalModCase, FrequencyClass::Normal), FrequentedBlock(zeroDenCase, FrequencyClass::Rare)); @@ -127,12 +134,14 @@ Value* multipliedBack = normalModCase->appendNew(m_proc, Mul, m_origin, divResult, m_value->child(1)); Value* result = normalModCase->appendNew(m_proc, Sub, m_origin, m_value->child(0), multipliedBack); UpsilonValue* normalResult = normalModCase->appendNew(m_proc, m_origin, result); - normalModCase->appendNew(m_proc, Jump, m_origin, FrequentedBlock(m_block)); + normalModCase->appendNew(m_proc, Jump, m_origin); + normalModCase->setSuccessors(FrequentedBlock(m_block)); UpsilonValue* zeroResult = zeroDenCase->appendNew( m_proc, m_origin, zeroDenCase->appendIntConstant(m_proc, m_value, 0)); - zeroDenCase->appendNew(m_proc, Jump, m_origin, FrequentedBlock(m_block)); + zeroDenCase->appendNew(m_proc, Jump, m_origin); + zeroDenCase->setSuccessors(FrequentedBlock(m_block)); Value* phi = m_insertionSet.insert(m_index, Phi, m_value->type(), m_origin); normalResult->setPhi(phi); @@ -147,15 +156,16 @@ case Switch: { SwitchValue* switchValue = m_value->as(); Vector cases; - for (const SwitchCase& switchCase : *switchValue) + for (const SwitchCase& switchCase : switchValue->cases(m_block)) cases.append(switchCase); std::sort( cases.begin(), cases.end(), [] (const SwitchCase& left, const SwitchCase& right) { return left.caseValue() < right.caseValue(); }); + FrequentedBlock fallThrough = m_block->fallThrough(); m_block->values().removeLast(); - recursivelyBuildSwitch(cases, 0, false, cases.size(), m_block); + recursivelyBuildSwitch(cases, fallThrough, 0, false, cases.size(), m_block); m_proc.deleteValue(switchValue); m_block->updatePredecessorsAfter(); m_changed = true; @@ -210,27 +220,27 @@ BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block); BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block); - before->replaceLastWithNew( - m_proc, Branch, m_origin, isDenOK, + before->replaceLastWithNew(m_proc, Branch, m_origin, isDenOK); + before->setSuccessors( FrequentedBlock(normalDivCase, FrequencyClass::Normal), FrequentedBlock(shadyDenCase, FrequencyClass::Rare)); UpsilonValue* normalResult = normalDivCase->appendNew( m_proc, m_origin, normalDivCase->appendNew(m_proc, nonChillOpcode, m_origin, num, den)); - normalDivCase->appendNew( - m_proc, Jump, m_origin, FrequentedBlock(m_block)); + normalDivCase->appendNew(m_proc, Jump, m_origin); + normalDivCase->setSuccessors(FrequentedBlock(m_block)); - shadyDenCase->appendNew( - m_proc, Branch, m_origin, den, + shadyDenCase->appendNew(m_proc, Branch, m_origin, den); + shadyDenCase->setSuccessors( FrequentedBlock(neg1DenCase, FrequencyClass::Normal), FrequentedBlock(zeroDenCase, FrequencyClass::Rare)); UpsilonValue* zeroResult = zeroDenCase->appendNew( m_proc, m_origin, zeroDenCase->appendIntConstant(m_proc, m_value, 0)); - zeroDenCase->appendNew( - m_proc, Jump, m_origin, FrequentedBlock(m_block)); + zeroDenCase->appendNew(m_proc, Jump, m_origin); + zeroDenCase->setSuccessors(FrequentedBlock(m_block)); int64_t badNumeratorConst = 0; switch (m_value->type()) { @@ -248,18 +258,19 @@ Value* badNumerator = neg1DenCase->appendIntConstant(m_proc, m_value, badNumeratorConst); - neg1DenCase->appendNew( + neg1DenCase->appendNew( m_proc, Branch, m_origin, neg1DenCase->appendNew( - m_proc, Equal, m_origin, num, badNumerator), + m_proc, Equal, m_origin, num, badNumerator)); + neg1DenCase->setSuccessors( FrequentedBlock(intMinCase, FrequencyClass::Rare), FrequentedBlock(normalDivCase, FrequencyClass::Normal)); Value* intMinResult = nonChillOpcode == Div ? badNumerator : intMinCase->appendIntConstant(m_proc, m_value, 0); UpsilonValue* intMinResultUpsilon = intMinCase->appendNew( m_proc, m_origin, intMinResult); - intMinCase->appendNew( - m_proc, Jump, m_origin, FrequentedBlock(m_block)); + intMinCase->appendNew(m_proc, Jump, m_origin); + intMinCase->setSuccessors(FrequentedBlock(m_block)); Value* phi = m_insertionSet.insert( m_index, Phi, m_value->type(), m_origin); @@ -272,11 +283,111 @@ } void recursivelyBuildSwitch( - const Vector& cases, unsigned start, bool hardStart, unsigned end, - BasicBlock* before) + const Vector& cases, FrequentedBlock fallThrough, unsigned start, bool hardStart, + unsigned end, BasicBlock* before) { - // FIXME: Add table-based switch lowering. - // https://bugs.webkit.org/show_bug.cgi?id=151141 + Value* child = m_value->child(0); + Type type = child->type(); + + // It's a good idea to use a table-based switch in some cases: the number of cases has to be + // large enough and they have to be dense enough. This could probably be improved a lot. For + // example, we could still use a jump table in cases where the inputs are sparse so long as we + // shift off the uninteresting bits. On the other hand, it's not clear that this would + // actually be any better than what we have done here and it's not clear that it would be + // better than a binary switch. + const unsigned minCasesForTable = 7; + const unsigned densityLimit = 4; + if (end - start >= minCasesForTable) { + int64_t firstValue = cases[start].caseValue(); + int64_t lastValue = cases[end - 1].caseValue(); + if ((lastValue - firstValue + 1) / (end - start) < densityLimit) { + BasicBlock* switchBlock = m_blockInsertionSet.insertAfter(m_block); + Value* index = before->appendNew( + m_proc, Sub, m_origin, child, + before->appendIntConstant(m_proc, m_origin, type, firstValue)); + before->appendNew( + m_proc, Branch, m_origin, + before->appendNew( + m_proc, Above, m_origin, index, + before->appendIntConstant(m_proc, m_origin, type, lastValue - firstValue))); + before->setSuccessors(fallThrough, FrequentedBlock(switchBlock)); + + size_t tableSize = lastValue - firstValue + 1; + + if (index->type() != pointerType() && index->type() == Int32) + index = switchBlock->appendNew(m_proc, ZExt32, m_origin, index); + + PatchpointValue* patchpoint = + switchBlock->appendNew(m_proc, Void, m_origin); + + // Even though this loads from the jump table, the jump table is immutable. For the + // purpose of alias analysis, reading something immutable is like reading nothing. + patchpoint->effects = Effects(); + patchpoint->effects.terminal = true; + + patchpoint->appendSomeRegister(index); + patchpoint->numGPScratchRegisters++; + // Technically, we don't have to clobber macro registers on X86_64. This is probably + // OK though. + patchpoint->clobber(RegisterSet::macroScratchRegisters()); + + BitVector handledIndices; + for (unsigned i = start; i < end; ++i) { + FrequentedBlock block = cases[i].target(); + int64_t value = cases[i].caseValue(); + switchBlock->appendSuccessor(block); + size_t index = value - firstValue; + ASSERT(!handledIndices.get(index)); + handledIndices.set(index); + } + + bool hasUnhandledIndex = false; + for (unsigned i = 0; i < tableSize; ++i) { + if (!handledIndices.get(i)) { + hasUnhandledIndex = true; + break; + } + } + + if (hasUnhandledIndex) + switchBlock->appendSuccessor(fallThrough); + + patchpoint->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + + MacroAssemblerCodePtr* jumpTable = static_cast( + params.proc().addDataSection(sizeof(MacroAssemblerCodePtr) * tableSize)); + + GPRReg index = params[0].gpr(); + GPRReg scratch = params.gpScratch(0); + + jit.move(CCallHelpers::TrustedImmPtr(jumpTable), scratch); + jit.jump(CCallHelpers::BaseIndex(scratch, index, CCallHelpers::timesPtr())); + + // These labels are guaranteed to be populated before either late paths or + // link tasks run. + Vector> labels = params.successorLabels(); + + jit.addLinkTask( + [=] (LinkBuffer& linkBuffer) { + if (hasUnhandledIndex) { + MacroAssemblerCodePtr fallThrough = + linkBuffer.locationOf(*labels.last()); + for (unsigned i = tableSize; i--;) + jumpTable[i] = fallThrough; + } + + unsigned labelIndex = 0; + for (unsigned tableIndex : handledIndices) { + jumpTable[tableIndex] = + linkBuffer.locationOf(*labels[labelIndex++]); + } + }); + }); + return; + } + } // See comments in jit/BinarySwitch.cpp for a justification of this algorithm. The only // thing we do differently is that we don't use randomness. @@ -304,25 +415,23 @@ for (unsigned i = 0; i < limit; ++i) { BasicBlock* nextCheck = m_blockInsertionSet.insertAfter(m_block); - before->appendNew( + before->appendNew( m_proc, Branch, m_origin, before->appendNew( - m_proc, Equal, m_origin, m_value->child(0), + m_proc, Equal, m_origin, child, before->appendIntConstant( - m_proc, m_origin, m_value->child(0)->type(), - cases[start + i].caseValue())), - cases[start + i].target(), FrequentedBlock(nextCheck)); + m_proc, m_origin, type, + cases[start + i].caseValue()))); + before->setSuccessors(cases[start + i].target(), FrequentedBlock(nextCheck)); before = nextCheck; } - if (allConsecutive) { - before->appendNew( - m_proc, Jump, m_origin, cases[end - 1].target()); - } else { - before->appendNew( - m_proc, Jump, m_origin, m_value->as()->fallThrough()); - } + before->appendNew(m_proc, Jump, m_origin); + if (allConsecutive) + before->setSuccessors(cases[end - 1].target()); + else + before->setSuccessors(fallThrough); return; } @@ -331,17 +440,17 @@ BasicBlock* left = m_blockInsertionSet.insertAfter(m_block); BasicBlock* right = m_blockInsertionSet.insertAfter(m_block); - before->appendNew( + before->appendNew( m_proc, Branch, m_origin, before->appendNew( - m_proc, LessThan, m_origin, m_value->child(0), + m_proc, LessThan, m_origin, child, before->appendIntConstant( - m_proc, m_origin, m_value->child(0)->type(), - cases[medianIndex].caseValue())), - FrequentedBlock(left), FrequentedBlock(right)); + m_proc, m_origin, type, + cases[medianIndex].caseValue()))); + before->setSuccessors(FrequentedBlock(left), FrequentedBlock(right)); - recursivelyBuildSwitch(cases, start, hardStart, medianIndex, left); - recursivelyBuildSwitch(cases, medianIndex, true, end, right); + recursivelyBuildSwitch(cases, fallThrough, start, hardStart, medianIndex, left); + recursivelyBuildSwitch(cases, fallThrough, medianIndex, true, end, right); } Procedure& m_proc; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3LowerToAir.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3LowerToAir.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3LowerToAir.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3LowerToAir.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -40,8 +40,6 @@ #include "B3CheckSpecial.h" #include "B3Commutativity.h" #include "B3Dominators.h" -#include "B3IndexMap.h" -#include "B3IndexSet.h" #include "B3MemoryValue.h" #include "B3PatchpointSpecial.h" #include "B3PatchpointValue.h" @@ -55,6 +53,8 @@ #include "B3ValueInlines.h" #include "B3Variable.h" #include "B3VariableValue.h" +#include +#include #include #if COMPILER(GCC) && ASSERT_DISABLED @@ -155,7 +155,6 @@ } // Make sure that the successors are set up correctly. - ASSERT(block->successors().size() <= 2); for (B3::FrequentedBlock successor : block->successors()) { m_blockToBlock[block]->successors().append( Air::FrequentedBlock(m_blockToBlock[successor.block()], successor.frequency())); @@ -715,8 +714,13 @@ // over three operand forms. if (left != right) { + ArgPromise leftAddr = loadPromise(left); + if (isValidForm(opcode, leftAddr.kind(), Arg::Tmp, Arg::Tmp)) { + append(opcode, leftAddr.consume(*this), tmp(right), result); + return; + } + if (commutativity == Commutative) { - ArgPromise leftAddr = loadPromise(left); if (isValidForm(opcode, leftAddr.kind(), Arg::Tmp)) { append(relaxedMoveForType(m_value->type()), tmp(right), result); append(opcode, leftAddr.consume(*this), result); @@ -725,6 +729,18 @@ } ArgPromise rightAddr = loadPromise(right); + if (isValidForm(opcode, Arg::Tmp, rightAddr.kind(), Arg::Tmp)) { + append(opcode, tmp(left), rightAddr.consume(*this), result); + return; + } + + if (commutativity == Commutative) { + if (isValidForm(opcode, rightAddr.kind(), Arg::Tmp, Arg::Tmp)) { + append(opcode, rightAddr.consume(*this), tmp(left), result); + return; + } + } + if (isValidForm(opcode, rightAddr.kind(), Arg::Tmp)) { append(relaxedMoveForType(m_value->type()), tmp(left), result); append(opcode, rightAddr.consume(*this), result); @@ -988,6 +1004,7 @@ case ValueRep::SomeRegister: arg = tmp(value.value()); break; + case ValueRep::LateRegister: case ValueRep::Register: stackmap->earlyClobbered().clear(value.rep().reg()); arg = Tmp(value.rep().reg()); @@ -1313,22 +1330,43 @@ Value* left = value->child(0); Value* right = value->child(1); - // FIXME: We don't actually have to worry about leftImm. - // https://bugs.webkit.org/show_bug.cgi?id=150954 - - Arg leftImm = imm(left); - Arg rightImm = imm(right); + bool hasRightConst; + int64_t rightConst; + Arg rightImm; + Arg rightImm64; + + hasRightConst = right->hasInt(); + if (hasRightConst) { + rightConst = right->asInt(); + rightImm = bitImm(right); + rightImm64 = bitImm64(right); + } - auto tryTestLoadImm = [&] (Arg::Width width, B3::Opcode loadOpcode) -> Inst { - if (rightImm && rightImm.isRepresentableAs(width, Arg::Unsigned)) { + auto tryTestLoadImm = [&] (Arg::Width width, Arg::Signedness signedness, B3::Opcode loadOpcode) -> Inst { + if (!hasRightConst) + return Inst(); + // Signed loads will create high bits, so if the immediate has high bits + // then we cannot proceed. Consider BitAnd(Load8S(ptr), 0x101). This cannot + // be turned into testb (ptr), $1, since if the high bit within that byte + // was set then it would be extended to include 0x100. The handling below + // won't anticipate this, so we need to catch it here. + if (signedness == Arg::Signed + && !Arg::isRepresentableAs(width, Arg::Unsigned, rightConst)) + return Inst(); + + // FIXME: If this is unsigned then we can chop things off of the immediate. + // This might make the immediate more legal. Perhaps that's a job for + // strength reduction? + + if (rightImm) { if (Inst result = tryTest(width, loadPromise(left, loadOpcode), rightImm)) { commitInternal(left); return result; } } - if (leftImm && leftImm.isRepresentableAs(width, Arg::Unsigned)) { - if (Inst result = tryTest(width, leftImm, loadPromise(right, loadOpcode))) { - commitInternal(right); + if (rightImm64) { + if (Inst result = tryTest(width, loadPromise(left, loadOpcode), rightImm64)) { + commitInternal(left); return result; } } @@ -1338,24 +1376,28 @@ if (canCommitInternal) { // First handle test's that involve fewer bits than B3's type system supports. - if (Inst result = tryTestLoadImm(Arg::Width8, Load8Z)) + if (Inst result = tryTestLoadImm(Arg::Width8, Arg::Unsigned, Load8Z)) return result; - if (Inst result = tryTestLoadImm(Arg::Width8, Load8S)) + if (Inst result = tryTestLoadImm(Arg::Width8, Arg::Signed, Load8S)) return result; - if (Inst result = tryTestLoadImm(Arg::Width16, Load16Z)) + if (Inst result = tryTestLoadImm(Arg::Width16, Arg::Unsigned, Load16Z)) return result; - if (Inst result = tryTestLoadImm(Arg::Width16, Load16S)) + if (Inst result = tryTestLoadImm(Arg::Width16, Arg::Signed, Load16S)) return result; - // Now handle test's that involve a load and an immediate. Note that immediates - // are 32-bit, and we want zero-extension. Hence, the immediate form is compiled - // as a 32-bit test. Note that this spits on the grave of inferior endians, such - // as the big one. + // This allows us to use a 32-bit test for 64-bit BitAnd if the immediate is + // representable as an unsigned 32-bit value. The logic involved is the same + // as if we were pondering using a 32-bit test for + // BitAnd(SExt(Load(ptr)), const), in the sense that in both cases we have + // to worry about high bits. So, we use the "Signed" version of this helper. + if (Inst result = tryTestLoadImm(Arg::Width32, Arg::Signed, Load)) + return result; - if (Inst result = tryTestLoadImm(Arg::Width32, Load)) + // This is needed to handle 32-bit test for arbitrary 32-bit immediates. + if (Inst result = tryTestLoadImm(width, Arg::Unsigned, Load)) return result; // Now handle test's that involve a load. @@ -1374,30 +1416,23 @@ // Now handle test's that involve an immediate and a tmp. - if (leftImm) { - if ((width == Arg::Width32 && leftImm.value() == 0xffffffff) - || (width == Arg::Width64 && leftImm.value() == -1)) { - ArgPromise argPromise = tmpPromise(right); - if (Inst result = tryTest(width, argPromise, argPromise)) - return result; - } - if (leftImm.isRepresentableAs()) { - if (Inst result = tryTest(Arg::Width32, leftImm, tmpPromise(right))) - return result; - } - } - - if (rightImm) { - if ((width == Arg::Width32 && rightImm.value() == 0xffffffff) - || (width == Arg::Width64 && rightImm.value() == -1)) { + if (hasRightConst) { + if ((width == Arg::Width32 && rightConst == 0xffffffff) + || (width == Arg::Width64 && rightConst == -1)) { ArgPromise argPromise = tmpPromise(left); if (Inst result = tryTest(width, argPromise, argPromise)) return result; } - if (rightImm.isRepresentableAs()) { + if (isRepresentableAs(rightConst)) { if (Inst result = tryTest(Arg::Width32, tmpPromise(left), rightImm)) return result; + if (Inst result = tryTest(Arg::Width32, tmpPromise(left), rightImm64)) + return result; } + if (Inst result = tryTest(width, tmpPromise(left), rightImm)) + return result; + if (Inst result = tryTest(width, tmpPromise(left), rightImm64)) + return result; } // Finally, just do tmp's. @@ -1415,37 +1450,37 @@ } } - if (Arg::isValidImmForm(-1)) { + if (Arg::isValidBitImmForm(-1)) { if (canCommitInternal && value->as()) { // Handle things like Branch(Load8Z(value)) - if (Inst result = tryTest(Arg::Width8, loadPromise(value, Load8Z), Arg::imm(-1))) { + if (Inst result = tryTest(Arg::Width8, loadPromise(value, Load8Z), Arg::bitImm(-1))) { commitInternal(value); return result; } - if (Inst result = tryTest(Arg::Width8, loadPromise(value, Load8S), Arg::imm(-1))) { + if (Inst result = tryTest(Arg::Width8, loadPromise(value, Load8S), Arg::bitImm(-1))) { commitInternal(value); return result; } - if (Inst result = tryTest(Arg::Width16, loadPromise(value, Load16Z), Arg::imm(-1))) { + if (Inst result = tryTest(Arg::Width16, loadPromise(value, Load16Z), Arg::bitImm(-1))) { commitInternal(value); return result; } - if (Inst result = tryTest(Arg::Width16, loadPromise(value, Load16S), Arg::imm(-1))) { + if (Inst result = tryTest(Arg::Width16, loadPromise(value, Load16S), Arg::bitImm(-1))) { commitInternal(value); return result; } - if (Inst result = tryTest(width, loadPromise(value), Arg::imm(-1))) { + if (Inst result = tryTest(width, loadPromise(value), Arg::bitImm(-1))) { commitInternal(value); return result; } } - if (Inst result = test(width, resCond, tmpPromise(value), Arg::imm(-1))) + if (Inst result = test(width, resCond, tmpPromise(value), Arg::bitImm(-1))) return result; } @@ -1800,7 +1835,7 @@ } } - appendUnOp(m_value->child(0)); + appendUnOp(m_value->child(0)); return; } @@ -2132,6 +2167,11 @@ return; } + case IToF: { + appendUnOp(m_value->child(0)); + return; + } + case B3::CCall: { CCallValue* cCall = m_value->as(); @@ -2171,6 +2211,7 @@ case ValueRep::ColdAny: case ValueRep::LateColdAny: case ValueRep::SomeRegister: + case ValueRep::SomeEarlyRegister: inst.args.append(tmp(patchpointValue)); break; case ValueRep::Register: { @@ -2390,6 +2431,10 @@ } case Return: { + if (!m_value->numChildren()) { + append(RetVoid); + return; + } Value* value = m_value->child(0); Tmp returnValueGPR = Tmp(GPRInfo::returnValueGPR); Tmp returnValueFPR = Tmp(FPRInfo::returnValueFPR); @@ -2423,6 +2468,11 @@ append(Air::Oops); return; } + + case B3::EntrySwitch: { + append(Air::EntrySwitch); + return; + } default: break; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3LowerToAir.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3LowerToAir.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3LowerToAir.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3LowerToAir.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,7 @@ // This lowers the current B3 procedure to an Air code. -void lowerToAir(Procedure&); +JS_EXPORT_PRIVATE void lowerToAir(Procedure&); } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3MathExtras.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3MathExtras.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3MathExtras.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3MathExtras.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,9 +33,9 @@ #include "B3Const32Value.h" #include "B3ConstDoubleValue.h" #include "B3ConstPtrValue.h" -#include "B3ControlValue.h" #include "B3UpsilonValue.h" #include "B3ValueInlines.h" +#include "MathCommon.h" namespace JSC { namespace B3 { @@ -50,11 +50,9 @@ Value* shouldGoSlowPath = start->appendNew(procedure, Above, origin, y, - start->appendNew(procedure, origin, 1000)); - start->appendNew( - procedure, Branch, origin, - shouldGoSlowPath, - FrequentedBlock(functionCallCase), FrequentedBlock(loopPreHeaderCase)); + start->appendNew(procedure, origin, maxExponentForIntegerMathPow)); + start->appendNew(procedure, Branch, origin, shouldGoSlowPath); + start->setSuccessors(FrequentedBlock(functionCallCase), FrequentedBlock(loopPreHeaderCase)); // Function call. Value* yAsDouble = functionCallCase->appendNew(procedure, IToD, origin, y); @@ -64,7 +62,8 @@ functionCallCase->appendNew(procedure, origin, bitwise_cast(powDouble)), x, yAsDouble); UpsilonValue* powResultUpsilon = functionCallCase->appendNew(procedure, origin, powResult); - functionCallCase->appendNew(procedure, Jump, origin, FrequentedBlock(continuation)); + functionCallCase->appendNew(procedure, Jump, origin); + functionCallCase->setSuccessors(FrequentedBlock(continuation)); // Loop pre-header. Value* initialResult = loopPreHeaderCase->appendNew(procedure, origin, 1.); @@ -72,7 +71,8 @@ UpsilonValue* initialResultValue = loopPreHeaderCase->appendNew(procedure, origin, initialResult); UpsilonValue* initialSquaredInput = loopPreHeaderCase->appendNew(procedure, origin, x); UpsilonValue* initialLoopCounter = loopPreHeaderCase->appendNew(procedure, origin, y); - loopPreHeaderCase->appendNew(procedure, Jump, origin, FrequentedBlock(loopTestForEvenCase)); + loopPreHeaderCase->appendNew(procedure, Jump, origin); + loopPreHeaderCase->setSuccessors(FrequentedBlock(loopTestForEvenCase)); // Test if what is left of the counter is even. Value* inLoopCounter = loopTestForEvenCase->appendNew(procedure, Phi, Int32, origin); @@ -80,10 +80,8 @@ Value* lastCounterBit = loopTestForEvenCase->appendNew(procedure, BitAnd, origin, inLoopCounter, loopTestForEvenCase->appendNew(procedure, origin, 1)); - loopTestForEvenCase->appendNew( - procedure, Branch, origin, - lastCounterBit, - FrequentedBlock(loopOdd), FrequentedBlock(loopEvenOdd)); + loopTestForEvenCase->appendNew(procedure, Branch, origin, lastCounterBit); + loopTestForEvenCase->setSuccessors(FrequentedBlock(loopOdd), FrequentedBlock(loopEvenOdd)); // Counter is odd. Value* inLoopResult = loopOdd->appendNew(procedure, Phi, Double, origin); @@ -93,7 +91,8 @@ updatedLoopResultUpsilon->setPhi(inLoopResult); UpsilonValue* updatedLoopResult = loopOdd->appendNew(procedure, origin, updatedResult); - loopOdd->appendNew(procedure, Jump, origin, FrequentedBlock(loopEvenOdd)); + loopOdd->appendNew(procedure, Jump, origin); + loopOdd->setSuccessors(FrequentedBlock(loopEvenOdd)); // Even value and following the Odd. Value* squaredInput = loopEvenOdd->appendNew(procedure, Mul, origin, inLoopSquaredInput, inLoopSquaredInput); @@ -108,10 +107,8 @@ initialLoopCounter->setPhi(inLoopCounter); updatedCounterUpsilon->setPhi(inLoopCounter); - loopEvenOdd->appendNew( - procedure, Branch, origin, - updatedCounter, - FrequentedBlock(loopTestForEvenCase), FrequentedBlock(continuation)); + loopEvenOdd->appendNew(procedure, Branch, origin, updatedCounter); + loopEvenOdd->setSuccessors(FrequentedBlock(loopTestForEvenCase), FrequentedBlock(continuation)); // Inline loop. Value* finalResultPhi = continuation->appendNew(procedure, Phi, Double, origin); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3MoveConstants.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3MoveConstants.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3MoveConstants.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3MoveConstants.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -62,7 +62,7 @@ hoistConstants( [&] (const ValueKey& key) -> bool { - return key.opcode() == Const32 || key.opcode() == Const64; + return key.opcode() == Const32 || key.opcode() == Const64 || key.opcode() == ArgumentReg; }); } @@ -125,7 +125,7 @@ if (valueForConstant.get(key) == value) value = m_proc.add(Nop, value->origin()); else - value->replaceWithNop(); + value->replaceWithNopIgnoringType(); } } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Opcode.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Opcode.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Opcode.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Opcode.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -188,6 +188,9 @@ case IToD: out.print("IToD"); return; + case IToF: + out.print("IToF"); + return; case FloatToDouble: out.print("FloatToDouble"); return; @@ -287,6 +290,9 @@ case Switch: out.print("Switch"); return; + case EntrySwitch: + out.print("EntrySwitch"); + return; case Return: out.print("Return"); return; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Opcode.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Opcode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Opcode.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Opcode.h 2016-11-03 07:04:20.000000000 +0000 @@ -111,10 +111,11 @@ ZExt32, // Takes Int64 and returns Int32: Trunc, - // Takes ints and returns Double. Note that we don't currently provide the opposite operation, + // Takes ints and returns floating point value. Note that we don't currently provide the opposite operation, // because double-to-int conversions have weirdly different semantics on different platforms. Use // a patchpoint if you need to do that. IToD, + IToF, // Convert between double and float. FloatToDouble, DoubleToFloat, @@ -206,21 +207,26 @@ Upsilon, // This uses the UpsilonValue class. Phi, - // Jump. Uses the ControlValue class. + // Jump. Jump, - // Polymorphic branch, usable with any integer type. Branches if not equal to zero. Uses the - // ControlValue class, with the 0-index successor being the true successor. + // Polymorphic branch, usable with any integer type. Branches if not equal to zero. The 0-index + // successor is the true successor. Branch, // Switch. Switches over either Int32 or Int64. Uses the SwitchValue class. Switch, + + // Multiple entrypoints are supported via the EntrySwitch operation. Place this in the root + // block and list the entrypoints as the successors. All blocks backwards-reachable from + // EntrySwitch are duplicated for each entrypoint. + EntrySwitch, // Return. Note that B3 procedures don't know their return type, so this can just return any - // type. Uses the ControlValue class. + // type. Return, - // This is a terminal that indicates that we will never get here. Uses the ControlValue class. + // This is a terminal that indicates that we will never get here. Oops }; @@ -258,13 +264,27 @@ } } +inline bool isDefinitelyTerminal(Opcode opcode) +{ + switch (opcode) { + case Jump: + case Branch: + case Switch: + case Oops: + case Return: + return true; + default: + return false; + } +} + } } // namespace JSC::B3 namespace WTF { class PrintStream; -void printInternal(PrintStream&, JSC::B3::Opcode); +JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Opcode); } // namespace WTF diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3PatchpointSpecial.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3PatchpointSpecial.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3PatchpointSpecial.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3PatchpointSpecial.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -46,17 +46,25 @@ void PatchpointSpecial::forEachArg(Inst& inst, const ScopedLambda& callback) { + PatchpointValue* patchpoint = inst.origin->as(); unsigned argIndex = 1; - if (inst.origin->type() != Void) - callback(inst.args[argIndex++], Arg::Def, inst.origin->airType(), inst.origin->airWidth()); + if (patchpoint->type() != Void) { + Arg::Role role; + if (patchpoint->resultConstraint.kind() == ValueRep::SomeEarlyRegister) + role = Arg::EarlyDef; + else + role = Arg::Def; + + callback(inst.args[argIndex++], role, inst.origin->airType(), inst.origin->airWidth()); + } forEachArgImpl(0, argIndex, inst, SameAsRep, Nullopt, callback); argIndex += inst.origin->numChildren(); - for (unsigned i = inst.origin->as()->numGPScratchRegisters; i--;) + for (unsigned i = patchpoint->numGPScratchRegisters; i--;) callback(inst.args[argIndex++], Arg::Scratch, Arg::GP, Arg::conservativeWidth(Arg::GP)); - for (unsigned i = inst.origin->as()->numFPScratchRegisters; i--;) + for (unsigned i = patchpoint->numFPScratchRegisters; i--;) callback(inst.args[argIndex++], Arg::Scratch, Arg::FP, Arg::conservativeWidth(Arg::FP)); } @@ -109,7 +117,9 @@ case ValueRep::StackArgument: return true; case ValueRep::SomeRegister: + case ValueRep::SomeEarlyRegister: case ValueRep::Register: + case ValueRep::LateRegister: return false; default: RELEASE_ASSERT_NOT_REACHED(); @@ -145,6 +155,11 @@ return CCallHelpers::Jump(); } +bool PatchpointSpecial::isTerminal(Inst& inst) +{ + return inst.origin->as()->effects.terminal; +} + void PatchpointSpecial::dumpImpl(PrintStream& out) const { out.print("Patchpoint"); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3PatchpointSpecial.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3PatchpointSpecial.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3PatchpointSpecial.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3PatchpointSpecial.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -56,6 +56,8 @@ // generates the stackmap. Super crazy dude! CCallHelpers::Jump generate(Air::Inst&, CCallHelpers&, Air::GenerationContext&) override; + + bool isTerminal(Air::Inst&) override; void dumpImpl(PrintStream&) const override; void deepDumpImpl(PrintStream&) const override; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3PhiChildren.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3PhiChildren.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3PhiChildren.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3PhiChildren.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,10 +28,10 @@ #if ENABLE(B3_JIT) -#include "B3IndexMap.h" #include "B3Procedure.h" #include "B3UpsilonValue.h" #include +#include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Procedure.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Procedure.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Procedure.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Procedure.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -36,6 +36,7 @@ #include "B3DataSection.h" #include "B3Dominators.h" #include "B3OpaqueByproducts.h" +#include "B3PhiChildren.h" #include "B3StackSlot.h" #include "B3ValueInlines.h" #include "B3Variable.h" @@ -147,38 +148,35 @@ void Procedure::resetReachability() { - if (shouldValidateIR()) { - // Validate the basic properties that we need for resetting reachability. We often reset - // reachability before IR validation, so without this mini-validation, you would crash inside - // B3::resetReachability() without getting any IR dump. - - BasicBlock* badBlock = nullptr; - for (BasicBlock* block : *this) { - if (!block->size()) { - badBlock = block; - break; - } - - if (!block->last()->as()) { - badBlock = block; - break; - } + recomputePredecessors(m_blocks); + + // The common case is that this does not find any dead blocks. + bool foundDead = false; + for (auto& block : m_blocks) { + if (isBlockDead(block.get())) { + foundDead = true; + break; } + } + if (!foundDead) + return; + + resetValueOwners(); - if (badBlock) { - dataLog("FATAL: Invalid basic block ", *badBlock, " while running Procedure::resetReachability().\n"); - dataLog(*this); - RELEASE_ASSERT_NOT_REACHED(); + for (Value* value : values()) { + if (UpsilonValue* upsilon = value->as()) { + if (isBlockDead(upsilon->phi()->owner)) + upsilon->replaceWithNop(); } } - B3::resetReachability( - m_blocks, - [&] (BasicBlock* deleted) { - // Gotta delete the values in this block. - for (Value* value : *deleted) + for (auto& block : m_blocks) { + if (isBlockDead(block.get())) { + for (Value* value : *block) deleteValue(value); - }); + block = nullptr; + } + } } void Procedure::invalidateCFG() @@ -282,6 +280,11 @@ return m_fastConstants.contains(constant); } +CCallHelpers::Label Procedure::entrypointLabel(unsigned index) const +{ + return m_code->entrypointLabel(index); +} + void* Procedure::addDataSection(size_t size) { if (!size) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Procedure.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Procedure.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Procedure.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Procedure.h 2016-11-03 07:04:20.000000000 +0000 @@ -34,11 +34,13 @@ #include "B3SparseCollection.h" #include "B3Type.h" #include "B3ValueKey.h" +#include "CCallHelpers.h" #include "PureNaN.h" #include "RegisterAtOffsetList.h" #include #include #include +#include #include #include #include @@ -57,6 +59,13 @@ namespace Air { class Code; } +// This represents B3's view of a piece of code. Note that this object must exist in a 1:1 +// relationship with Air::Code. B3::Procedure and Air::Code are just different facades of the B3 +// compiler's knowledge about a piece of code. Some kinds of state aren't perfect fits for either +// Procedure or Code, and are placed in one or the other based on convenience. Procedure always +// allocates a Code, and a Code cannot be allocated without an owning Procedure and they always +// have references to each other. + class Procedure { WTF_MAKE_NONCOPYABLE(Procedure); WTF_MAKE_FAST_ALLOCATED; @@ -113,7 +122,7 @@ Value* addBoolConstant(Origin, TriState); void resetValueOwners(); - void resetReachability(); + JS_EXPORT_PRIVATE void resetReachability(); // This destroys CFG analyses. If we ask for them again, we will recompute them. Usually you // should call this anytime you call resetReachability(). @@ -125,53 +134,7 @@ BasicBlock* at(unsigned index) const { return m_blocks[index].get(); } BasicBlock* operator[](unsigned index) const { return at(index); } - class iterator { - public: - iterator() - : m_procedure(nullptr) - , m_index(0) - { - } - - iterator(const Procedure& procedure, unsigned index) - : m_procedure(&procedure) - , m_index(findNext(index)) - { - } - - BasicBlock* operator*() - { - return m_procedure->at(m_index); - } - - iterator& operator++() - { - m_index = findNext(m_index + 1); - return *this; - } - - bool operator==(const iterator& other) const - { - ASSERT(m_procedure == other.m_procedure); - return m_index == other.m_index; - } - - bool operator!=(const iterator& other) const - { - return !(*this == other); - } - - private: - unsigned findNext(unsigned index) - { - while (index < m_procedure->size() && !m_procedure->at(index)) - index++; - return index; - } - - const Procedure* m_procedure; - unsigned m_index; - }; + typedef WTF::IndexedContainerIterator iterator; iterator begin() const { return iterator(*this, 0); } iterator end() const { return iterator(*this, size()); } @@ -209,6 +172,14 @@ void addFastConstant(const ValueKey&); bool isFastConstant(const ValueKey&); + + unsigned numEntrypoints() const { return m_numEntrypoints; } + void setNumEntrypoints(unsigned numEntrypoints) { m_numEntrypoints = numEntrypoints; } + + // Only call this after code generation is complete. Note that the label for the 0th entrypoint + // should point to exactly where the code generation cursor was before you started generating + // code. + JS_EXPORT_PRIVATE CCallHelpers::Label entrypointLabel(unsigned entrypointIndex) const; // The name has to be a string literal, since we don't do any memory management for the string. void setLastPhaseName(const char* name) @@ -218,7 +189,10 @@ const char* lastPhaseName() const { return m_lastPhaseName; } - void* addDataSection(size_t size); + // Allocates a slab of memory that will be kept alive by anyone who keeps the resulting code + // alive. Great for compiler-generated data sections, like switch jump tables and constant pools. + // This returns memory that has been zero-initialized. + JS_EXPORT_PRIVATE void* addDataSection(size_t); OpaqueByproducts& byproducts() { return *m_byproducts; } @@ -258,6 +232,7 @@ std::unique_ptr m_cfg; std::unique_ptr m_dominators; HashSet m_fastConstants; + unsigned m_numEntrypoints { 1 }; const char* m_lastPhaseName; std::unique_ptr m_byproducts; std::unique_ptr m_code; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,126 +29,462 @@ #if ENABLE(B3_JIT) #include "B3BasicBlock.h" +#include "B3InsertionSetInlines.h" #include "B3PhaseScope.h" +#include "B3UseCounts.h" #include "B3ValueInlines.h" +#include namespace JSC { namespace B3 { namespace { -void attemptSimplification(Value* candidate) -{ - switch (candidate->opcode()) { - case Add: - case Sub: - case Mul: - case Div: - if (candidate->child(0)->opcode() == FloatToDouble && candidate->child(1)->opcode() == FloatToDouble) { - candidate->child(0) = candidate->child(0)->child(0); - candidate->child(1) = candidate->child(1)->child(0); - candidate->setType(Float); - } - break; - case Abs: - case Ceil: - case Floor: - case Sqrt: - if (candidate->child(0)->opcode() == FloatToDouble) { - candidate->child(0) = candidate->child(0)->child(0); - candidate->setType(Float); - } - break; - default: - break; + +bool verbose = false; +bool printRemainingConversions = false; + +class DoubleToFloatReduction { +public: + DoubleToFloatReduction(Procedure& procedure) + : m_procedure(procedure) + { } -} -} // namespace + void run() + { + if (!findCandidates()) + return; -// The goal of this phase is to transform Double operations -// into float if the Double result is never used as Double. -// -// In C, that would be something like: -// float add(float a, float b) { -// return (double)a + (double)b; -// } -// -// Such operation arise in JS because there are is no Float type -// and float operations are generated by adding double-to-float rounding. -// -// The operations can be done entirely without Double conversion. -// Using float in place remove the useless conversion, and the float -// ops is sometime massively cheaper (SQRT for example). -// -// If the Double value is used as Double, we do not do the conversion. -// It is cheaper to do a conversion than repeat any floating-point operation. -void reduceDoubleToFloat(Procedure& procedure) -{ - // FIXME: We should tune this phase for performance and make it part of ReduceStrength. - // ReduceStrength can eliminate nodes that prevents us from simplifying operations. - PhaseScope phaseScope(procedure, "reduceDoubleToFloat"); + findPhisContainingFloat(); - HashSet candidates; + simplify(); - // First, we find any value that is converted to float - // and only used as float. - // We also simplify comparisons since that's always safe and we - // don't want them to appear in the next loop. - for (BasicBlock* block : procedure) { - for (Value* value : *block) { - value->performSubstitution(); + cleanUp(); + } + +private: + // This step find values that are used as Double and cannot be converted to Float.. + // It flows the information backward through Phi-Upsilons. + bool findCandidates() + { + bool foundConversionCandidate = false; + Vector upsilons; + + // First, we find all values that are strictly used as double. + // Those are values used by something else than DoubleToFloat. + // + // We don't know the state of Upsilons until their Phi has been + // set. We just keep a list of them and update them next. + for (BasicBlock* block : m_procedure) { + for (Value* value : *block) { + value->performSubstitution(); + + if (value->opcode() == DoubleToFloat) { + foundConversionCandidate = true; + + Value* child = value->child(0); + if (child->opcode() == FloatToDouble) { + // We don't really need to simplify this early but it simplifies debugging. + value->replaceWithIdentity(child->child(0)); + } + continue; + } - switch (value->opcode()) { - case DoubleToFloat: - candidates.add(value->child(0)); - break; - case Equal: - case NotEqual: - case LessThan: - case GreaterThan: - case LessEqual: - case GreaterEqual: - case EqualOrUnordered: - if (value->child(0)->opcode() == FloatToDouble && value->child(1)->opcode() == FloatToDouble) { - value->child(0) = value->child(0)->child(0); - value->child(1) = value->child(1)->child(0); - } - break; - default: - break; + if (value->opcode() == FloatToDouble) + foundConversionCandidate = true; + + if (value->opcode() == Upsilon) { + Value* child = value->child(0); + if (child->type() == Double) + upsilons.append(value); + continue; + } + + for (Value* child : value->children()) { + if (child->type() == Double) + m_valuesUsedAsDouble.add(child); + } + } + } + + if (!foundConversionCandidate) + return false; + + // Now we just need to propagate through Phi-Upsilon. + // A Upsilon can convert its input to float if its phi is never used as double. + // If we modify a phi, we need to continue until all the Upsilon-Phi converge. + bool changedPhiState; + do { + changedPhiState = false; + for (Value* value : upsilons) { + UpsilonValue* upsilon = value->as(); + Value* phi = upsilon->phi(); + if (!m_valuesUsedAsDouble.contains(phi)) + continue; + + Value* child = value->child(0); + bool childChanged = m_valuesUsedAsDouble.add(child); + if (childChanged && child->opcode() == Phi) + changedPhiState = true; + } + } while (changedPhiState); + + if (verbose) { + dataLog("Conversion candidates:\n"); + for (BasicBlock* block : m_procedure) { + for (Value* value : *block) { + if (value->type() == Double && !m_valuesUsedAsDouble.contains(value)) + dataLog(" ", deepDump(m_procedure, value), "\n"); + } } + dataLog("\n"); } + + return true; } - for (BasicBlock* block : procedure) { - for (Value* value : *block) { - if (value->opcode() == DoubleToFloat) - continue; + // This step finds Phis of type Double that effectively contains Float values. + // It flows that information forward through Phi-Upsilons. + void findPhisContainingFloat() + { + Vector upsilons; + + // The Double value that can be safely turned into a Float are: + // - FloatToDouble + // - ConstDouble with a value that converts to Float without losing precision. + for (BasicBlock* block : m_procedure) { + for (Value* value : *block) { + if (value->opcode() != Upsilon) + continue; + + Value* child = value->child(0); + if (child->type() != Double + || child->opcode() == FloatToDouble) + continue; + + if (child->hasDouble()) { + double constValue = child->asDouble(); + if (isIdentical(static_cast(static_cast(constValue)), constValue)) + continue; + } + + if (child->opcode() == Phi) { + upsilons.append(value); + continue; + } + + UpsilonValue* upsilon = value->as(); + Value* phi = upsilon->phi(); + m_phisContainingDouble.add(phi); + } + } + + // Propagate the flags forward. + bool changedPhiState; + do { + changedPhiState = false; + for (Value* value : upsilons) { + Value* child = value->child(0); + if (m_phisContainingDouble.contains(child)) { + UpsilonValue* upsilon = value->as(); + Value* phi = upsilon->phi(); + changedPhiState |= m_phisContainingDouble.add(phi); + } + } + } while (changedPhiState); - for (Value* child : value->children()) { - if (child->type() == Double) - candidates.remove(child); + if (verbose) { + dataLog("Phis containing float values:\n"); + for (BasicBlock* block : m_procedure) { + for (Value* value : *block) { + if (value->opcode() == Phi + && value->type() == Double + && !m_phisContainingDouble.contains(value)) + dataLog(" ", deepDump(m_procedure, value), "\n"); + } } + dataLog("\n"); + } + } + + bool canBeTransformedToFloat(Value* value) + { + if (value->opcode() == FloatToDouble) + return true; + + if (value->hasDouble()) + return true; // Double constant truncated to float. + + if (value->opcode() == Phi) { + return value->type() == Float + || (value->type() == Double && !m_phisContainingDouble.contains(value)); + } + return false; + } + + Value* transformToFloat(Value* value, unsigned valueIndex, InsertionSet& insertionSet) + { + ASSERT(canBeTransformedToFloat(value)); + if (value->opcode() == FloatToDouble) + return value->child(0); + + if (value->hasDouble()) + return insertionSet.insert(valueIndex, value->origin(), static_cast(value->asDouble())); + + if (value->opcode() == Phi) { + convertPhi(value); + return value; } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; + } + + void convertPhi(Value* phi) + { + ASSERT(phi->opcode() == Phi); + phi->setType(Float); + m_convertedPhis.add(phi); + } + + bool attemptTwoOperandsSimplify(Value* candidate, unsigned candidateIndex, InsertionSet& insertionSet) + { + Value* left = candidate->child(0); + Value* right = candidate->child(1); + if (!canBeTransformedToFloat(left) || !canBeTransformedToFloat(right)) + return false; + + m_convertedValue.add(candidate); + candidate->child(0) = transformToFloat(left, candidateIndex, insertionSet); + candidate->child(1) = transformToFloat(right, candidateIndex, insertionSet); + return true; } - if (candidates.isEmpty()) + // Simplify Double operations into Float operations. + void simplify() + { + Vector upsilonReferencingDoublePhi; + + InsertionSet insertionSet(m_procedure); + for (BasicBlock* block : m_procedure) { + for (unsigned index = 0; index < block->size(); ++index) { + Value* value = block->at(index); + + switch (value->opcode()) { + case Equal: + case NotEqual: + case LessThan: + case GreaterThan: + case LessEqual: + case GreaterEqual: + case EqualOrUnordered: + attemptTwoOperandsSimplify(value, index, insertionSet); + continue; + case Upsilon: { + Value* child = value->child(0); + if (child->opcode() == Phi && child->type() == Double) + upsilonReferencingDoublePhi.append(value); + continue; + } + default: + break; + } + + if (m_valuesUsedAsDouble.contains(value)) + continue; + + switch (value->opcode()) { + case Add: + case Sub: + case Mul: + case Div: + if (attemptTwoOperandsSimplify(value, index, insertionSet)) + value->setType(Float); + break; + case Abs: + case Ceil: + case Floor: + case Neg: + case Sqrt: { + Value* child = value->child(0); + if (canBeTransformedToFloat(child)) { + value->child(0) = transformToFloat(child, index, insertionSet); + value->setType(Float); + m_convertedValue.add(value); + } + break; + } + case IToD: { + Value* iToF = insertionSet.insert(index, IToF, value->origin(), value->child(0)); + value->setType(Float); + value->replaceWithIdentity(iToF); + m_convertedValue.add(value); + break; + } + case FloatToDouble: + // This happens if we round twice. + // Typically, this is indirect through Phi-Upsilons. + // The Upsilon rounds and the Phi rounds. + value->setType(Float); + value->replaceWithIdentity(value->child(0)); + m_convertedValue.add(value); + break; + case Phi: + // If a Phi is always converted to Float, we always make it into a float Phi-Upsilon. + // This is a simplistic view of things. Ideally we should keep type that will minimize + // the amount of conversion in the loop. + if (value->type() == Double) + convertPhi(value); + break; + default: + break; + } + } + insertionSet.execute(block); + } + + if (!upsilonReferencingDoublePhi.isEmpty()) { + // If a Phi contains Float values typed as Double, but is not used as Float + // by a non-trivial operation, we did not convert it. + // + // We fix that now by converting the remaining phis that contains + // float but where not converted to float. + bool changedPhi; + do { + changedPhi = false; + + for (Value* value : upsilonReferencingDoublePhi) { + UpsilonValue* upsilon = value->as(); + Value* child = value->child(0); + Value* phi = upsilon->phi(); + if (phi->type() == Float && child->type() == Double + && !m_phisContainingDouble.contains(child)) { + convertPhi(child); + changedPhi = true; + } + } + + } while (changedPhi); + } + } + + // We are in an inconsistent state where we have + // DoubleToFloat nodes over values producing float and Phis that are + // float for Upsilons that are Double. + // + // This steps puts us back in a consistent state. + void cleanUp() + { + InsertionSet insertionSet(m_procedure); + + for (BasicBlock* block : m_procedure) { + for (unsigned index = 0; index < block->size(); ++index) { + Value* value = block->at(index); + if (value->opcode() == DoubleToFloat && value->child(0)->type() == Float) { + value->replaceWithIdentity(value->child(0)); + continue; + } + + if (value->opcode() == Upsilon) { + UpsilonValue* upsilon = value->as(); + Value* child = value->child(0); + Value* phi = upsilon->phi(); + + if (phi->type() == Float) { + if (child->type() == Double) { + Value* newChild = nullptr; + if (child->opcode() == FloatToDouble) + newChild = child->child(0); + else if (child->hasDouble()) + newChild = insertionSet.insert(index, child->origin(), static_cast(child->asDouble())); + else + newChild = insertionSet.insert(index, DoubleToFloat, upsilon->origin(), child); + upsilon->child(0) = newChild; + } + continue; + } + } + + if (!m_convertedValue.contains(value)) { + // Phis can be converted from Double to Float if the value they contain + // is not more precise than a Float. + // If the value is needed as Double, it has to be converted back. + for (Value*& child : value->children()) { + if (m_convertedPhis.contains(child)) + child = insertionSet.insert(index, FloatToDouble, value->origin(), child); + } + } + } + insertionSet.execute(block); + } + } + + Procedure& m_procedure; + + // Set of all the Double values that are actually used as Double. + // Converting any of them to Float would lose precision. + IndexSet m_valuesUsedAsDouble; + + // Set of all the Phi of type Double that really contains a Double. + // Any Double Phi not in the set can be converted to Float without losing precision. + IndexSet m_phisContainingDouble; + + // Any value that was converted from producing a Double to producing a Float. + // This set does not include Phi-Upsilons. + IndexSet m_convertedValue; + + // Any value that previously produced Double and now produce Float. + IndexSet m_convertedPhis; +}; + +void printGraphIfConverting(Procedure& procedure) +{ + if (!printRemainingConversions) return; - // Second, we go over the candidates and attempt to simplify them. - // This leaves the graph in an invalid state where Float Values are - // used by DoubleToFloat Values. This is only temporary. - for (Value* candidate : candidates) - attemptSimplification(candidate); + UseCounts useCount(procedure); + + Vector doubleToFloat; + Vector floatToDouble; - // Finally, remove the DoubleToFloat made useless by the simplifications. for (BasicBlock* block : procedure) { for (Value* value : *block) { - if (value->opcode() == DoubleToFloat && value->child(0)->type() == Float) - value->replaceWithIdentity(value->child(0)); + if (!useCount.numUses(value)) + continue; + + if (value->opcode() == DoubleToFloat) + doubleToFloat.append(value); + if (value->opcode() == FloatToDouble) + floatToDouble.append(value); } } - // We do not clean all the useless nodes and conversions. ReduceStrength does that better. + if (doubleToFloat.isEmpty() && floatToDouble.isEmpty()) + return; + + dataLog("Procedure with Float-Double conversion:\n", procedure, "\n"); + dataLog("Converting nodes:\n"); + for (Value* value : doubleToFloat) + dataLog(" ", deepDump(procedure, value), "\n"); + for (Value* value : floatToDouble) + dataLog(" ", deepDump(procedure, value), "\n"); + +} + +} // anonymous namespace. + +void reduceDoubleToFloat(Procedure& procedure) +{ + PhaseScope phaseScope(procedure, "reduceDoubleToFloat"); + + if (verbose) + dataLog("Before DoubleToFloatReduction:\n", procedure, "\n"); + + DoubleToFloatReduction doubleToFloatReduction(procedure); + doubleToFloatReduction.run(); + + if (verbose) + dataLog("After DoubleToFloatReduction:\n", procedure, "\n"); + + printGraphIfConverting(procedure); } } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ReduceStrength.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ReduceStrength.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ReduceStrength.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ReduceStrength.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -31,9 +31,7 @@ #include "B3BasicBlockInlines.h" #include "B3BlockInsertionSet.h" #include "B3ComputeDivisionMagic.h" -#include "B3ControlValue.h" #include "B3Dominators.h" -#include "B3IndexSet.h" #include "B3InsertionSetInlines.h" #include "B3MemoryValue.h" #include "B3PhaseScope.h" @@ -49,6 +47,7 @@ #include "B3VariableValue.h" #include #include +#include namespace JSC { namespace B3 { @@ -418,7 +417,30 @@ dataLog("B3 after iteration #", index - 1, " of reduceStrength:\n"); dataLog(m_proc); } + + simplifyCFG(); + if (m_changedCFG) { + m_proc.resetReachability(); + m_proc.invalidateCFG(); + m_changed = true; + } + + // We definitely want to do DCE before we do CSE so that we don't hoist things. For + // example: + // + // @dead = Mul(@a, @b) + // ... lots of control flow and stuff + // @thing = Mul(@a, @b) + // + // If we do CSE before DCE, we will remove @thing and keep @dead. Effectively, we will + // "hoist" @thing. On the other hand, if we run DCE before CSE, we will kill @dead and + // keep @thing. That's better, since we usually want things to stay wherever the client + // put them. We're not actually smart enough to move things around at random. + killDeadCode(); + + simplifySSA(); + m_proc.resetValueOwners(); m_dominators = &m_proc.dominators(); // Recompute if necessary. m_pureCSE.clear(); @@ -441,23 +463,13 @@ m_insertionSet.execute(m_block); } - if (m_blockInsertionSet.execute()) { - m_proc.resetReachability(); - m_proc.invalidateCFG(); - m_dominators = &m_proc.dominators(); // Recompute if necessary. - m_changedCFG = true; - } - - simplifyCFG(); - + m_changedCFG |= m_blockInsertionSet.execute(); if (m_changedCFG) { m_proc.resetReachability(); m_proc.invalidateCFG(); + m_dominators = nullptr; // Dominators are not valid anymore, and we don't need them yet. m_changed = true; } - - killDeadCode(); - simplifySSA(); result |= m_changed; } while (m_changed); @@ -1324,6 +1336,24 @@ } break; + case IToD: + // Turn this: IToD(constant) + // Into this: ConstDouble(constant) + if (Value* constant = m_value->child(0)->iToDConstant(m_proc)) { + replaceWithNewValue(constant); + break; + } + break; + + case IToF: + // Turn this: IToF(constant) + // Into this: ConstFloat(constant) + if (Value* constant = m_value->child(0)->iToFConstant(m_proc)) { + replaceWithNewValue(constant); + break; + } + break; + case FloatToDouble: // Turn this: FloatToDouble(constant) // Into this: ConstDouble(constant) @@ -1698,8 +1728,8 @@ // Replace the rest of the block with an Oops. for (unsigned i = m_index + 1; i < m_block->size() - 1; ++i) - m_block->at(i)->replaceWithNop(); - m_block->last()->as()->convertToOops(); + m_block->at(i)->replaceWithBottom(m_insertionSet, m_index); + m_block->last()->replaceWithOops(m_block); m_block->last()->setOrigin(checkValue->origin()); // Replace ourselves last. @@ -1755,6 +1785,7 @@ return value->opcode() == Select && (value->child(1)->isConstant() && value->child(2)->isConstant()); }); + if (select) { specializeSelect(select); break; @@ -1763,50 +1794,48 @@ } case Branch: { - ControlValue* branch = m_value->as(); - // Turn this: Branch(NotEqual(x, 0)) // Into this: Branch(x) - if (branch->child(0)->opcode() == NotEqual && branch->child(0)->child(1)->isInt(0)) { - branch->child(0) = branch->child(0)->child(0); + if (m_value->child(0)->opcode() == NotEqual && m_value->child(0)->child(1)->isInt(0)) { + m_value->child(0) = m_value->child(0)->child(0); m_changed = true; } // Turn this: Branch(Equal(x, 0), then, else) // Into this: Branch(x, else, then) - if (branch->child(0)->opcode() == Equal && branch->child(0)->child(1)->isInt(0)) { - branch->child(0) = branch->child(0)->child(0); - std::swap(branch->taken(), branch->notTaken()); + if (m_value->child(0)->opcode() == Equal && m_value->child(0)->child(1)->isInt(0)) { + m_value->child(0) = m_value->child(0)->child(0); + std::swap(m_block->taken(), m_block->notTaken()); m_changed = true; } // Turn this: Branch(BitXor(bool, 1), then, else) // Into this: Branch(bool, else, then) - if (branch->child(0)->opcode() == BitXor - && branch->child(0)->child(1)->isInt32(1) - && branch->child(0)->child(0)->returnsBool()) { - branch->child(0) = branch->child(0)->child(0); - std::swap(branch->taken(), branch->notTaken()); + if (m_value->child(0)->opcode() == BitXor + && m_value->child(0)->child(1)->isInt32(1) + && m_value->child(0)->child(0)->returnsBool()) { + m_value->child(0) = m_value->child(0)->child(0); + std::swap(m_block->taken(), m_block->notTaken()); m_changed = true; } // Turn this: Branch(BitAnd(bool, xyb1), then, else) // Into this: Branch(bool, then, else) - if (branch->child(0)->opcode() == BitAnd - && branch->child(0)->child(1)->hasInt() - && branch->child(0)->child(1)->asInt() & 1 - && branch->child(0)->child(0)->returnsBool()) { - branch->child(0) = branch->child(0)->child(0); + if (m_value->child(0)->opcode() == BitAnd + && m_value->child(0)->child(1)->hasInt() + && m_value->child(0)->child(1)->asInt() & 1 + && m_value->child(0)->child(0)->returnsBool()) { + m_value->child(0) = m_value->child(0)->child(0); m_changed = true; } - TriState triState = branch->child(0)->asTriState(); + TriState triState = m_value->child(0)->asTriState(); // Turn this: Branch(0, then, else) // Into this: Jump(else) if (triState == FalseTriState) { - branch->taken().block()->removePredecessor(m_block); - branch->convertToJump(branch->notTaken().block()); + m_block->taken().block()->removePredecessor(m_block); + m_value->replaceWithJump(m_block, m_block->notTaken()); m_changedCFG = true; break; } @@ -1814,8 +1843,8 @@ // Turn this: Branch(not 0, then, else) // Into this: Jump(then) if (triState == TrueTriState) { - branch->notTaken().block()->removePredecessor(m_block); - branch->convertToJump(branch->taken().block()); + m_block->notTaken().block()->removePredecessor(m_block); + m_value->replaceWithJump(m_block, m_block->taken()); m_changedCFG = true; break; } @@ -1824,12 +1853,12 @@ // of makes sense here because it's cheap, but hacks like this show that we're going // to need SCCP. Value* check = m_pureCSE.findMatch( - ValueKey(Check, Void, branch->child(0)), m_block, *m_dominators); + ValueKey(Check, Void, m_value->child(0)), m_block, *m_dominators); if (check) { // The Check would have side-exited if child(0) was non-zero. So, it must be // zero here. - branch->taken().block()->removePredecessor(m_block); - branch->convertToJump(branch->notTaken().block()); + m_block->taken().block()->removePredecessor(m_block); + m_value->replaceWithJump(m_block, m_block->notTaken()); m_changedCFG = true; } break; @@ -1968,13 +1997,12 @@ // Remove the values from the predecessor. predecessor->values().resize(startIndex); - predecessor->appendNew( - m_proc, Branch, source->origin(), predicate, - FrequentedBlock(cases[0]), FrequentedBlock(cases[1])); + predecessor->appendNew(m_proc, Branch, source->origin(), predicate); + predecessor->setSuccessors(FrequentedBlock(cases[0]), FrequentedBlock(cases[1])); for (unsigned i = 0; i < numCases; ++i) { - cases[i]->appendNew( - m_proc, Jump, m_value->origin(), FrequentedBlock(m_block)); + cases[i]->appendNew(m_proc, Jump, m_value->origin()); + cases[i]->setSuccessors(FrequentedBlock(m_block)); } m_changed = true; @@ -2203,7 +2231,7 @@ dataLog( "Changing ", pointerDump(block), "'s terminal to a Jump.\n"); } - block->last()->as()->convertToJump(firstSuccessor); + block->last()->replaceWithJump(block, FrequentedBlock(firstSuccessor)); m_changedCFG = true; } } @@ -2221,16 +2249,18 @@ // Remove the terminal. Value* value = block->values().takeLast(); Origin jumpOrigin = value->origin(); - RELEASE_ASSERT(value->as()); + RELEASE_ASSERT(value->effects().terminal); m_proc.deleteValue(value); // Append the full contents of the successor to the predecessor. block->values().appendVector(successor->values()); + block->successors() = successor->successors(); // Make sure that the successor has nothing left in it. Make sure that the block // has a terminal so that nobody chokes when they look at it. successor->values().resize(0); - successor->appendNew(m_proc, Oops, jumpOrigin); + successor->appendNew(m_proc, Oops, jumpOrigin); + successor->clearSuccessors(); // Ensure that predecessors of block's new successors know what's up. for (BasicBlock* newSuccessor : block->successorBlocks()) @@ -2315,11 +2345,6 @@ block->at(targetIndex++) = value; } else { m_proc.deleteValue(value); - - // It's not entirely clear if this is needed. I think it makes sense to have - // this force a rerun of the fixpoint for now, since that will make it easier - // to do peephole optimizations: removing dead code will make the peephole - // easier to spot. m_changed = true; } } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ReduceStrength.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ReduceStrength.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ReduceStrength.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ReduceStrength.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,7 +40,7 @@ // add sophisticated optimizations to it. For that reason we have full CSE in a different phase, for // example. -bool reduceStrength(Procedure&); +JS_EXPORT_PRIVATE bool reduceStrength(Procedure&); } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SparseCollection.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SparseCollection.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SparseCollection.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SparseCollection.h 2016-11-03 07:04:20.000000000 +0000 @@ -57,8 +57,8 @@ index = m_indexFreeList.takeLast(); value->m_index = index; - - m_vector[index] = WTFMove(value); + ASSERT(!m_vector[index]); + new (NotNull, &m_vector[index]) std::unique_ptr(WTFMove(value)); return result; } @@ -134,8 +134,8 @@ iterator end() const { return iterator(*this, size()); } private: - Vector> m_vector; - Vector m_indexFreeList; + Vector, 0, UnsafeVectorOverflow> m_vector; + Vector m_indexFreeList; }; } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SSACalculator.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SSACalculator.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SSACalculator.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SSACalculator.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,9 +29,9 @@ #if ENABLE(B3_JIT) #include "B3Dominators.h" -#include "B3IndexMap.h" #include "B3ProcedureInlines.h" #include +#include #include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3StackmapGenerationParams.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3StackmapGenerationParams.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3StackmapGenerationParams.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3StackmapGenerationParams.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,6 +59,27 @@ return result; } +Vector> StackmapGenerationParams::successorLabels() const +{ + RELEASE_ASSERT(m_context.indexInBlock == m_context.currentBlock->size() - 1); + RELEASE_ASSERT(m_value->effects().terminal); + + Vector> result(m_context.currentBlock->numSuccessors()); + for (unsigned i = m_context.currentBlock->numSuccessors(); i--;) + result[i] = m_context.blockLabels[m_context.currentBlock->successorBlock(i)]; + return result; +} + +bool StackmapGenerationParams::fallsThroughToSuccessor(unsigned successorIndex) const +{ + RELEASE_ASSERT(m_context.indexInBlock == m_context.currentBlock->size() - 1); + RELEASE_ASSERT(m_value->effects().terminal); + + Air::BasicBlock* successor = m_context.currentBlock->successorBlock(successorIndex); + Air::BasicBlock* nextBlock = m_context.code->findNextBlock(m_context.currentBlock); + return successor == nextBlock; +} + Procedure& StackmapGenerationParams::proc() const { return m_context.code->proc(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3StackmapGenerationParams.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3StackmapGenerationParams.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3StackmapGenerationParams.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3StackmapGenerationParams.h 2016-11-03 07:04:20.000000000 +0000 @@ -30,7 +30,9 @@ #include "AirGenerationContext.h" #include "B3ValueRep.h" +#include "CCallHelpers.h" #include "RegisterSet.h" +#include namespace JSC { namespace B3 { @@ -39,6 +41,8 @@ class Procedure; class StackmapValue; +// NOTE: It's possible to capture StackmapGenerationParams by value, but not all of the methods will +// work if you do that. class StackmapGenerationParams { public: // This is the stackmap value that we're generating. @@ -80,9 +84,18 @@ GPRReg gpScratch(unsigned index) const { return m_gpScratch[index]; } FPRReg fpScratch(unsigned index) const { return m_fpScratch[index]; } + + // This is computed lazily, so it won't work if you capture StackmapGenerationParams by value. + // These labels will get populated before any late paths or link tasks execute. + JS_EXPORT_PRIVATE Vector> successorLabels() const; + + // This is computed lazily, so it won't work if you capture StackmapGenerationParams by value. + // Returns true if the successor at the given index is going to be emitted right after the + // patchpoint. + JS_EXPORT_PRIVATE bool fallsThroughToSuccessor(unsigned successorIndex) const; // This is provided for convenience; it means that you don't have to capture it if you don't want to. - Procedure& proc() const; + JS_EXPORT_PRIVATE Procedure& proc() const; // The Air::GenerationContext gives you even more power. Air::GenerationContext& context() const { return m_context; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -107,12 +107,18 @@ case ValueRep::Constant: role = Arg::Use; break; + case ValueRep::LateRegister: + role = Arg::LateUse; + break; case ValueRep::ColdAny: role = Arg::ColdUse; break; case ValueRep::LateColdAny: role = Arg::LateColdUse; break; + default: + RELEASE_ASSERT_NOT_REACHED(); + break; } break; case ForceLateUse: @@ -227,7 +233,9 @@ // We already verified by isArgValidForValue(). return true; case ValueRep::SomeRegister: + case ValueRep::SomeEarlyRegister: return arg.isTmp(); + case ValueRep::LateRegister: case ValueRep::Register: return arg == Tmp(rep.reg()); case ValueRep::StackArgument: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SwitchValue.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SwitchValue.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SwitchValue.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SwitchValue.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -37,30 +37,76 @@ { } -SwitchCase SwitchValue::removeCase(unsigned index) +SwitchCase SwitchValue::removeCase(BasicBlock* block, unsigned index) { - FrequentedBlock resultBlock = m_successors[index]; + FrequentedBlock resultBlock = block->successor(index); int64_t resultValue = m_values[index]; - m_successors[index] = m_successors.last(); - m_successors.removeLast(); + block->successor(index) = block->successors().last(); + block->successors().removeLast(); m_values[index] = m_values.last(); m_values.removeLast(); return SwitchCase(resultValue, resultBlock); } -void SwitchValue::appendCase(const SwitchCase& switchCase) +bool SwitchValue::hasFallThrough(const BasicBlock* block) const +{ + unsigned numSuccessors = block->numSuccessors(); + unsigned numValues = m_values.size(); + RELEASE_ASSERT(numValues == numSuccessors || numValues + 1 == numSuccessors); + + return numValues + 1 == numSuccessors; +} + +bool SwitchValue::hasFallThrough() const +{ + return hasFallThrough(owner); +} + +void SwitchValue::setFallThrough(BasicBlock* block, const FrequentedBlock& target) +{ + if (!hasFallThrough()) + block->successors().append(target); + else + block->successors().last() = target; + ASSERT(hasFallThrough(block)); +} + +void SwitchValue::appendCase(BasicBlock* block, const SwitchCase& switchCase) { - m_successors.append(m_successors.last()); - m_successors[m_successors.size() - 2] = switchCase.target(); + if (!hasFallThrough()) + block->successors().append(switchCase.target()); + else { + block->successors().append(block->successors().last()); + block->successor(block->numSuccessors() - 2) = switchCase.target(); + } m_values.append(switchCase.caseValue()); } +void SwitchValue::setFallThrough(const FrequentedBlock& target) +{ + setFallThrough(owner, target); +} + +void SwitchValue::appendCase(const SwitchCase& switchCase) +{ + appendCase(owner, switchCase); +} + +void SwitchValue::dumpSuccessors(const BasicBlock* block, PrintStream& out) const +{ + // We must not crash due to a number-of-successors mismatch! Someone debugging a + // number-of-successors bug will want to dump IR! + if (numCaseValues() + 1 != block->numSuccessors()) { + Value::dumpSuccessors(block, out); + return; + } + + out.print(cases(block)); +} + void SwitchValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const { - // This destructively overrides ControlValue's dumpMeta(). - for (SwitchCase switchCase : *this) - out.print(comma, switchCase); - out.print(comma, "fallThrough = ", fallThrough()); + out.print(comma, "cases = [", listDump(m_values), "]"); } Value* SwitchValue::cloneImpl() const @@ -68,10 +114,9 @@ return new SwitchValue(*this); } -SwitchValue::SwitchValue(Origin origin, Value* child, const FrequentedBlock& fallThrough) - : ControlValue(Switch, Void, origin, child) +SwitchValue::SwitchValue(Origin origin, Value* child) + : Value(CheckedOpcode, Switch, Void, origin, child) { - m_successors.append(fallThrough); } } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SwitchValue.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SwitchValue.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3SwitchValue.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3SwitchValue.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,12 +28,13 @@ #if ENABLE(B3_JIT) -#include "B3ControlValue.h" +#include "B3CaseCollection.h" #include "B3SwitchCase.h" +#include "B3Value.h" namespace JSC { namespace B3 { -class SwitchValue : public ControlValue { +class SwitchValue : public Value { public: static bool accepts(Opcode opcode) { return opcode == Switch; } @@ -47,72 +48,26 @@ const Vector& caseValues() const { return m_values; } - FrequentedBlock fallThrough() const { return successors().last(); } - FrequentedBlock& fallThrough() { return successors().last(); } - - unsigned size() const { return numCaseValues(); } - SwitchCase at(unsigned index) const - { - return SwitchCase(caseValue(index), successor(index)); - } - SwitchCase operator[](unsigned index) const - { - return at(index); - } - - class iterator { - public: - iterator() - : m_switch(nullptr) - , m_index(0) - { - } - - iterator(const SwitchValue& switchValue, unsigned index) - : m_switch(&switchValue) - , m_index(index) - { - } - - SwitchCase operator*() - { - return m_switch->at(m_index); - } - - iterator& operator++() - { - m_index++; - return *this; - } - - bool operator==(const iterator& other) const - { - ASSERT(m_switch == other.m_switch); - return m_index == other.m_index; - } - - bool operator!=(const iterator& other) const - { - return !(*this == other); - } - - private: - const SwitchValue* m_switch; - unsigned m_index; - }; - - typedef iterator const_iterator; - - iterator begin() const { return iterator(*this, 0); } - iterator end() const { return iterator(*this, size()); } + CaseCollection cases(const BasicBlock* owner) const { return CaseCollection(this, owner); } + CaseCollection cases() const { return cases(owner); } // This removes the case and reorders things a bit. If you're iterating the cases from 0 to N, // then you can keep iterating after this so long as you revisit this same index (which will now // contain some other case value). This removes the case that was removed. - SwitchCase removeCase(unsigned index); + SwitchCase removeCase(BasicBlock*, unsigned index); + bool hasFallThrough(const BasicBlock*) const; + bool hasFallThrough() const; + + // These two functions can be called in any order. + void setFallThrough(BasicBlock*, const FrequentedBlock&); + void appendCase(BasicBlock*, const SwitchCase&); + + JS_EXPORT_PRIVATE void setFallThrough(const FrequentedBlock&); JS_EXPORT_PRIVATE void appendCase(const SwitchCase&); + void dumpSuccessors(const BasicBlock*, PrintStream&) const override; + protected: void dumpMeta(CommaPrinter&, PrintStream&) const override; @@ -121,7 +76,7 @@ private: friend class Procedure; - JS_EXPORT_PRIVATE SwitchValue(Origin, Value* child, const FrequentedBlock& fallThrough); + JS_EXPORT_PRIVATE SwitchValue(Origin, Value* child); Vector m_values; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Type.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Type.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Type.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Type.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,11 +39,12 @@ namespace JSC { namespace B3 { enum Type : int8_t { - Void, Int32, Int64, Float, - Double + Double, + LastValueType = Double, + Void }; inline bool isInt(Type type) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3TypeMap.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3TypeMap.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3TypeMap.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3TypeMap.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef B3TypeMap_h +#define B3TypeMap_h + +#if ENABLE(B3_JIT) + +#include "B3Type.h" +#include + +#if COMPILER(GCC) && ASSERT_DISABLED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-type" +#endif // COMPILER(GCC) && ASSERT_DISABLED + +namespace JSC { namespace B3 { + +template +class TypeMap { +public: + TypeMap() + : m_void() + , m_int32() + , m_int64() + , m_float() + , m_double() + { + } + + T& at(Type type) + { + switch (type) { + case Void: + return m_void; + case Int32: + return m_int32; + case Int64: + return m_int64; + case Float: + return m_float; + case Double: + return m_double; + } + ASSERT_NOT_REACHED(); + } + + const T& at(Type type) const + { + return bitwise_cast(this)->at(type); + } + + T& operator[](Type type) + { + return at(type); + } + + const T& operator[](Type type) const + { + return at(type); + } + + void dump(PrintStream& out) const + { + out.print( + "{void = ", m_void, + ", int32 = ", m_int32, + ", int64 = ", m_int64, + ", float = ", m_float, + ", double = ", m_double, "}"); + } + +private: + T m_void; + T m_int32; + T m_int64; + T m_float; + T m_double; +}; + +} } // namespace JSC::B3 + +#if COMPILER(GCC) && ASSERT_DISABLED +#pragma GCC diagnostic pop +#endif // COMPILER(GCC) && ASSERT_DISABLED + +#endif // ENABLE(B3_JIT) + +#endif // B3TypeMap_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3UseCounts.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3UseCounts.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3UseCounts.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3UseCounts.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,8 +28,8 @@ #if ENABLE(B3_JIT) -#include "B3IndexMap.h" #include "B3Value.h" +#include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Validate.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Validate.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Validate.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Validate.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -35,6 +35,7 @@ #include "B3Procedure.h" #include "B3SlotBaseValue.h" #include "B3StackSlot.h" +#include "B3SwitchValue.h" #include "B3UpsilonValue.h" #include "B3ValueInlines.h" #include "B3Variable.h" @@ -107,8 +108,8 @@ for (BasicBlock* block : blocks) { VALIDATE(block->size() >= 1, ("At ", *block)); for (unsigned i = 0; i < block->size() - 1; ++i) - VALIDATE(!ControlValue::accepts(block->at(i)->opcode()), ("At ", *block->at(i))); - VALIDATE(ControlValue::accepts(block->last()->opcode()), ("At ", *block->last())); + VALIDATE(!block->at(i)->effects().terminal, ("At ", *block->at(i))); + VALIDATE(block->last()->effects().terminal, ("At ", *block->last())); for (BasicBlock* successor : block->successorBlocks()) { allPredecessors.add(successor, HashSet()).iterator->value.add(block); @@ -129,8 +130,6 @@ VALIDATE(child->type() != Void, ("At ", *value, "->", *child)); switch (value->opcode()) { case Nop: - case Jump: - case Oops: VALIDATE(!value->numChildren(), ("At ", *value)); VALIDATE(value->type() == Void, ("At ", *value)); break; @@ -252,6 +251,11 @@ VALIDATE(isInt(value->child(0)->type()), ("At ", *value)); VALIDATE(value->type() == Double, ("At ", *value)); break; + case IToF: + VALIDATE(value->numChildren() == 1, ("At ", *value)); + VALIDATE(isInt(value->child(0)->type()), ("At ", *value)); + VALIDATE(value->type() == Float, ("At ", *value)); + break; case FloatToDouble: VALIDATE(value->numChildren() == 1, ("At ", *value)); VALIDATE(value->child(0)->type() == Float, ("At ", *value)); @@ -333,6 +337,7 @@ switch (value->as()->resultConstraint.kind()) { case ValueRep::WarmAny: case ValueRep::SomeRegister: + case ValueRep::SomeEarlyRegister: case ValueRep::Register: case ValueRep::StackArgument: break; @@ -341,7 +346,7 @@ break; } - validateStackmapConstraint(value, ConstrainedValue(value, value->as()->resultConstraint)); + validateStackmapConstraint(value, ConstrainedValue(value, value->as()->resultConstraint), ConstraintRole::Def); } validateStackmap(value); break; @@ -372,15 +377,48 @@ VALIDATE(!value->numChildren(), ("At ", *value)); VALIDATE(value->type() != Void, ("At ", *value)); break; + case Jump: + VALIDATE(!value->numChildren(), ("At ", *value)); + VALIDATE(value->type() == Void, ("At ", *value)); + VALIDATE(valueOwner.get(value)->numSuccessors() == 1, ("At ", *value)); + break; + case Oops: + VALIDATE(!value->numChildren(), ("At ", *value)); + VALIDATE(value->type() == Void, ("At ", *value)); + VALIDATE(!valueOwner.get(value)->numSuccessors(), ("At ", *value)); + break; case Return: - VALIDATE(value->numChildren() == 1, ("At ", *value)); + VALIDATE(value->numChildren() <= 1, ("At ", *value)); VALIDATE(value->type() == Void, ("At ", *value)); + VALIDATE(!valueOwner.get(value)->numSuccessors(), ("At ", *value)); break; case Branch: - case Switch: VALIDATE(value->numChildren() == 1, ("At ", *value)); VALIDATE(isInt(value->child(0)->type()), ("At ", *value)); VALIDATE(value->type() == Void, ("At ", *value)); + VALIDATE(valueOwner.get(value)->numSuccessors() == 2, ("At ", *value)); + break; + case Switch: { + VALIDATE(value->numChildren() == 1, ("At ", *value)); + VALIDATE(isInt(value->child(0)->type()), ("At ", *value)); + VALIDATE(value->type() == Void, ("At ", *value)); + VALIDATE(value->as()->hasFallThrough(valueOwner.get(value)), ("At ", *value)); + // This validates the same thing as hasFallThrough, but more explicitly. We want to + // make sure that if anyone tries to change the definition of hasFallThrough, they + // will feel some pain here, since this is fundamental. + VALIDATE(valueOwner.get(value)->numSuccessors() == value->as()->numCaseValues() + 1, ("At ", *value)); + + // Check that there are no duplicate cases. + Vector caseValues = value->as()->caseValues(); + std::sort(caseValues.begin(), caseValues.end()); + for (unsigned i = 1; i < caseValues.size(); ++i) + VALIDATE(caseValues[i - 1] != caseValues[i], ("At ", *value, ", caseValue = ", caseValues[i])); + break; + } + case EntrySwitch: + VALIDATE(!value->numChildren(), ("At ", *value)); + VALIDATE(value->type() == Void, ("At ", *value)); + VALIDATE(valueOwner.get(value)->numSuccessors() == m_procedure.numEntrypoints(), ("At ", *value)); break; } @@ -401,7 +439,11 @@ validateStackmapConstraint(stackmap, child); } - void validateStackmapConstraint(Value* context, const ConstrainedValue& value) + enum class ConstraintRole { + Use, + Def + }; + void validateStackmapConstraint(Value* context, const ConstrainedValue& value, ConstraintRole role = ConstraintRole::Use) { switch (value.rep().kind()) { case ValueRep::WarmAny: @@ -410,7 +452,11 @@ case ValueRep::SomeRegister: case ValueRep::StackArgument: break; + case ValueRep::SomeEarlyRegister: + VALIDATE(role == ConstraintRole::Def, ("At ", *context, ": ", value)); + break; case ValueRep::Register: + case ValueRep::LateRegister: if (value.rep().reg().isGPR()) VALIDATE(isInt(value.value()->type()), ("At ", *context, ": ", value)); else diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Validate.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Validate.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Validate.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Validate.h 2016-11-03 07:04:20.000000000 +0000 @@ -32,7 +32,7 @@ class Procedure; -void validate(Procedure&, const char* dumpBefore = nullptr); +JS_EXPORT_PRIVATE void validate(Procedure&, const char* dumpBefore = nullptr); } } // namespace JSC::B3 diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Value.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Value.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Value.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Value.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -29,8 +29,9 @@ #if ENABLE(B3_JIT) #include "B3ArgumentRegValue.h" +#include "B3BasicBlockInlines.h" +#include "B3BottomProvider.h" #include "B3CCallValue.h" -#include "B3ControlValue.h" #include "B3MemoryValue.h" #include "B3OriginDump.h" #include "B3ProcedureInlines.h" @@ -41,6 +42,7 @@ #include "B3ValueKeyInlines.h" #include "B3VariableValue.h" #include +#include #include namespace JSC { namespace B3 { @@ -60,7 +62,7 @@ ASSERT(m_type == value->m_type); if (m_type == Void) { - replaceWithNop(); + replaceWithNopIgnoringType(); return; } @@ -79,8 +81,19 @@ this->m_index = index; } +void Value::replaceWithBottom(InsertionSet& insertionSet, size_t index) +{ + replaceWithBottom(BottomProvider(insertionSet, index)); +} + void Value::replaceWithNop() { + RELEASE_ASSERT(m_type == Void); + replaceWithNopIgnoringType(); +} + +void Value::replaceWithNopIgnoringType() +{ unsigned index = m_index; Origin origin = m_origin; BasicBlock* owner = this->owner; @@ -113,6 +126,50 @@ this->m_index = index; } +void Value::replaceWithJump(BasicBlock* owner, FrequentedBlock target) +{ + RELEASE_ASSERT(owner->last() == this); + + unsigned index = m_index; + Origin origin = m_origin; + + this->~Value(); + + new (this) Value(Jump, Void, origin); + + this->owner = owner; + this->m_index = index; + + owner->setSuccessors(target); +} + +void Value::replaceWithOops(BasicBlock* owner) +{ + RELEASE_ASSERT(owner->last() == this); + + unsigned index = m_index; + Origin origin = m_origin; + + this->~Value(); + + new (this) Value(Oops, Void, origin); + + this->owner = owner; + this->m_index = index; + + owner->clearSuccessors(); +} + +void Value::replaceWithJump(FrequentedBlock target) +{ + replaceWithJump(owner, target); +} + +void Value::replaceWithOops() +{ + replaceWithOops(owner); +} + void Value::dump(PrintStream& out) const { bool isConstant = false; @@ -177,6 +234,19 @@ out.print(")"); } +void Value::dumpSuccessors(const BasicBlock* block, PrintStream& out) const +{ + // Note that this must not crash if we have the wrong number of successors, since someone + // debugging a number-of-successors bug will probably want to dump IR! + + if (opcode() == Branch && block->numSuccessors() == 2) { + out.print("Then:", block->taken(), ", Else:", block->notTaken()); + return; + } + + out.print(listDump(block->successors())); +} + Value* Value::negConstant(Procedure&) const { return nullptr; @@ -267,6 +337,16 @@ return nullptr; } +Value* Value::iToDConstant(Procedure&) const +{ + return nullptr; +} + +Value* Value::iToFConstant(Procedure&) const +{ + return nullptr; +} + Value* Value::doubleToFloatConstant(Procedure&) const { return nullptr; @@ -368,6 +448,7 @@ case Floor: case Ceil: case IToD: + case IToF: return true; case ConstDouble: { @@ -470,6 +551,7 @@ case ZExt32: case Trunc: case IToD: + case IToF: case FloatToDouble: case DoubleToFloat: case Equal: @@ -530,6 +612,7 @@ case Switch: case Return: case Oops: + case EntrySwitch: result.terminal = true; break; } @@ -553,6 +636,7 @@ case Clz: case Trunc: case IToD: + case IToF: case FloatToDouble: case DoubleToFloat: case Check: @@ -616,28 +700,24 @@ } } -void Value::dumpMeta(CommaPrinter&, PrintStream&) const +bool Value::isFree() const { + switch (opcode()) { + case Const32: + case Const64: + case ConstDouble: + case ConstFloat: + case Identity: + case Nop: + return true; + default: + return false; + } } -#if !ASSERT_DISABLED -void Value::checkOpcode(Opcode opcode) +void Value::dumpMeta(CommaPrinter&, PrintStream&) const { - ASSERT(!ArgumentRegValue::accepts(opcode)); - ASSERT(!CCallValue::accepts(opcode)); - ASSERT(!CheckValue::accepts(opcode)); - ASSERT(!Const32Value::accepts(opcode)); - ASSERT(!Const64Value::accepts(opcode)); - ASSERT(!ConstDoubleValue::accepts(opcode)); - ASSERT(!ConstFloatValue::accepts(opcode)); - ASSERT(!ControlValue::accepts(opcode)); - ASSERT(!MemoryValue::accepts(opcode)); - ASSERT(!PatchpointValue::accepts(opcode)); - ASSERT(!SlotBaseValue::accepts(opcode)); - ASSERT(!UpsilonValue::accepts(opcode)); - ASSERT(!VariableValue::accepts(opcode)); } -#endif // !ASSERT_DISABLED Type Value::typeFor(Opcode opcode, Value* firstChild, Value* secondChild) { @@ -690,6 +770,7 @@ case IToD: return Double; case DoubleToFloat: + case IToF: return Float; case BitwiseCast: switch (firstChild->type()) { @@ -706,6 +787,11 @@ } return Void; case Nop: + case Jump: + case Branch: + case Return: + case Oops: + case EntrySwitch: return Void; case Select: ASSERT(secondChild); @@ -715,6 +801,12 @@ } } +void Value::badOpcode(Opcode opcode, unsigned numArgs) +{ + dataLog("Bad opcode ", opcode, " with ", numArgs, " args.\n"); + RELEASE_ASSERT_NOT_REACHED(); +} + } } // namespace JSC::B3 #endif // ENABLE(B3_JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Value.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Value.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3Value.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3Value.h 2016-11-03 07:04:20.000000000 +0000 @@ -30,6 +30,7 @@ #include "AirArg.h" #include "B3Effects.h" +#include "B3FrequentedBlock.h" #include "B3Opcode.h" #include "B3Origin.h" #include "B3SparseCollection.h" @@ -43,6 +44,7 @@ class BasicBlock; class CheckValue; +class InsertionSet; class PhiChildren; class Procedure; @@ -59,7 +61,8 @@ unsigned index() const { return m_index; } - // Note that the opcode is immutable, except for replacing values with Identity or Nop. + // Note that the opcode is immutable, except for replacing values with: + // Identity, Nop, Oops, Jump, and Phi. See below for replaceWithXXX() methods. Opcode opcode() const { return m_opcode; } Origin origin() const { return m_origin; } @@ -83,12 +86,44 @@ AdjacencyList& children() { return m_children; } const AdjacencyList& children() const { return m_children; } + // If you want to replace all uses of this value with a different value, then replace this + // value with Identity. Then do a pass of performSubstitution() on all of the values that use + // this one. Usually we do all of this in one pass in pre-order, which ensures that the + // X->replaceWithIdentity() calls happen before the performSubstitution() calls on X's users. void replaceWithIdentity(Value*); + + // It's often necessary to kill a value. It's tempting to replace the value with Nop or to + // just remove it. But unless you are sure that the value is Void, you will probably still + // have other values that use this one. Sure, you may kill those later, or you might not. This + // method lets you kill a value safely. It will replace Void values with Nop and non-Void + // values with Identities on bottom constants. For this reason, this takes a callback that is + // responsible for creating bottoms. There's a utility for this, see B3BottomProvider.h. You + // can also access that utility using replaceWithBottom(InsertionSet&, size_t). + template + void replaceWithBottom(const BottomProvider&); + + void replaceWithBottom(InsertionSet&, size_t index); + + // Use this if you want to kill a value and you are sure that the value is Void. void replaceWithNop(); + + // Use this if you want to kill a value and you are sure that nobody is using it anymore. + void replaceWithNopIgnoringType(); + void replaceWithPhi(); + + // These transformations are only valid for terminals. + void replaceWithJump(BasicBlock* owner, FrequentedBlock); + void replaceWithOops(BasicBlock* owner); + + // You can use this form if owners are valid. They're usually not valid. + void replaceWithJump(FrequentedBlock); + void replaceWithOops(); void dump(PrintStream&) const; void deepDump(const Procedure*, PrintStream&) const; + + virtual void dumpSuccessors(const BasicBlock*, PrintStream&) const; // This is how you cast Values. For example, if you want to do something provided that we have a // ArgumentRegValue, you can do: @@ -133,6 +168,8 @@ virtual Value* sShrConstant(Procedure&, const Value* other) const; virtual Value* zShrConstant(Procedure&, const Value* other) const; virtual Value* bitwiseCastConstant(Procedure&) const; + virtual Value* iToDConstant(Procedure&) const; + virtual Value* iToFConstant(Procedure&) const; virtual Value* doubleToFloatConstant(Procedure&) const; virtual Value* floatToDoubleConstant(Procedure&) const; virtual Value* absConstant(Procedure&) const; @@ -151,7 +188,7 @@ virtual TriState aboveEqualConstant(const Value* other) const; virtual TriState belowEqualConstant(const Value* other) const; virtual TriState equalOrUnorderedConstant(const Value* other) const; - + // If the value is a comparison then this returns the inverted form of that comparison, if // possible. It can be impossible for double comparisons, where for example LessThan and // GreaterEqual behave differently. If this returns a value, it is a new value, which must be @@ -208,6 +245,11 @@ // repoint it at the Identity's child. For simplicity, this will follow arbitrarily long chains // of Identity's. void performSubstitution(); + + // Free values are those whose presence is guaranteed not to hurt code. We consider constants, + // Identities, and Nops to be free. Constants are free because we hoist them to an optimal place. + // Identities and Nops are free because we remove them. + bool isFree() const; // Walk the ancestors of this value (i.e. the graph of things it transitively uses). This // either walks phis or not, depending on whether PhiChildren is null. Your callback gets @@ -233,11 +275,79 @@ friend class SparseCollection; // Checks that this opcode is valid for use with B3::Value. -#if ASSERT_DISABLED - static void checkOpcode(Opcode) { } -#else - static void checkOpcode(Opcode); -#endif + ALWAYS_INLINE static void checkOpcode(Opcode opcode, unsigned numArgs) + { + switch (opcode) { + case FramePointer: + case Nop: + case Phi: + case Jump: + case Oops: + case EntrySwitch: + if (UNLIKELY(numArgs)) + badOpcode(opcode, numArgs); + break; + case Return: + if (UNLIKELY(numArgs > 1)) + badOpcode(opcode, numArgs); + break; + case Identity: + case Neg: + case Clz: + case Abs: + case Ceil: + case Floor: + case Sqrt: + case SExt8: + case SExt16: + case Trunc: + case SExt32: + case ZExt32: + case FloatToDouble: + case IToD: + case DoubleToFloat: + case IToF: + case BitwiseCast: + case Branch: + if (UNLIKELY(numArgs != 1)) + badOpcode(opcode, numArgs); + break; + case Add: + case Sub: + case Mul: + case Div: + case Mod: + case ChillDiv: + case ChillMod: + case BitAnd: + case BitOr: + case BitXor: + case Shl: + case SShr: + case ZShr: + case Equal: + case NotEqual: + case LessThan: + case GreaterThan: + case LessEqual: + case GreaterEqual: + case Above: + case Below: + case AboveEqual: + case BelowEqual: + case EqualOrUnordered: + if (UNLIKELY(numArgs != 2)) + badOpcode(opcode, numArgs); + break; + case Select: + if (UNLIKELY(numArgs != 3)) + badOpcode(opcode, numArgs); + break; + default: + badOpcode(opcode, numArgs); + break; + } + } protected: enum CheckedOpcodeTag { CheckedOpcode }; @@ -307,10 +417,34 @@ // This is the constructor you end up actually calling, if you're instantiating Value // directly. template - explicit Value(Opcode opcode, Arguments&&... arguments) - : Value(CheckedOpcode, opcode, std::forward(arguments)...) + explicit Value(Opcode opcode, Type type, Origin origin) + : Value(CheckedOpcode, opcode, type, origin) { - checkOpcode(opcode); + checkOpcode(opcode, 0); + } + template + explicit Value(Opcode opcode, Type type, Origin origin, Value* firstChild, Arguments&&... arguments) + : Value(CheckedOpcode, opcode, type, origin, firstChild, std::forward(arguments)...) + { + checkOpcode(opcode, 1 + sizeof...(arguments)); + } + template + explicit Value(Opcode opcode, Type type, Origin origin, const AdjacencyList& children) + : Value(CheckedOpcode, opcode, type, origin, children) + { + checkOpcode(opcode, children.size()); + } + template + explicit Value(Opcode opcode, Type type, Origin origin, AdjacencyList&& children) + : Value(CheckedOpcode, opcode, type, origin, WTFMove(children)) + { + checkOpcode(opcode, m_children.size()); + } + template + explicit Value(Opcode opcode, Origin origin, Arguments&&... arguments) + : Value(CheckedOpcode, opcode, origin, std::forward(arguments)...) + { + checkOpcode(opcode, sizeof...(arguments)); } private: @@ -328,6 +462,8 @@ Origin m_origin; AdjacencyList m_children; + JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH static void badOpcode(Opcode, unsigned); + public: BasicBlock* owner { nullptr }; // computed by Procedure::resetValueOwners(). }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueInlines.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -41,6 +41,20 @@ namespace JSC { namespace B3 { +template +void Value::replaceWithBottom(const BottomProvider& bottomProvider) +{ + if (m_type == Void) { + replaceWithNop(); + return; + } + + if (isConstant()) + return; + + replaceWithIdentity(bottomProvider(m_origin, m_type)); +} + template T* Value::as() { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueKey.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueKey.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueKey.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueKey.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -68,6 +68,7 @@ case Clz: case Trunc: case IToD: + case IToF: case FloatToDouble: case DoubleToFloat: case Check: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueKey.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueKey.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueKey.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueKey.h 2016-11-03 07:04:20.000000000 +0000 @@ -33,7 +33,6 @@ #include "B3Origin.h" #include "B3Type.h" #include -#include namespace JSC { namespace B3 { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueRep.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueRep.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueRep.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueRep.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -40,8 +40,10 @@ case ColdAny: case LateColdAny: case SomeRegister: + case SomeEarlyRegister: case Constant: return; + case LateRegister: case Register: set.set(reg()); return; @@ -69,7 +71,9 @@ case ColdAny: case LateColdAny: case SomeRegister: + case SomeEarlyRegister: return; + case LateRegister: case Register: out.print("(", reg(), ")"); return; @@ -90,6 +94,7 @@ { if (reg.isGPR()) { switch (kind()) { + case LateRegister: case Register: if (isGPR()) jit.move(gpr(), reg.gpr()); @@ -110,6 +115,7 @@ } switch (kind()) { + case LateRegister: case Register: if (isGPR()) jit.move64ToDouble(gpr(), reg.fpr()); @@ -132,6 +138,7 @@ ValueRecovery ValueRep::recoveryForJSValue() const { switch (kind()) { + case LateRegister: case Register: return ValueRecovery::inGPR(gpr(), DataFormatJS); case Stack: @@ -168,9 +175,15 @@ case ValueRep::SomeRegister: out.print("SomeRegister"); return; + case ValueRep::SomeEarlyRegister: + out.print("SomeEarlyRegister"); + return; case ValueRep::Register: out.print("Register"); return; + case ValueRep::LateRegister: + out.print("LateRegister"); + return; case ValueRep::Stack: out.print("Stack"); return; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueRep.h webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueRep.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/B3ValueRep.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/B3ValueRep.h 2016-11-03 07:04:20.000000000 +0000 @@ -67,10 +67,21 @@ // register that this claims to clobber! SomeRegister, + // As an input representation, this tells us that B3 should pick some register, but implies + // that the def happens before any of the effects of the stackmap. This is only valid for + // the result constraint of a Patchpoint. + SomeEarlyRegister, + // As an input representation, this forces a particular register. As an output // representation, this tells us what register B3 picked. Register, + // As an input representation, this forces a particular register and states that + // the register is used late. This means that the register is used after the result + // is defined (i.e, the result will interfere with this as an input). + // It's not valid for this to be used as a result kind. + LateRegister, + // As an output representation, this tells us what stack slot B3 picked. It's not a valid // input representation. Stack, @@ -97,7 +108,7 @@ ValueRep(Kind kind) : m_kind(kind) { - ASSERT(kind == WarmAny || kind == ColdAny || kind == LateColdAny || kind == SomeRegister); + ASSERT(kind == WarmAny || kind == ColdAny || kind == LateColdAny || kind == SomeRegister || kind == SomeEarlyRegister); } static ValueRep reg(Reg reg) @@ -105,6 +116,13 @@ return ValueRep(reg); } + static ValueRep lateReg(Reg reg) + { + ValueRep result(reg); + result.m_kind = LateRegister; + return result; + } + static ValueRep stack(intptr_t offsetFromFP) { ValueRep result; @@ -141,6 +159,7 @@ if (kind() != other.kind()) return false; switch (kind()) { + case LateRegister: case Register: return u.reg == other.u.reg; case Stack: @@ -163,9 +182,7 @@ bool isAny() const { return kind() == WarmAny || kind() == ColdAny || kind() == LateColdAny; } - bool isSomeRegister() const { return kind() == SomeRegister; } - - bool isReg() const { return kind() == Register; } + bool isReg() const { return kind() == Register || kind() == LateRegister; } Reg reg() const { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/b3/testb3.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/b3/testb3.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/b3/testb3.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/b3/testb3.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -25,6 +25,9 @@ #include "config.h" +#include "AirCode.h" +#include "AirInstInlines.h" +#include "AirValidate.h" #include "AllowMacroScratchRegisterUsage.h" #include "B3ArgumentRegValue.h" #include "B3BasicBlockInlines.h" @@ -33,18 +36,24 @@ #include "B3ComputeDivisionMagic.h" #include "B3Const32Value.h" #include "B3ConstPtrValue.h" -#include "B3ControlValue.h" #include "B3Effects.h" +#include "B3Generate.h" +#include "B3LowerToAir.h" #include "B3MathExtras.h" #include "B3MemoryValue.h" #include "B3Procedure.h" +#include "B3ReduceStrength.h" #include "B3SlotBaseValue.h" #include "B3StackSlot.h" #include "B3StackmapGenerationParams.h" #include "B3SwitchValue.h" #include "B3UpsilonValue.h" +#include "B3Validate.h" #include "B3ValueInlines.h" +#include "B3VariableValue.h" #include "CCallHelpers.h" +#include "FPRInfo.h" +#include "GPRInfo.h" #include "InitializeThreading.h" #include "JSCInlines.h" #include "LinkBuffer.h" @@ -52,6 +61,7 @@ #include "VM.h" #include #include +#include #include #include #include @@ -73,6 +83,11 @@ namespace { +bool shouldBeVerbose() +{ + return shouldDumpIR(B3Mode); +} + StaticLock crashLock; // Nothing fancy for now; we just use the existing WTF assertion machinery. @@ -84,6 +99,16 @@ CRASH(); \ } while (false) +#define CHECK_EQ(x, y) do { \ + auto __x = (x); \ + auto __y = (y); \ + if (__x == __y) \ + break; \ + crashLock.lock(); \ + WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, toCString(#x " == " #y, " (" #x " == ", __x, ", " #y " == ", __y, ")").data()); \ + CRASH(); \ + } while (false) + VM* vm; std::unique_ptr compile(Procedure& procedure, unsigned optLevel = 1) @@ -92,18 +117,40 @@ } template -T invoke(const Compilation& code, Arguments... arguments) +T invoke(MacroAssemblerCodePtr ptr, Arguments... arguments) { - T (*function)(Arguments...) = bitwise_cast(code.code().executableAddress()); + T (*function)(Arguments...) = bitwise_cast(ptr.executableAddress()); return function(arguments...); } template +T invoke(const Compilation& code, Arguments... arguments) +{ + return invoke(code.code(), arguments...); +} + +template T compileAndRun(Procedure& procedure, Arguments... arguments) { return invoke(*compile(procedure), arguments...); } +void lowerToAirForTesting(Procedure& proc) +{ + proc.resetReachability(); + + if (shouldBeVerbose()) + dataLog("B3 before lowering:\n", proc); + + validate(proc); + lowerToAir(proc); + + if (shouldBeVerbose()) + dataLog("Air after lowering:\n", proc.code()); + + Air::validate(proc.code()); +} + template struct Operand { const char* name; @@ -150,6 +197,7 @@ static Vector int64Operands() { Vector operands; + operands.append({ "0", 0 }); operands.append({ "1", 1 }); operands.append({ "-1", -1 }); operands.append({ "42", 42 }); @@ -191,7 +239,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* const42 = root->appendNew(proc, Origin(), 42); - root->appendNew(proc, Return, Origin(), const42); + root->appendNewControlValue(proc, Return, Origin(), const42); CHECK(compileAndRun(proc) == 42); } @@ -201,7 +249,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); int x = 42; - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Load, Int32, Origin(), @@ -217,7 +265,7 @@ BasicBlock* root = proc.addBlock(); int64_t x = -42; Value* base = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Load, Int64, Origin(), @@ -232,7 +280,7 @@ BasicBlock* root = proc.addBlock(); int32_t x = -42; Value* base = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Load, Int32, Origin(), @@ -285,7 +333,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); @@ -296,19 +344,27 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), value)); CHECK(compileAndRun(proc) == value); } +void testReturnVoid() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + root->appendNewControlValue(proc, Return, Origin()); + compileAndRun(proc); +} + void testAddArg(int a) { Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), value, value)); @@ -319,7 +375,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -333,7 +389,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -347,7 +403,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -367,7 +423,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), load); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int64_t inputOutput = b; CHECK(!compileAndRun(proc, a, &inputOutput)); @@ -383,7 +439,7 @@ Value* result = root->appendNew(proc, Add, Origin(), load, root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, &a, b) == a + b); } @@ -398,7 +454,7 @@ root->appendNew(proc, Origin(), a), load); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int64_t inputOutput = b; CHECK(!compileAndRun(proc, &inputOutput)); @@ -411,7 +467,7 @@ BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), value, value)); @@ -422,7 +478,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -446,7 +502,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* result = root->appendNew(proc, Add, Origin(), argument, load); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int32_t inputOutput = b; CHECK(!compileAndRun(proc, a, &inputOutput)); @@ -462,7 +518,7 @@ Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); Value* result = root->appendNew(proc, Add, Origin(), load, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, &a, b) == a + b); } @@ -477,7 +533,7 @@ root->appendNew(proc, Origin(), a), load); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int32_t inputOutput = b; CHECK(!compileAndRun(proc, &inputOutput)); @@ -492,7 +548,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* constZero = root->appendNew(proc, Origin(), 0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -512,7 +568,7 @@ Value* load = root->appendNew( proc, Load, Int32, Origin(), root->appendNew(proc, Origin(), &value)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), load, load)); @@ -529,7 +585,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), value, value)); @@ -542,7 +598,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), valueA, valueB)); @@ -555,7 +611,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), valueA, valueB)); @@ -568,7 +624,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), valueA, valueB)); @@ -581,7 +637,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Add, Origin(), valueA, valueB)); @@ -597,7 +653,7 @@ Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Add, Origin(), floatValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a + a))); @@ -615,7 +671,7 @@ Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); Value* result = root->appendNew(proc, Add, Origin(), floatValue1, floatValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a + b))); } @@ -630,7 +686,7 @@ Value* constValue = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Add, Origin(), floatValue, constValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a + b))); } @@ -645,7 +701,7 @@ Value* constValue = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Add, Origin(), constValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(b)), bitwise_cast(a + b))); } @@ -658,7 +714,7 @@ Value* constValue2 = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Add, Origin(), constValue1, constValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc), bitwise_cast(a + b))); } @@ -674,7 +730,7 @@ Value* result = root->appendNew(proc, Add, Origin(), asDouble, asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a + a))); } @@ -694,7 +750,7 @@ Value* result = root->appendNew(proc, Add, Origin(), asDouble1, asDouble2); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a + b))); } @@ -716,7 +772,7 @@ Value* doubleAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); root->appendNew(proc, Store, Origin(), result, doubleAddress); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b), &effect), bitwise_cast(a + b))); @@ -729,7 +785,7 @@ BasicBlock* root = proc.addBlock(); Value* value = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), value, value)); @@ -756,7 +812,7 @@ proc, Store, Origin(), mul, root->appendNew(proc, Origin(), &mulSlot)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); CHECK(!compileAndRun(proc, a)); @@ -771,7 +827,7 @@ Value* value = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -785,7 +841,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Mul, Origin(), @@ -799,7 +855,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Mul, Origin(), @@ -813,7 +869,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Mul, Origin(), @@ -827,7 +883,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Mul, Origin(), @@ -850,7 +906,7 @@ Value* load = root->appendNew( proc, Load, Int32, Origin(), root->appendNew(proc, Origin(), &value)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), load, load)); @@ -872,7 +928,7 @@ Value* arg2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg0, arg1); Value* added = root->appendNew(proc, Add, Origin(), multiplied, arg2); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -896,7 +952,7 @@ Value* arg2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg1, arg2); Value* added = root->appendNew(proc, Add, Origin(), arg0, multiplied); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -923,7 +979,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR2)); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg0, arg1); Value* added = root->appendNew(proc, Add, Origin(), multiplied, arg2); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -950,7 +1006,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR2)); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg1, arg2); Value* added = root->appendNew(proc, Add, Origin(), arg0, multiplied); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -974,7 +1030,7 @@ Value* arg2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg0, arg1); Value* added = root->appendNew(proc, Sub, Origin(), multiplied, arg2); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -998,7 +1054,7 @@ Value* arg2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg1, arg2); Value* added = root->appendNew(proc, Sub, Origin(), arg0, multiplied); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -1025,7 +1081,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR2)); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg0, arg1); Value* added = root->appendNew(proc, Sub, Origin(), multiplied, arg2); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -1052,7 +1108,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR2)); Value* multiplied = root->appendNew(proc, Mul, Origin(), arg1, arg2); Value* added = root->appendNew(proc, Sub, Origin(), arg0, multiplied); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -1076,7 +1132,7 @@ Value* multiplied = root->appendNew(proc, Mul, Origin(), arg0, arg1); Value* zero = root->appendNew(proc, Origin(), 0); Value* added = root->appendNew(proc, Sub, Origin(), zero, multiplied); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -1100,7 +1156,7 @@ Value* multiplied = root->appendNew(proc, Mul, Origin(), arg0, arg1); Value* zero = root->appendNew(proc, Origin(), 0); Value* added = root->appendNew(proc, Sub, Origin(), zero, multiplied); - root->appendNew(proc, Return, Origin(), added); + root->appendNewControlValue(proc, Return, Origin(), added); auto code = compile(proc); @@ -1117,7 +1173,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), value, value)); @@ -1130,7 +1186,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), valueA, valueB)); @@ -1143,7 +1199,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), valueA, valueB)); @@ -1156,7 +1212,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), valueA, valueB)); @@ -1169,7 +1225,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mul, Origin(), valueA, valueB)); @@ -1185,7 +1241,7 @@ Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Mul, Origin(), floatValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a * a))); @@ -1203,7 +1259,7 @@ Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); Value* result = root->appendNew(proc, Mul, Origin(), floatValue1, floatValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a * b))); } @@ -1218,7 +1274,7 @@ Value* constValue = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Mul, Origin(), floatValue, constValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a * b))); } @@ -1233,7 +1289,7 @@ Value* constValue = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Mul, Origin(), constValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(b)), bitwise_cast(a * b))); } @@ -1246,7 +1302,7 @@ Value* constValue2 = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Mul, Origin(), constValue1, constValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc), bitwise_cast(a * b))); } @@ -1262,7 +1318,7 @@ Value* result = root->appendNew(proc, Mul, Origin(), asDouble, asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a * a))); } @@ -1282,7 +1338,7 @@ Value* result = root->appendNew(proc, Mul, Origin(), asDouble1, asDouble2); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a * b))); } @@ -1304,7 +1360,7 @@ Value* doubleMulress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); root->appendNew(proc, Store, Origin(), result, doubleMulress); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b), &effect), bitwise_cast(a * b))); @@ -1316,7 +1372,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Div, Origin(), value, value)); @@ -1329,7 +1385,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Div, Origin(), valueA, valueB)); @@ -1342,7 +1398,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Div, Origin(), valueA, valueB)); @@ -1355,7 +1411,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Div, Origin(), valueA, valueB)); @@ -1368,7 +1424,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Div, Origin(), valueA, valueB)); @@ -1384,7 +1440,7 @@ Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Div, Origin(), floatValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a / a))); @@ -1402,7 +1458,7 @@ Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); Value* result = root->appendNew(proc, Div, Origin(), floatValue1, floatValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a / b))); } @@ -1417,7 +1473,7 @@ Value* constValue = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Div, Origin(), floatValue, constValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a / b))); } @@ -1432,7 +1488,7 @@ Value* constValue = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Div, Origin(), constValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(b)), bitwise_cast(a / b))); } @@ -1445,7 +1501,7 @@ Value* constValue2 = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Div, Origin(), constValue1, constValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc), bitwise_cast(a / b))); } @@ -1455,7 +1511,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mod, Origin(), value, value)); @@ -1468,7 +1524,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mod, Origin(), valueA, valueB)); @@ -1481,7 +1537,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mod, Origin(), valueA, valueB)); @@ -1494,7 +1550,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mod, Origin(), valueA, valueB)); @@ -1507,7 +1563,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Mod, Origin(), valueA, valueB)); @@ -1523,7 +1579,7 @@ Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Mod, Origin(), floatValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(fmod(a, a))))); @@ -1541,7 +1597,7 @@ Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); Value* result = root->appendNew(proc, Mod, Origin(), floatValue1, floatValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(static_cast(fmod(a, b))))); } @@ -1556,7 +1612,7 @@ Value* constValue = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Mod, Origin(), floatValue, constValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(fmod(a, b))))); } @@ -1571,7 +1627,7 @@ Value* constValue = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Mod, Origin(), constValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(b)), bitwise_cast(static_cast(fmod(a, b))))); } @@ -1584,7 +1640,7 @@ Value* constValue2 = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Mod, Origin(), constValue1, constValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc), bitwise_cast(static_cast(fmod(a, b))))); } @@ -1600,7 +1656,7 @@ Value* result = root->appendNew(proc, Div, Origin(), asDouble, asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a / a))); } @@ -1620,7 +1676,7 @@ Value* result = root->appendNew(proc, Div, Origin(), asDouble1, asDouble2); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a / b))); } @@ -1642,7 +1698,7 @@ Value* doubleDivress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); root->appendNew(proc, Store, Origin(), result, doubleDivress); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b), &effect), bitwise_cast(a / b))); @@ -1654,7 +1710,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sub, Origin(), value, value)); @@ -1665,7 +1721,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -1679,7 +1735,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -1700,7 +1756,7 @@ Value* negArgumentMinusOne = root->appendNew(proc, Sub, Origin(), negArgument, root->appendNew(proc, Origin(), 1)); - root->appendNew(proc, Return, Origin(), negArgumentMinusOne); + root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne); CHECK(compileAndRun(proc, a) == -a - 1); } @@ -1708,7 +1764,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -1727,7 +1783,7 @@ Value* result = root->appendNew(proc, Sub, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), load); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, a, &b) == a - b); } @@ -1742,7 +1798,7 @@ load, root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int64_t inputOutput = a; CHECK(!compileAndRun(proc, &inputOutput, b)); @@ -1759,7 +1815,7 @@ root->appendNew(proc, Origin(), a), load); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int64_t inputOutput = b; CHECK(!compileAndRun(proc, &inputOutput)); @@ -1776,7 +1832,7 @@ load, root->appendNew(proc, Origin(), b)); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int64_t inputOutput = a; CHECK(!compileAndRun(proc, &inputOutput)); @@ -1788,7 +1844,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -1806,7 +1862,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -1822,7 +1878,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -1844,7 +1900,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); Value* result = root->appendNew(proc, Sub, Origin(), load, argument); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int32_t inputOutput = a; CHECK(!compileAndRun(proc, &inputOutput, b)); @@ -1860,7 +1916,7 @@ Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* result = root->appendNew(proc, Sub, Origin(), argument, load); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, a, &b) == a - b); } @@ -1875,7 +1931,7 @@ root->appendNew(proc, Origin(), a), load); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int32_t inputOutput = b; CHECK(!compileAndRun(proc, &inputOutput)); @@ -1892,7 +1948,7 @@ load, root->appendNew(proc, Origin(), b)); root->appendNew(proc, Store, Origin(), result, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int32_t inputOutput = a; CHECK(!compileAndRun(proc, &inputOutput)); @@ -1911,7 +1967,7 @@ Value* negArgumentMinusOne = root->appendNew(proc, Sub, Origin(), negArgument, root->appendNew(proc, Origin(), 1)); - root->appendNew(proc, Return, Origin(), negArgumentMinusOne); + root->appendNewControlValue(proc, Return, Origin(), negArgumentMinusOne); CHECK(compileAndRun(proc, a) == -a - 1); } @@ -1920,7 +1976,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* value = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sub, Origin(), value, value)); @@ -1933,7 +1989,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sub, Origin(), valueA, valueB)); @@ -1946,7 +2002,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sub, Origin(), valueA, valueB)); @@ -1959,7 +2015,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sub, Origin(), valueA, valueB)); @@ -1972,7 +2028,7 @@ BasicBlock* root = proc.addBlock(); Value* valueA = root->appendNew(proc, Origin(), a); Value* valueB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sub, Origin(), valueA, valueB)); @@ -1988,7 +2044,7 @@ Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Sub, Origin(), floatValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a - a))); @@ -2006,7 +2062,7 @@ Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); Value* result = root->appendNew(proc, Sub, Origin(), floatValue1, floatValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a - b))); } @@ -2021,7 +2077,7 @@ Value* constValue = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Sub, Origin(), floatValue, constValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a - b))); } @@ -2036,7 +2092,7 @@ Value* constValue = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Sub, Origin(), constValue, floatValue); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(b)), bitwise_cast(a - b))); } @@ -2049,7 +2105,7 @@ Value* constValue2 = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, Sub, Origin(), constValue1, constValue2); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc), bitwise_cast(a - b))); } @@ -2065,7 +2121,7 @@ Value* result = root->appendNew(proc, Sub, Origin(), asDouble, asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(a - a))); } @@ -2085,7 +2141,7 @@ Value* result = root->appendNew(proc, Sub, Origin(), asDouble1, asDouble2); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitwise_cast(a - b))); } @@ -2107,18 +2163,93 @@ Value* doubleSubress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); root->appendNew(proc, Store, Origin(), result, doubleSubress); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b), &effect), bitwise_cast(a - b))); CHECK(isIdentical(effect, static_cast(a) - static_cast(b))); } +void testTernarySubInstructionSelection(B3::Opcode valueModifier, Type valueType, Air::Opcode expectedOpcode) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + + Value* left = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* right = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); + + if (valueModifier == Trunc) { + left = root->appendNew(proc, valueModifier, valueType, Origin(), left); + right = root->appendNew(proc, valueModifier, valueType, Origin(), right); + } + + root->appendNewControlValue( + proc, Return, Origin(), + root->appendNew(proc, Sub, Origin(), left, right)); + + lowerToAirForTesting(proc); + + auto block = proc.code()[0]; + unsigned numberOfSubInstructions = 0; + for (auto instruction : *block) { + if (instruction.opcode == expectedOpcode) { + CHECK_EQ(instruction.args.size(), 3ul); + CHECK_EQ(instruction.args[0].kind(), Air::Arg::Tmp); + CHECK_EQ(instruction.args[1].kind(), Air::Arg::Tmp); + CHECK_EQ(instruction.args[2].kind(), Air::Arg::Tmp); + numberOfSubInstructions++; + } + } + CHECK_EQ(numberOfSubInstructions, 1ul); +} + +void testNegDouble(double a) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + root->appendNewControlValue( + proc, Return, Origin(), + root->appendNew( + proc, Neg, Origin(), + root->appendNew(proc, Origin(), FPRInfo::argumentFPR0))); + + CHECK(isIdentical(compileAndRun(proc, a), -a)); +} + +void testNegFloat(float a) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* argument32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); + root->appendNewControlValue( + proc, Return, Origin(), + root->appendNew(proc, Neg, Origin(), floatValue)); + + CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), -a)); +} + +void testNegFloatWithUselessDoubleConversion(float a) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* argumentInt32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argumentInt32); + Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), floatValue); + Value* result = root->appendNew(proc, Neg, Origin(), asDouble); + Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), floatResult); + + CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), -a)); +} + void testBitAndArgs(int64_t a, int64_t b) { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2133,7 +2264,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2147,7 +2278,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2161,7 +2292,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2175,7 +2306,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2193,7 +2324,7 @@ proc, BitAnd, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), root->appendNew(proc, Origin(), b)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2211,7 +2342,7 @@ proc, BitAnd, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), root->appendNew(proc, Origin(), c)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2225,7 +2356,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2245,7 +2376,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2259,7 +2390,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2273,7 +2404,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2289,7 +2420,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2311,7 +2442,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), root->appendNew(proc, Origin(), b)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2331,7 +2462,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), root->appendNew(proc, Origin(), c)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -2358,7 +2489,7 @@ root->appendNew(proc, Origin(), 42), root->appendNew(proc, Origin(), -5)); - root->appendNew(proc, Return, Origin(), select); + root->appendNewControlValue(proc, Return, Origin(), select); int64_t expected = (a == b) ? -5 : 42; CHECK(compileAndRun(proc, a, b) == expected); @@ -2375,7 +2506,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* result = root->appendNew(proc, BitAnd, Origin(), argument, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc, a), bitAndDouble(a, a))); } @@ -2387,7 +2518,7 @@ Value* argumentA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* argumentB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); Value* result = root->appendNew(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc, a, b), bitAndDouble(a, b))); } @@ -2399,7 +2530,7 @@ Value* argumentA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* argumentB = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc, a, b), bitAndDouble(a, b))); } @@ -2411,7 +2542,7 @@ Value* argumentA = root->appendNew(proc, Origin(), a); Value* argumentB = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc), bitAndDouble(a, b))); } @@ -2429,7 +2560,7 @@ root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))); Value* result = root->appendNew(proc, BitAnd, Origin(), argument, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitAndFloat(a, a))); } @@ -2445,7 +2576,7 @@ root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR1))); Value* result = root->appendNew(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitAndFloat(a, b))); } @@ -2459,7 +2590,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))); Value* argumentB = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)), bitAndFloat(a, b))); } @@ -2471,7 +2602,7 @@ Value* argumentA = root->appendNew(proc, Origin(), a); Value* argumentB = root->appendNew(proc, Origin(), b); Value* result = root->appendNew(proc, BitAnd, Origin(), argumentA, argumentB); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(isIdentical(compileAndRun(proc), bitAndFloat(a, b))); } @@ -2490,7 +2621,7 @@ Value* argumentBasDouble = root->appendNew(proc, FloatToDouble, Origin(), argumentB); Value* doubleResult = root->appendNew(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), doubleResult); - root->appendNew(proc, Return, Origin(), floatResult); + root->appendNewControlValue(proc, Return, Origin(), floatResult); double doubleA = a; double doubleB = b; @@ -2502,7 +2633,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2517,7 +2648,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2531,7 +2662,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2545,7 +2676,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2559,7 +2690,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2577,7 +2708,7 @@ proc, BitOr, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), root->appendNew(proc, Origin(), b)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2595,7 +2726,7 @@ proc, BitOr, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), root->appendNew(proc, Origin(), c)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2609,7 +2740,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2630,7 +2761,7 @@ Value* argument = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2644,7 +2775,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2658,7 +2789,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2674,7 +2805,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2696,7 +2827,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), root->appendNew(proc, Origin(), b)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2716,7 +2847,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), root->appendNew(proc, Origin(), c)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitOr, Origin(), @@ -2730,7 +2861,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2745,7 +2876,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2759,7 +2890,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2773,7 +2904,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2787,7 +2918,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2805,7 +2936,7 @@ proc, BitXor, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), root->appendNew(proc, Origin(), b)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2823,7 +2954,7 @@ proc, BitXor, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), root->appendNew(proc, Origin(), c)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2837,7 +2968,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2858,7 +2989,7 @@ Value* argument = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2872,7 +3003,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2886,7 +3017,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2902,7 +3033,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2924,7 +3055,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), root->appendNew(proc, Origin(), b)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2944,7 +3075,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), root->appendNew(proc, Origin(), c)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2958,7 +3089,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2972,7 +3103,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -2992,7 +3123,7 @@ root->appendNew(proc, Origin(), -1), load); root->appendNew(proc, Store, Origin(), notLoad, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int64_t input = a; compileAndRun(proc, &input); @@ -3005,7 +3136,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, BitXor, Origin(), root->appendNew(proc, Origin(), -1), @@ -3017,7 +3148,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitXor, Origin(), @@ -3037,7 +3168,7 @@ root->appendNew(proc, Origin(), -1), load); root->appendNew(proc, Store, Origin(), notLoad, address); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); int32_t input = a; compileAndRun(proc, &input); @@ -3060,16 +3191,16 @@ root->appendNew(proc, Origin(), -1), argsAreEqual); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), argsAreNotEqual, FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -42)); @@ -3081,7 +3212,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), @@ -3097,7 +3228,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), @@ -3111,7 +3242,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), @@ -3128,7 +3259,7 @@ Value* value = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Shl, Origin(), value, value)); @@ -3139,7 +3270,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), @@ -3157,7 +3288,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), @@ -3171,7 +3302,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), @@ -3187,7 +3318,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -3203,7 +3334,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -3217,7 +3348,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -3234,7 +3365,7 @@ Value* value = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, SShr, Origin(), value, value)); @@ -3245,7 +3376,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -3263,7 +3394,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -3277,7 +3408,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -3293,7 +3424,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), @@ -3309,7 +3440,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), @@ -3323,7 +3454,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), @@ -3340,7 +3471,7 @@ Value* value = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, ZShr, Origin(), value, value)); @@ -3351,7 +3482,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), @@ -3369,7 +3500,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), @@ -3383,7 +3514,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), @@ -3416,7 +3547,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* clzValue = root->appendNew(proc, Clz, Origin(), argument); - root->appendNew(proc, Return, Origin(), clzValue); + root->appendNewControlValue(proc, Return, Origin(), clzValue); CHECK(compileAndRun(proc, a) == countLeadingZero(a)); } @@ -3427,7 +3558,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* value = root->appendNew(proc, Load, Int64, Origin(), address); Value* clzValue = root->appendNew(proc, Clz, Origin(), value); - root->appendNew(proc, Return, Origin(), clzValue); + root->appendNewControlValue(proc, Return, Origin(), clzValue); CHECK(compileAndRun(proc, &a) == countLeadingZero(a)); } @@ -3438,7 +3569,7 @@ Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* clzValue = root->appendNew(proc, Clz, Origin(), argument); - root->appendNew(proc, Return, Origin(), clzValue); + root->appendNewControlValue(proc, Return, Origin(), clzValue); CHECK(compileAndRun(proc, a) == countLeadingZero(a)); } @@ -3449,7 +3580,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* value = root->appendNew(proc, Load, Int32, Origin(), address); Value* clzValue = root->appendNew(proc, Clz, Origin(), value); - root->appendNew(proc, Return, Origin(), clzValue); + root->appendNewControlValue(proc, Return, Origin(), clzValue); CHECK(compileAndRun(proc, &a) == countLeadingZero(a)); } @@ -3457,7 +3588,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Abs, Origin(), @@ -3471,7 +3602,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), a); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Abs, Origin(), argument)); @@ -3484,7 +3615,7 @@ BasicBlock* root = proc.addBlock(); Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadDouble = root->appendNew(proc, Load, Double, Origin(), address); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Abs, Origin(), loadDouble)); @@ -3498,7 +3629,7 @@ Value* firstAbs = root->appendNew(proc, Abs, Origin(), root->appendNew(proc, Origin(), FPRInfo::argumentFPR0)); Value* secondAbs = root->appendNew(proc, Abs, Origin(), firstAbs); - root->appendNew(proc, Return, Origin(), secondAbs); + root->appendNewControlValue(proc, Return, Origin(), secondAbs); CHECK(isIdentical(compileAndRun(proc, a), fabs(a))); } @@ -3510,7 +3641,7 @@ Value* argumentAsInt64 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* argumentAsDouble = root->appendNew(proc, BitwiseCast, Origin(), argumentAsInt64); Value* absValue = root->appendNew(proc, Abs, Origin(), argumentAsDouble); - root->appendNew(proc, Return, Origin(), absValue); + root->appendNewControlValue(proc, Return, Origin(), absValue); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), fabs(a))); } @@ -3524,7 +3655,7 @@ Value* absValue = root->appendNew(proc, Abs, Origin(), argumentAsDouble); Value* resultAsInt64 = root->appendNew(proc, BitwiseCast, Origin(), absValue); - root->appendNew(proc, Return, Origin(), resultAsInt64); + root->appendNewControlValue(proc, Return, Origin(), resultAsInt64); int64_t expectedResult = bitwise_cast(fabs(a)); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), expectedResult)); @@ -3539,7 +3670,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Abs, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(fabs(a))))); } @@ -3551,7 +3682,7 @@ Value* argument = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Abs, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(fabs(a))))); } @@ -3564,7 +3695,7 @@ MemoryValue* loadFloat = root->appendNew(proc, Load, Float, Origin(), address); Value* result = root->appendNew(proc, Abs, Origin(), loadFloat); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, &a), bitwise_cast(static_cast(fabs(a))))); } @@ -3578,7 +3709,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* firstAbs = root->appendNew(proc, Abs, Origin(), argument); Value* secondAbs = root->appendNew(proc, Abs, Origin(), firstAbs); - root->appendNew(proc, Return, Origin(), secondAbs); + root->appendNewControlValue(proc, Return, Origin(), secondAbs); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), static_cast(fabs(a)))); } @@ -3591,7 +3722,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* argumentAsfloat = root->appendNew(proc, BitwiseCast, Origin(), argumentAsInt32); Value* absValue = root->appendNew(proc, Abs, Origin(), argumentAsfloat); - root->appendNew(proc, Return, Origin(), absValue); + root->appendNewControlValue(proc, Return, Origin(), absValue); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), static_cast(fabs(a)))); } @@ -3606,7 +3737,7 @@ Value* absValue = root->appendNew(proc, Abs, Origin(), argumentAsfloat); Value* resultAsInt64 = root->appendNew(proc, BitwiseCast, Origin(), absValue); - root->appendNew(proc, Return, Origin(), resultAsInt64); + root->appendNewControlValue(proc, Return, Origin(), resultAsInt64); int32_t expectedResult = bitwise_cast(static_cast(fabs(a))); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), expectedResult)); @@ -3623,7 +3754,7 @@ Value* result = root->appendNew(proc, Abs, Origin(), asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(fabs(a))))); } @@ -3641,7 +3772,7 @@ Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); Value* doubleAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); root->appendNew(proc, Store, Origin(), result, doubleAddress); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; int32_t resultValue = compileAndRun(proc, bitwise_cast(a), &effect); @@ -3653,7 +3784,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Ceil, Origin(), @@ -3667,7 +3798,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), a); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Ceil, Origin(), argument)); @@ -3680,7 +3811,7 @@ BasicBlock* root = proc.addBlock(); Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadDouble = root->appendNew(proc, Load, Double, Origin(), address); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Ceil, Origin(), loadDouble)); @@ -3694,7 +3825,7 @@ Value* firstCeil = root->appendNew(proc, Ceil, Origin(), root->appendNew(proc, Origin(), FPRInfo::argumentFPR0)); Value* secondCeil = root->appendNew(proc, Ceil, Origin(), firstCeil); - root->appendNew(proc, Return, Origin(), secondCeil); + root->appendNewControlValue(proc, Return, Origin(), secondCeil); CHECK(isIdentical(compileAndRun(proc, a), ceil(a))); } @@ -3706,7 +3837,7 @@ Value* firstCeil = root->appendNew(proc, Ceil, Origin(), root->appendNew(proc, Origin(), FPRInfo::argumentFPR0)); Value* wrappingFloor = root->appendNew(proc, Floor, Origin(), firstCeil); - root->appendNew(proc, Return, Origin(), wrappingFloor); + root->appendNewControlValue(proc, Return, Origin(), wrappingFloor); CHECK(isIdentical(compileAndRun(proc, a), ceil(a))); } @@ -3718,7 +3849,7 @@ Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* argumentAsDouble = root->appendNew(proc, IToD, Origin(), argument); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Ceil, Origin(), argumentAsDouble)); @@ -3733,7 +3864,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* argumentAsDouble = root->appendNew(proc, IToD, Origin(), argument); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Ceil, Origin(), argumentAsDouble)); @@ -3749,7 +3880,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Ceil, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(ceilf(a)))); } @@ -3761,7 +3892,7 @@ Value* argument = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Ceil, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(ceilf(a)))); } @@ -3774,7 +3905,7 @@ MemoryValue* loadFloat = root->appendNew(proc, Load, Float, Origin(), address); Value* result = root->appendNew(proc, Ceil, Origin(), loadFloat); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, &a), bitwise_cast(ceilf(a)))); } @@ -3788,7 +3919,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* firstCeil = root->appendNew(proc, Ceil, Origin(), argument); Value* secondCeil = root->appendNew(proc, Ceil, Origin(), firstCeil); - root->appendNew(proc, Return, Origin(), secondCeil); + root->appendNewControlValue(proc, Return, Origin(), secondCeil); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), ceilf(a))); } @@ -3802,7 +3933,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* firstCeil = root->appendNew(proc, Ceil, Origin(), argument); Value* wrappingFloor = root->appendNew(proc, Floor, Origin(), firstCeil); - root->appendNew(proc, Return, Origin(), wrappingFloor); + root->appendNewControlValue(proc, Return, Origin(), wrappingFloor); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), ceilf(a))); } @@ -3818,7 +3949,7 @@ Value* result = root->appendNew(proc, Ceil, Origin(), asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(ceilf(a)))); } @@ -3836,7 +3967,7 @@ Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); Value* doubleAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); root->appendNew(proc, Store, Origin(), result, doubleAddress); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; int32_t resultValue = compileAndRun(proc, bitwise_cast(a), &effect); @@ -3848,7 +3979,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Floor, Origin(), @@ -3862,7 +3993,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), a); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Floor, Origin(), argument)); @@ -3875,7 +4006,7 @@ BasicBlock* root = proc.addBlock(); Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadDouble = root->appendNew(proc, Load, Double, Origin(), address); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Floor, Origin(), loadDouble)); @@ -3889,7 +4020,7 @@ Value* firstFloor = root->appendNew(proc, Floor, Origin(), root->appendNew(proc, Origin(), FPRInfo::argumentFPR0)); Value* secondFloor = root->appendNew(proc, Floor, Origin(), firstFloor); - root->appendNew(proc, Return, Origin(), secondFloor); + root->appendNewControlValue(proc, Return, Origin(), secondFloor); CHECK(isIdentical(compileAndRun(proc, a), floor(a))); } @@ -3901,7 +4032,7 @@ Value* firstFloor = root->appendNew(proc, Floor, Origin(), root->appendNew(proc, Origin(), FPRInfo::argumentFPR0)); Value* wrappingCeil = root->appendNew(proc, Ceil, Origin(), firstFloor); - root->appendNew(proc, Return, Origin(), wrappingCeil); + root->appendNewControlValue(proc, Return, Origin(), wrappingCeil); CHECK(isIdentical(compileAndRun(proc, a), floor(a))); } @@ -3913,7 +4044,7 @@ Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* argumentAsDouble = root->appendNew(proc, IToD, Origin(), argument); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Floor, Origin(), argumentAsDouble)); @@ -3928,7 +4059,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* argumentAsDouble = root->appendNew(proc, IToD, Origin(), argument); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Floor, Origin(), argumentAsDouble)); @@ -3944,7 +4075,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Floor, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(floorf(a)))); } @@ -3956,7 +4087,7 @@ Value* argument = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Floor, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(floorf(a)))); } @@ -3969,7 +4100,7 @@ MemoryValue* loadFloat = root->appendNew(proc, Load, Float, Origin(), address); Value* result = root->appendNew(proc, Floor, Origin(), loadFloat); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, &a), bitwise_cast(floorf(a)))); } @@ -3983,7 +4114,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* firstFloor = root->appendNew(proc, Floor, Origin(), argument); Value* secondFloor = root->appendNew(proc, Floor, Origin(), firstFloor); - root->appendNew(proc, Return, Origin(), secondFloor); + root->appendNewControlValue(proc, Return, Origin(), secondFloor); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), floorf(a))); } @@ -3997,7 +4128,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* firstFloor = root->appendNew(proc, Floor, Origin(), argument); Value* wrappingCeil = root->appendNew(proc, Ceil, Origin(), firstFloor); - root->appendNew(proc, Return, Origin(), wrappingCeil); + root->appendNewControlValue(proc, Return, Origin(), wrappingCeil); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), floorf(a))); } @@ -4013,7 +4144,7 @@ Value* result = root->appendNew(proc, Floor, Origin(), asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(floorf(a)))); } @@ -4031,7 +4162,7 @@ Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); Value* doubleAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); root->appendNew(proc, Store, Origin(), result, doubleAddress); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; int32_t resultValue = compileAndRun(proc, bitwise_cast(a), &effect); @@ -4043,7 +4174,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sqrt, Origin(), @@ -4057,7 +4188,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), a); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sqrt, Origin(), argument)); @@ -4070,7 +4201,7 @@ BasicBlock* root = proc.addBlock(); Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadDouble = root->appendNew(proc, Load, Double, Origin(), address); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Sqrt, Origin(), loadDouble)); @@ -4086,7 +4217,7 @@ Value* argument = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* result = root->appendNew(proc, Sqrt, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(sqrt(a))))); } @@ -4098,7 +4229,7 @@ Value* argument = root->appendNew(proc, Origin(), a); Value* result = root->appendNew(proc, Sqrt, Origin(), argument); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(sqrt(a))))); } @@ -4111,7 +4242,7 @@ MemoryValue* loadFloat = root->appendNew(proc, Load, Float, Origin(), address); Value* result = root->appendNew(proc, Sqrt, Origin(), loadFloat); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), result); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, &a), bitwise_cast(static_cast(sqrt(a))))); } @@ -4127,7 +4258,7 @@ Value* result = root->appendNew(proc, Sqrt, Origin(), asDouble); Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), result); Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(a)), bitwise_cast(static_cast(sqrt(a))))); } @@ -4145,7 +4276,7 @@ Value* result32 = root->appendNew(proc, BitwiseCast, Origin(), floatResult); Value* doubleAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); root->appendNew(proc, Store, Origin(), result, doubleAddress); - root->appendNew(proc, Return, Origin(), result32); + root->appendNewControlValue(proc, Return, Origin(), result32); double effect = 0; int32_t resultValue = compileAndRun(proc, bitwise_cast(a), &effect); @@ -4153,13 +4284,272 @@ CHECK(isIdentical(effect, sqrt(a))); } +void testCompareTwoFloatToDouble(float a, float b) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + + Value* arg1As32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* arg1Float = root->appendNew(proc, BitwiseCast, Origin(), arg1As32); + Value* arg1AsDouble = root->appendNew(proc, FloatToDouble, Origin(), arg1Float); + + Value* arg2As32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* arg2Float = root->appendNew(proc, BitwiseCast, Origin(), arg2As32); + Value* arg2AsDouble = root->appendNew(proc, FloatToDouble, Origin(), arg2Float); + Value* equal = root->appendNew(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble); + + root->appendNewControlValue(proc, Return, Origin(), equal); + + CHECK(compileAndRun(proc, bitwise_cast(a), bitwise_cast(b)) == (a == b)); +} + +void testCompareOneFloatToDouble(float a, double b) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + + Value* arg1As32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* arg1Float = root->appendNew(proc, BitwiseCast, Origin(), arg1As32); + Value* arg1AsDouble = root->appendNew(proc, FloatToDouble, Origin(), arg1Float); + + Value* arg2AsDouble = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); + Value* equal = root->appendNew(proc, Equal, Origin(), arg1AsDouble, arg2AsDouble); + + root->appendNewControlValue(proc, Return, Origin(), equal); + + CHECK(compileAndRun(proc, bitwise_cast(a), b) == (a == b)); +} + +void testCompareFloatToDoubleThroughPhi(float a, float b) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + BasicBlock* tail = proc.addBlock(); + + Value* condition = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + + Value* arg1As32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* arg1Float = root->appendNew(proc, BitwiseCast, Origin(), arg1As32); + Value* arg1AsDouble = root->appendNew(proc, FloatToDouble, Origin(), arg1Float); + + Value* arg2AsDouble = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); + Value* arg2AsFloat = root->appendNew(proc, DoubleToFloat, Origin(), arg2AsDouble); + Value* arg2AsFRoundedDouble = root->appendNew(proc, FloatToDouble, Origin(), arg2AsFloat); + + root->appendNewControlValue( + proc, Branch, Origin(), + condition, + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + UpsilonValue* thenValue = thenCase->appendNew(proc, Origin(), arg1AsDouble); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* elseConst = elseCase->appendNew(proc, Origin(), 0.); + UpsilonValue* elseValue = elseCase->appendNew(proc, Origin(), elseConst); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* doubleInput = tail->appendNew(proc, Phi, Double, Origin()); + thenValue->setPhi(doubleInput); + elseValue->setPhi(doubleInput); + Value* equal = tail->appendNew(proc, Equal, Origin(), doubleInput, arg2AsFRoundedDouble); + tail->appendNewControlValue(proc, Return, Origin(), equal); + + auto code = compile(proc); + int32_t integerA = bitwise_cast(a); + double doubleB = b; + CHECK(invoke(*code, 1, integerA, doubleB) == (a == b)); + CHECK(invoke(*code, 0, integerA, doubleB) == (b == 0)); +} + +void testDoubleToFloatThroughPhi(float value) +{ + // Simple case of: + // if (a) { + // x = DoubleAdd(a, b) + // else + // x = DoubleAdd(a, c) + // DoubleToFloat(x) + // + // Both Adds can be converted to float add. + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + BasicBlock* tail = proc.addBlock(); + + Value* condition = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* argument32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); + Value* argAsDouble = root->appendNew(proc, FloatToDouble, Origin(), floatValue); + + root->appendNewControlValue( + proc, Branch, Origin(), + condition, + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + Value* postitiveConst = thenCase->appendNew(proc, Origin(), 42.5f); + Value* thenAdd = thenCase->appendNew(proc, Add, Origin(), argAsDouble, postitiveConst); + UpsilonValue* thenValue = thenCase->appendNew(proc, Origin(), thenAdd); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* elseConst = elseCase->appendNew(proc, Origin(), M_PI); + UpsilonValue* elseValue = elseCase->appendNew(proc, Origin(), elseConst); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* doubleInput = tail->appendNew(proc, Phi, Double, Origin()); + thenValue->setPhi(doubleInput); + elseValue->setPhi(doubleInput); + Value* floatResult = tail->appendNew(proc, DoubleToFloat, Origin(), doubleInput); + tail->appendNewControlValue(proc, Return, Origin(), floatResult); + + auto code = compile(proc); + CHECK(isIdentical(invoke(*code, 1, bitwise_cast(value)), value + 42.5f)); + CHECK(isIdentical(invoke(*code, 0, bitwise_cast(value)), static_cast(M_PI))); +} + +void testDoubleProducerPhiToFloatConversion(float value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + BasicBlock* tail = proc.addBlock(); + + Value* condition = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* argument32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); + + root->appendNewControlValue( + proc, Branch, Origin(), + condition, + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + Value* asDouble = thenCase->appendNew(proc, FloatToDouble, Origin(), floatValue); + UpsilonValue* thenValue = thenCase->appendNew(proc, Origin(), asDouble); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* constDouble = elseCase->appendNew(proc, Origin(), 42.5); + UpsilonValue* elseValue = elseCase->appendNew(proc, Origin(), constDouble); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* doubleInput = tail->appendNew(proc, Phi, Double, Origin()); + thenValue->setPhi(doubleInput); + elseValue->setPhi(doubleInput); + + Value* argAsDoubleAgain = tail->appendNew(proc, FloatToDouble, Origin(), floatValue); + Value* finalAdd = tail->appendNew(proc, Add, Origin(), doubleInput, argAsDoubleAgain); + Value* floatResult = tail->appendNew(proc, DoubleToFloat, Origin(), finalAdd); + tail->appendNewControlValue(proc, Return, Origin(), floatResult); + + auto code = compile(proc); + CHECK(isIdentical(invoke(*code, 1, bitwise_cast(value)), value + value)); + CHECK(isIdentical(invoke(*code, 0, bitwise_cast(value)), 42.5f + value)); +} + +void testDoubleProducerPhiToFloatConversionWithDoubleConsumer(float value) +{ + // In this case, the Upsilon-Phi effectively contains a Float value, but it is used + // as a Float and as a Double. + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + BasicBlock* tail = proc.addBlock(); + + Value* condition = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* argument32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); + + root->appendNewControlValue( + proc, Branch, Origin(), + condition, + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + Value* asDouble = thenCase->appendNew(proc, FloatToDouble, Origin(), floatValue); + UpsilonValue* thenValue = thenCase->appendNew(proc, Origin(), asDouble); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* constDouble = elseCase->appendNew(proc, Origin(), 42.5); + UpsilonValue* elseValue = elseCase->appendNew(proc, Origin(), constDouble); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* doubleInput = tail->appendNew(proc, Phi, Double, Origin()); + thenValue->setPhi(doubleInput); + elseValue->setPhi(doubleInput); + + Value* argAsDoubleAgain = tail->appendNew(proc, FloatToDouble, Origin(), floatValue); + Value* floatAdd = tail->appendNew(proc, Add, Origin(), doubleInput, argAsDoubleAgain); + + // FRound. + Value* floatResult = tail->appendNew(proc, DoubleToFloat, Origin(), floatAdd); + Value* doubleResult = tail->appendNew(proc, FloatToDouble, Origin(), floatResult); + + // This one *cannot* be eliminated + Value* doubleAdd = tail->appendNew(proc, Add, Origin(), doubleInput, doubleResult); + + tail->appendNewControlValue(proc, Return, Origin(), doubleAdd); + + auto code = compile(proc); + CHECK(isIdentical(invoke(*code, 1, bitwise_cast(value)), (value + value) + static_cast(value))); + CHECK(isIdentical(invoke(*code, 0, bitwise_cast(value)), (42.5f + value) + 42.5f)); +} + +void testDoubleProducerPhiWithNonFloatConst(float value, double constValue) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + BasicBlock* tail = proc.addBlock(); + + Value* condition = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* argument32 = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); + + root->appendNewControlValue( + proc, Branch, Origin(), + condition, + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + Value* asDouble = thenCase->appendNew(proc, FloatToDouble, Origin(), floatValue); + UpsilonValue* thenValue = thenCase->appendNew(proc, Origin(), asDouble); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* constDouble = elseCase->appendNew(proc, Origin(), constValue); + UpsilonValue* elseValue = elseCase->appendNew(proc, Origin(), constDouble); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + Value* doubleInput = tail->appendNew(proc, Phi, Double, Origin()); + thenValue->setPhi(doubleInput); + elseValue->setPhi(doubleInput); + + Value* argAsDoubleAgain = tail->appendNew(proc, FloatToDouble, Origin(), floatValue); + Value* finalAdd = tail->appendNew(proc, Add, Origin(), doubleInput, argAsDoubleAgain); + Value* floatResult = tail->appendNew(proc, DoubleToFloat, Origin(), finalAdd); + tail->appendNewControlValue(proc, Return, Origin(), floatResult); + + auto code = compile(proc); + CHECK(isIdentical(invoke(*code, 1, bitwise_cast(value)), value + value)); + CHECK(isIdentical(invoke(*code, 0, bitwise_cast(value)), static_cast(constValue + value))); +} + void testDoubleArgToInt64BitwiseCast(double value) { Procedure proc; BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4173,7 +4563,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), value); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4188,7 +4578,7 @@ Value* argument = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* first = root->appendNew(proc, BitwiseCast, Origin(), argument); Value* second = root->appendNew(proc, BitwiseCast, Origin(), first); - root->appendNew(proc, Return, Origin(), second); + root->appendNewControlValue(proc, Return, Origin(), second); CHECK(isIdentical(compileAndRun(proc, value), value)); } @@ -4200,7 +4590,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadDouble = root->appendNew(proc, Load, Double, Origin(), address); Value* cast = root->appendNew(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew(proc, Return, Origin(), cast); + root->appendNewControlValue(proc, Return, Origin(), cast); CHECK(isIdentical(compileAndRun(proc, &value), bitwise_cast(value))); } @@ -4217,7 +4607,7 @@ Value* address = root->appendNew(proc, Add, Origin(), base, scaledOffset); MemoryValue* loadDouble = root->appendNew(proc, Load, Double, Origin(), address); Value* cast = root->appendNew(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew(proc, Return, Origin(), cast); + root->appendNewControlValue(proc, Return, Origin(), cast); CHECK(isIdentical(compileAndRun(proc, &value, 0), bitwise_cast(value))); } @@ -4228,7 +4618,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4242,7 +4632,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), value); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4257,7 +4647,7 @@ Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* first = root->appendNew(proc, BitwiseCast, Origin(), argument); Value* second = root->appendNew(proc, BitwiseCast, Origin(), first); - root->appendNew(proc, Return, Origin(), second); + root->appendNewControlValue(proc, Return, Origin(), second); CHECK(isIdentical(compileAndRun(proc, value), value)); } @@ -4269,7 +4659,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadDouble = root->appendNew(proc, Load, Int64, Origin(), address); Value* cast = root->appendNew(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew(proc, Return, Origin(), cast); + root->appendNewControlValue(proc, Return, Origin(), cast); CHECK(isIdentical(compileAndRun(proc, &value), bitwise_cast(value))); } @@ -4286,7 +4676,7 @@ Value* address = root->appendNew(proc, Add, Origin(), base, scaledOffset); MemoryValue* loadDouble = root->appendNew(proc, Load, Int64, Origin(), address); Value* cast = root->appendNew(proc, BitwiseCast, Origin(), loadDouble); - root->appendNew(proc, Return, Origin(), cast); + root->appendNewControlValue(proc, Return, Origin(), cast); CHECK(isIdentical(compileAndRun(proc, &value, 0), bitwise_cast(value))); } @@ -4297,7 +4687,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), value); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4312,7 +4702,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadFloat = root->appendNew(proc, Load, Float, Origin(), address); Value* cast = root->appendNew(proc, BitwiseCast, Origin(), loadFloat); - root->appendNew(proc, Return, Origin(), cast); + root->appendNewControlValue(proc, Return, Origin(), cast); CHECK(isIdentical(compileAndRun(proc, &value), bitwise_cast(value))); } @@ -4323,7 +4713,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4337,7 +4727,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), value); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitwiseCast, Origin(), argument)); @@ -4352,7 +4742,7 @@ Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* first = root->appendNew(proc, BitwiseCast, Origin(), argument); Value* second = root->appendNew(proc, BitwiseCast, Origin(), first); - root->appendNew(proc, Return, Origin(), second); + root->appendNewControlValue(proc, Return, Origin(), second); CHECK(isIdentical(compileAndRun(proc, value), value)); } @@ -4364,7 +4754,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadFloat = root->appendNew(proc, Load, Int32, Origin(), address); Value* cast = root->appendNew(proc, BitwiseCast, Origin(), loadFloat); - root->appendNew(proc, Return, Origin(), cast); + root->appendNewControlValue(proc, Return, Origin(), cast); CHECK(isIdentical(compileAndRun(proc, &value), bitwise_cast(value))); } @@ -4375,7 +4765,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* asFloat = root->appendNew(proc, DoubleToFloat, Origin(), argument); - root->appendNew(proc, Return, Origin(), asFloat); + root->appendNewControlValue(proc, Return, Origin(), asFloat); CHECK(isIdentical(compileAndRun(proc, value), static_cast(value))); } @@ -4386,7 +4776,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), value); Value* asFloat = root->appendNew(proc, DoubleToFloat, Origin(), argument); - root->appendNew(proc, Return, Origin(), asFloat); + root->appendNewControlValue(proc, Return, Origin(), asFloat); CHECK(isIdentical(compileAndRun(proc), static_cast(value))); } @@ -4398,7 +4788,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadedDouble = root->appendNew(proc, Load, Double, Origin(), address); Value* asFloat = root->appendNew(proc, DoubleToFloat, Origin(), loadedDouble); - root->appendNew(proc, Return, Origin(), asFloat); + root->appendNewControlValue(proc, Return, Origin(), asFloat); CHECK(isIdentical(compileAndRun(proc, &value), static_cast(value))); } @@ -4411,7 +4801,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* floatValue = root->appendNew(proc, BitwiseCast, Origin(), argument32); Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), floatValue); - root->appendNew(proc, Return, Origin(), asDouble); + root->appendNewControlValue(proc, Return, Origin(), asDouble); CHECK(isIdentical(compileAndRun(proc, bitwise_cast(value)), static_cast(value))); } @@ -4422,7 +4812,7 @@ BasicBlock* root = proc.addBlock(); Value* argument = root->appendNew(proc, Origin(), value); Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), argument); - root->appendNew(proc, Return, Origin(), asDouble); + root->appendNewControlValue(proc, Return, Origin(), asDouble); CHECK(isIdentical(compileAndRun(proc), static_cast(value))); } @@ -4434,7 +4824,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); MemoryValue* loadedFloat = root->appendNew(proc, Load, Float, Origin(), address); Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), loadedFloat); - root->appendNew(proc, Return, Origin(), asDouble); + root->appendNewControlValue(proc, Return, Origin(), asDouble); CHECK(isIdentical(compileAndRun(proc, &value), static_cast(value))); } @@ -4447,7 +4837,7 @@ Value* asFloat = root->appendNew(proc, DoubleToFloat, Origin(), argument); Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), asFloat); Value* asFloatAgain = root->appendNew(proc, DoubleToFloat, Origin(), asDouble); - root->appendNew(proc, Return, Origin(), asFloatAgain); + root->appendNewControlValue(proc, Return, Origin(), asFloatAgain); CHECK(isIdentical(compileAndRun(proc, value), static_cast(value))); } @@ -4463,7 +4853,7 @@ Value* asFloatAgain = root->appendNew(proc, DoubleToFloat, Origin(), asDouble); root->appendNew(proc, Store, Origin(), asFloatAgain, dst); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); float input = value; float output = 0.; @@ -4478,7 +4868,7 @@ Value* argument = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* asFloat = root->appendNew(proc, DoubleToFloat, Origin(), argument); Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), asFloat); - root->appendNew(proc, Return, Origin(), asDouble); + root->appendNewControlValue(proc, Return, Origin(), asDouble); CHECK(isIdentical(compileAndRun(proc, value), static_cast(static_cast(value)))); } @@ -4491,88 +4881,283 @@ MemoryValue* loadedDouble = root->appendNew(proc, Load, Double, Origin(), address); Value* asFloat = root->appendNew(proc, DoubleToFloat, Origin(), loadedDouble); Value* asDouble = root->appendNew(proc, FloatToDouble, Origin(), asFloat); - root->appendNew(proc, Return, Origin(), asDouble); + root->appendNewControlValue(proc, Return, Origin(), asDouble); CHECK(isIdentical(compileAndRun(proc, &value), static_cast(static_cast(value)))); } -void testStore32(int value) +void testIToD64Arg() { Procedure proc; BasicBlock* root = proc.addBlock(); - int slot = 0xbaadbeef; - root->appendNew( - proc, Store, Origin(), - root->appendNew( - proc, Trunc, Origin(), - root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), - root->appendNew(proc, Origin(), &slot)); - root->appendNew( - proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + Value* src = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* srcAsDouble = root->appendNew(proc, IToD, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); - CHECK(!compileAndRun(proc, value)); - CHECK(slot == value); + auto code = compile(proc); + for (auto testValue : int64Operands()) + CHECK(isIdentical(invoke(*code, testValue.value), static_cast(testValue.value))); } -void testStoreConstant(int value) +void testIToF64Arg() { Procedure proc; BasicBlock* root = proc.addBlock(); - int slot = 0xbaadbeef; - root->appendNew( - proc, Store, Origin(), - root->appendNew(proc, Origin(), value), - root->appendNew(proc, Origin(), &slot)); - root->appendNew( - proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + Value* src = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* srcAsFloat = root->appendNew(proc, IToF, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); - CHECK(!compileAndRun(proc)); - CHECK(slot == value); + auto code = compile(proc); + for (auto testValue : int64Operands()) + CHECK(isIdentical(invoke(*code, testValue.value), static_cast(testValue.value))); } -void testStoreConstantPtr(intptr_t value) +void testIToD32Arg() { Procedure proc; BasicBlock* root = proc.addBlock(); - intptr_t slot; - if (is64Bit()) - slot = (static_cast(0xbaadbeef) << 32) + static_cast(0xbaadbeef); - else - slot = 0xbaadbeef; - root->appendNew( - proc, Store, Origin(), - root->appendNew(proc, Origin(), value), - root->appendNew(proc, Origin(), &slot)); - root->appendNew( - proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + Value* src = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* srcAsDouble = root->appendNew(proc, IToD, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); - CHECK(!compileAndRun(proc)); - CHECK(slot == value); + auto code = compile(proc); + for (auto testValue : int32Operands()) + CHECK(isIdentical(invoke(*code, testValue.value), static_cast(testValue.value))); } -void testStore8Arg() +void testIToF32Arg() { - { // Direct addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* srcAsFloat = root->appendNew(proc, IToF, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); - Value* value = root->appendNew(proc, Trunc, Origin(), - root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); + auto code = compile(proc); + for (auto testValue : int32Operands()) + CHECK(isIdentical(invoke(*code, testValue.value), static_cast(testValue.value))); +} - root->appendNew(proc, Store8, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); +void testIToD64Mem() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + MemoryValue* loadedSrc = root->appendNew(proc, Load, Int64, Origin(), address); + Value* srcAsDouble = root->appendNew(proc, IToD, Origin(), loadedSrc); + root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); - int8_t storage = 0; - CHECK(compileAndRun(proc, 42, &storage) == 42); - CHECK(storage == 42); + auto code = compile(proc); + int64_t inMemoryValue; + for (auto testValue : int64Operands()) { + inMemoryValue = testValue.value; + CHECK(isIdentical(invoke(*code, &inMemoryValue), static_cast(testValue.value))); + CHECK(inMemoryValue == testValue.value); } +} - { // Indexed addressing. - Procedure proc; - BasicBlock* root = proc.addBlock(); +void testIToF64Mem() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + MemoryValue* loadedSrc = root->appendNew(proc, Load, Int64, Origin(), address); + Value* srcAsFloat = root->appendNew(proc, IToF, Origin(), loadedSrc); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); - Value* value = root->appendNew(proc, Trunc, Origin(), + auto code = compile(proc); + int64_t inMemoryValue; + for (auto testValue : int64Operands()) { + inMemoryValue = testValue.value; + CHECK(isIdentical(invoke(*code, &inMemoryValue), static_cast(testValue.value))); + CHECK(inMemoryValue == testValue.value); + } +} + +void testIToD32Mem() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + MemoryValue* loadedSrc = root->appendNew(proc, Load, Int32, Origin(), address); + Value* srcAsDouble = root->appendNew(proc, IToD, Origin(), loadedSrc); + root->appendNewControlValue(proc, Return, Origin(), srcAsDouble); + + auto code = compile(proc); + int32_t inMemoryValue; + for (auto testValue : int32Operands()) { + inMemoryValue = testValue.value; + CHECK(isIdentical(invoke(*code, &inMemoryValue), static_cast(testValue.value))); + CHECK(inMemoryValue == testValue.value); + } +} + +void testIToF32Mem() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + MemoryValue* loadedSrc = root->appendNew(proc, Load, Int32, Origin(), address); + Value* srcAsFloat = root->appendNew(proc, IToF, Origin(), loadedSrc); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloat); + + auto code = compile(proc); + int32_t inMemoryValue; + for (auto testValue : int32Operands()) { + inMemoryValue = testValue.value; + CHECK(isIdentical(invoke(*code, &inMemoryValue), static_cast(testValue.value))); + CHECK(inMemoryValue == testValue.value); + } +} + +void testIToD64Imm(int64_t value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Origin(), value); + Value* srcAsFloatingPoint = root->appendNew(proc, IToD, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); + CHECK(isIdentical(compileAndRun(proc), static_cast(value))); +} + +void testIToF64Imm(int64_t value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Origin(), value); + Value* srcAsFloatingPoint = root->appendNew(proc, IToF, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); + CHECK(isIdentical(compileAndRun(proc), static_cast(value))); +} + +void testIToD32Imm(int32_t value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Origin(), value); + Value* srcAsFloatingPoint = root->appendNew(proc, IToD, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); + CHECK(isIdentical(compileAndRun(proc), static_cast(value))); +} + +void testIToF32Imm(int32_t value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Origin(), value); + Value* srcAsFloatingPoint = root->appendNew(proc, IToF, Origin(), src); + root->appendNewControlValue(proc, Return, Origin(), srcAsFloatingPoint); + CHECK(isIdentical(compileAndRun(proc), static_cast(value))); +} + +void testIToDReducedToIToF64Arg() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* srcAsDouble = root->appendNew(proc, IToD, Origin(), src); + Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), srcAsDouble); + root->appendNewControlValue(proc, Return, Origin(), floatResult); + + auto code = compile(proc); + for (auto testValue : int64Operands()) + CHECK(isIdentical(invoke(*code, testValue.value), static_cast(testValue.value))); +} + +void testIToDReducedToIToF32Arg() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* src = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* srcAsDouble = root->appendNew(proc, IToD, Origin(), src); + Value* floatResult = root->appendNew(proc, DoubleToFloat, Origin(), srcAsDouble); + root->appendNewControlValue(proc, Return, Origin(), floatResult); + + auto code = compile(proc); + for (auto testValue : int32Operands()) + CHECK(isIdentical(invoke(*code, testValue.value), static_cast(testValue.value))); +} + +void testStore32(int value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + int slot = 0xbaadbeef; + root->appendNew( + proc, Store, Origin(), + root->appendNew( + proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), + root->appendNew(proc, Origin(), &slot)); + root->appendNewControlValue( + proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + + CHECK(!compileAndRun(proc, value)); + CHECK(slot == value); +} + +void testStoreConstant(int value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + int slot = 0xbaadbeef; + root->appendNew( + proc, Store, Origin(), + root->appendNew(proc, Origin(), value), + root->appendNew(proc, Origin(), &slot)); + root->appendNewControlValue( + proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + + CHECK(!compileAndRun(proc)); + CHECK(slot == value); +} + +void testStoreConstantPtr(intptr_t value) +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + intptr_t slot; + if (is64Bit()) + slot = (static_cast(0xbaadbeef) << 32) + static_cast(0xbaadbeef); + else + slot = 0xbaadbeef; + root->appendNew( + proc, Store, Origin(), + root->appendNew(proc, Origin(), value), + root->appendNew(proc, Origin(), &slot)); + root->appendNewControlValue( + proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + + CHECK(!compileAndRun(proc)); + CHECK(slot == value); +} + +void testStore8Arg() +{ + { // Direct addressing. + Procedure proc; + BasicBlock* root = proc.addBlock(); + + Value* value = root->appendNew(proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); + + root->appendNew(proc, Store8, Origin(), value, address); + root->appendNewControlValue(proc, Return, Origin(), value); + + int8_t storage = 0; + CHECK(compileAndRun(proc, 42, &storage) == 42); + CHECK(storage == 42); + } + + { // Indexed addressing. + Procedure proc; + BasicBlock* root = proc.addBlock(); + + Value* value = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* base = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); Value* offset = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); @@ -4582,7 +5167,7 @@ Value* address = root->appendNew(proc, Add, Origin(), baseDisplacement, offset); root->appendNew(proc, Store8, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int8_t storage = 0; CHECK(compileAndRun(proc, 42, &storage, 1) == 42); @@ -4600,7 +5185,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); root->appendNew(proc, Store8, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int8_t storage = 0; CHECK(compileAndRun(proc, &storage) == 42); @@ -4620,7 +5205,7 @@ Value* address = root->appendNew(proc, Add, Origin(), baseDisplacement, offset); root->appendNew(proc, Store8, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int8_t storage = 0; CHECK(compileAndRun(proc, &storage, 1) == 42); @@ -4672,7 +5257,7 @@ // if we use X86 partial registers. root->appendNew(proc, Store8, Origin(), patchpoint, whereToStore); - root->appendNew(proc, Return, Origin(), returnValue); + root->appendNewControlValue(proc, Return, Origin(), returnValue); int8_t storage = 0xff; CHECK(compileAndRun(proc, 0x12345678abcdef12, &storage) == 0x12345678abcdef12); @@ -4690,7 +5275,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); root->appendNew(proc, Store16, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int16_t storage = -1; CHECK(compileAndRun(proc, 42, &storage) == 42); @@ -4711,7 +5296,7 @@ Value* address = root->appendNew(proc, Add, Origin(), baseDisplacement, offset); root->appendNew(proc, Store16, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int16_t storage = -1; CHECK(compileAndRun(proc, 42, &storage, 1) == 42); @@ -4729,7 +5314,7 @@ Value* address = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); root->appendNew(proc, Store16, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int16_t storage = -1; CHECK(compileAndRun(proc, &storage) == 42); @@ -4749,7 +5334,7 @@ Value* address = root->appendNew(proc, Add, Origin(), baseDisplacement, offset); root->appendNew(proc, Store16, Origin(), value, address); - root->appendNew(proc, Return, Origin(), value); + root->appendNewControlValue(proc, Return, Origin(), value); int16_t storage = -1; CHECK(compileAndRun(proc, &storage, 1) == 42); @@ -4761,7 +5346,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -4774,7 +5359,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -4790,7 +5375,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -4804,7 +5389,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -4820,7 +5405,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Sub, Origin(), @@ -4845,7 +5430,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4866,7 +5451,7 @@ root->appendNew(proc, Load, Int32, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4889,7 +5474,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4910,7 +5495,7 @@ root->appendNew(proc, loadOpcode, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4933,7 +5518,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4954,7 +5539,7 @@ root->appendNew(proc, loadOpcode, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4975,7 +5560,7 @@ root->appendNew(proc, Load, Int64, Origin(), slotPtr), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -4996,7 +5581,7 @@ root->appendNew(proc, Load, Int64, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5028,7 +5613,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5058,7 +5643,7 @@ root->appendNew(proc, Load, Int32, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5090,7 +5675,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5120,7 +5705,7 @@ root->appendNew(proc, loadOpcode, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5152,7 +5737,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5182,7 +5767,7 @@ root->appendNew(proc, loadOpcode, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5212,7 +5797,7 @@ root->appendNew(proc, Load, Int64, Origin(), slotPtr), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5242,7 +5827,7 @@ root->appendNew(proc, Load, Int64, Origin(), slotPtr), root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5266,7 +5851,7 @@ proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5293,7 +5878,7 @@ proc, Add, Origin(), load, root->appendNew(proc, Origin(), amount)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5317,7 +5902,7 @@ root->appendNew(proc, Origin(), amount)), root->appendNew(proc, Origin(), mask)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -5342,7 +5927,7 @@ root->appendNew(proc, Load, Int32, Origin(), slotPtr)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); CHECK(!compileAndRun(proc)); @@ -5366,7 +5951,7 @@ root->appendNew(proc, Load, pointerType(), Origin(), slotPtr)), slotPtr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); CHECK(!compileAndRun(proc)); @@ -5377,7 +5962,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -5395,7 +5980,7 @@ BasicBlock* root = proc.addBlock(); int array[] = { 1, 2 }; ConstPtrValue* arrayPtr = root->appendNew(proc, Origin(), array); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -5411,7 +5996,7 @@ BasicBlock* root = proc.addBlock(); int array[] = { 1, 2 }; Value* arrayPtr = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -5427,7 +6012,7 @@ BasicBlock* root = proc.addBlock(); int array[] = { 1, 2 }; ConstPtrValue* arrayPtr = root->appendNew(proc, Origin(), array); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -5468,7 +6053,7 @@ proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0); root->appendNew( proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, sizeof(int)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), left, right)); @@ -5484,7 +6069,7 @@ BasicBlock* root = proc.addBlock(); int array[] = { 1, 2 }; Value* arrayPtr = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -5520,7 +6105,7 @@ *slot = 8675309; - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Load, Int32, Origin(), @@ -5536,7 +6121,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, FramePointer, Origin())); @@ -5559,7 +6144,7 @@ Value* fp = root->appendNew(proc, FramePointer, Origin()); Value* result = root->appendNew(proc, Sub, Origin(), fp, offset); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, 1)); } { @@ -5575,7 +6160,7 @@ Value* offsetArg = root->appendNew(proc, Add, Origin(), offset, arg); Value* result = root->appendNew(proc, Add, Origin(), offsetArg, offsetFP); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, 1, 2)); } } @@ -5584,7 +6169,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), proc.addStackSlot(1))); @@ -5597,7 +6182,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Load, pointerType(), Origin(), @@ -5624,7 +6209,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), stack); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Load, Int32, Origin(), stack)); @@ -5659,7 +6244,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, opcode, type, Origin(), @@ -5673,7 +6258,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, opcode, type, Origin(), @@ -5687,7 +6272,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, opcode, type, Origin(), @@ -5702,7 +6287,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, opcode, type, Origin(), @@ -5722,7 +6307,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, opcode, type, Origin(), @@ -5762,7 +6347,7 @@ Value* destinationAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); root->appendNew(proc, Store, Origin(), argumentAsFloat, destinationAddress); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); float output = 0.; CHECK(!compileAndRun(proc, input, &output)); @@ -5786,7 +6371,7 @@ root->appendNew(proc, Store, Origin(), argumentAsFloat, destinationAddress); - root->appendNew(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); float output = 0.; CHECK(!compileAndRun(proc, input, &output - 1, 1)); @@ -5794,6 +6379,25 @@ } } +void testStoreDoubleConstantAsFloat(double input) +{ + // Simple store from an address in a register. + Procedure proc; + BasicBlock* root = proc.addBlock(); + Value* value = root->appendNew(proc, Origin(), input); + Value* valueAsFloat = root->appendNew(proc, DoubleToFloat, Origin(), value); + + Value* destinationAddress = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + + root->appendNew(proc, Store, Origin(), valueAsFloat, destinationAddress); + + root->appendNewControlValue(proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); + + float output = 0.; + CHECK(!compileAndRun(proc, input, &output)); + CHECK(isIdentical(static_cast(input), output)); +} + void testSpillGP() { Procedure proc; @@ -5813,7 +6417,7 @@ for (Value* value : sources) total = root->appendNew(proc, Add, Origin(), total, value); - root->appendNew(proc, Return, Origin(), total); + root->appendNewControlValue(proc, Return, Origin(), total); compileAndRun(proc, 1, 2); } @@ -5836,7 +6440,7 @@ for (Value* value : sources) total = root->appendNew(proc, Add, Origin(), total, value); - root->appendNew(proc, Return, Origin(), total); + root->appendNewControlValue(proc, Return, Origin(), total); compileAndRun(proc, 1.1, 2.5); } @@ -5852,7 +6456,7 @@ Value* counter = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); UpsilonValue* originalTotal = root->appendNew(proc, Origin(), total); UpsilonValue* originalCounter = root->appendNew(proc, Origin(), counter); - root->appendNew(proc, Jump, Origin(), FrequentedBlock(loop)); + root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop)); // Loop. Value* loopCounter = loop->appendNew(proc, Phi, Int64, Origin()); @@ -5869,13 +6473,13 @@ Value* decCounter = loop->appendNew(proc, Sub, Origin(), loopCounter, loop->appendNew(proc, Origin(), 1)); UpsilonValue* decCounterUpsilon = loop->appendNew(proc, Origin(), decCounter); decCounterUpsilon->setPhi(loopCounter); - loop->appendNew( + loop->appendNewControlValue( proc, Branch, Origin(), decCounter, FrequentedBlock(loop), FrequentedBlock(done)); // Tail. - done->appendNew(proc, Return, Origin(), updatedTotal); + done->appendNewControlValue(proc, Return, Origin(), updatedTotal); CHECK(isIdentical(compileAndRun(proc, 100000), 5000050000.)); } @@ -5895,7 +6499,7 @@ Value* forPaddingInputAddress = root->appendNew(proc, Origin(), &forPaddingInput); uint64_t forPaddingOutput; Value* forPaddingOutputAddress = root->appendNew(proc, Origin(), &forPaddingOutput); - root->appendNew(proc, Jump, Origin(), FrequentedBlock(loop)); + root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop)); // Loop. Value* loopCounter = loop->appendNew(proc, Phi, Int64, Origin()); @@ -5929,13 +6533,13 @@ Value* decCounter = loop->appendNew(proc, Sub, Origin(), loopCounter, loop->appendNew(proc, Origin(), 1)); UpsilonValue* decCounterUpsilon = loop->appendNew(proc, Origin(), decCounter); decCounterUpsilon->setPhi(loopCounter); - loop->appendNew( + loop->appendNewControlValue( proc, Branch, Origin(), decCounter, FrequentedBlock(loop), FrequentedBlock(done)); // Tail. - done->appendNew(proc, Return, Origin(), updatedTotal); + done->appendNewControlValue(proc, Return, Origin(), updatedTotal); CHECK(isIdentical(compileAndRun(proc, 100000), 5000050000.)); } @@ -5946,18 +6550,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -5973,16 +6577,16 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -5999,7 +6603,7 @@ BasicBlock* elseCase = proc.addBlock(); BasicBlock* done = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -6008,16 +6612,16 @@ UpsilonValue* thenResult = thenCase->appendNew( proc, Origin(), thenCase->appendNew(proc, Origin(), 1)); - thenCase->appendNew(proc, Jump, Origin(), FrequentedBlock(done)); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done)); UpsilonValue* elseResult = elseCase->appendNew( proc, Origin(), elseCase->appendNew(proc, Origin(), 0)); - elseCase->appendNew(proc, Jump, Origin(), FrequentedBlock(done)); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done)); Value* phi = done->appendNew(proc, Phi, Int32, Origin()); thenResult->setPhi(phi); elseResult->setPhi(phi); - done->appendNew(proc, Return, Origin(), phi); + done->appendNewControlValue(proc, Return, Origin(), phi); auto code = compile(proc); CHECK(invoke(*code, 42) == 1); @@ -6031,7 +6635,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, NotEqual, Origin(), @@ -6041,11 +6645,11 @@ root->appendNew(proc, Origin(), 0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6061,7 +6665,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, NotEqual, Origin(), @@ -6071,11 +6675,11 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6091,7 +6695,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, NotEqual, Origin(), @@ -6104,11 +6708,11 @@ root->appendNew(proc, Origin(), 0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6124,7 +6728,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Equal, Origin(), @@ -6134,11 +6738,11 @@ root->appendNew(proc, Origin(), 0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 0)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 1)); @@ -6154,7 +6758,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Equal, Origin(), @@ -6167,11 +6771,11 @@ root->appendNew(proc, Origin(), 0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6187,7 +6791,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Equal, Origin(), @@ -6197,11 +6801,11 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 0)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 1)); @@ -6217,7 +6821,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Equal, Origin(), @@ -6230,11 +6834,11 @@ root->appendNew(proc, Origin(), 1)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 0)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 1)); @@ -6252,7 +6856,7 @@ Value* argumentA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* argumentB = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6260,11 +6864,11 @@ argumentB), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6284,7 +6888,7 @@ Value* argumentB = root->appendNew(proc, Load, Float, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6292,11 +6896,11 @@ argumentB), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6321,16 +6925,16 @@ proc, Equal, Origin(), root->appendNew(proc, Origin(), 0), equalOrUnordered); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), notEqualAndOrdered, FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6357,16 +6961,16 @@ proc, Equal, Origin(), root->appendNew(proc, Origin(), 0), equalOrUnordered); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), notEqualAndOrdered, FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6383,7 +6987,7 @@ Value* argumentA = root->appendNew(proc, Origin(), FPRInfo::argumentFPR0); Value* argumentB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6391,11 +6995,11 @@ argumentB), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6414,7 +7018,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* argumentB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6422,11 +7026,11 @@ argumentB), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6443,7 +7047,7 @@ Value* argumentA = root->appendNew(proc, Origin(), a); Value* argumentB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6451,11 +7055,11 @@ argumentB), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6473,7 +7077,7 @@ Value* argumentA = root->appendNew(proc, Origin(), a); Value* argumentB = root->appendNew(proc, Origin(), b); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6481,11 +7085,11 @@ argumentB), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6507,7 +7111,7 @@ Value* argument1AsDouble = root->appendNew(proc, FloatToDouble, Origin(), argument1); Value* argument2AsDouble = root->appendNew(proc, FloatToDouble, Origin(), argument2); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, EqualOrUnordered, Origin(), @@ -6515,11 +7119,11 @@ argument2AsDouble), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 42)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), -13)); @@ -6534,16 +7138,16 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Origin(), value), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6558,23 +7162,23 @@ BasicBlock* elseCase = proc.addBlock(); BasicBlock* done = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Origin(), value), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); UpsilonValue* thenResult = thenCase->appendNew( proc, Origin(), thenCase->appendNew(proc, Origin(), 1)); - thenCase->appendNew(proc, Jump, Origin(), FrequentedBlock(done)); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done)); UpsilonValue* elseResult = elseCase->appendNew( proc, Origin(), elseCase->appendNew(proc, Origin(), 0)); - elseCase->appendNew(proc, Jump, Origin(), FrequentedBlock(done)); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(done)); Value* phi = done->appendNew(proc, Phi, Int32, Origin()); thenResult->setPhi(phi); elseResult->setPhi(phi); - done->appendNew(proc, Return, Origin(), phi); + done->appendNewControlValue(proc, Return, Origin(), phi); CHECK(compileAndRun(proc) == !!value); } @@ -6586,7 +7190,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, NotEqual, Origin(), @@ -6594,11 +7198,11 @@ root->appendNew(proc, Origin(), 0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6612,7 +7216,7 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Equal, Origin(), @@ -6620,11 +7224,11 @@ root->appendNew(proc, Origin(), 0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6638,18 +7242,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Load, pointerType(), Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6668,18 +7272,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Load, Int32, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6698,18 +7302,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Load8S, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6728,18 +7332,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Load8Z, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6758,18 +7362,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Load16S, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6788,18 +7392,18 @@ BasicBlock* thenCase = proc.addBlock(); BasicBlock* elseCase = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew( proc, Load16Z, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 1)); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -6811,6 +7415,46 @@ CHECK(invoke(*code, &cond) == 0); } +void testBranch8WithLoad8ZIndex() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + + int logScale = 1; + root->appendNewControlValue( + proc, Branch, Origin(), + root->appendNew( + proc, Above, Origin(), + root->appendNew( + proc, Load8Z, Origin(), + root->appendNew( + proc, Add, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), + root->appendNew( + proc, Shl, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1), + root->appendNew(proc, Origin(), logScale)))), + root->appendNew(proc, Origin(), 250)), + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + thenCase->appendNewControlValue( + proc, Return, Origin(), + thenCase->appendNew(proc, Origin(), 1)); + + elseCase->appendNewControlValue( + proc, Return, Origin(), + elseCase->appendNew(proc, Origin(), 0)); + + auto code = compile(proc); + uint32_t cond; + cond = 0xffffffffU; // All bytes are 0xff. + CHECK(invoke(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 1); + cond = 0x00000000U; // All bytes are 0. + CHECK(invoke(*code, &cond - 2, (sizeof(uint32_t) * 2) >> logScale) == 0); +} + void testComplex(unsigned numVars, unsigned numConstructs) { double before = monotonicallyIncreasingTimeMS(); @@ -6841,7 +7485,7 @@ BasicBlock* elseBlock = proc.addBlock(); BasicBlock* continuation = proc.addBlock(); - current->appendNew( + current->appendNewControlValue( proc, Branch, Origin(), vars[predicateVarIndex], FrequentedBlock(thenBlock), FrequentedBlock(elseBlock)); @@ -6850,14 +7494,14 @@ thenBlock->appendNew(proc, Add, Origin(), vars[thenIncVarIndex], one)); UpsilonValue* thenElseResult = thenBlock->appendNew( proc, Origin(), vars[elseIncVarIndex]); - thenBlock->appendNew(proc, Jump, Origin(), FrequentedBlock(continuation)); + thenBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation)); UpsilonValue* elseElseResult = elseBlock->appendNew( proc, Origin(), elseBlock->appendNew(proc, Add, Origin(), vars[elseIncVarIndex], one)); UpsilonValue* elseThenResult = elseBlock->appendNew( proc, Origin(), vars[thenIncVarIndex]); - elseBlock->appendNew(proc, Jump, Origin(), FrequentedBlock(continuation)); + elseBlock->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation)); Value* thenPhi = continuation->appendNew(proc, Phi, Int32, Origin()); thenThenResult->setPhi(thenPhi); @@ -6882,7 +7526,7 @@ Value* startIndex = vars[((i >> 1) + 1) % numVars]; Value* startSum = current->appendNew(proc, Origin(), 0); - current->appendNew( + current->appendNewControlValue( proc, Branch, Origin(), startIndex, FrequentedBlock(loopEntry), FrequentedBlock(loopSkip)); @@ -6890,7 +7534,7 @@ proc, Origin(), startIndex); UpsilonValue* startSumForBody = loopEntry->appendNew( proc, Origin(), startSum); - loopEntry->appendNew(proc, Jump, Origin(), FrequentedBlock(loopBody)); + loopEntry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody)); Value* bodyIndex = loopBody->appendNew(proc, Phi, Int32, Origin()); startIndexForBody->setPhi(bodyIndex); @@ -6915,19 +7559,19 @@ loopBody->appendNew( proc, Origin(), numVars - 1))), loopBody->appendNew(proc, Origin(), 2))))); - loopBody->appendNew( + loopBody->appendNewControlValue( proc, Branch, Origin(), newBodyIndex, FrequentedBlock(loopReentry), FrequentedBlock(loopExit)); loopReentry->appendNew(proc, Origin(), newBodyIndex, bodyIndex); loopReentry->appendNew(proc, Origin(), newBodySum, bodySum); - loopReentry->appendNew(proc, Jump, Origin(), FrequentedBlock(loopBody)); + loopReentry->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loopBody)); UpsilonValue* exitSum = loopExit->appendNew(proc, Origin(), newBodySum); - loopExit->appendNew(proc, Jump, Origin(), FrequentedBlock(continuation)); + loopExit->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation)); UpsilonValue* skipSum = loopSkip->appendNew(proc, Origin(), startSum); - loopSkip->appendNew(proc, Jump, Origin(), FrequentedBlock(continuation)); + loopSkip->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(continuation)); Value* finalSum = continuation->appendNew(proc, Phi, Int32, Origin()); exitSum->setPhi(finalSum); @@ -6938,7 +7582,7 @@ } } - current->appendNew(proc, Return, Origin(), vars[0]); + current->appendNewControlValue(proc, Return, Origin(), vars[0]); compile(proc); @@ -6964,7 +7608,7 @@ CHECK(params[2].isGPR()); add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -6995,7 +7639,7 @@ }); Value* result = root->appendNew(proc, Add, Origin(), arg1, arg2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7044,7 +7688,7 @@ Value* result = root->appendNew(proc, Add, Origin(), patchpoint, root->appendNew(proc, Add, Origin(), arg1, arg2)); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, 1, 2) == 58); } @@ -7075,7 +7719,7 @@ }); Value* result = root->appendNew(proc, Add, Origin(), arg1, arg2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, 1.5, 2.5) == 4); } @@ -7116,7 +7760,7 @@ Value* result = root->appendNew(proc, Add, Origin(), patchpoint, root->appendNew(proc, Add, Origin(), arg1, arg2)); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, 1.5, 2.5) == 59.6); } @@ -7141,7 +7785,7 @@ add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); }; @@ -7174,7 +7818,7 @@ CCallHelpers::Address(GPRInfo::callFrameRegister, params[2].offsetFromFP()), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7197,7 +7841,7 @@ CHECK(params[2] == ValueRep(GPRInfo::regT1)); add32(jit, GPRInfo::regT0, GPRInfo::regT1, params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7221,7 +7865,7 @@ CHECK(params[2].isGPR()); add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7257,7 +7901,7 @@ CHECK(!params.unavailableRegisters().get(params.gpScratch(1))); add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7287,7 +7931,7 @@ CHECK(!params.unavailableRegisters().get(params.fpScratch(1))); add32(jit, params[1].gpr(), params[2].gpr(), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7329,7 +7973,7 @@ } } }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc) == (things.size() * (things.size() - 1)) / 2); } @@ -7357,7 +8001,7 @@ CCallHelpers::TrustedImm32(static_cast(params[2].value())), params[1].gpr(), params[0].gpr()); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1) == 43); } @@ -7383,7 +8027,7 @@ CHECK(params[2] == ValueRep::constant(43000000000000ll)); CHECK(params[3] == ValueRep::constant(bitwise_cast(42.5))); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -7409,7 +8053,7 @@ CHECK(params[2].isGPR()); add32(jit, params[1].gpr(), params[2].gpr(), GPRInfo::nonArgGPR0); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7435,7 +8079,7 @@ jit.add32(params[1].gpr(), params[2].gpr(), jit.scratchRegister()); jit.store32(jit.scratchRegister(), CCallHelpers::Address(CCallHelpers::stackPointerRegister, 0)); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7464,7 +8108,7 @@ jit.convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0); jit.storeDouble(FPRInfo::fpRegT0, CCallHelpers::Address(GPRInfo::callFrameRegister, params[0].offsetFromFP())); }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); CHECK(compileAndRun(proc, 1, 2) == 3); } @@ -7486,7 +8130,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7505,7 +8149,7 @@ [&] (CCallHelpers&, const StackmapGenerationParams&) { CHECK(!"This should not have executed"); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7531,7 +8175,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7562,7 +8206,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7608,7 +8252,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7663,7 +8307,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7727,7 +8371,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); auto code = compile(proc); @@ -7777,7 +8421,7 @@ root->appendNew(proc, Load8S, Origin(), ptr), root->appendNew(proc, Origin(), 42)); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), branchPredicate, FrequentedBlock(thenCase), FrequentedBlock(elseCase)); @@ -7793,7 +8437,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew(proc, Origin(), 43)); CheckValue* check2 = elseCase->appendNew(proc, Check, Origin(), checkPredicate); @@ -7808,7 +8452,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 45)); auto code = compile(proc); @@ -7862,7 +8506,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkAdd)); @@ -7898,7 +8542,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkAdd)); @@ -7933,7 +8577,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkAdd)); @@ -7970,7 +8614,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkAdd)); @@ -8003,7 +8647,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkAdd)); @@ -8026,7 +8670,7 @@ [&] (CCallHelpers&, const StackmapGenerationParams&) { CHECK(!"Should have been folded"); }); - root->appendNew(proc, Return, Origin(), checkAdd); + root->appendNewControlValue(proc, Return, Origin(), checkAdd); auto code = compile(proc); @@ -8047,7 +8691,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew(proc, Return, Origin(), checkAdd); + root->appendNewControlValue(proc, Return, Origin(), checkAdd); auto code = compile(proc); @@ -8086,7 +8730,7 @@ CheckValue* checkAdd3 = root->appendNew(proc, CheckAdd, Origin(), checkAdd1, checkAdd2); checkAdd3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - root->appendNew(proc, Return, Origin(), checkAdd3); + root->appendNewControlValue(proc, Return, Origin(), checkAdd3); CHECK(compileAndRun(proc, 1, 2, 3) == 8); } @@ -8129,7 +8773,7 @@ CheckValue* checkAdd3 = root->appendNew(proc, CheckAdd, Origin(), checkAdd1, checkAdd2); checkAdd3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - root->appendNew(proc, Return, Origin(), checkAdd3); + root->appendNewControlValue(proc, Return, Origin(), checkAdd3); CHECK(compileAndRun(proc, 1, 2, 3) == 8); } @@ -8154,7 +8798,7 @@ opaqueUse->append(ConstrainedValue(arg, ValueRep::SomeRegister)); opaqueUse->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), checkAdd); + root->appendNewControlValue(proc, Return, Origin(), checkAdd); auto code = compile(proc); @@ -8185,7 +8829,7 @@ opaqueUse->append(ConstrainedValue(arg, ValueRep::SomeRegister)); opaqueUse->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), checkAdd); + root->appendNewControlValue(proc, Return, Origin(), checkAdd); auto code = compile(proc); @@ -8218,7 +8862,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkSub)); @@ -8260,7 +8904,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkSub)); @@ -8297,7 +8941,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkSub)); @@ -8335,7 +8979,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkSub)); @@ -8358,7 +9002,7 @@ [&] (CCallHelpers&, const StackmapGenerationParams&) { CHECK(!"Should have been folded"); }); - root->appendNew(proc, Return, Origin(), checkSub); + root->appendNewControlValue(proc, Return, Origin(), checkSub); auto code = compile(proc); @@ -8379,7 +9023,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew(proc, Return, Origin(), checkSub); + root->appendNewControlValue(proc, Return, Origin(), checkSub); auto code = compile(proc); @@ -8406,7 +9050,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkNeg)); @@ -8436,7 +9080,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkNeg)); @@ -8473,7 +9117,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkMul)); @@ -8514,7 +9158,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkMul)); @@ -8561,7 +9205,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkMul)); @@ -8594,7 +9238,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkMul)); @@ -8617,7 +9261,7 @@ [&] (CCallHelpers&, const StackmapGenerationParams&) { CHECK(!"Should have been folded"); }); - root->appendNew(proc, Return, Origin(), checkMul); + root->appendNewControlValue(proc, Return, Origin(), checkMul); auto code = compile(proc); @@ -8638,7 +9282,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew(proc, Return, Origin(), checkMul); + root->appendNewControlValue(proc, Return, Origin(), checkMul); auto code = compile(proc); @@ -8677,7 +9321,7 @@ CheckValue* checkMul3 = root->appendNew(proc, CheckMul, Origin(), checkMul1, checkMul2); checkMul3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - root->appendNew(proc, Return, Origin(), checkMul3); + root->appendNewControlValue(proc, Return, Origin(), checkMul3); CHECK(compileAndRun(proc, 2, 3, 4) == 72); } @@ -8720,7 +9364,7 @@ CheckValue* checkMul3 = root->appendNew(proc, CheckMul, Origin(), checkMul1, checkMul2); checkMul3->setGenerator([&] (CCallHelpers& jit, const StackmapGenerationParams&) { jit.oops(); }); - root->appendNew(proc, Return, Origin(), checkMul3); + root->appendNewControlValue(proc, Return, Origin(), checkMul3); CHECK(compileAndRun(proc, 2, 3, 4) == 72); } @@ -8752,7 +9396,7 @@ jit.emitFunctionEpilogue(); jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, IToD, Origin(), checkMul)); @@ -8778,7 +9422,7 @@ Value* rightValue = rightFunctor(root, proc); Value* comparisonResult = root->appendNew(proc, opcode, Origin(), leftValue, rightValue); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, NotEqual, Origin(), @@ -8798,7 +9442,7 @@ Value* leftValue = leftFunctor(root, proc); Value* rightValue = rightFunctor(root, proc); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, opcode, Origin(), leftValue, rightValue), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); @@ -8812,9 +9456,9 @@ CHECK(params[0].isGPR()); jit.move(CCallHelpers::TrustedImm32(1), params[0].gpr()); }); - thenCase->appendNew(proc, Return, Origin(), patchpoint); + thenCase->appendNewControlValue(proc, Return, Origin(), patchpoint); - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew(proc, Origin(), 0)); @@ -9053,7 +9697,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Equal, Origin(), @@ -9072,7 +9716,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Int32, Origin(), @@ -9090,16 +9734,16 @@ BasicBlock* common = proc.addBlock(); BasicBlock* rare = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), FrequentedBlock(rare, FrequencyClass::Rare), FrequentedBlock(common)); - common->appendNew( + common->appendNewControlValue( proc, Return, Origin(), common->appendNew(proc, Origin(), 0)); - rare->appendNew( + rare->appendNewControlValue( proc, Return, Origin(), rare->appendNew( proc, Int32, Origin(), @@ -9117,16 +9761,16 @@ BasicBlock* common = proc.addBlock(); BasicBlock* rare = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), FrequentedBlock(rare, FrequencyClass::Rare), FrequentedBlock(common)); - common->appendNew( + common->appendNewControlValue( proc, Return, Origin(), common->appendNew(proc, Origin(), 0)); - rare->appendNew( + rare->appendNewControlValue( proc, Return, Origin(), rare->appendNew( proc, Add, Origin(), @@ -9146,7 +9790,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Int32, Origin(), Effects::none(), @@ -9176,7 +9820,7 @@ root->appendNew(proc, Origin(), bitwise_cast(functionWithHellaArguments))); call->children().appendVector(args); - root->appendNew(proc, Return, Origin(), call); + root->appendNewControlValue(proc, Return, Origin(), call); CHECK(compileAndRun(proc) == functionWithHellaArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)); } @@ -9185,7 +9829,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), value)); @@ -9196,7 +9840,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), value)); @@ -9212,7 +9856,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Double, Origin(), @@ -9238,7 +9882,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); Value* floatValue1 = root->appendNew(proc, BitwiseCast, Origin(), argument1int32); Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Float, Origin(), @@ -9268,7 +9912,7 @@ root->appendNew(proc, Origin(), bitwise_cast(functionWithHellaDoubleArguments))); call->children().appendVector(args); - root->appendNew(proc, Return, Origin(), call); + root->appendNewControlValue(proc, Return, Origin(), call); CHECK(compileAndRun(proc) == functionWithHellaDoubleArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)); } @@ -9292,7 +9936,7 @@ root->appendNew(proc, Origin(), bitwise_cast(functionWithHellaFloatArguments))); call->children().appendVector(args); - root->appendNew(proc, Return, Origin(), call); + root->appendNewControlValue(proc, Return, Origin(), call); CHECK(compileAndRun(proc) == functionWithHellaFloatArguments(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)); } @@ -9304,7 +9948,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ChillDiv, Origin(), @@ -9323,7 +9967,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ChillDiv, Origin(), @@ -9339,7 +9983,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Add, Origin(), @@ -9373,7 +10017,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ChillDiv, Origin(), @@ -9388,7 +10032,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ChillDiv, Origin(), @@ -9409,7 +10053,7 @@ Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* result = root->appendNew(proc, Mod, Origin(), argument, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(!compileAndRun(proc, value)); } @@ -9427,7 +10071,7 @@ Value* argument1 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* argument2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); Value* result = root->appendNew(proc, Mod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == numerator % denominator); } @@ -9445,7 +10089,7 @@ Value* argument1 = root->appendNew(proc, Origin(), numerator); Value* argument2 = root->appendNew(proc, Origin(), denominator); Value* result = root->appendNew(proc, Mod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == numerator % denominator); } @@ -9461,7 +10105,7 @@ Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* result = root->appendNew(proc, Mod, Origin(), argument, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(!compileAndRun(proc, value)); } @@ -9481,7 +10125,7 @@ Value* argument2 = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); Value* result = root->appendNew(proc, Mod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == numerator % denominator); } @@ -9499,7 +10143,7 @@ Value* argument1 = root->appendNew(proc, Origin(), numerator); Value* argument2 = root->appendNew(proc, Origin(), denominator); Value* result = root->appendNew(proc, Mod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == numerator % denominator); } @@ -9511,7 +10155,7 @@ Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* result = root->appendNew(proc, ChillMod, Origin(), argument, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(!compileAndRun(proc, value)); } @@ -9524,7 +10168,7 @@ Value* argument1 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* argument2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); Value* result = root->appendNew(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == chillMod(numerator, denominator)); } @@ -9537,7 +10181,7 @@ Value* argument1 = root->appendNew(proc, Origin(), numerator); Value* argument2 = root->appendNew(proc, Origin(), denominator); Value* result = root->appendNew(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == chillMod(numerator, denominator)); } @@ -9550,7 +10194,7 @@ Value* argument = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* result = root->appendNew(proc, ChillMod, Origin(), argument, argument); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(!compileAndRun(proc, value)); } @@ -9565,7 +10209,7 @@ Value* argument2 = root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); Value* result = root->appendNew(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == chillMod(numerator, denominator)); } @@ -9578,7 +10222,7 @@ Value* argument1 = root->appendNew(proc, Origin(), numerator); Value* argument2 = root->appendNew(proc, Origin(), denominator); Value* result = root->appendNew(proc, ChillMod, Origin(), argument1, argument2); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); CHECK(compileAndRun(proc, numerator, denominator) == chillMod(numerator, denominator)); } @@ -9589,18 +10233,17 @@ BasicBlock* root = proc.addBlock(); BasicBlock* terminate = proc.addBlock(); - terminate->appendNew( + terminate->appendNewControlValue( proc, Return, Origin(), terminate->appendNew(proc, Origin(), 0)); SwitchValue* switchValue = root->appendNew( - proc, Origin(), - root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(terminate)); + proc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + switchValue->setFallThrough(FrequentedBlock(terminate)); for (unsigned i = 0; i < degree; ++i) { BasicBlock* newBlock = proc.addBlock(); - newBlock->appendNew( + newBlock->appendNewControlValue( proc, Return, Origin(), newBlock->appendNew( proc, Origin(), (i & 1) ? GPRInfo::argumentGPR2 : GPRInfo::argumentGPR1)); @@ -9631,19 +10274,18 @@ Value* right = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); BasicBlock* terminate = proc.addBlock(); - terminate->appendNew( + terminate->appendNewControlValue( proc, Return, Origin(), terminate->appendNew(proc, Origin(), 0)); SwitchValue* switchValue = root->appendNew( - proc, Origin(), - root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(terminate)); + proc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + switchValue->setFallThrough(FrequentedBlock(terminate)); for (unsigned i = 0; i < degree; ++i) { BasicBlock* newBlock = proc.addBlock(); - newBlock->appendNew( + newBlock->appendNewControlValue( proc, Return, Origin(), newBlock->appendNew( proc, ChillDiv, Origin(), (i & 1) ? right : left, (i & 1) ? left : right)); @@ -9654,7 +10296,10 @@ auto code = compile(proc); for (unsigned i = 0; i < degree; ++i) { - CHECK(invoke(*code, i * gap, 42, 11) == ((i & 1) ? 11/42 : 42/11)); + dataLog("i = ", i, "\n"); + int32_t result = invoke(*code, i * gap, 42, 11); + dataLog("result = ", result, "\n"); + CHECK(result == ((i & 1) ? 11/42 : 42/11)); if (gap > 1) { CHECK(!invoke(*code, i * gap + 1, 42, 11)); CHECK(!invoke(*code, i * gap - 1, 42, 11)); @@ -9672,17 +10317,16 @@ BasicBlock* root = proc.addBlock(); BasicBlock* terminate = proc.addBlock(); - terminate->appendNew( + terminate->appendNewControlValue( proc, Return, Origin(), terminate->appendNew(proc, Origin(), 5)); SwitchValue* switchValue = root->appendNew( - proc, Origin(), - root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), - FrequentedBlock(terminate)); + proc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + switchValue->setFallThrough(FrequentedBlock(terminate)); BasicBlock* otherTarget = proc.addBlock(); - otherTarget->appendNew( + otherTarget->appendNewControlValue( proc, Return, Origin(), otherTarget->appendNew(proc, Origin(), 42)); switchValue->appendCase(SwitchCase(3, FrequentedBlock(otherTarget))); @@ -9702,18 +10346,16 @@ BasicBlock* root = proc.addBlock(); BasicBlock* terminate = proc.addBlock(); - terminate->appendNew( + terminate->appendNewControlValue( proc, Return, Origin(), terminate->appendNew(proc, Origin(), 42)); Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - SwitchValue* switchValue = root->appendNew( - proc, Origin(), - argument, - FrequentedBlock(terminate)); + SwitchValue* switchValue = root->appendNew(proc, Origin(), argument); + switchValue->setFallThrough(FrequentedBlock(terminate)); BasicBlock* otherTarget = proc.addBlock(); - otherTarget->appendNew( + otherTarget->appendNewControlValue( proc, Return, Origin(), argument); switchValue->appendCase(SwitchCase(3, FrequentedBlock(otherTarget))); switchValue->appendCase(SwitchCase(13, FrequentedBlock(otherTarget))); @@ -9730,7 +10372,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -9743,7 +10385,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZExt32, Origin(), @@ -9758,7 +10400,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZExt32, Origin(), @@ -9771,7 +10413,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt32, Origin(), @@ -9786,7 +10428,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt32, Origin(), @@ -9799,7 +10441,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -9816,7 +10458,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -9833,7 +10475,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt8, Origin(), @@ -9848,7 +10490,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt8, Origin(), @@ -9861,7 +10503,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt8, Origin(), @@ -9878,7 +10520,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt8, Origin(), @@ -9895,7 +10537,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt8, Origin(), @@ -9913,7 +10555,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -9931,7 +10573,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt16, Origin(), @@ -9946,7 +10588,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt16, Origin(), @@ -9959,7 +10601,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt16, Origin(), @@ -9976,7 +10618,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt16, Origin(), @@ -9993,7 +10635,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt16, Origin(), @@ -10011,7 +10653,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -10029,7 +10671,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SExt32, Origin(), @@ -10047,7 +10689,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -10065,7 +10707,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10087,7 +10729,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10106,7 +10748,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10137,7 +10779,7 @@ Value* floatValue1 = root->appendNew(proc, BitwiseCast, Origin(), argument1int32); Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10175,7 +10817,7 @@ Value* doubleValue1 = root->appendNew(proc, FloatToDouble, Origin(), floatValue1); Value* doubleValue2 = root->appendNew(proc, FloatToDouble, Origin(), floatValue2); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10203,7 +10845,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10225,7 +10867,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10244,7 +10886,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10274,7 +10916,7 @@ Value* floatValue1 = root->appendNew(proc, BitwiseCast, Origin(), argument1int32); Value* floatValue2 = root->appendNew(proc, BitwiseCast, Origin(), argument2int32); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10305,7 +10947,7 @@ Value* floatValue3 = root->appendNew(proc, BitwiseCast, Origin(), argument3int32); Value* floatValue4 = root->appendNew(proc, BitwiseCast, Origin(), argument4int32); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10331,7 +10973,7 @@ Value* arg2 = root->appendNew(proc, Origin(), FPRInfo::argumentFPR2); Value* arg3 = root->appendNew(proc, Origin(), FPRInfo::argumentFPR3); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10367,7 +11009,7 @@ keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10394,7 +11036,7 @@ keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10422,7 +11064,7 @@ keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10439,7 +11081,7 @@ Value* arg1 = root->appendNew(proc, Origin(), FPRInfo::argumentFPR1); Value* arg2 = root->appendNew(proc, Origin(), FPRInfo::argumentFPR2); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10474,7 +11116,7 @@ keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10517,7 +11159,7 @@ root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR3))); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10561,7 +11203,7 @@ keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10596,7 +11238,7 @@ keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10632,7 +11274,7 @@ keepValuesLive->append(ConstrainedValue(arg3, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10655,7 +11297,7 @@ root->appendNew(proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR2))); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10696,7 +11338,7 @@ keepValuesLive->append(ConstrainedValue(arg2, ValueRep::SomeRegister)); keepValuesLive->setGenerator([&] (CCallHelpers&, const StackmapGenerationParams&) { }); - root->appendNew(proc, Return, Origin(), result); + root->appendNewControlValue(proc, Return, Origin(), result); auto code = compile(proc); for (auto& left : floatingPointOperands()) { @@ -10723,7 +11365,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10743,7 +11385,7 @@ { Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Select, Origin(), @@ -10796,7 +11438,7 @@ jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -10867,7 +11509,7 @@ jit.ret(); }); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Origin(), 0)); @@ -10903,7 +11545,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); auto result = powDoubleInt32(proc, root, Origin(), x, y); BasicBlock* continuation = result.first; - continuation->appendNew(proc, Return, Origin(), result.second); + continuation->appendNewControlValue(proc, Return, Origin(), result.second); CHECK(isIdentical(compileAndRun(proc, xOperand, yOperand), b3Pow(xOperand, yOperand))); } @@ -10913,7 +11555,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -10931,7 +11573,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Trunc, Origin(), @@ -10949,7 +11591,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -10968,7 +11610,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, BitAnd, Origin(), @@ -10991,20 +11633,20 @@ Value* arg1 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* arg2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Equal, Origin(), arg1, arg2), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); bool trueResult = true; - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew( proc, Load8Z, Origin(), thenCase->appendNew(proc, Origin(), &trueResult))); bool elseResult = false; - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew( proc, Load8Z, Origin(), @@ -11022,20 +11664,20 @@ Value* arg1 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); Value* arg2 = root->appendNew(proc, Origin(), right); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Equal, Origin(), arg1, arg2), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); bool trueResult = true; - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew( proc, Load8Z, Origin(), thenCase->appendNew(proc, Origin(), &trueResult))); bool elseResult = false; - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew( proc, Load8Z, Origin(), @@ -11055,20 +11697,20 @@ proc, Load, pointerType(), Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* arg2 = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Equal, Origin(), arg1, arg2), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); bool trueResult = true; - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew( proc, Load8Z, Origin(), thenCase->appendNew(proc, Origin(), &trueResult))); bool elseResult = false; - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew( proc, Load8Z, Origin(), @@ -11088,20 +11730,20 @@ proc, Load, pointerType(), Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); Value* arg2 = root->appendNew(proc, Origin(), right); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), root->appendNew(proc, Equal, Origin(), arg1, arg2), FrequentedBlock(thenCase), FrequentedBlock(elseCase)); bool trueResult = true; - thenCase->appendNew( + thenCase->appendNewControlValue( proc, Return, Origin(), thenCase->appendNew( proc, Load8Z, Origin(), thenCase->appendNew(proc, Origin(), &trueResult))); bool elseResult = false; - elseCase->appendNew( + elseCase->appendNewControlValue( proc, Return, Origin(), elseCase->appendNew( proc, Load8Z, Origin(), @@ -11125,7 +11767,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), ptr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Load8Z, Origin(), ptr)); @@ -11147,7 +11789,7 @@ root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), ptr); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Load16Z, Origin(), ptr)); @@ -11159,7 +11801,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -11181,7 +11823,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), @@ -11209,8 +11851,8 @@ Procedure proc; BasicBlock* root = proc.addBlock(); BasicBlock* loop = proc.addBlock(); - root->appendNew(proc, Jump, Origin(), FrequentedBlock(loop)); - loop->appendNew(proc, Jump, Origin(), FrequentedBlock(loop)); + root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop)); + loop->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(loop)); compile(proc); } @@ -11224,15 +11866,15 @@ Value* arg = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Branch, Origin(), arg, FrequentedBlock(thenBlock), FrequentedBlock(elseBlock)); - thenBlock->appendNew( + thenBlock->appendNewControlValue( proc, Return, Origin(), thenBlock->appendNew( proc, Equal, Origin(), arg, thenBlock->appendNew(proc, Origin(), 0))); - elseBlock->appendNew( + elseBlock->appendNewControlValue( proc, Return, Origin(), elseBlock->appendNew( proc, Equal, Origin(), arg, elseBlock->appendNew(proc, Origin(), 0))); @@ -11250,7 +11892,7 @@ Value* arg = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, Shl, Origin(), arg, arg)); @@ -11273,7 +11915,7 @@ Value* arg = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, SShr, Origin(), arg, arg)); @@ -11296,7 +11938,7 @@ Value* arg = root->appendNew( proc, Trunc, Origin(), root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew(proc, ZShr, Origin(), arg, arg)); @@ -11317,7 +11959,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* arg = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, Shl, Origin(), arg, root->appendNew(proc, Trunc, Origin(), arg))); @@ -11341,7 +11983,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* arg = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, SShr, Origin(), arg, root->appendNew(proc, Trunc, Origin(), arg))); @@ -11365,7 +12007,7 @@ Procedure proc; BasicBlock* root = proc.addBlock(); Value* arg = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); - root->appendNew( + root->appendNewControlValue( proc, Return, Origin(), root->appendNew( proc, ZShr, Origin(), arg, root->appendNew(proc, Trunc, Origin(), arg))); @@ -11401,13 +12043,990 @@ numCalls++; }); - root->appendNew(proc, Return, Origin(), patchpoint); + root->appendNewControlValue(proc, Return, Origin(), patchpoint); auto code = compile(proc); CHECK(numCalls == 1); CHECK(invoke(*code, 42.5) == 42.5); } +void testSpillDefSmallerThanUse() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + + // Move32. + Value* arg32 = root->appendNew( + proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + Value* arg64 = root->appendNew(proc, ZExt32, Origin(), arg32); + + // Make sure arg64 is on the stack. + PatchpointValue* forceSpill = root->appendNew(proc, Int64, Origin()); + RegisterSet clobberSet = RegisterSet::allGPRs(); + clobberSet.exclude(RegisterSet::stackRegisters()); + clobberSet.exclude(RegisterSet::reservedHardwareRegisters()); + clobberSet.clear(GPRInfo::returnValueGPR); // Force the return value for aliasing below. + forceSpill->clobberLate(clobberSet); + forceSpill->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + jit.xor64(params[0].gpr(), params[0].gpr()); + }); + + // On x86, Sub admit an address for any operand. If it uses the stack, the top bits must be zero. + Value* result = root->appendNew(proc, Sub, Origin(), forceSpill, arg64); + root->appendNewControlValue(proc, Return, Origin(), result); + + auto code = compile(proc); + CHECK(invoke(*code, 0xffffffff00000000) == 0); +} + +void testSpillUseLargerThanDef() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + BasicBlock* thenCase = proc.addBlock(); + BasicBlock* elseCase = proc.addBlock(); + BasicBlock* tail = proc.addBlock(); + + RegisterSet clobberSet = RegisterSet::allGPRs(); + clobberSet.exclude(RegisterSet::stackRegisters()); + clobberSet.exclude(RegisterSet::reservedHardwareRegisters()); + + Value* condition = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + Value* argument = root->appendNew(proc, Origin(), GPRInfo::argumentGPR1); + root->appendNewControlValue( + proc, Branch, Origin(), + root->appendNew( + proc, Trunc, Origin(), + condition), + FrequentedBlock(thenCase), FrequentedBlock(elseCase)); + + Value* truncated = thenCase->appendNew(proc, ZExt32, Origin(), + thenCase->appendNew(proc, Trunc, Origin(), argument)); + UpsilonValue* thenResult = thenCase->appendNew(proc, Origin(), truncated); + thenCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + UpsilonValue* elseResult = elseCase->appendNew(proc, Origin(), argument); + elseCase->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(tail)); + + for (unsigned i = 0; i < 100; ++i) { + PatchpointValue* preventTailDuplication = tail->appendNew(proc, Void, Origin()); + preventTailDuplication->clobberLate(clobberSet); + preventTailDuplication->setGenerator([] (CCallHelpers&, const StackmapGenerationParams&) { }); + } + + PatchpointValue* forceSpill = tail->appendNew(proc, Void, Origin()); + forceSpill->clobberLate(clobberSet); + forceSpill->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams&) { + AllowMacroScratchRegisterUsage allowScratch(jit); + clobberSet.forEach([&] (Reg reg) { + jit.move(CCallHelpers::TrustedImm64(0xffffffffffffffff), reg.gpr()); + }); + }); + + Value* phi = tail->appendNew(proc, Phi, Int64, Origin()); + thenResult->setPhi(phi); + elseResult->setPhi(phi); + tail->appendNewControlValue(proc, Return, Origin(), phi); + + auto code = compile(proc); + CHECK(invoke(*code, 1, 0xffffffff00000000) == 0); + CHECK(invoke(*code, 0, 0xffffffff00000000) == 0xffffffff00000000); + + // A second time since the previous run is still on the stack. + CHECK(invoke(*code, 1, 0xffffffff00000000) == 0); + +} + +void testLateRegister() +{ + Procedure proc; + BasicBlock* root = proc.addBlock(); + + // This works by making all but 1 register be input to the first patchpoint as LateRegister. + // The other 1 register is just a regular Register input. We assert our result is the regular + // register input. There would be no other way for the register allocator to arrange things + // because LateRegister interferes with the result. + // Then, the second patchpoint takes the result of the first as an argument and asks for + // it in a register that was a LateRegister. This is to incentivize the register allocator + // to use that LateRegister as the result for the first patchpoint. But of course it can not do that. + // So it must issue a mov after the first patchpoint from the first's result into the second's input. + + RegisterSet regs = RegisterSet::allGPRs(); + regs.exclude(RegisterSet::stackRegisters()); + regs.exclude(RegisterSet::reservedHardwareRegisters()); + Vector lateUseArgs; + unsigned result = 0; + for (GPRReg reg = CCallHelpers::firstRegister(); reg <= CCallHelpers::lastRegister(); reg = CCallHelpers::nextRegister(reg)) { + if (!regs.get(reg)) + continue; + result++; + if (reg == GPRInfo::regT0) + continue; + Value* value = root->appendNew(proc, Origin(), 1); + lateUseArgs.append(value); + } + Value* regularUse = root->appendNew(proc, Origin(), 1); + PatchpointValue* firstPatchpoint = root->appendNew(proc, Int64, Origin()); + { + unsigned i = 0; + for (GPRReg reg = CCallHelpers::firstRegister(); reg <= CCallHelpers::lastRegister(); reg = CCallHelpers::nextRegister(reg)) { + if (!regs.get(reg)) + continue; + if (reg == GPRInfo::regT0) + continue; + Value* value = lateUseArgs[i++]; + firstPatchpoint->append(value, ValueRep::lateReg(reg)); + } + firstPatchpoint->append(regularUse, ValueRep::reg(GPRInfo::regT0)); + } + + firstPatchpoint->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + CHECK(params[0].gpr() == GPRInfo::regT0); + // Note that regT0 should also start off as 1, so we're implicitly starting our add with 1, which is also an argument. + unsigned skipped = 0; + for (unsigned i = 1; i < params.size(); i++) { + if (params[i].gpr() == params[0].gpr()) { + skipped = i; + continue; + } + jit.add64(params[i].gpr(), params[0].gpr()); + } + CHECK(!!skipped); + }); + + PatchpointValue* secondPatchpoint = root->appendNew(proc, Int64, Origin()); + secondPatchpoint->append(firstPatchpoint, ValueRep::reg(GPRInfo::regT1)); + secondPatchpoint->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + CHECK(params[1].gpr() == GPRInfo::regT1); + jit.nop(); + jit.nop(); + jit.move(params[1].gpr(), params[0].gpr()); + jit.nop(); + jit.nop(); + }); + root->appendNewControlValue(proc, Return, Origin(), secondPatchpoint); + + auto code = compile(proc); + CHECK(invoke(*code) == result); +} + +void interpreterPrint(Vector* stream, intptr_t value) +{ + stream->append(value); +} + +void testInterpreter() +{ + // This implements a silly interpreter to test building custom switch statements using + // Patchpoint. + + Procedure proc; + + BasicBlock* root = proc.addBlock(); + BasicBlock* dispatch = proc.addBlock(); + BasicBlock* addToDataPointer = proc.addBlock(); + BasicBlock* addToCodePointer = proc.addBlock(); + BasicBlock* addToCodePointerTaken = proc.addBlock(); + BasicBlock* addToCodePointerNotTaken = proc.addBlock(); + BasicBlock* addToData = proc.addBlock(); + BasicBlock* print = proc.addBlock(); + BasicBlock* stop = proc.addBlock(); + + Variable* dataPointer = proc.addVariable(pointerType()); + Variable* codePointer = proc.addVariable(pointerType()); + + root->appendNew( + proc, Set, Origin(), dataPointer, + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + root->appendNew( + proc, Set, Origin(), codePointer, + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1)); + Value* context = root->appendNew(proc, Origin(), GPRInfo::argumentGPR2); + root->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch)); + + // NOTE: It's totally valid for this patchpoint to be tail-duplicated. + Value* codePointerValue = + dispatch->appendNew(proc, B3::Get, Origin(), codePointer); + Value* opcode = dispatch->appendNew( + proc, Load, pointerType(), Origin(), codePointerValue); + PatchpointValue* polyJump = dispatch->appendNew(proc, Void, Origin()); + polyJump->effects = Effects(); + polyJump->effects.terminal = true; + polyJump->appendSomeRegister(opcode); + polyJump->clobber(RegisterSet::macroScratchRegisters()); + polyJump->numGPScratchRegisters++; + dispatch->appendSuccessor(FrequentedBlock(addToDataPointer)); + dispatch->appendSuccessor(FrequentedBlock(addToCodePointer)); + dispatch->appendSuccessor(FrequentedBlock(addToData)); + dispatch->appendSuccessor(FrequentedBlock(print)); + dispatch->appendSuccessor(FrequentedBlock(stop)); + + // Our "opcodes". + static const intptr_t AddDP = 0; + static const intptr_t AddCP = 1; + static const intptr_t Add = 2; + static const intptr_t Print = 3; + static const intptr_t Stop = 4; + + polyJump->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + Vector> labels = params.successorLabels(); + + MacroAssemblerCodePtr* jumpTable = bitwise_cast( + params.proc().addDataSection(sizeof(MacroAssemblerCodePtr) * labels.size())); + + jit.move(CCallHelpers::TrustedImmPtr(jumpTable), params.gpScratch(0)); + jit.jump(CCallHelpers::BaseIndex(params.gpScratch(0), params[0].gpr(), CCallHelpers::timesPtr())); + + jit.addLinkTask( + [&, jumpTable, labels] (LinkBuffer& linkBuffer) { + for (unsigned i = labels.size(); i--;) + jumpTable[i] = linkBuffer.locationOf(*labels[i]); + }); + }); + + // AddDP : adds to DP. + codePointerValue = + addToDataPointer->appendNew(proc, B3::Get, Origin(), codePointer); + addToDataPointer->appendNew( + proc, Set, Origin(), dataPointer, + addToDataPointer->appendNew( + proc, B3::Add, Origin(), + addToDataPointer->appendNew(proc, B3::Get, Origin(), dataPointer), + addToDataPointer->appendNew( + proc, Mul, Origin(), + addToDataPointer->appendNew( + proc, Load, pointerType(), Origin(), codePointerValue, sizeof(intptr_t)), + addToDataPointer->appendIntConstant( + proc, Origin(), pointerType(), sizeof(intptr_t))))); + addToDataPointer->appendNew( + proc, Set, Origin(), codePointer, + addToDataPointer->appendNew( + proc, B3::Add, Origin(), codePointerValue, + addToDataPointer->appendIntConstant( + proc, Origin(), pointerType(), sizeof(intptr_t) * 2))); + addToDataPointer->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch)); + + // AddCP : adds to CP if the current value at DP is non-zero, otherwise + // falls through normally. + codePointerValue = + addToCodePointer->appendNew(proc, B3::Get, Origin(), codePointer); + Value* dataPointerValue = + addToCodePointer->appendNew(proc, B3::Get, Origin(), dataPointer); + addToCodePointer->appendNewControlValue( + proc, Branch, Origin(), + addToCodePointer->appendNew( + proc, Load, pointerType(), Origin(), dataPointerValue), + FrequentedBlock(addToCodePointerTaken), FrequentedBlock(addToCodePointerNotTaken)); + addToCodePointerTaken->appendNew( + proc, Set, Origin(), codePointer, + addToCodePointerTaken->appendNew( + proc, B3::Add, Origin(), codePointerValue, + addToCodePointerTaken->appendNew( + proc, Mul, Origin(), + addToCodePointerTaken->appendNew( + proc, Load, pointerType(), Origin(), codePointerValue, sizeof(intptr_t)), + addToCodePointerTaken->appendIntConstant( + proc, Origin(), pointerType(), sizeof(intptr_t))))); + addToCodePointerTaken->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch)); + addToCodePointerNotTaken->appendNew( + proc, Set, Origin(), codePointer, + addToCodePointerNotTaken->appendNew( + proc, B3::Add, Origin(), codePointerValue, + addToCodePointerNotTaken->appendIntConstant( + proc, Origin(), pointerType(), sizeof(intptr_t) * 2))); + addToCodePointerNotTaken->appendNewControlValue( + proc, Jump, Origin(), FrequentedBlock(dispatch)); + + // Add : adds to the slot pointed to by DP. + codePointerValue = addToData->appendNew(proc, B3::Get, Origin(), codePointer); + dataPointerValue = addToData->appendNew(proc, B3::Get, Origin(), dataPointer); + addToData->appendNew( + proc, Store, Origin(), + addToData->appendNew( + proc, B3::Add, Origin(), + addToData->appendNew( + proc, Load, pointerType(), Origin(), dataPointerValue), + addToData->appendNew( + proc, Load, pointerType(), Origin(), codePointerValue, sizeof(intptr_t))), + dataPointerValue); + addToData->appendNew( + proc, Set, Origin(), codePointer, + addToData->appendNew( + proc, B3::Add, Origin(), codePointerValue, + addToData->appendIntConstant(proc, Origin(), pointerType(), sizeof(intptr_t) * 2))); + addToData->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch)); + + // Print: "prints" the value pointed to by DP. What this actually means is that the value is + // appended to the stream vector by the interpreterPrint function. + codePointerValue = print->appendNew(proc, B3::Get, Origin(), codePointer); + dataPointerValue = print->appendNew(proc, B3::Get, Origin(), dataPointer); + print->appendNew( + proc, Void, Origin(), + print->appendNew( + proc, Origin(), bitwise_cast(interpreterPrint)), + context, + print->appendNew(proc, Load, pointerType(), Origin(), dataPointerValue)); + print->appendNew( + proc, Set, Origin(), codePointer, + print->appendNew( + proc, B3::Add, Origin(), codePointerValue, + print->appendIntConstant(proc, Origin(), pointerType(), sizeof(intptr_t)))); + print->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(dispatch)); + + // Stop: returns. + stop->appendNewControlValue( + proc, Return, Origin(), + stop->appendIntConstant(proc, Origin(), pointerType(), 0)); + + auto interpreter = compile(proc); + + Vector data; + Vector code; + Vector stream; + + data.append(1); + data.append(0); + + if (shouldBeVerbose()) + dataLog("data = ", listDump(data), "\n"); + + // We'll write a program that prints the numbers 1..100. + // We expect DP to point at #0. + code.append(AddCP); + code.append(6); // go to loop body + + // Loop re-entry: + // We expect DP to point at #1 and for #1 to be offset by -100. + code.append(Add); + code.append(100); + + code.append(AddDP); + code.append(-1); + + // Loop header: + // We expect DP to point at #0. + code.append(AddDP); + code.append(1); + + code.append(Add); + code.append(1); + + code.append(Print); + + code.append(Add); + code.append(-100); + + // We want to stop if it's zero and continue if it's non-zero. AddCP takes the branch if it's + // non-zero. + code.append(AddCP); + code.append(-11); // go to loop re-entry. + + code.append(Stop); + + if (shouldBeVerbose()) + dataLog("code = ", listDump(code), "\n"); + + CHECK(!invoke(*interpreter, data.data(), code.data(), &stream)); + + CHECK(stream.size() == 100); + for (unsigned i = 0; i < 100; ++i) + CHECK(stream[i] == i + 1); + + if (shouldBeVerbose()) + dataLog("stream = ", listDump(stream), "\n"); +} + +void testReduceStrengthCheckBottomUseInAnotherBlock() +{ + Procedure proc; + + BasicBlock* one = proc.addBlock(); + BasicBlock* two = proc.addBlock(); + + CheckValue* check = one->appendNew( + proc, Check, Origin(), one->appendNew(proc, Origin(), 1)); + check->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams&) { + AllowMacroScratchRegisterUsage allowScratch(jit); + + jit.move(CCallHelpers::TrustedImm32(666), GPRInfo::returnValueGPR); + jit.emitFunctionEpilogue(); + jit.ret(); + }); + Value* arg = one->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + one->appendNewControlValue(proc, Jump, Origin(), FrequentedBlock(two)); + + check = two->appendNew( + proc, CheckAdd, Origin(), arg, + two->appendNew(proc, Origin(), 1)); + check->setGenerator( + [&] (CCallHelpers&, const StackmapGenerationParams&) { + CHECK(!"Should not execute"); + }); + two->appendNewControlValue(proc, Return, Origin(), check); + + proc.resetReachability(); + reduceStrength(proc); +} + +void testResetReachabilityDanglingReference() +{ + Procedure proc; + + BasicBlock* one = proc.addBlock(); + BasicBlock* two = proc.addBlock(); + + UpsilonValue* upsilon = one->appendNew( + proc, Origin(), one->appendNew(proc, Origin(), 42)); + one->appendNewControlValue(proc, Oops, Origin()); + + Value* phi = two->appendNew(proc, Phi, Int32, Origin()); + upsilon->setPhi(phi); + two->appendNewControlValue(proc, Oops, Origin()); + + proc.resetReachability(); + validate(proc); +} + +void testEntrySwitchSimple() +{ + Procedure proc; + proc.setNumEntrypoints(3); + + BasicBlock* root = proc.addBlock(); + BasicBlock* one = proc.addBlock(); + BasicBlock* two = proc.addBlock(); + BasicBlock* three = proc.addBlock(); + + root->appendNew(proc, EntrySwitch, Origin()); + root->appendSuccessor(FrequentedBlock(one)); + root->appendSuccessor(FrequentedBlock(two)); + root->appendSuccessor(FrequentedBlock(three)); + + one->appendNew( + proc, Return, Origin(), + one->appendNew( + proc, Add, Origin(), + one->appendNew(proc, Origin(), GPRInfo::argumentGPR0), + one->appendNew(proc, Origin(), GPRInfo::argumentGPR1))); + + two->appendNew( + proc, Return, Origin(), + two->appendNew( + proc, Sub, Origin(), + two->appendNew(proc, Origin(), GPRInfo::argumentGPR0), + two->appendNew(proc, Origin(), GPRInfo::argumentGPR1))); + + three->appendNew( + proc, Return, Origin(), + three->appendNew( + proc, Mul, Origin(), + three->appendNew(proc, Origin(), GPRInfo::argumentGPR0), + three->appendNew(proc, Origin(), GPRInfo::argumentGPR1))); + + prepareForGeneration(proc); + + CCallHelpers jit(vm); + generate(proc, jit); + LinkBuffer linkBuffer(*vm, jit, nullptr); + CodeLocationLabel labelOne = linkBuffer.locationOf(proc.entrypointLabel(0)); + CodeLocationLabel labelTwo = linkBuffer.locationOf(proc.entrypointLabel(1)); + CodeLocationLabel labelThree = linkBuffer.locationOf(proc.entrypointLabel(2)); + + MacroAssemblerCodeRef codeRef = FINALIZE_CODE(linkBuffer, ("testb3 compilation")); + + CHECK(invoke(labelOne, 1, 2) == 3); + CHECK(invoke(labelTwo, 1, 2) == -1); + CHECK(invoke(labelThree, 1, 2) == 2); + CHECK(invoke(labelOne, -1, 2) == 1); + CHECK(invoke(labelTwo, -1, 2) == -3); + CHECK(invoke(labelThree, -1, 2) == -2); +} + +void testEntrySwitchNoEntrySwitch() +{ + Procedure proc; + proc.setNumEntrypoints(3); + + BasicBlock* root = proc.addBlock(); + + root->appendNew( + proc, Return, Origin(), + root->appendNew( + proc, Add, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR1))); + + prepareForGeneration(proc); + + CCallHelpers jit(vm); + generate(proc, jit); + LinkBuffer linkBuffer(*vm, jit, nullptr); + CodeLocationLabel labelOne = linkBuffer.locationOf(proc.entrypointLabel(0)); + CodeLocationLabel labelTwo = linkBuffer.locationOf(proc.entrypointLabel(1)); + CodeLocationLabel labelThree = linkBuffer.locationOf(proc.entrypointLabel(2)); + + MacroAssemblerCodeRef codeRef = FINALIZE_CODE(linkBuffer, ("testb3 compilation")); + + CHECK_EQ(invoke(labelOne, 1, 2), 3); + CHECK_EQ(invoke(labelTwo, 1, 2), 3); + CHECK_EQ(invoke(labelThree, 1, 2), 3); + CHECK_EQ(invoke(labelOne, -1, 2), 1); + CHECK_EQ(invoke(labelTwo, -1, 2), 1); + CHECK_EQ(invoke(labelThree, -1, 2), 1); +} + +void testEntrySwitchWithCommonPaths() +{ + Procedure proc; + proc.setNumEntrypoints(3); + + BasicBlock* root = proc.addBlock(); + BasicBlock* one = proc.addBlock(); + BasicBlock* two = proc.addBlock(); + BasicBlock* three = proc.addBlock(); + BasicBlock* end = proc.addBlock(); + + root->appendNew(proc, EntrySwitch, Origin()); + root->appendSuccessor(FrequentedBlock(one)); + root->appendSuccessor(FrequentedBlock(two)); + root->appendSuccessor(FrequentedBlock(three)); + + UpsilonValue* upsilonOne = one->appendNew( + proc, Origin(), + one->appendNew( + proc, Add, Origin(), + one->appendNew( + proc, Trunc, Origin(), + one->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), + one->appendNew( + proc, Trunc, Origin(), + one->appendNew(proc, Origin(), GPRInfo::argumentGPR1)))); + one->appendNew(proc, Jump, Origin()); + one->setSuccessors(FrequentedBlock(end)); + + UpsilonValue* upsilonTwo = two->appendNew( + proc, Origin(), + two->appendNew( + proc, Sub, Origin(), + two->appendNew( + proc, Trunc, Origin(), + two->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), + two->appendNew( + proc, Trunc, Origin(), + two->appendNew(proc, Origin(), GPRInfo::argumentGPR1)))); + two->appendNew(proc, Jump, Origin()); + two->setSuccessors(FrequentedBlock(end)); + + UpsilonValue* upsilonThree = three->appendNew( + proc, Origin(), + three->appendNew( + proc, Mul, Origin(), + three->appendNew( + proc, Trunc, Origin(), + three->appendNew(proc, Origin(), GPRInfo::argumentGPR0)), + three->appendNew( + proc, Trunc, Origin(), + three->appendNew(proc, Origin(), GPRInfo::argumentGPR1)))); + three->appendNew(proc, Jump, Origin()); + three->setSuccessors(FrequentedBlock(end)); + + Value* phi = end->appendNew(proc, Phi, Int32, Origin()); + upsilonOne->setPhi(phi); + upsilonTwo->setPhi(phi); + upsilonThree->setPhi(phi); + + end->appendNew( + proc, Return, Origin(), + end->appendNew( + proc, ChillMod, Origin(), + phi, end->appendNew( + proc, Trunc, Origin(), + end->appendNew(proc, Origin(), GPRInfo::argumentGPR2)))); + + prepareForGeneration(proc); + + CCallHelpers jit(vm); + generate(proc, jit); + LinkBuffer linkBuffer(*vm, jit, nullptr); + CodeLocationLabel labelOne = linkBuffer.locationOf(proc.entrypointLabel(0)); + CodeLocationLabel labelTwo = linkBuffer.locationOf(proc.entrypointLabel(1)); + CodeLocationLabel labelThree = linkBuffer.locationOf(proc.entrypointLabel(2)); + + MacroAssemblerCodeRef codeRef = FINALIZE_CODE(linkBuffer, ("testb3 compilation")); + + CHECK_EQ(invoke(labelOne, 1, 2, 10), 3); + CHECK_EQ(invoke(labelTwo, 1, 2, 10), -1); + CHECK_EQ(invoke(labelThree, 1, 2, 10), 2); + CHECK_EQ(invoke(labelOne, -1, 2, 10), 1); + CHECK_EQ(invoke(labelTwo, -1, 2, 10), -3); + CHECK_EQ(invoke(labelThree, -1, 2, 10), -2); + CHECK_EQ(invoke(labelOne, 1, 2, 2), 1); + CHECK_EQ(invoke(labelTwo, 1, 2, 2), -1); + CHECK_EQ(invoke(labelThree, 1, 2, 2), 0); + CHECK_EQ(invoke(labelOne, -1, 2, 2), 1); + CHECK_EQ(invoke(labelTwo, -1, 2, 2), -1); + CHECK_EQ(invoke(labelThree, -1, 2, 2), 0); + CHECK_EQ(invoke(labelOne, 1, 2, 0), 0); + CHECK_EQ(invoke(labelTwo, 1, 2, 0), 0); + CHECK_EQ(invoke(labelThree, 1, 2, 0), 0); + CHECK_EQ(invoke(labelOne, -1, 2, 0), 0); + CHECK_EQ(invoke(labelTwo, -1, 2, 0), 0); + CHECK_EQ(invoke(labelThree, -1, 2, 0), 0); +} + +void testEntrySwitchWithCommonPathsAndNonTrivialEntrypoint() +{ + Procedure proc; + proc.setNumEntrypoints(3); + + BasicBlock* root = proc.addBlock(); + BasicBlock* negate = proc.addBlock(); + BasicBlock* dispatch = proc.addBlock(); + BasicBlock* one = proc.addBlock(); + BasicBlock* two = proc.addBlock(); + BasicBlock* three = proc.addBlock(); + BasicBlock* end = proc.addBlock(); + + UpsilonValue* upsilonBase = root->appendNew( + proc, Origin(), root->appendNew( + proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))); + root->appendNew( + proc, Branch, Origin(), + root->appendNew( + proc, BitAnd, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR3), + root->appendNew(proc, Origin(), 0xff))); + root->setSuccessors(FrequentedBlock(negate), FrequentedBlock(dispatch)); + + UpsilonValue* upsilonNegate = negate->appendNew( + proc, Origin(), + negate->appendNew( + proc, Neg, Origin(), + negate->appendNew( + proc, Trunc, Origin(), + negate->appendNew(proc, Origin(), GPRInfo::argumentGPR0)))); + negate->appendNew(proc, Jump, Origin()); + negate->setSuccessors(FrequentedBlock(dispatch)); + + Value* arg0 = dispatch->appendNew(proc, Phi, Int32, Origin()); + upsilonBase->setPhi(arg0); + upsilonNegate->setPhi(arg0); + dispatch->appendNew(proc, EntrySwitch, Origin()); + dispatch->appendSuccessor(FrequentedBlock(one)); + dispatch->appendSuccessor(FrequentedBlock(two)); + dispatch->appendSuccessor(FrequentedBlock(three)); + + UpsilonValue* upsilonOne = one->appendNew( + proc, Origin(), + one->appendNew( + proc, Add, Origin(), + arg0, one->appendNew( + proc, Trunc, Origin(), + one->appendNew(proc, Origin(), GPRInfo::argumentGPR1)))); + one->appendNew(proc, Jump, Origin()); + one->setSuccessors(FrequentedBlock(end)); + + UpsilonValue* upsilonTwo = two->appendNew( + proc, Origin(), + two->appendNew( + proc, Sub, Origin(), + arg0, two->appendNew( + proc, Trunc, Origin(), + two->appendNew(proc, Origin(), GPRInfo::argumentGPR1)))); + two->appendNew(proc, Jump, Origin()); + two->setSuccessors(FrequentedBlock(end)); + + UpsilonValue* upsilonThree = three->appendNew( + proc, Origin(), + three->appendNew( + proc, Mul, Origin(), + arg0, three->appendNew( + proc, Trunc, Origin(), + three->appendNew(proc, Origin(), GPRInfo::argumentGPR1)))); + three->appendNew(proc, Jump, Origin()); + three->setSuccessors(FrequentedBlock(end)); + + Value* phi = end->appendNew(proc, Phi, Int32, Origin()); + upsilonOne->setPhi(phi); + upsilonTwo->setPhi(phi); + upsilonThree->setPhi(phi); + + end->appendNew( + proc, Return, Origin(), + end->appendNew( + proc, ChillMod, Origin(), + phi, end->appendNew( + proc, Trunc, Origin(), + end->appendNew(proc, Origin(), GPRInfo::argumentGPR2)))); + + prepareForGeneration(proc); + + CCallHelpers jit(vm); + generate(proc, jit); + LinkBuffer linkBuffer(*vm, jit, nullptr); + CodeLocationLabel labelOne = linkBuffer.locationOf(proc.entrypointLabel(0)); + CodeLocationLabel labelTwo = linkBuffer.locationOf(proc.entrypointLabel(1)); + CodeLocationLabel labelThree = linkBuffer.locationOf(proc.entrypointLabel(2)); + + MacroAssemblerCodeRef codeRef = FINALIZE_CODE(linkBuffer, ("testb3 compilation")); + + CHECK_EQ(invoke(labelOne, 1, 2, 10, false), 3); + CHECK_EQ(invoke(labelTwo, 1, 2, 10, false), -1); + CHECK_EQ(invoke(labelThree, 1, 2, 10, false), 2); + CHECK_EQ(invoke(labelOne, -1, 2, 10, false), 1); + CHECK_EQ(invoke(labelTwo, -1, 2, 10, false), -3); + CHECK_EQ(invoke(labelThree, -1, 2, 10, false), -2); + CHECK_EQ(invoke(labelOne, 1, 2, 10, true), 1); + CHECK_EQ(invoke(labelTwo, 1, 2, 10, true), -3); + CHECK_EQ(invoke(labelThree, 1, 2, 10, true), -2); + CHECK_EQ(invoke(labelOne, -1, 2, 10, true), 3); + CHECK_EQ(invoke(labelTwo, -1, 2, 10, true), -1); + CHECK_EQ(invoke(labelThree, -1, 2, 10, true), 2); + CHECK_EQ(invoke(labelOne, 1, 2, 2, false), 1); + CHECK_EQ(invoke(labelTwo, 1, 2, 2, false), -1); + CHECK_EQ(invoke(labelThree, 1, 2, 2, false), 0); + CHECK_EQ(invoke(labelOne, -1, 2, 2, false), 1); + CHECK_EQ(invoke(labelTwo, -1, 2, 2, false), -1); + CHECK_EQ(invoke(labelThree, -1, 2, 2, false), 0); + CHECK_EQ(invoke(labelOne, 1, 2, 0, false), 0); + CHECK_EQ(invoke(labelTwo, 1, 2, 0, false), 0); + CHECK_EQ(invoke(labelThree, 1, 2, 0, false), 0); + CHECK_EQ(invoke(labelOne, -1, 2, 0, false), 0); + CHECK_EQ(invoke(labelTwo, -1, 2, 0, false), 0); + CHECK_EQ(invoke(labelThree, -1, 2, 0, false), 0); +} + +void testEntrySwitchLoop() +{ + // This is a completely absurd use of EntrySwitch, where it impacts the loop condition. This + // should cause duplication of either nearly the entire Procedure. At time of writing, we ended + // up duplicating all of it, which is fine. It's important to test this case, to make sure that + // the duplication algorithm can handle interesting control flow. + + Procedure proc; + proc.setNumEntrypoints(2); + + BasicBlock* root = proc.addBlock(); + BasicBlock* loopHeader = proc.addBlock(); + BasicBlock* loopFooter = proc.addBlock(); + BasicBlock* end = proc.addBlock(); + + UpsilonValue* initialValue = root->appendNew( + proc, Origin(), root->appendNew( + proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0))); + root->appendNew(proc, Jump, Origin()); + root->setSuccessors(loopHeader); + + Value* valueInLoop = loopHeader->appendNew(proc, Phi, Int32, Origin()); + initialValue->setPhi(valueInLoop); + Value* newValue = loopHeader->appendNew( + proc, Add, Origin(), valueInLoop, + loopHeader->appendNew(proc, Origin(), 1)); + loopHeader->appendNew(proc, EntrySwitch, Origin()); + loopHeader->appendSuccessor(end); + loopHeader->appendSuccessor(loopFooter); + + loopFooter->appendNew(proc, Origin(), newValue, valueInLoop); + loopFooter->appendNew( + proc, Branch, Origin(), + loopFooter->appendNew( + proc, LessThan, Origin(), newValue, + loopFooter->appendNew(proc, Origin(), 100))); + loopFooter->setSuccessors(loopHeader, end); + + end->appendNew(proc, Return, Origin(), newValue); + + prepareForGeneration(proc); + + CCallHelpers jit(vm); + generate(proc, jit); + LinkBuffer linkBuffer(*vm, jit, nullptr); + CodeLocationLabel labelOne = linkBuffer.locationOf(proc.entrypointLabel(0)); + CodeLocationLabel labelTwo = linkBuffer.locationOf(proc.entrypointLabel(1)); + + MacroAssemblerCodeRef codeRef = FINALIZE_CODE(linkBuffer, ("testb3 compilation")); + + CHECK(invoke(labelOne, 0) == 1); + CHECK(invoke(labelOne, 42) == 43); + CHECK(invoke(labelOne, 1000) == 1001); + + CHECK(invoke(labelTwo, 0) == 100); + CHECK(invoke(labelTwo, 42) == 100); + CHECK(invoke(labelTwo, 1000) == 1001); +} + +void testSomeEarlyRegister() +{ + auto run = [&] (bool succeed) { + Procedure proc; + + BasicBlock* root = proc.addBlock(); + + PatchpointValue* patchpoint = root->appendNew(proc, Int32, Origin()); + patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR); + bool ranFirstPatchpoint = false; + patchpoint->setGenerator( + [&] (CCallHelpers&, const StackmapGenerationParams& params) { + CHECK(params[0].gpr() == GPRInfo::returnValueGPR); + ranFirstPatchpoint = true; + }); + + Value* arg = patchpoint; + + patchpoint = root->appendNew(proc, Int32, Origin()); + patchpoint->appendSomeRegister(arg); + if (succeed) + patchpoint->resultConstraint = ValueRep::SomeEarlyRegister; + bool ranSecondPatchpoint = false; + patchpoint->setGenerator( + [&] (CCallHelpers&, const StackmapGenerationParams& params) { + if (succeed) + CHECK(params[0].gpr() != params[1].gpr()); + else + CHECK(params[0].gpr() == params[1].gpr()); + ranSecondPatchpoint = true; + }); + + root->appendNew(proc, Return, Origin(), patchpoint); + + compile(proc); + CHECK(ranFirstPatchpoint); + CHECK(ranSecondPatchpoint); + }; + + run(true); + run(false); +} + +void testBranchBitAndImmFusion( + B3::Opcode valueModifier, Type valueType, int64_t constant, + Air::Opcode expectedOpcode, Air::Arg::Kind firstKind) +{ + // Currently this test should pass on all CPUs. But some CPUs may not support this fused + // instruction. It's OK to skip this test on those CPUs. + + Procedure proc; + + BasicBlock* root = proc.addBlock(); + BasicBlock* one = proc.addBlock(); + BasicBlock* two = proc.addBlock(); + + Value* left = root->appendNew(proc, Origin(), GPRInfo::argumentGPR0); + + if (valueModifier != Identity) { + if (MemoryValue::accepts(valueModifier)) + left = root->appendNew(proc, valueModifier, valueType, Origin(), left); + else + left = root->appendNew(proc, valueModifier, valueType, Origin(), left); + } + + root->appendNew( + proc, Branch, Origin(), + root->appendNew( + proc, BitAnd, Origin(), left, + root->appendIntConstant(proc, Origin(), valueType, constant))); + root->setSuccessors(FrequentedBlock(one), FrequentedBlock(two)); + + one->appendNew(proc, Oops, Origin()); + two->appendNew(proc, Oops, Origin()); + + lowerToAirForTesting(proc); + + // The first basic block must end in a BranchTest64(resCond, tmp, bitImm). + Air::Inst terminal = proc.code()[0]->last(); + CHECK_EQ(terminal.opcode, expectedOpcode); + CHECK_EQ(terminal.args[0].kind(), Air::Arg::ResCond); + CHECK_EQ(terminal.args[1].kind(), firstKind); + CHECK(terminal.args[2].kind() == Air::Arg::BitImm || terminal.args[2].kind() == Air::Arg::BitImm64); +} + +void testPatchpointTerminalReturnValue(bool successIsRare) +{ + // This is a unit test for how FTL's heap allocation fast paths behave. + Procedure proc; + + BasicBlock* root = proc.addBlock(); + BasicBlock* success = proc.addBlock(); + BasicBlock* slowPath = proc.addBlock(); + BasicBlock* continuation = proc.addBlock(); + + Value* arg = root->appendNew( + proc, Trunc, Origin(), + root->appendNew(proc, Origin(), GPRInfo::argumentGPR0)); + + PatchpointValue* patchpoint = root->appendNew(proc, Int32, Origin()); + patchpoint->effects.terminal = true; + patchpoint->clobber(RegisterSet::macroScratchRegisters()); + + if (successIsRare) { + root->appendSuccessor(FrequentedBlock(success, FrequencyClass::Rare)); + root->appendSuccessor(slowPath); + } else { + root->appendSuccessor(success); + root->appendSuccessor(FrequentedBlock(slowPath, FrequencyClass::Rare)); + } + + patchpoint->appendSomeRegister(arg); + + patchpoint->setGenerator( + [&] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + + CCallHelpers::Jump jumpToSlow = + jit.branch32(CCallHelpers::Above, params[1].gpr(), CCallHelpers::TrustedImm32(42)); + + jit.add32(CCallHelpers::TrustedImm32(31), params[1].gpr(), params[0].gpr()); + + CCallHelpers::Jump jumpToSuccess; + if (!params.fallsThroughToSuccessor(0)) + jumpToSuccess = jit.jump(); + + Vector> labels = params.successorLabels(); + + params.addLatePath( + [=] (CCallHelpers& jit) { + jumpToSlow.linkTo(*labels[1], &jit); + if (jumpToSuccess.isSet()) + jumpToSuccess.linkTo(*labels[0], &jit); + }); + }); + + UpsilonValue* successUpsilon = success->appendNew(proc, Origin(), patchpoint); + success->appendNew(proc, Jump, Origin()); + success->setSuccessors(continuation); + + UpsilonValue* slowPathUpsilon = slowPath->appendNew( + proc, Origin(), slowPath->appendNew(proc, Origin(), 666)); + slowPath->appendNew(proc, Jump, Origin()); + slowPath->setSuccessors(continuation); + + Value* phi = continuation->appendNew(proc, Phi, Int32, Origin()); + successUpsilon->setPhi(phi); + slowPathUpsilon->setPhi(phi); + continuation->appendNew(proc, Return, Origin(), phi); + + auto code = compile(proc); + CHECK_EQ(invoke(*code, 0), 31); + CHECK_EQ(invoke(*code, 1), 32); + CHECK_EQ(invoke(*code, 41), 72); + CHECK_EQ(invoke(*code, 42), 73); + CHECK_EQ(invoke(*code, 43), 666); + CHECK_EQ(invoke(*code, -1), 666); +} + // Make sure the compiler does not try to optimize anything out. NEVER_INLINE double zero() { @@ -11419,8 +13038,6 @@ return -zero(); } - - #define RUN(test) do { \ if (!shouldRun(#test)) \ break; \ @@ -11484,6 +13101,7 @@ RUN(testArg(43)); RUN(testReturnConst64(5)); RUN(testReturnConst64(-42)); + RUN(testReturnVoid()); RUN(testAddArg(111)); RUN(testAddArgs(1, 1)); @@ -11697,6 +13315,10 @@ RUN_BINARY(testSubArgsFloatWithUselessDoubleConversion, floatingPointOperands(), floatingPointOperands()); RUN_BINARY(testSubArgsFloatWithEffectfulDoubleConversion, floatingPointOperands(), floatingPointOperands()); + RUN_UNARY(testNegDouble, floatingPointOperands()); + RUN_UNARY(testNegFloat, floatingPointOperands()); + RUN_UNARY(testNegFloatWithUselessDoubleConversion, floatingPointOperands()); + RUN(testBitAndArgs(43, 43)); RUN(testBitAndArgs(43, 0)); RUN(testBitAndArgs(10, 3)); @@ -12056,6 +13678,14 @@ RUN_UNARY(testSqrtArgWithUselessDoubleConversion, floatingPointOperands()); RUN_UNARY(testSqrtArgWithEffectfulDoubleConversion, floatingPointOperands()); + RUN_BINARY(testCompareTwoFloatToDouble, floatingPointOperands(), floatingPointOperands()); + RUN_BINARY(testCompareOneFloatToDouble, floatingPointOperands(), floatingPointOperands()); + RUN_BINARY(testCompareFloatToDoubleThroughPhi, floatingPointOperands(), floatingPointOperands()); + RUN_UNARY(testDoubleToFloatThroughPhi, floatingPointOperands()); + RUN_UNARY(testDoubleProducerPhiToFloatConversion, floatingPointOperands()); + RUN_UNARY(testDoubleProducerPhiToFloatConversionWithDoubleConsumer, floatingPointOperands()); + RUN_BINARY(testDoubleProducerPhiWithNonFloatConst, floatingPointOperands(), floatingPointOperands()); + RUN_UNARY(testDoubleArgToInt64BitwiseCast, floatingPointOperands()); RUN_UNARY(testDoubleImmToInt64BitwiseCast, floatingPointOperands()); RUN_UNARY(testTwoBitwiseCastOnDouble, floatingPointOperands()); @@ -12081,10 +13711,26 @@ RUN_UNARY(testConvertFloatToDoubleMem, floatingPointOperands()); RUN_UNARY(testConvertDoubleToFloatToDoubleToFloat, floatingPointOperands()); RUN_UNARY(testStoreFloat, floatingPointOperands()); + RUN_UNARY(testStoreDoubleConstantAsFloat, floatingPointOperands()); RUN_UNARY(testLoadFloatConvertDoubleConvertFloatStoreFloat, floatingPointOperands()); RUN_UNARY(testFroundArg, floatingPointOperands()); RUN_UNARY(testFroundMem, floatingPointOperands()); + RUN(testIToD64Arg()); + RUN(testIToF64Arg()); + RUN(testIToD32Arg()); + RUN(testIToF32Arg()); + RUN(testIToD64Mem()); + RUN(testIToF64Mem()); + RUN(testIToD32Mem()); + RUN(testIToF32Mem()); + RUN_UNARY(testIToD64Imm, int64Operands()); + RUN_UNARY(testIToF64Imm, int64Operands()); + RUN_UNARY(testIToD32Imm, int32Operands()); + RUN_UNARY(testIToF32Imm, int32Operands()); + RUN(testIToDReducedToIToF64Arg()); + RUN(testIToDReducedToIToF32Arg()); + RUN(testStore32(44)); RUN(testStoreConstant(49)); RUN(testStoreConstantPtr(49)); @@ -12180,6 +13826,7 @@ RUN(testBranchLoad8Z()); RUN(testBranchLoad16S()); RUN(testBranchLoad16Z()); + RUN(testBranch8WithLoad8ZIndex()); RUN(testComplex(64, 128)); RUN(testComplex(4, 128)); @@ -12783,6 +14430,38 @@ RUN(testLShiftSelf64()); RUN(testPatchpointDoubleRegs()); + RUN(testSpillDefSmallerThanUse()); + RUN(testSpillUseLargerThanDef()); + RUN(testLateRegister()); + RUN(testInterpreter()); + RUN(testReduceStrengthCheckBottomUseInAnotherBlock()); + RUN(testResetReachabilityDanglingReference()); + + RUN(testEntrySwitchSimple()); + RUN(testEntrySwitchNoEntrySwitch()); + RUN(testEntrySwitchWithCommonPaths()); + RUN(testEntrySwitchWithCommonPathsAndNonTrivialEntrypoint()); + RUN(testEntrySwitchLoop()); + + RUN(testSomeEarlyRegister()); + RUN(testPatchpointTerminalReturnValue(true)); + RUN(testPatchpointTerminalReturnValue(false)); + + if (isX86()) { + RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp)); + RUN(testBranchBitAndImmFusion(Identity, Int64, 0xff, Air::BranchTest32, Air::Arg::Tmp)); + RUN(testBranchBitAndImmFusion(Trunc, Int32, 1, Air::BranchTest32, Air::Arg::Tmp)); + RUN(testBranchBitAndImmFusion(Trunc, Int32, 0xff, Air::BranchTest32, Air::Arg::Tmp)); + RUN(testBranchBitAndImmFusion(Load8S, Int32, 1, Air::BranchTest8, Air::Arg::Addr)); + RUN(testBranchBitAndImmFusion(Load8Z, Int32, 1, Air::BranchTest8, Air::Arg::Addr)); + RUN(testBranchBitAndImmFusion(Load, Int32, 1, Air::BranchTest32, Air::Arg::Addr)); + RUN(testBranchBitAndImmFusion(Load, Int64, 1, Air::BranchTest32, Air::Arg::Addr)); + } + + if (isARM64()) { + RUN(testTernarySubInstructionSelection(Identity, Int64, Air::Sub64)); + RUN(testTernarySubInstructionSelection(Trunc, Int32, Air::Sub32)); + } if (tasks.isEmpty()) usage(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -41,20 +41,6 @@ namespace Deprecated { -void ScriptCallArgumentHandler::appendArgument(const Deprecated::ScriptObject& argument) -{ - if (argument.scriptState() != m_exec) { - ASSERT_NOT_REACHED(); - return; - } - m_arguments.append(argument.jsObject()); -} - -void ScriptCallArgumentHandler::appendArgument(const Deprecated::ScriptValue& argument) -{ - m_arguments.append(argument.jsValue()); -} - void ScriptCallArgumentHandler::appendArgument(const String& argument) { JSLockHolder lock(m_exec); @@ -115,7 +101,7 @@ { } -Deprecated::ScriptValue ScriptFunctionCall::call(bool& hadException) +JSValue ScriptFunctionCall::call(bool& hadException) { JSObject* thisObject = m_thisObject.jsObject(); @@ -124,13 +110,13 @@ JSValue function = thisObject->get(m_exec, Identifier::fromString(m_exec, m_name)); if (m_exec->hadException()) { hadException = true; - return Deprecated::ScriptValue(); + return { }; } CallData callData; CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return Deprecated::ScriptValue(); + if (callType == CallType::None) + return { }; JSValue result; NakedPtr exception; @@ -142,15 +128,15 @@ if (exception) { // Do not treat a terminated execution exception as having an exception. Just treat it as an empty result. hadException = !isTerminatedExecutionException(exception); - return Deprecated::ScriptValue(); + return { }; } - return Deprecated::ScriptValue(m_exec->vm(), result); + return result; } -Deprecated::ScriptValue ScriptFunctionCall::call() +JSC::JSValue ScriptFunctionCall::call() { - bool hadException = false; + bool hadException; return call(hadException); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptFunctionCall.h webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptFunctionCall.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptFunctionCall.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptFunctionCall.h 2016-11-03 07:04:20.000000000 +0000 @@ -46,8 +46,6 @@ public: ScriptCallArgumentHandler(JSC::ExecState* state) : m_exec(state) { } - void appendArgument(const ScriptObject&); - void appendArgument(const ScriptValue&); void appendArgument(const char*); void appendArgument(const String&); void appendArgument(JSC::JSValue); @@ -73,8 +71,8 @@ public: typedef JSC::JSValue (*ScriptFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr&); ScriptFunctionCall(const ScriptObject& thisObject, const String& name, ScriptFunctionCallHandler handler = nullptr); - ScriptValue call(bool& hadException); - ScriptValue call(); + JSC::JSValue call(bool& hadException); + JSC::JSValue call(); protected: ScriptFunctionCallHandler m_callHandler; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptObject.h webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptObject.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptObject.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptObject.h 2016-09-16 09:56:47.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptObject_h -#define ScriptObject_h +#pragma once #include "JSObject.h" #include "ScriptValue.h" @@ -41,15 +40,15 @@ public: JS_EXPORT_PRIVATE ScriptObject(JSC::ExecState*, JSC::JSObject*); JS_EXPORT_PRIVATE ScriptObject(JSC::ExecState*, const ScriptValue&); - ScriptObject() : m_scriptState(nullptr) { } + ScriptObject() { } + + operator JSC::JSObject*() const { return jsObject(); } JSC::JSObject* jsObject() const { return asObject(jsValue()); } JSC::ExecState* scriptState() const { return m_scriptState; } -protected: - JSC::ExecState* m_scriptState; +private: + JSC::ExecState* m_scriptState { nullptr }; }; } // namespace Deprecated - -#endif // ScriptObject_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptValue.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptValue.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptValue.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptValue.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -32,12 +32,77 @@ #include "APICast.h" #include "InspectorValues.h" +#include "JSCInlines.h" #include "JSLock.h" -#include "StructureInlines.h" using namespace JSC; using namespace Inspector; +namespace Inspector { + +static RefPtr jsToInspectorValue(ExecState& scriptState, JSValue value, int maxDepth) +{ + if (!value) { + ASSERT_NOT_REACHED(); + return nullptr; + } + + if (!maxDepth) + return nullptr; + + maxDepth--; + + if (value.isUndefinedOrNull()) + return InspectorValue::null(); // FIXME: Why is it OK to turn undefined into null? + if (value.isBoolean()) + return InspectorValue::create(value.asBoolean()); + if (value.isNumber() && value.isDouble()) + return InspectorValue::create(value.asNumber()); + if (value.isNumber() && value.isAnyInt()) + return InspectorValue::create(static_cast(value.asAnyInt())); + if (value.isString()) + return InspectorValue::create(value.getString(&scriptState)); + + if (value.isObject()) { + if (isJSArray(value)) { + auto inspectorArray = InspectorArray::create(); + auto& array = *asArray(value); + unsigned length = array.length(); + for (unsigned i = 0; i < length; i++) { + auto elementValue = jsToInspectorValue(scriptState, array.getIndex(&scriptState, i), maxDepth); + if (!elementValue) + return nullptr; + inspectorArray->pushValue(WTFMove(elementValue)); + } + return WTFMove(inspectorArray); + } + auto inspectorObject = InspectorObject::create(); + auto& object = *value.getObject(); + PropertyNameArray propertyNames(&scriptState, PropertyNameMode::Strings); + object.methodTable()->getOwnPropertyNames(&object, &scriptState, propertyNames, EnumerationMode()); + for (auto& name : propertyNames) { + auto inspectorValue = jsToInspectorValue(scriptState, object.get(&scriptState, name), maxDepth); + if (!inspectorValue) + return nullptr; + inspectorObject->setValue(name.string(), WTFMove(inspectorValue)); + } + return WTFMove(inspectorObject); + } + + ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr toInspectorValue(ExecState& state, JSValue value) +{ + // FIXME: Maybe we should move the JSLockHolder stuff to the callers since this function takes a JSValue directly. + // Doing the locking here made sense when we were trying to abstract the difference between multiple JavaScript engines. + JSLockHolder holder(&state); + return jsToInspectorValue(state, value, InspectorValue::maxDepth); +} + +} // namespace Inspector + namespace Deprecated { ScriptValue::~ScriptValue() @@ -94,69 +159,13 @@ bool ScriptValue::isFunction() const { CallData callData; - return getCallData(m_value.get(), callData) != CallTypeNone; -} - -static RefPtr jsToInspectorValue(ExecState* scriptState, JSValue value, int maxDepth) -{ - if (!value) { - ASSERT_NOT_REACHED(); - return nullptr; - } - - if (!maxDepth) - return nullptr; - - maxDepth--; - - if (value.isNull() || value.isUndefined()) - return InspectorValue::null(); - if (value.isBoolean()) - return InspectorBasicValue::create(value.asBoolean()); - if (value.isNumber() && value.isDouble()) - return InspectorBasicValue::create(value.asNumber()); - if (value.isNumber() && value.isMachineInt()) - return InspectorBasicValue::create(static_cast(value.asMachineInt())); - if (value.isString()) - return InspectorString::create(value.getString(scriptState)); - - if (value.isObject()) { - if (isJSArray(value)) { - Ref inspectorArray = InspectorArray::create(); - JSArray* array = asArray(value); - unsigned length = array->length(); - for (unsigned i = 0; i < length; i++) { - JSValue element = array->getIndex(scriptState, i); - RefPtr elementValue = jsToInspectorValue(scriptState, element, maxDepth); - if (!elementValue) - return nullptr; - inspectorArray->pushValue(WTFMove(elementValue)); - } - return WTFMove(inspectorArray); - } - Ref inspectorObject = InspectorObject::create(); - JSObject* object = value.getObject(); - PropertyNameArray propertyNames(scriptState, PropertyNameMode::Strings); - object->methodTable()->getOwnPropertyNames(object, scriptState, propertyNames, EnumerationMode()); - for (size_t i = 0; i < propertyNames.size(); i++) { - const Identifier& name = propertyNames[i]; - JSValue propertyValue = object->get(scriptState, name); - RefPtr inspectorValue = jsToInspectorValue(scriptState, propertyValue, maxDepth); - if (!inspectorValue) - return nullptr; - inspectorObject->setValue(name.string(), WTFMove(inspectorValue)); - } - return WTFMove(inspectorObject); - } - - ASSERT_NOT_REACHED(); - return nullptr; + return getCallData(m_value.get(), callData) != CallType::None; } RefPtr ScriptValue::toInspectorValue(ExecState* scriptState) const { JSLockHolder holder(scriptState); - return jsToInspectorValue(scriptState, m_value.get(), InspectorValue::maxDepth); + return jsToInspectorValue(*scriptState, m_value.get(), InspectorValue::maxDepth); } } // namespace Deprecated diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptValue.h webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptValue.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bindings/ScriptValue.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bindings/ScriptValue.h 2016-11-03 07:04:20.000000000 +0000 @@ -37,11 +37,14 @@ #include "Operations.h" #include "Strong.h" #include "StrongInlines.h" -#include #include namespace Inspector { + class InspectorValue; + +JS_EXPORT_PRIVATE RefPtr toInspectorValue(JSC::ExecState&, JSC::JSValue); + } namespace Deprecated { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ArrayConstructor.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ArrayConstructor.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ArrayConstructor.js 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ArrayConstructor.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,8 +28,7 @@ "use strict"; var length = arguments.length; - // TODO: Need isConstructor(this) instead of typeof "function" check. - var array = typeof this === 'function' ? new this(length) : new @Array(length); + var array = @isConstructor(this) ? new this(length) : @newArrayWithSize(length); for (var k = 0; k < length; ++k) @putByValDirect(array, k, arguments[k]); array.length = length; @@ -57,13 +56,12 @@ if (items == null) throw new @TypeError("Array.from requires an array-like object - not null or undefined"); - var iteratorMethod = items[@symbolIterator]; + var iteratorMethod = items.@iteratorSymbol; if (iteratorMethod != null) { if (typeof iteratorMethod !== "function") throw new @TypeError("Array.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function"); - // TODO: Need isConstructor(thisObj) instead of typeof "function" check. - var result = (typeof thisObj === "function") ? @Object(new thisObj()) : []; + var result = @isConstructor(thisObj) ? new thisObj() : []; var k = 0; var iterator = iteratorMethod.@call(items); @@ -71,11 +69,8 @@ // Since for-of loop once more looks up the @@iterator property of a given iterable, // it could be observable if the user defines a getter for @@iterator. // To avoid this situation, we define a wrapper object that @@iterator just returns a given iterator. - var wrapper = { - [@symbolIterator]() { - return iterator; - } - }; + var wrapper = {} + wrapper.@iteratorSymbol = function() { return iterator; }; for (var value of wrapper) { if (mapFn) @@ -92,8 +87,7 @@ var arrayLike = @Object(items); var arrayLikeLength = @toLength(arrayLike.length); - // TODO: Need isConstructor(thisObj) instead of typeof "function" check. - var result = (typeof thisObj === "function") ? @Object(new thisObj(arrayLikeLength)) : new @Array(arrayLikeLength); + var result = @isConstructor(thisObj) ? new thisObj(arrayLikeLength) : @newArrayWithSize(arrayLikeLength); var k = 0; while (k < arrayLikeLength) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Yusuke Suzuki . + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,31 +31,78 @@ if (this == null) throw new @TypeError("%ArrayIteratorPrototype%.next requires that |this| not be null or undefined"); - var itemKind = this.@arrayIterationKind; - if (itemKind === @undefined) + let next = this.@arrayIteratorNext; + if (next === @undefined) throw new @TypeError("%ArrayIteratorPrototype%.next requires that |this| be an Array Iterator instance"); + return next.@call(this); +} + +@globalPrivate +function arrayIteratorValueNext() +{ + "use strict"; + var done = true; + var value; + + var array = this.@iteratedObject; + if (!this.@arrayIteratorIsDone) { + var index = this.@arrayIteratorNextIndex; + var length = array.length >>> 0; + if (index >= length) { + this.@arrayIteratorIsDone = true; + } else { + this.@arrayIteratorNextIndex = index + 1; + done = false; + value = array[index]; + } + } + + return { done, value }; +} + +@globalPrivate +function arrayIteratorKeyNext() +{ + "use strict"; + var done = true; + var value; + + var array = this.@iteratedObject; + if (!this.@arrayIteratorIsDone) { + var index = this.@arrayIteratorNextIndex; + var length = array.length >>> 0; + if (index >= length) { + this.@arrayIteratorIsDone = true; + } else { + this.@arrayIteratorNextIndex = index + 1; + done = false; + value = index; + } + } + + return { done, value }; +} + +@globalPrivate +function arrayIteratorKeyValueNext() +{ + "use strict"; var done = true; - var value = @undefined; + var value; var array = this.@iteratedObject; - if (array !== @undefined) { + if (!this.@arrayIteratorIsDone) { var index = this.@arrayIteratorNextIndex; var length = array.length >>> 0; if (index >= length) { - this.@iteratedObject = @undefined; + this.@arrayIteratorIsDone = true; } else { this.@arrayIteratorNextIndex = index + 1; done = false; - if (itemKind === @arrayIterationKindKey) { - value = index; - } else if (itemKind === @arrayIterationKindValue) { - value = array[index]; - } else { - value = [ index, array[index] ]; - } + value = [ index, array[index] ]; } } - return {done, value}; + return { done, value }; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ArrayPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ArrayPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ArrayPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ArrayPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * Copyright (C) 2015 Yusuke Suzuki . * * Redistribution and use in source and binary forms, with or without @@ -24,15 +24,53 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -function reduce(callback /*, initialValue */) +@constructor +@globalPrivate +function createArrayIterator(iteratedObject, kind, iterationFunction) +{ + this.@iteratedObject = iteratedObject; + this.@arrayIteratorKind = kind; + this.@arrayIteratorNextIndex = 0; + this.@arrayIteratorNext = iterationFunction; + this.@arrayIteratorIsDone = false; +} + +function values() +{ + "use strict"; + + if (this == null) + throw new @TypeError("Array.prototype.values requires that |this| not be null or undefined"); + + return new @createArrayIterator(@Object(this), "value", @arrayIteratorValueNext); +} + +function keys() { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.reduce requires that |this| not be null"); + if (this == null) + throw new @TypeError("Array.prototype.keys requires that |this| not be null or undefined"); - if (this === @undefined) - throw new @TypeError("Array.prototype.reduce requires that |this| not be undefined"); + return new @createArrayIterator(@Object(this), "key", @arrayIteratorKeyNext); +} + +function entries() +{ + "use strict"; + + if (this == null) + throw new @TypeError("Array.prototype.entries requires that |this| not be null or undefined"); + + return new @createArrayIterator(@Object(this), "key+value", @arrayIteratorKeyValueNext); +} + +function reduce(callback /*, initialValue */) +{ + "use strict"; + + if (this == null) + throw new @TypeError("Array.prototype.reduce requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -66,11 +104,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.reduceRight requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.reduceRight requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.reduceRight requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -104,11 +139,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.every requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.every requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.every requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -132,11 +164,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.forEach requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.forEach requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.forEach requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -156,11 +185,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.filter requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.filter requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.filter requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -169,7 +195,28 @@ throw new @TypeError("Array.prototype.filter callback must be a function"); var thisArg = arguments.length > 1 ? arguments[1] : @undefined; - var result = []; + + // Do 9.4.2.3 ArraySpeciesCreate + var result; + var constructor; + if (@isArray(array)) { + constructor = array.constructor; + // We have this check so that if some array from a different global object + // calls this map they don't get an array with the Array.prototype of the + // other global object. + if (@isArrayConstructor(constructor) && @Array !== constructor) + constructor = @undefined; + if (@isObject(constructor)) { + constructor = constructor.@speciesSymbol; + if (constructor === null) + constructor = @undefined; + } + } + if (constructor === @Array || constructor === @undefined) + result = @newArrayWithSize(0); + else + result = new constructor(0); + var nextIndex = 0; for (var i = 0; i < length; i++) { if (!(i in array)) @@ -187,11 +234,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.map requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.map requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.map requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -200,8 +244,28 @@ throw new @TypeError("Array.prototype.map callback must be a function"); var thisArg = arguments.length > 1 ? arguments[1] : @undefined; - var result = []; - result.length = length; + + // Do 9.4.2.3 ArraySpeciesCreate + var result; + var constructor; + if (@isArray(array)) { + constructor = array.constructor; + // We have this check so that if some array from a different global object + // calls this map they don't get an array with the Array.prototype of the + // other global object. + if (@isArrayConstructor(constructor) && @Array !== constructor) + constructor = @undefined; + if (@isObject(constructor)) { + constructor = constructor.@speciesSymbol; + if (constructor === null) + constructor = @undefined; + } + } + if (constructor === @Array || constructor === @undefined) + result = @newArrayWithSize(length); + else + result = new constructor(length); + var nextIndex = 0; for (var i = 0; i < length; i++) { if (!(i in array)) @@ -216,11 +280,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.some requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.some requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.some requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -242,53 +303,49 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.fill requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.fill requires that |this| not be undefined"); - var O = @Object(this); - var len = @toLength(O.length); + if (this == null) + throw new @TypeError("Array.prototype.fill requires that |this| not be null or undefined"); + + var array = @Object(this); + var length = @toLength(array.length); + var relativeStart = 0; if (arguments.length > 1 && arguments[1] !== @undefined) relativeStart = arguments[1] | 0; var k = 0; if (relativeStart < 0) { - k = len + relativeStart; + k = length + relativeStart; if (k < 0) k = 0; } else { k = relativeStart; - if (k > len) - k = len; + if (k > length) + k = length; } - var relativeEnd = len; + var relativeEnd = length; if (arguments.length > 2 && arguments[2] !== @undefined) relativeEnd = arguments[2] | 0; var final = 0; if (relativeEnd < 0) { - final = len + relativeEnd; + final = length + relativeEnd; if (final < 0) final = 0; } else { final = relativeEnd; - if (final > len) - final = len; + if (final > length) + final = length; } for (; k < final; k++) - O[k] = value; - return O; + array[k] = value; + return array; } function find(callback /*, thisArg */) { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.find requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.find requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.find requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -309,11 +366,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.findIndex requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.findIndex requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.findIndex requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -333,11 +387,8 @@ { "use strict"; - if (this === null) - throw new @TypeError("Array.prototype.includes requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.includes requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.includes requires that |this| not be null or undefined"); var array = @Object(this); var length = @toLength(array.length); @@ -347,7 +398,7 @@ var fromIndex = 0; if (arguments.length > 1 && arguments[1] !== @undefined) - fromIndex = arguments[1] | 0; + fromIndex = @toInteger(arguments[1]); var index; if (fromIndex >= 0) @@ -579,18 +630,15 @@ var valueCount = compact(array, length); - var strings = new @Array(valueCount); + var strings = @newArrayWithSize(valueCount); for (var i = 0; i < valueCount; ++i) strings[i] = { string: @toString(array[i]), value: array[i] }; bucketSort(array, 0, strings, 0); } - if (this === null) - throw new @TypeError("Array.prototype.sort requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("Array.prototype.sort requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("Array.prototype.sort requires that |this| not be null or undefined"); if (typeof this == "string") throw new @TypeError("Attempted to assign to readonly property."); @@ -605,6 +653,86 @@ return array; } +function concatSlowPath() +{ + "use strict"; + + if (this == null) + throw new @TypeError("Array.prototype.concat requires that |this| not be null or undefined"); + + var currentElement = @Object(this); + + var constructor; + if (@isArray(currentElement)) { + constructor = currentElement.constructor; + // We have this check so that if some array from a different global object + // calls this map they don't get an array with the Array.prototype of the + // other global object. + if (@isArrayConstructor(constructor) && @Array !== constructor) + constructor = @undefined; + else if (@isObject(constructor)) { + constructor = constructor.@speciesSymbol; + if (constructor === null) + constructor = @Array; + } + } + + var argCount = arguments.length; + var result; + if (constructor === @Array || constructor === @undefined) + result = @newArrayWithSize(0); + else + result = new constructor(0); + var resultIsArray = @isJSArray(result); + + var resultIndex = 0; + var argIndex = 0; + + do { + let spreadable = @isObject(currentElement) && currentElement.@isConcatSpreadableSymbol; + if ((spreadable === @undefined && @isArray(currentElement)) || spreadable) { + let length = @toLength(currentElement.length); + if (resultIsArray && @isJSArray(currentElement)) { + @appendMemcpy(result, currentElement, resultIndex); + resultIndex += length; + } else { + if (length + resultIndex > @MAX_SAFE_INTEGER) + throw @TypeError("length exceeded the maximum safe integer"); + for (var i = 0; i < length; i++) { + if (i in currentElement) + @putByValDirect(result, resultIndex, currentElement[i]); + resultIndex++; + } + } + } else { + if (resultIndex >= @MAX_SAFE_INTEGER) + throw @TypeError("length exceeded the maximum safe integer"); + @putByValDirect(result, resultIndex++, currentElement); + } + currentElement = arguments[argIndex]; + } while (argIndex++ < argCount); + + result.length = resultIndex; + return result; +} + +function concat(first) +{ + "use strict"; + + if (@argumentCount() === 1 + && @isJSArray(this) + && this.@isConcatSpreadableSymbol === @undefined + && (!@isObject(first) || first.@isConcatSpreadableSymbol === @undefined)) { + + let result = @concatMemcpy(this, first); + if (result !== null) + return result; + } + + return @tailCallForwardArguments(@concatSlowPath, this); +} + function copyWithin(target, start /*, end */) { "use strict"; @@ -619,11 +747,11 @@ return (maybeNegativeZero < positive) ? maybeNegativeZero : positive; } - if (this === null || this === @undefined) + if (this == null) throw new @TypeError("Array.copyWithin requires that |this| not be null or undefined"); - var thisObject = @Object(this); - var length = @toLength(thisObject.length); + var array = @Object(this); + var length = @toLength(array.length); var relativeTarget = @toInteger(target); var to = (relativeTarget < 0) ? maxWithPositives(length + relativeTarget, 0) : minWithMaybeNegativeZeroAndPositive(relativeTarget, length); @@ -653,11 +781,11 @@ } for (var i = 0; i < count; ++i, from += direction, to += direction) { - if (from in thisObject) - thisObject[to] = thisObject[from]; + if (from in array) + array[to] = array[from]; else - delete thisObject[to]; + delete array[to]; } - return thisObject; + return array; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BuiltinExecutableCreator.h" + +#include "BuiltinExecutables.h" + +namespace JSC { + +UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& source, const Identifier& ident, ConstructorKind kind, ConstructAbility ability) +{ + return BuiltinExecutables::createExecutable(vm, source, ident, kind, ability); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutableCreator.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BuiltinExecutableCreator_h +#define BuiltinExecutableCreator_h + +#include "ConstructAbility.h" +#include "ParserModes.h" +#include "SourceCode.h" + +namespace JSC { + +JS_EXPORT_PRIVATE UnlinkedFunctionExecutable* createBuiltinExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility); + +} // namespace JSC + +#endif /* BuiltinExecutableCreator_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -35,8 +35,6 @@ namespace JSC { -static UnlinkedFunctionExecutable* createExecutableInternal(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility); - BuiltinExecutables::BuiltinExecutables(VM& vm) : m_vm(vm) #define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, length) , m_##name##Source(makeSource(StringImpl::createFromLiteral(s_##name, length))) @@ -54,9 +52,9 @@ case ConstructorKind::None: break; case ConstructorKind::Base: - return createExecutableInternal(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct); - case ConstructorKind::Derived: - return createExecutableInternal(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct); + return createExecutable(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct); + case ConstructorKind::Extends: + return createExecutable(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct); } ASSERT_NOT_REACHED(); return nullptr; @@ -64,15 +62,15 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructAbility constructAbility) { - return createExecutableInternal(m_vm, code, name, ConstructorKind::None, constructAbility); + return createExecutable(m_vm, code, name, ConstructorKind::None, constructAbility); } UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& code, const Identifier& name, ConstructAbility constructAbility) { - return createExecutableInternal(vm, code, name, ConstructorKind::None, constructAbility); + return BuiltinExecutables::createExecutable(vm, code, name, ConstructorKind::None, constructAbility); } -UnlinkedFunctionExecutable* createExecutableInternal(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility) +UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility) { JSTextPosition positionBeforeLastNewline; ParserError error; @@ -82,7 +80,7 @@ RefPtr sourceOverride = isParsingDefaultConstructor ? source.provider() : nullptr; std::unique_ptr program = parse( &vm, source, Identifier(), builtinMode, - JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error, + JSParserStrictMode::NotStrict, JSParserCommentMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error, &positionBeforeLastNewline, constructorKind); if (!program) { @@ -108,8 +106,7 @@ RELEASE_ASSERT(metadata); metadata->overrideName(name); VariableEnvironment dummyTDZVariables; - UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, dummyTDZVariables, DerivedContextType::None, WTFMove(sourceOverride)); - functionExecutable->setNameValue(vm, jsString(&vm, name.string())); + UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, JSParserCommentMode::Classic, dummyTDZVariables, DerivedContextType::None, WTFMove(sourceOverride)); return functionExecutable; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutables.h webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutables.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinExecutables.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinExecutables.h 2016-11-03 07:04:20.000000000 +0000 @@ -52,6 +52,7 @@ UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name); + static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility); private: void finalize(Handle, void* context) override; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinNames.h webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinNames.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinNames.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinNames.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,28 +27,172 @@ #define BuiltinNames_h #include "BuiltinUtils.h" +#include "BytecodeIntrinsicRegistry.h" #include "CommonIdentifiers.h" #include "JSCBuiltins.h" namespace JSC { +#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \ + JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \ + JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \ + macro(arrayIteratorNextIndex) \ + macro(arrayIterationKind) \ + macro(arrayIteratorNext) \ + macro(arrayIteratorIsDone) \ + macro(arrayIteratorKind) \ + macro(charCodeAt) \ + macro(isView) \ + macro(iteratedObject) \ + macro(iteratedString) \ + macro(stringIteratorNextIndex) \ + macro(promise) \ + macro(fulfillmentHandler) \ + macro(rejectionHandler) \ + macro(index) \ + macro(deferred) \ + macro(countdownHolder) \ + macro(Object) \ + macro(ownEnumerablePropertyKeys) \ + macro(Number) \ + macro(Array) \ + macro(ArrayBuffer) \ + macro(String) \ + macro(RegExp) \ + macro(Map) \ + macro(Promise) \ + macro(Reflect) \ + macro(InternalPromise) \ + macro(abs) \ + macro(floor) \ + macro(trunc) \ + macro(create) \ + macro(defineProperty) \ + macro(getPrototypeOf) \ + macro(getOwnPropertyDescriptor) \ + macro(getOwnPropertyNames) \ + macro(ownKeys) \ + macro(Error) \ + macro(RangeError) \ + macro(TypeError) \ + macro(typedArrayLength) \ + macro(typedArraySort) \ + macro(typedArrayGetOriginalConstructor) \ + macro(typedArraySubarrayCreate) \ + macro(BuiltinLog) \ + macro(homeObject) \ + macro(getTemplateObject) \ + macro(enqueueJob) \ + macro(handler) \ + macro(promiseState) \ + macro(promiseFulfillReactions) \ + macro(promiseRejectReactions) \ + macro(promiseResult) \ + macro(push) \ + macro(repeatCharacter) \ + macro(capabilities) \ + macro(starDefault) \ + macro(InspectorInstrumentation) \ + macro(get) \ + macro(set) \ + macro(shift) \ + macro(allocateTypedArray) \ + macro(Int8Array) \ + macro(Int16Array) \ + macro(Int32Array) \ + macro(Uint8Array) \ + macro(Uint8ClampedArray) \ + macro(Uint16Array) \ + macro(Uint32Array) \ + macro(Float32Array) \ + macro(Float64Array) \ + macro(exec) \ + macro(generator) \ + macro(generatorNext) \ + macro(generatorState) \ + macro(generatorFrame) \ + macro(generatorValue) \ + macro(generatorThis) \ + macro(generatorResumeMode) \ + macro(Collator) \ + macro(DateTimeFormat) \ + macro(NumberFormat) \ + macro(intlSubstituteValue) \ + macro(thisTimeValue) \ + macro(thisNumberValue) \ + macro(newTargetLocal) \ + macro(derivedConstructor) \ + macro(isTypedArrayView) \ + macro(isBoundFunction) \ + macro(hasInstanceBoundFunction) \ + macro(instanceOf) \ + macro(isArray) \ + macro(isArrayConstructor) \ + macro(isConstructor) \ + macro(isDerivedConstructor) \ + macro(isRegExpObject) \ + macro(concatMemcpy) \ + macro(appendMemcpy) \ + macro(predictFinalLengthFromArgumunts) \ + macro(print) \ + macro(isSet) \ + macro(isMap) \ + macro(regExpCreate) \ + macro(SetIterator) \ + macro(setIteratorNext) \ + macro(replaceUsingRegExp) \ + macro(replaceUsingStringSearch) \ + macro(MapIterator) \ + macro(mapIteratorNext) \ + macro(regExpBuiltinExec) \ + macro(regExpMatchFast) \ + macro(regExpProtoFlagsGetter) \ + macro(regExpProtoGlobalGetter) \ + macro(regExpProtoIgnoreCaseGetter) \ + macro(regExpProtoMultilineGetter) \ + macro(regExpProtoSourceGetter) \ + macro(regExpProtoStickyGetter) \ + macro(regExpProtoUnicodeGetter) \ + macro(regExpPrototypeSymbolReplace) \ + macro(regExpReplaceFast) \ + macro(regExpSearchFast) \ + macro(regExpSplitFast) \ + macro(regExpTestFast) \ + macro(stringIncludesInternal) \ + macro(stringSplitFast) \ + macro(stringSubstrInternal) + + #define INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY(name) m_privateToPublicMap.add(m_##name##PrivateName.impl(), &m_##name); #define INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name.impl(), &m_##name##PrivateName); +// We commandeer the publicToPrivateMap to allow us to convert private symbol names into the appropriate symbol. +// e.g. @iteratorSymbol points to Symbol.iterator in this map rather than to a an actual private name. +// FIXME: This is a weird hack and we shouldn't need to do this. +#define INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name##SymbolPrivateIdentifier.impl(), &m_##name##Symbol); + class BuiltinNames { WTF_MAKE_NONCOPYABLE(BuiltinNames); WTF_MAKE_FAST_ALLOCATED; public: + // We treat the dollarVM name as a special case below for $vm (because CommonIdentifiers does not + // yet support the $ character). + BuiltinNames(VM* vm, CommonIdentifiers* commonIdentifiers) : m_emptyIdentifier(commonIdentifiers->emptyIdentifier) JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_BUILTIN_NAMES) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_BUILTIN_SYMBOLS) + , m_dollarVMName(Identifier::fromString(vm, "$vm")) + , m_dollarVMPrivateName(Identifier::fromUid(PrivateName(PrivateName::Description, ASCIILiteral("PrivateSymbol.$vm")))) { JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY) JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY) + JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_SYMBOL_PUBLIC_TO_PRIVATE_ENTRY) + m_privateToPublicMap.add(m_dollarVMPrivateName.impl(), &m_dollarVMName); + m_publicToPrivateMap.add(m_dollarVMName.impl(), &m_dollarVMPrivateName); } bool isPrivateName(SymbolImpl& uid) const; @@ -62,12 +206,16 @@ JSC_FOREACH_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(DECLARE_BUILTIN_SYMBOL_ACCESSOR) + const JSC::Identifier& dollarVMPublicName() const { return m_dollarVMName; } + const JSC::Identifier& dollarVMPrivateName() const { return m_dollarVMPrivateName; } private: Identifier m_emptyIdentifier; JSC_FOREACH_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_NAMES) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_NAMES) JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(DECLARE_BUILTIN_SYMBOLS) + const JSC::Identifier m_dollarVMName; + const JSC::Identifier m_dollarVMPrivateName; typedef HashMap, const Identifier*, IdentifierRepHash> BuiltinNamesMap; BuiltinNamesMap m_publicToPrivateMap; BuiltinNamesMap m_privateToPublicMap; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinUtils.h webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinUtils.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/BuiltinUtils.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/BuiltinUtils.h 2016-11-03 07:04:20.000000000 +0000 @@ -37,8 +37,8 @@ const JSC::Identifier& name##PublicName() const { return m_##name; } \ const JSC::Identifier& name##PrivateName() const { return m_##name##PrivateName; } -#define INITIALIZE_BUILTIN_SYMBOLS(name) , m_##name##Symbol(JSC::Identifier::fromUid(JSC::PrivateName(JSC::PrivateName::Description, ASCIILiteral("Symbol." #name)))) -#define DECLARE_BUILTIN_SYMBOLS(name) const JSC::Identifier m_##name##Symbol; +#define INITIALIZE_BUILTIN_SYMBOLS(name) , m_##name##Symbol(JSC::Identifier::fromUid(JSC::PrivateName(JSC::PrivateName::Description, ASCIILiteral("Symbol." #name)))), m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name "Symbol")) +#define DECLARE_BUILTIN_SYMBOLS(name) const JSC::Identifier m_##name##Symbol; const JSC::Identifier m_##name##SymbolPrivateIdentifier; #define DECLARE_BUILTIN_SYMBOL_ACCESSOR(name) \ const JSC::Identifier& name##Symbol() const { return m_##name##Symbol; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/DatePrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/DatePrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/DatePrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/DatePrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -55,7 +55,7 @@ // Only create descendant if it will have own properties. if (needsDefaults) { - options = @Object.create(options) + options = @Object.@create(options); options.year = "numeric"; options.month = "numeric"; options.day = "numeric"; @@ -109,7 +109,7 @@ // Only create descendant if it will have own properties. if (needsDefaults) { - options = @Object.create(options) + options = @Object.@create(options); options.year = "numeric"; options.month = "numeric"; options.day = "numeric"; @@ -158,7 +158,7 @@ // Only create descendant if it will have own properties. if (needsDefaults) { - options = @Object.create(options) + options = @Object.@create(options); options.hour = "numeric"; options.minute = "numeric"; options.second = "numeric"; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/FunctionPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/FunctionPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/FunctionPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/FunctionPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -27,7 +27,12 @@ { "use strict"; - return this.@call(...arguments); + let argumentValues = []; + // Start from 1 to ignore thisArgument + for (let i = 1; i < arguments.length; i++) + @putByValDirect(argumentValues, i-1, arguments[i]); + + return this.@apply(thisArgument, argumentValues); } function apply(thisValue, argumentValues) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/GeneratorPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/GeneratorPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/GeneratorPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/GeneratorPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,6 @@ /* - * Copyright (C) 2015 Yusuke Suzuki . + * Copyright (C) 2015-2016 Yusuke Suzuki . + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,19 +26,11 @@ // 25.3.3.3 GeneratorResume ( generator, value ) // 25.3.3.4 GeneratorResumeAbrupt(generator, abruptCompletion) +@globalPrivate function generatorResume(generator, sentValue, resumeMode) { "use strict"; - // GeneratorState. - const Completed = -1; - const Executing = -2; - - // ResumeMode. - const NormalMode = 0; - const ReturnMode = 1; - const ThrowMode = 2; - let state = generator.@generatorState; let done = false; let value = @undefined; @@ -45,26 +38,26 @@ if (typeof state !== 'number') throw new @TypeError("|this| should be a generator"); - if (state === Executing) + if (state === @GeneratorStateExecuting) throw new @TypeError("Generator is executing"); - if (state === Completed) { - if (resumeMode === ThrowMode) + if (state === @GeneratorStateCompleted) { + if (resumeMode === @GeneratorResumeModeThrow) throw sentValue; done = true; - if (resumeMode === ReturnMode) + if (resumeMode === @GeneratorResumeModeReturn) value = sentValue; } else { try { - generator.@generatorState = Executing; - value = generator.@generatorNext.@call(generator.@generatorThis, generator, state, sentValue, resumeMode); - if (generator.@generatorState === Executing) { - generator.@generatorState = Completed; + generator.@generatorState = @GeneratorStateExecuting; + value = generator.@generatorNext.@call(generator.@generatorThis, generator, state, sentValue, resumeMode, generator.@generatorFrame); + if (generator.@generatorState === @GeneratorStateExecuting) { + generator.@generatorState = @GeneratorStateCompleted; done = true; } } catch (error) { - generator.@generatorState = Completed; + generator.@generatorState = @GeneratorStateCompleted; throw error; } } @@ -75,19 +68,19 @@ { "use strict"; - return @generatorResume(this, value, /* NormalMode */ 0); + return @generatorResume(this, value, @GeneratorResumeModeNormal); } function return(value) { "use strict"; - return @generatorResume(this, value, /* ReturnMode */ 1); + return @generatorResume(this, value, @GeneratorResumeModeReturn); } function throw(exception) { "use strict"; - return @generatorResume(this, exception, /* ThrowMode */ 2); + return @generatorResume(this, exception, @GeneratorResumeModeThrow); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/GlobalObject.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/GlobalObject.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/GlobalObject.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/GlobalObject.js 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,6 @@ /* - * Copyright (C) 2015 Yusuke Suzuki . + * Copyright (C) 2015-2016 Yusuke Suzuki . + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,44 +24,23 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @internal - -function toInteger(target) +@globalPrivate +function isFinite(value) { "use strict"; - var numberValue = @Number(target); - - // isNaN(numberValue) + var numberValue = @toNumber(value); + // Return false if numberValue is |NaN|. if (numberValue !== numberValue) - return 0; - - if (numberValue === 0 || !@isFinite(numberValue)) - return numberValue; - - return (numberValue > 0 ? 1 : -1) * @floor(@abs(numberValue)); -} - -function toLength(target) -{ - "use strict"; - - var maxSafeInteger = 0x1FFFFFFFFFFFFF; - var length = @toInteger(target); - // originally Math.min(Math.max(length, 0), maxSafeInteger)); - return length > 0 ? (length < maxSafeInteger ? length : maxSafeInteger) : 0; + return false; + return numberValue !== @Infinity && numberValue !== -@Infinity; } -function isDictionary(object) +@globalPrivate +function isNaN(value) { "use strict"; - return object === @undefined || object == null || typeof object === "object"; -} - -// FIXME: this needs to have it's name changed to "get [Symbol.species]". -// see: https://bugs.webkit.org/show_bug.cgi?id=151363 -function speciesGetter() -{ - return this; + var numberValue = @toNumber(value); + return numberValue !== numberValue; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/GlobalOperations.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/GlobalOperations.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/GlobalOperations.js 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/GlobalOperations.js 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// @internal + +@globalPrivate +function toInteger(target) +{ + "use strict"; + + var numberValue = @Number(target); + + // isNaN(numberValue) + if (numberValue !== numberValue) + return 0; + return @trunc(numberValue); +} + +@globalPrivate +function toLength(target) +{ + "use strict"; + + var length = @toInteger(target); + // originally Math.min(Math.max(length, 0), maxSafeInteger)); + return length > 0 ? (length < @MAX_SAFE_INTEGER ? length : @MAX_SAFE_INTEGER) : 0; +} + +@globalPrivate +function isDictionary(object) +{ + "use strict"; + + return object == null || typeof object === "object"; +} + +// FIXME: this needs to have it's name changed to "get [Symbol.species]". +// see: https://bugs.webkit.org/show_bug.cgi?id=151363 +@globalPrivate +function speciesGetter() +{ + return this; +} + +@globalPrivate +function speciesConstructor(obj, defaultConstructor) +{ + var constructor = obj.constructor; + if (constructor === @undefined) + return defaultConstructor; + if (!@isObject(constructor)) + throw new @TypeError("|this|.constructor is not an Object or undefined"); + constructor = constructor.@speciesSymbol; + if (constructor == null) + return defaultConstructor; + if (@isConstructor(constructor)) + return constructor; + throw new @TypeError("|this|.constructor[Symbol.species] is not a constructor"); +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ModuleLoaderObject.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ModuleLoaderObject.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ModuleLoaderObject.js 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ModuleLoaderObject.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// https://whatwg.github.io/loader/#loader-object -// Module Loader has several hooks that can be customized by the platform. -// For example, the [[Fetch]] hook can be provided by the JavaScriptCore shell -// as fetching the payload from the local file system. -// Currently, there are 4 hooks. -// 1. Loader.resolve -// 2. Loader.fetch -// 3. Loader.translate -// 4. Loader.instantiate - -function setStateToMax(entry, newState) -{ - // https://whatwg.github.io/loader/#set-state-to-max - - "use strict"; - - if (entry.state < newState) - entry.state = newState; -} - -function newRegistryEntry(key) -{ - // https://whatwg.github.io/loader/#registry - // - // Each registry entry becomes one of the 5 states. - // 1. Fetch - // Ready to fetch (or now fetching) the resource of this module. - // Typically, we fetch the source code over the network or from the file system. - // a. If the status is Fetch and there is no entry.fetch promise, the entry is ready to fetch. - // b. If the status is Fetch and there is the entry.fetch promise, the entry is just fetching the resource. - // - // 2. Translate - // Ready to translate (or now translating) the raw fetched resource to the ECMAScript source code. - // We can insert the hook that translates the resources e.g. transpilers. - // a. If the status is Translate and there is no entry.translate promise, the entry is ready to translate. - // b. If the status is Translate and there is the entry.translate promise, the entry is just translating - // the payload to the source code. - // - // 3. Instantiate (AnalyzeModule) - // Ready to instantiate (or now instantiating) the module record from the fetched (and translated) - // source code. - // Typically, we parse the module code, extract the dependencies and binding information. - // a. If the status is Instantiate and there is no entry.instantiate promise, the entry is ready to instantiate. - // b. If the status is Instantiate and there is the entry.translate promise, the entry is just instantiating - // the module record. - // - // 4. ResolveDependencies (not in the draft) https://github.com/whatwg/loader/issues/68 - // Ready to request the dependent modules (or now requesting & resolving). - // Without this state, the current draft causes infinite recursion when there is circular dependency. - // a. If the status is ResolveDependencies and there is no entry.resolveDependencies promise, the entry is ready to resolve the dependencies. - // b. If the status is ResolveDependencies and there is the entry.resolveDependencies promise, the entry is just resolving - // the dependencies. - // - // 5. Link - // Ready to link the module with the other modules. - // Linking means that the module imports and exports the bindings from/to the other modules. - // - // 6. Ready - // The module is linked, so the module is ready to be executed. - // - // Each registry entry has the 4 promises; "fetch", "translate", "instantiate" and "resolveDependencies". - // They are assigned when starting the each phase. And they are fulfilled when the each phase is completed. - // - // In the current module draft, linking will be performed after the whole modules are instantiated and the dependencies are resolved. - // And execution is also done after the all modules are linked. - // - // TODO: We need to exploit the way to execute the module while fetching non-related modules. - // One solution; introducing the ready promise chain to execute the modules concurrently while keeping - // the execution order. - - "use strict"; - - return { - key: key, - state: this.Fetch, - metadata: @undefined, - fetch: @undefined, - translate: @undefined, - instantiate: @undefined, - resolveDependencies: @undefined, - dependencies: [], // To keep the module order, we store the module keys in the array. - dependenciesMap: @undefined, - module: @undefined, // JSModuleRecord - error: @undefined, - }; -} - -function ensureRegistered(key) -{ - // https://whatwg.github.io/loader/#ensure-registered - - "use strict"; - - var entry = this.registry.@get(key); - if (entry) - return entry; - - entry = this.newRegistryEntry(key); - this.registry.@set(key, entry); - - return entry; -} - -function forceFulfillPromise(promise, value) -{ - "use strict"; - - if (promise.@promiseState === @promiseStatePending) - @fulfillPromise(promise, value); -} - -function fulfillFetch(entry, payload) -{ - // https://whatwg.github.io/loader/#fulfill-fetch - - "use strict"; - - if (!entry.fetch) - entry.fetch = @newPromiseCapability(@InternalPromise).@promise; - this.forceFulfillPromise(entry.fetch, payload); - this.setStateToMax(entry, this.Translate); -} - -function fulfillTranslate(entry, source) -{ - // https://whatwg.github.io/loader/#fulfill-translate - - "use strict"; - - if (!entry.translate) - entry.translate = @newPromiseCapability(@InternalPromise).@promise; - this.forceFulfillPromise(entry.translate, source); - this.setStateToMax(entry, this.Instantiate); -} - -function fulfillInstantiate(entry, optionalInstance, source) -{ - // https://whatwg.github.io/loader/#fulfill-instantiate - - "use strict"; - - if (!entry.instantiate) - entry.instantiate = @newPromiseCapability(@InternalPromise).@promise; - this.commitInstantiated(entry, optionalInstance, source); - - // FIXME: The draft fulfills the promise in the CommitInstantiated operation. - // But it CommitInstantiated is also used in the requestInstantiate and - // we should not "force fulfill" there. - // So we separate "force fulfill" operation from the CommitInstantiated operation. - // https://github.com/whatwg/loader/pull/67 - this.forceFulfillPromise(entry.instantiate, entry); -} - -function commitInstantiated(entry, optionalInstance, source) -{ - // https://whatwg.github.io/loader/#commit-instantiated - - "use strict"; - - var moduleRecord = this.instantiation(optionalInstance, source, entry); - - // FIXME: Described in the draft, - // 4. Fulfill entry.[[Instantiate]] with instance. - // But, instantiate promise should be fulfilled with the entry. - // We remove this statement because instantiate promise will be - // fulfilled without this "force fulfill" operation. - // https://github.com/whatwg/loader/pull/67 - - var dependencies = []; - var dependenciesMap = moduleRecord.dependenciesMap; - moduleRecord.registryEntry = entry; - var requestedModules = this.requestedModules(moduleRecord); - for (var i = 0, length = requestedModules.length; i < length; ++i) { - var depKey = requestedModules[i]; - var pair = { - key: depKey, - value: @undefined - }; - @putByValDirect(dependencies, i, pair); - dependenciesMap.@set(depKey, pair); - } - entry.dependencies = dependencies; - entry.dependenciesMap = dependenciesMap; - entry.module = moduleRecord; - this.setStateToMax(entry, this.ResolveDependencies); -} - -function instantiation(result, source, entry) -{ - // https://whatwg.github.io/loader/#instantiation - // FIXME: Current implementation does not support optionalInstance. - // https://bugs.webkit.org/show_bug.cgi?id=148171 - - "use strict"; - - return this.parseModule(entry.key, source); -} - -// Loader. - -function requestFetch(key) -{ - // https://whatwg.github.io/loader/#request-fetch - - "use strict"; - - var entry = this.ensureRegistered(key); - if (entry.state > this.Link) { - var deferred = @newPromiseCapability(@InternalPromise); - deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); - return deferred.@promise; - } - - if (entry.fetch) - return entry.fetch; - - var loader = this; - - // Hook point. - // 2. Loader.fetch - // https://whatwg.github.io/loader/#browser-fetch - // Take the key and fetch the resource actually. - // For example, JavaScriptCore shell can provide the hook fetching the resource - // from the local file system. - var fetchPromise = this.fetch(key).then(function (payload) { - loader.setStateToMax(entry, loader.Translate); - return payload; - }); - entry.fetch = fetchPromise; - return fetchPromise; -} - -function requestTranslate(key) -{ - // https://whatwg.github.io/loader/#request-translate - - "use strict"; - - var entry = this.ensureRegistered(key); - if (entry.state > this.Link) { - var deferred = @newPromiseCapability(@InternalPromise); - deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); - return deferred.@promise; - } - - if (entry.translate) - return entry.translate; - - var loader = this; - var translatePromise = this.requestFetch(key).then(function (payload) { - // Hook point. - // 3. Loader.translate - // https://whatwg.github.io/loader/#browser-translate - // Take the key and the fetched source code and translate it to the ES6 source code. - // Typically it is used by the transpilers. - return loader.translate(key, payload).then(function (source) { - loader.setStateToMax(entry, loader.Instantiate); - return source; - }); - }); - entry.translate = translatePromise; - return translatePromise; -} - -function requestInstantiate(key) -{ - // https://whatwg.github.io/loader/#request-instantiate - - "use strict"; - - var entry = this.ensureRegistered(key); - if (entry.state > this.Link) { - var deferred = @newPromiseCapability(@InternalPromise); - deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); - return deferred.@promise; - } - - if (entry.instantiate) - return entry.instantiate; - - var loader = this; - var instantiatePromise = this.requestTranslate(key).then(function (source) { - // Hook point. - // 4. Loader.instantiate - // https://whatwg.github.io/loader/#browser-instantiate - // Take the key and the translated source code, and instantiate the module record - // by parsing the module source code. - // It has the chance to provide the optional module instance that is different from - // the ordinary one. - return loader.instantiate(key, source).then(function (optionalInstance) { - loader.commitInstantiated(entry, optionalInstance, source); - return entry; - }); - }); - entry.instantiate = instantiatePromise; - return instantiatePromise; -} - -function requestResolveDependencies(key) -{ - // FIXME: In the spec, after requesting instantiation, we will resolve - // the dependencies without any status change. As a result, when there - // is circular dependencies, instantiation is done only once, but - // repeatedly resolving the dependencies. This means that infinite - // recursion occur when the given modules have circular dependency. To - // avoid this situation, we introduce new state, "ResolveDependencies". This means - // "Now the module is instantiated, so ready to resolve the dependencies - // or now resolving them". - // https://github.com/whatwg/loader/issues/68 - - "use strict"; - - var entry = this.ensureRegistered(key); - if (entry.state > this.Link) { - var deferred = @newPromiseCapability(@InternalPromise); - deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); - return deferred.@promise; - } - - if (entry.resolveDependencies) - return entry.resolveDependencies; - - var loader = this; - var resolveDependenciesPromise = this.requestInstantiate(key).then(function (entry) { - var depLoads = []; - for (var i = 0, length = entry.dependencies.length; i < length; ++i) { - let pair = entry.dependencies[i]; - - // Hook point. - // 1. Loader.resolve. - // https://whatwg.github.io/loader/#browser-resolve - // Take the name and resolve it to the unique identifier for the resource location. - // For example, take the "jquery" and return the URL for the resource. - var promise = loader.resolve(pair.key, key).then(function (depKey) { - var depEntry = loader.ensureRegistered(depKey); - - // Recursive resolving. The dependencies of this entry is being resolved or already resolved. - // Stop tracing the circular dependencies. - // But to retrieve the instantiated module record correctly, - // we need to wait for the instantiation for the dependent module. - // For example, reaching here, the module is starting resolving the dependencies. - // But the module may or may not reach the instantiation phase in the loader's pipeline. - // If we wait for the ResolveDependencies for this module, it construct the circular promise chain and - // rejected by the Promises runtime. Since only we need is the instantiated module, instead of waiting - // the ResolveDependencies for this module, we just wait Instantiate for this. - if (depEntry.resolveDependencies) { - return depEntry.instantiate.then(function (entry) { - pair.value = entry.module; - return entry; - }); - } - - return loader.requestResolveDependencies(depKey).then(function (entry) { - pair.value = entry.module; - return entry; - }); - }); - @putByValDirect(depLoads, i, promise); - } - - return @InternalPromise.internalAll(depLoads).then(function (modules) { - loader.setStateToMax(entry, loader.Link); - return entry; - }); - }); - - entry.resolveDependencies = resolveDependenciesPromise; - return resolveDependenciesPromise; -} - -function requestInstantiateAll(key) -{ - // https://whatwg.github.io/loader/#request-instantiate-all - - "use strict"; - - return this.requestResolveDependencies(key); -} - -function requestLink(key) -{ - // https://whatwg.github.io/loader/#request-link - - "use strict"; - - var entry = this.ensureRegistered(key); - if (entry.state > this.Link) { - var deferred = @newPromiseCapability(@InternalPromise); - deferred.@resolve.@call(@undefined, entry.module); - return deferred.@promise; - } - - var loader = this; - return this.requestInstantiateAll(key).then(function (entry) { - loader.link(entry); - return entry; - }); -} - -function requestReady(key) -{ - // https://whatwg.github.io/loader/#request-ready - - "use strict"; - - var loader = this; - return this.requestLink(key).then(function (entry) { - loader.moduleEvaluation(entry.module); - }); -} - -// Linking semantics. - -function link(entry) -{ - // https://whatwg.github.io/loader/#link - - "use strict"; - - // FIXME: Current implementation does not support optionalInstance. - // So Link's step 3 is skipped. - // https://bugs.webkit.org/show_bug.cgi?id=148171 - - if (entry.state === this.Ready) - return; - this.setStateToMax(entry, this.Ready); - - // Since we already have the "dependencies" field, - // we can call moduleDeclarationInstantiation with the correct order - // without constructing the dependency graph by calling dependencyGraph. - var dependencies = entry.dependencies; - for (var i = 0, length = dependencies.length; i < length; ++i) { - var pair = dependencies[i]; - this.link(pair.value.registryEntry); - } - - this.moduleDeclarationInstantiation(entry.module); -} - -// Module semantics. - -function moduleEvaluation(moduleRecord) -{ - // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation - - "use strict"; - - if (moduleRecord.evaluated) - return; - moduleRecord.evaluated = true; - - var entry = moduleRecord.registryEntry; - - // The contents of the [[RequestedModules]] is cloned into entry.dependencies. - var dependencies = entry.dependencies; - for (var i = 0, length = dependencies.length; i < length; ++i) { - var pair = dependencies[i]; - var requiredModuleRecord = pair.value; - this.moduleEvaluation(requiredModuleRecord); - } - this.evaluate(entry.key, moduleRecord); -} - -// APIs to control the module loader. - -function provide(key, stage, value) -{ - "use strict"; - - var entry = this.ensureRegistered(key); - - if (stage === this.Fetch) { - if (entry.status > this.Fetch) - throw new @TypeError("Requested module is already fetched."); - this.fulfillFetch(entry, value); - return; - } - - if (stage === this.Translate) { - if (entry.status > this.Translate) - throw new @TypeError("Requested module is already translated."); - this.fulfillFetch(entry, @undefined); - this.fulfillTranslate(entry, value); - return; - } - - if (stage === this.Instantiate) { - if (entry.status > this.Instantiate) - throw new @TypeError("Requested module is already instantiated."); - this.fulfillFetch(entry, @undefined); - this.fulfillTranslate(entry, value); - var loader = this; - entry.translate.then(function (source) { - loader.fulfillInstantiate(entry, value, source); - }); - return; - } - - throw new @TypeError("Requested module is already ready to be executed."); -} - -function loadAndEvaluateModule(moduleName, referrer) -{ - "use strict"; - - var loader = this; - // Loader.resolve hook point. - // resolve: moduleName => Promise(moduleKey) - // Take the name and resolve it to the unique identifier for the resource location. - // For example, take the "jquery" and return the URL for the resource. - return this.resolve(moduleName, referrer).then(function (key) { - return loader.requestReady(key); - }); -} - -function loadModule(moduleName, referrer) -{ - "use strict"; - - var loader = this; - // Loader.resolve hook point. - // resolve: moduleName => Promise(moduleKey) - // Take the name and resolve it to the unique identifier for the resource location. - // For example, take the "jquery" and return the URL for the resource. - return this.resolve(moduleName, referrer).then(function (key) { - return loader.requestInstantiateAll(key); - }).then(function (entry) { - return entry.key; - }); -} - -function linkAndEvaluateModule(key) -{ - "use strict"; - - return this.requestReady(key); -} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// https://whatwg.github.io/loader/#loader-object +// Module Loader has several hooks that can be customized by the platform. +// For example, the [[Fetch]] hook can be provided by the JavaScriptCore shell +// as fetching the payload from the local file system. +// Currently, there are 4 hooks. +// 1. Loader.resolve +// 2. Loader.fetch +// 3. Loader.translate +// 4. Loader.instantiate + +function setStateToMax(entry, newState) +{ + // https://whatwg.github.io/loader/#set-state-to-max + + "use strict"; + + if (entry.state < newState) + entry.state = newState; +} + +function newRegistryEntry(key) +{ + // https://whatwg.github.io/loader/#registry + // + // Each registry entry becomes one of the 5 states. + // 1. Fetch + // Ready to fetch (or now fetching) the resource of this module. + // Typically, we fetch the source code over the network or from the file system. + // a. If the status is Fetch and there is no entry.fetch promise, the entry is ready to fetch. + // b. If the status is Fetch and there is the entry.fetch promise, the entry is just fetching the resource. + // + // 2. Translate + // Ready to translate (or now translating) the raw fetched resource to the ECMAScript source code. + // We can insert the hook that translates the resources e.g. transpilers. + // a. If the status is Translate and there is no entry.translate promise, the entry is ready to translate. + // b. If the status is Translate and there is the entry.translate promise, the entry is just translating + // the payload to the source code. + // + // 3. Instantiate (AnalyzeModule) + // Ready to instantiate (or now instantiating) the module record from the fetched (and translated) + // source code. + // Typically, we parse the module code, extract the dependencies and binding information. + // a. If the status is Instantiate and there is no entry.instantiate promise, the entry is ready to instantiate. + // b. If the status is Instantiate and there is the entry.translate promise, the entry is just instantiating + // the module record. + // + // 4. Satisfy + // Ready to request the dependent modules (or now requesting & resolving). + // Without this state, the current draft causes infinite recursion when there is circular dependency. + // a. If the status is Satisfy and there is no entry.satisfy promise, the entry is ready to resolve the dependencies. + // b. If the status is Satisfy and there is the entry.satisfy promise, the entry is just resolving + // the dependencies. + // + // 5. Link + // Ready to link the module with the other modules. + // Linking means that the module imports and exports the bindings from/to the other modules. + // + // 6. Ready + // The module is linked, so the module is ready to be executed. + // + // Each registry entry has the 4 promises; "fetch", "translate", "instantiate" and "satisfy". + // They are assigned when starting the each phase. And they are fulfilled when the each phase is completed. + // + // In the current module draft, linking will be performed after the whole modules are instantiated and the dependencies are resolved. + // And execution is also done after the all modules are linked. + // + // TODO: We need to exploit the way to execute the module while fetching non-related modules. + // One solution; introducing the ready promise chain to execute the modules concurrently while keeping + // the execution order. + + "use strict"; + + return { + key: key, + state: @ModuleFetch, + metadata: @undefined, + fetch: @undefined, + translate: @undefined, + instantiate: @undefined, + satisfy: @undefined, + dependencies: [], // To keep the module order, we store the module keys in the array. + dependenciesMap: @undefined, + module: @undefined, // JSModuleRecord + error: @undefined, + }; +} + +function ensureRegistered(key) +{ + // https://whatwg.github.io/loader/#ensure-registered + + "use strict"; + + var entry = this.registry.@get(key); + if (entry) + return entry; + + entry = this.newRegistryEntry(key); + this.registry.@set(key, entry); + + return entry; +} + +function forceFulfillPromise(promise, value) +{ + "use strict"; + + if (promise.@promiseState === @promiseStatePending) + @fulfillPromise(promise, value); +} + +function fulfillFetch(entry, payload) +{ + // https://whatwg.github.io/loader/#fulfill-fetch + + "use strict"; + + if (!entry.fetch) + entry.fetch = @newPromiseCapability(@InternalPromise).@promise; + this.forceFulfillPromise(entry.fetch, payload); + this.setStateToMax(entry, @ModuleTranslate); +} + +function fulfillTranslate(entry, source) +{ + // https://whatwg.github.io/loader/#fulfill-translate + + "use strict"; + + if (!entry.translate) + entry.translate = @newPromiseCapability(@InternalPromise).@promise; + this.forceFulfillPromise(entry.translate, source); + this.setStateToMax(entry, @ModuleInstantiate); +} + +function fulfillInstantiate(entry, optionalInstance, source) +{ + // https://whatwg.github.io/loader/#fulfill-instantiate + + "use strict"; + + if (!entry.instantiate) + entry.instantiate = @newPromiseCapability(@InternalPromise).@promise; + this.commitInstantiated(entry, optionalInstance, source); + + // FIXME: The draft fulfills the promise in the CommitInstantiated operation. + // But it CommitInstantiated is also used in the requestInstantiate and + // we should not "force fulfill" there. + // So we separate "force fulfill" operation from the CommitInstantiated operation. + // https://github.com/whatwg/loader/pull/67 + this.forceFulfillPromise(entry.instantiate, entry); +} + +function commitInstantiated(entry, optionalInstance, source) +{ + // https://whatwg.github.io/loader/#commit-instantiated + + "use strict"; + + var moduleRecord = this.instantiation(optionalInstance, source, entry); + + // FIXME: Described in the draft, + // 4. Fulfill entry.[[Instantiate]] with instance. + // But, instantiate promise should be fulfilled with the entry. + // We remove this statement because instantiate promise will be + // fulfilled without this "force fulfill" operation. + // https://github.com/whatwg/loader/pull/67 + + var dependencies = []; + var dependenciesMap = moduleRecord.dependenciesMap; + moduleRecord.registryEntry = entry; + var requestedModules = this.requestedModules(moduleRecord); + for (var i = 0, length = requestedModules.length; i < length; ++i) { + var depKey = requestedModules[i]; + var pair = { + key: depKey, + value: @undefined + }; + dependencies.@push(pair); + dependenciesMap.@set(depKey, pair); + } + entry.dependencies = dependencies; + entry.dependenciesMap = dependenciesMap; + entry.module = moduleRecord; + this.setStateToMax(entry, @ModuleSatisfy); +} + +function instantiation(result, source, entry) +{ + // https://whatwg.github.io/loader/#instantiation + // FIXME: Current implementation does not support optionalInstance. + // https://bugs.webkit.org/show_bug.cgi?id=148171 + + "use strict"; + + return this.parseModule(entry.key, source); +} + +// Loader. + +function requestFetch(key, initiator) +{ + // https://whatwg.github.io/loader/#request-fetch + + "use strict"; + + var entry = this.ensureRegistered(key); + if (entry.state > @ModuleLink) { + var deferred = @newPromiseCapability(@InternalPromise); + deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); + return deferred.@promise; + } + + if (entry.fetch) + return entry.fetch; + + // Hook point. + // 2. Loader.fetch + // https://whatwg.github.io/loader/#browser-fetch + // Take the key and fetch the resource actually. + // For example, JavaScriptCore shell can provide the hook fetching the resource + // from the local file system. + var fetchPromise = this.fetch(key, initiator).then((payload) => { + this.setStateToMax(entry, @ModuleTranslate); + return payload; + }); + entry.fetch = fetchPromise; + return fetchPromise; +} + +function requestTranslate(key, initiator) +{ + // https://whatwg.github.io/loader/#request-translate + + "use strict"; + + var entry = this.ensureRegistered(key); + if (entry.state > @ModuleLink) { + var deferred = @newPromiseCapability(@InternalPromise); + deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); + return deferred.@promise; + } + + if (entry.translate) + return entry.translate; + + var translatePromise = this.requestFetch(key, initiator).then((payload) => { + // Hook point. + // 3. Loader.translate + // https://whatwg.github.io/loader/#browser-translate + // Take the key and the fetched source code and translate it to the ES6 source code. + // Typically it is used by the transpilers. + return this.translate(key, payload, initiator).then((source) => { + this.setStateToMax(entry, @ModuleInstantiate); + return source; + }); + }); + entry.translate = translatePromise; + return translatePromise; +} + +function requestInstantiate(key, initiator) +{ + // https://whatwg.github.io/loader/#request-instantiate + + "use strict"; + + var entry = this.ensureRegistered(key); + if (entry.state > @ModuleLink) { + var deferred = @newPromiseCapability(@InternalPromise); + deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); + return deferred.@promise; + } + + if (entry.instantiate) + return entry.instantiate; + + var instantiatePromise = this.requestTranslate(key, initiator).then((source) => { + // Hook point. + // 4. Loader.instantiate + // https://whatwg.github.io/loader/#browser-instantiate + // Take the key and the translated source code, and instantiate the module record + // by parsing the module source code. + // It has the chance to provide the optional module instance that is different from + // the ordinary one. + return this.instantiate(key, source, initiator).then((optionalInstance) => { + this.commitInstantiated(entry, optionalInstance, source); + return entry; + }); + }); + entry.instantiate = instantiatePromise; + return instantiatePromise; +} + +function requestSatisfy(key, initiator) +{ + // https://whatwg.github.io/loader/#satisfy-instance + + "use strict"; + + var entry = this.ensureRegistered(key); + if (entry.state > @ModuleLink) { + var deferred = @newPromiseCapability(@InternalPromise); + deferred.@reject.@call(@undefined, new @TypeError("Requested module is already ready to be executed.")); + return deferred.@promise; + } + + if (entry.satisfy) + return entry.satisfy; + + var satisfyPromise = this.requestInstantiate(key, initiator).then((entry) => { + var depLoads = []; + for (var i = 0, length = entry.dependencies.length; i < length; ++i) { + let pair = entry.dependencies[i]; + + // Hook point. + // 1. Loader.resolve. + // https://whatwg.github.io/loader/#browser-resolve + // Take the name and resolve it to the unique identifier for the resource location. + // For example, take the "jquery" and return the URL for the resource. + var promise = this.resolve(pair.key, key, initiator).then((depKey) => { + var depEntry = this.ensureRegistered(depKey); + + // Recursive resolving. The dependencies of this entry is being resolved or already resolved. + // Stop tracing the circular dependencies. + // But to retrieve the instantiated module record correctly, + // we need to wait for the instantiation for the dependent module. + // For example, reaching here, the module is starting resolving the dependencies. + // But the module may or may not reach the instantiation phase in the loader's pipeline. + // If we wait for the Satisfy for this module, it construct the circular promise chain and + // rejected by the Promises runtime. Since only we need is the instantiated module, instead of waiting + // the Satisfy for this module, we just wait Instantiate for this. + if (depEntry.satisfy) { + return depEntry.instantiate.then((entry) => { + pair.value = entry.module; + return entry; + }); + } + + return this.requestSatisfy(depKey, initiator).then((entry) => { + pair.value = entry.module; + return entry; + }); + }); + depLoads.@push(promise); + } + + return @InternalPromise.internalAll(depLoads).then((modules) => { + this.setStateToMax(entry, @ModuleLink); + return entry; + }); + }); + + entry.satisfy = satisfyPromise; + return satisfyPromise; +} + +function requestInstantiateAll(key, initiator) +{ + // https://whatwg.github.io/loader/#request-instantiate-all + + "use strict"; + + return this.requestSatisfy(key, initiator); +} + +function requestLink(key, initiator) +{ + // https://whatwg.github.io/loader/#request-link + + "use strict"; + + var entry = this.ensureRegistered(key); + if (entry.state > @ModuleLink) { + var deferred = @newPromiseCapability(@InternalPromise); + deferred.@resolve.@call(@undefined, entry); + return deferred.@promise; + } + + return this.requestInstantiateAll(key, initiator).then((entry) => { + this.link(entry, initiator); + return entry; + }); +} + +function requestReady(key, initiator) +{ + // https://whatwg.github.io/loader/#request-ready + + "use strict"; + + return this.requestLink(key, initiator).then((entry) => { + this.moduleEvaluation(entry.module, initiator); + }); +} + +// Linking semantics. + +function link(entry, initiator) +{ + // https://whatwg.github.io/loader/#link + + "use strict"; + + // FIXME: Current implementation does not support optionalInstance. + // So Link's step 3 is skipped. + // https://bugs.webkit.org/show_bug.cgi?id=148171 + + if (entry.state === @ModuleReady) + return; + this.setStateToMax(entry, @ModuleReady); + + // Since we already have the "dependencies" field, + // we can call moduleDeclarationInstantiation with the correct order + // without constructing the dependency graph by calling dependencyGraph. + var dependencies = entry.dependencies; + for (var i = 0, length = dependencies.length; i < length; ++i) { + var pair = dependencies[i]; + this.link(pair.value.registryEntry, initiator); + } + + this.moduleDeclarationInstantiation(entry.module, initiator); +} + +// Module semantics. + +function moduleEvaluation(moduleRecord, initiator) +{ + // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation + + "use strict"; + + if (moduleRecord.evaluated) + return; + moduleRecord.evaluated = true; + + var entry = moduleRecord.registryEntry; + + // The contents of the [[RequestedModules]] is cloned into entry.dependencies. + var dependencies = entry.dependencies; + for (var i = 0, length = dependencies.length; i < length; ++i) { + var pair = dependencies[i]; + var requiredModuleRecord = pair.value; + this.moduleEvaluation(requiredModuleRecord, initiator); + } + this.evaluate(entry.key, moduleRecord, initiator); +} + +// APIs to control the module loader. + +function provide(key, stage, value) +{ + "use strict"; + + var entry = this.ensureRegistered(key); + + if (stage === @ModuleFetch) { + if (entry.state > @ModuleFetch) + throw new @TypeError("Requested module is already fetched."); + this.fulfillFetch(entry, value); + return; + } + + if (stage === @ModuleTranslate) { + if (entry.state > @ModuleTranslate) + throw new @TypeError("Requested module is already translated."); + this.fulfillFetch(entry, @undefined); + this.fulfillTranslate(entry, value); + return; + } + + if (stage === @ModuleInstantiate) { + if (entry.state > @ModuleInstantiate) + throw new @TypeError("Requested module is already instantiated."); + this.fulfillFetch(entry, @undefined); + this.fulfillTranslate(entry, value); + entry.translate.then((source) => { + this.fulfillInstantiate(entry, value, source); + }); + return; + } + + throw new @TypeError("Requested module is already ready to be executed."); +} + +function loadAndEvaluateModule(moduleName, referrer, initiator) +{ + "use strict"; + + // Loader.resolve hook point. + // resolve: moduleName => Promise(moduleKey) + // Take the name and resolve it to the unique identifier for the resource location. + // For example, take the "jquery" and return the URL for the resource. + return this.resolve(moduleName, referrer, initiator).then((key) => { + return this.requestReady(key, initiator); + }); +} + +function loadModule(moduleName, referrer, initiator) +{ + "use strict"; + + // Loader.resolve hook point. + // resolve: moduleName => Promise(moduleKey) + // Take the name and resolve it to the unique identifier for the resource location. + // For example, take the "jquery" and return the URL for the resource. + return this.resolve(moduleName, referrer, initiator).then((key) => { + return this.requestInstantiateAll(key, initiator); + }).then((entry) => { + return entry.key; + }); +} + +function linkAndEvaluateModule(key, initiator) +{ + "use strict"; + + var entry = this.ensureRegistered(key); + if (entry.state < @ModuleLink) + throw new @TypeError("Requested module is not instantiated yet."); + + this.link(entry, initiator); + return this.moduleEvaluation(entry.module, initiator); +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/NumberConstructor.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/NumberConstructor.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/NumberConstructor.js 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/NumberConstructor.js 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +function isFinite(value) +{ + "use strict"; + + if (typeof value !== "number") + return false; + + // Return false if value is |NaN|. + if (value !== value) + return false; + + return value !== @Infinity && value !== -@Infinity; +} + +function isNaN(value) +{ + "use strict"; + + return value !== value; +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/NumberPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/NumberPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/NumberPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/NumberPrototype.js 2016-09-16 09:56:47.000000000 +0000 @@ -34,9 +34,7 @@ // 1. Let x be thisNumberValue(this value). // 2. ReturnIfAbrupt(x). - var number = this; - if (!(typeof number === "number" || number instanceof @Number)) - throw new @TypeError("Number.prototype.toLocaleString called on incompatible " + typeof number); + var number = @thisNumberValue.@call(this); // 3. Let numberFormat be Construct(%NumberFormat%, «locales, options»). // 4. ReturnIfAbrupt(numberFormat). diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ObjectConstructor.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ObjectConstructor.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ObjectConstructor.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ObjectConstructor.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,4 +1,5 @@ /* + * Copyright (C) 2016 Oleksandr Skachkov . * Copyright (C) 2015 Jordan Harband. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,6 +24,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +@globalPrivate +function enumerableOwnProperties(object, kind) +{ + "use strict"; + + const obj = @Object(object); + const ownKeys = @Reflect.@ownKeys(obj); + const properties = []; + for (let i = 0, keysLength = ownKeys.length; i < keysLength; ++i) { + let nextKey = ownKeys[i]; + if (typeof nextKey === 'string') { + let descriptor = @Reflect.@getOwnPropertyDescriptor(obj, nextKey); + if (descriptor !== @undefined && descriptor.enumerable) { + if (kind === @iterationKindValue) + properties.@push(obj[nextKey]); + else if (kind === @iterationKindKeyValue) + properties.@push([nextKey, obj[nextKey]]); + } + } + } + + return properties; +} + +function values(object) +{ + "use strict"; + + if (object == null) + throw new @TypeError("Object.values requires that input parameter not be null or undefined"); + + return @enumerableOwnProperties(object, @iterationKindValue); +} + +function entries(object) +{ + "use strict"; + + if (object == null) + throw new @TypeError("Object.entries requires that input parameter not be null or undefined"); + + return @enumerableOwnProperties(object, @iterationKindKeyValue); +} + function assign(target/*[*/, /*...*/sources/*] */) { "use strict"; @@ -30,15 +75,17 @@ if (target == null) throw new @TypeError("can't convert " + target + " to object"); - var objTarget = @Object(target); - for (var s = 1, argumentsLength = arguments.length; s < argumentsLength; ++s) { - var nextSource = arguments[s]; + let objTarget = @Object(target); + for (let s = 1, argumentsLength = arguments.length; s < argumentsLength; ++s) { + let nextSource = arguments[s]; if (nextSource != null) { - var from = @Object(nextSource); - var keys = @ownEnumerablePropertyKeys(from); - for (var i = 0, keysLength = keys.length; i < keysLength; ++i) { - var nextKey = keys[i]; - objTarget[nextKey] = from[nextKey]; + let from = @Object(nextSource); + let keys = @Reflect.@ownKeys(from); + for (let i = 0, keysLength = keys.length; i < keysLength; ++i) { + let nextKey = keys[i]; + let descriptor = @Reflect.@getOwnPropertyDescriptor(from, nextKey); + if (descriptor !== @undefined && descriptor.enumerable) + objTarget[nextKey] = from[nextKey]; } } } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/PromiseConstructor.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/PromiseConstructor.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/PromiseConstructor.js 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/PromiseConstructor.js 2016-11-03 07:04:20.000000000 +0000 @@ -30,11 +30,7 @@ if (!@isObject(this)) throw new @TypeError("|this| is not a object"); - // FIXME: Fix this code when @@species well-known symbol is landed. - // https://bugs.webkit.org/show_bug.cgi?id=146624 - var constructor = this; - - var promiseCapability = @newPromiseCapability(constructor); + var promiseCapability = @newPromiseCapability(this); var values = []; var index = 0; @@ -62,7 +58,7 @@ try { for (var value of iterable) { @putByValDirect(values, index, @undefined); - var nextPromise = constructor.resolve(value); + var nextPromise = this.resolve(value); var resolveElement = newResolveElement(index); ++remainingElementsCount; nextPromise.then(resolveElement, promiseCapability.@reject); @@ -86,15 +82,11 @@ if (!@isObject(this)) throw new @TypeError("|this| is not a object"); - // FIXME: Fix this code when @@species well-known symbol is landed. - // https://bugs.webkit.org/show_bug.cgi?id=146624 - var constructor = this; - - var promiseCapability = @newPromiseCapability(constructor); + var promiseCapability = @newPromiseCapability(this); try { for (var value of iterable) { - var nextPromise = constructor.resolve(value); + var nextPromise = this.resolve(value); nextPromise.then(promiseCapability.@resolve, promiseCapability.@reject); } } catch (error) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/PromiseOperations.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/PromiseOperations.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/PromiseOperations.js 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/PromiseOperations.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Yusuke Suzuki . + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,6 +26,7 @@ // @internal +@globalPrivate function isPromise(promise) { "use strict"; @@ -32,6 +34,7 @@ return @isObject(promise) && !!promise.@promiseState; } +@globalPrivate function newPromiseReaction(capability, handler) { "use strict"; @@ -42,12 +45,12 @@ }; } +@globalPrivate function newPromiseCapability(constructor) { "use strict"; - // FIXME: Check isConstructor(constructor). - if (typeof constructor !== "function") + if (!@isConstructor(constructor)) throw new @TypeError("promise capability requires a constructor function"); var promiseCapability = { @@ -80,6 +83,7 @@ return promiseCapability; } +@globalPrivate function triggerPromiseReactions(reactions, argument) { "use strict"; @@ -88,6 +92,7 @@ @enqueueJob(@promiseReactionJob, [reactions[index], argument]); } +@globalPrivate function rejectPromise(promise, reason) { "use strict"; @@ -103,6 +108,7 @@ @triggerPromiseReactions(reactions, reason); } +@globalPrivate function fulfillPromise(promise, value) { "use strict"; @@ -118,6 +124,7 @@ @triggerPromiseReactions(reactions, value); } +@globalPrivate function createResolvingFunctions(promise) { "use strict"; @@ -164,6 +171,7 @@ }; } +@globalPrivate function promiseReactionJob(reaction, argument) { "use strict"; @@ -180,6 +188,7 @@ return promiseCapability.@resolve.@call(@undefined, result); } +@globalPrivate function promiseResolveThenableJob(promiseToResolve, thenable, then) { "use strict"; @@ -193,6 +202,7 @@ } } +@globalPrivate function initializePromise(executor) { "use strict"; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/PromisePrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/PromisePrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/PromisePrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/PromisePrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,9 +37,7 @@ if (!@isPromise(this)) throw new @TypeError("|this| is not a object"); - // FIXME: Fix this code when @@species well-known symbol is landed. - // https://bugs.webkit.org/show_bug.cgi?id=146624 - var constructor = this.constructor; + var constructor = @speciesConstructor(this, @Promise); var resultCapability = @newPromiseCapability(constructor); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ReflectObject.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ReflectObject.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/ReflectObject.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/ReflectObject.js 2016-11-03 07:04:20.000000000 +0000 @@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// http://www.ecma-international.org/ecma-262/6.0/#sec-reflect.apply +// https://tc39.github.io/ecma262/#sec-reflect.apply function apply(target, thisArgument, argumentsList) { "use strict"; @@ -37,7 +37,7 @@ return target.@apply(thisArgument, argumentsList); } -// http://www.ecma-international.org/ecma-262/6.0/#sec-reflect.deleteproperty +// https://tc39.github.io/ecma262/#sec-reflect.deleteproperty function deleteProperty(target, propertyKey) { // Intentionally keep the code the sloppy mode to suppress the TypeError @@ -49,7 +49,7 @@ return delete target[propertyKey]; } -// http://www.ecma-international.org/ecma-262/6.0/#sec-reflect.has +// https://tc39.github.io/ecma262/#sec-reflect.has function has(target, propertyKey) { "use strict"; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/RegExpPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/RegExpPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/RegExpPrototype.js 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/RegExpPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,529 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@globalPrivate +function advanceStringIndex(string, index, unicode) +{ + // This function implements AdvanceStringIndex described in ES6 21.2.5.2.3. + "use strict"; + + if (!unicode) + return index + 1; + + if (index + 1 >= string.length) + return index + 1; + + let first = string.@charCodeAt(index); + if (first < 0xD800 || first > 0xDBFF) + return index + 1; + + let second = string.@charCodeAt(index + 1); + if (second < 0xDC00 || second > 0xDFFF) + return index + 1; + + return index + 2; +} + +@globalPrivate +function regExpExec(regexp, str) +{ + "use strict"; + + let exec = regexp.exec; + let builtinExec = @regExpBuiltinExec; + if (exec !== builtinExec && typeof exec === "function") { + let result = exec.@call(regexp, str); + if (result !== null && !@isObject(result)) + throw new @TypeError("The result of a RegExp exec must be null or an object"); + return result; + } + return builtinExec.@call(regexp, str); +} + +@globalPrivate +function hasObservableSideEffectsForRegExpMatch(regexp) { + // This is accessed by the RegExpExec internal function. + let regexpExec = @tryGetById(regexp, "exec"); + if (regexpExec !== @regExpBuiltinExec) + return true; + + let regexpGlobal = @tryGetById(regexp, "global"); + if (regexpGlobal !== @regExpProtoGlobalGetter) + return true; + let regexpUnicode = @tryGetById(regexp, "unicode"); + if (regexpUnicode !== @regExpProtoUnicodeGetter) + return true; + + return !@isRegExpObject(regexp); +} + +function match(strArg) +{ + "use strict"; + + if (!@isObject(this)) + throw new @TypeError("RegExp.prototype.@@match requires that |this| be an Object"); + + let regexp = this; + + // Check for observable side effects and call the fast path if there aren't any. + if (!@hasObservableSideEffectsForRegExpMatch(regexp)) + return @regExpMatchFast.@call(regexp, strArg); + + let str = @toString(strArg); + + if (!regexp.global) + return @regExpExec(regexp, str); + + let unicode = regexp.unicode; + regexp.lastIndex = 0; + let resultList = []; + + // FIXME: It would be great to implement a solution similar to what we do in + // RegExpObject::matchGlobal(). It's not clear if this is possible, since this loop has + // effects. https://bugs.webkit.org/show_bug.cgi?id=158145 + const maximumReasonableMatchSize = 100000000; + + while (true) { + let result = @regExpExec(regexp, str); + + if (result === null) { + if (resultList.length === 0) + return null; + return resultList; + } + + if (resultList.length > maximumReasonableMatchSize) + throw new @Error("Out of memory"); + + if (!@isObject(result)) + throw new @TypeError("RegExp.prototype.@@match call to RegExp.exec didn't return null or an object"); + + let resultString = @toString(result[0]); + + if (!resultString.length) + regexp.lastIndex = @advanceStringIndex(str, regexp.lastIndex, unicode); + + resultList.@push(resultString); + } +} + +function replace(strArg, replace) +{ + "use strict"; + + function getSubstitution(matched, str, position, captures, replacement) + { + "use strict"; + + let matchLength = matched.length; + let stringLength = str.length; + let tailPos = position + matchLength; + let m = captures.length; + let replacementLength = replacement.length; + let result = ""; + let lastStart = 0; + + for (let start = 0; start = replacement.indexOf("$", lastStart), start !== -1; lastStart = start) { + if (start - lastStart > 0) + result = result + replacement.substring(lastStart, start); + start++; + let ch = replacement.charAt(start); + if (ch === "") + result = result + "$"; + else { + switch (ch) + { + case "$": + result = result + "$"; + start++; + break; + case "&": + result = result + matched; + start++; + break; + case "`": + if (position > 0) + result = result + str.substring(0, position); + start++; + break; + case "'": + if (tailPos < stringLength) + result = result + str.substring(tailPos); + start++; + break; + default: + let chCode = ch.charCodeAt(0); + if (chCode >= 0x30 && chCode <= 0x39) { + start++; + let n = chCode - 0x30; + if (n > m) + break; + if (start < replacementLength) { + let nextChCode = replacement.charCodeAt(start); + if (nextChCode >= 0x30 && nextChCode <= 0x39) { + let nn = 10 * n + nextChCode - 0x30; + if (nn <= m) { + n = nn; + start++; + } + } + } + + if (n == 0) + break; + + if (captures[n] != @undefined) + result = result + captures[n]; + } else + result = result + "$"; + break; + } + } + } + + return result + replacement.substring(lastStart); + } + + if (!@isObject(this)) + throw new @TypeError("RegExp.prototype.@@replace requires that |this| be an Object"); + + let regexp = this; + + let str = @toString(strArg); + let stringLength = str.length; + let functionalReplace = typeof replace === 'function'; + + if (!functionalReplace) + replace = @toString(replace); + + let global = regexp.global; + let unicode = false; + + if (global) { + unicode = regexp.unicode; + regexp.lastIndex = 0; + } + + let resultList = []; + let result; + let done = false; + while (!done) { + result = @regExpExec(regexp, str); + + if (result === null) + done = true; + else { + resultList.@push(result); + if (!global) + done = true; + else { + let matchStr = @toString(result[0]); + + if (!matchStr.length) + regexp.lastIndex = @advanceStringIndex(str, regexp.lastIndex, unicode); + } + } + } + + let accumulatedResult = ""; + let nextSourcePosition = 0; + let lastPosition = 0; + + for (result of resultList) { + let nCaptures = result.length - 1; + if (nCaptures < 0) + nCaptures = 0; + let matched = @toString(result[0]); + let matchLength = matched.length; + let position = result.index; + position = (position > stringLength) ? stringLength : position; + position = (position < 0) ? 0 : position; + + let captures = []; + for (let n = 1; n <= nCaptures; n++) { + let capN = result[n]; + if (capN !== @undefined) + capN = @toString(capN); + captures[n] = capN; + } + + let replacement; + + if (functionalReplace) { + let replacerArgs = [ matched ].concat(captures.slice(1)); + replacerArgs.@push(position); + replacerArgs.@push(str); + + let replValue = replace.@apply(@undefined, replacerArgs); + replacement = @toString(replValue); + } else + replacement = getSubstitution(matched, str, position, captures, replace); + + if (position >= nextSourcePosition && position >= lastPosition) { + accumulatedResult = accumulatedResult + str.substring(nextSourcePosition, position) + replacement; + nextSourcePosition = position + matchLength; + lastPosition = position; + } + } + + if (nextSourcePosition >= stringLength) + return accumulatedResult; + + return accumulatedResult + str.substring(nextSourcePosition); +} + +// 21.2.5.9 RegExp.prototype[@@search] (string) +function search(strArg) +{ + "use strict"; + + let regexp = this; + + // Check for observable side effects and call the fast path if there aren't any. + if (@isRegExpObject(regexp) && @tryGetById(regexp, "exec") === @regExpBuiltinExec) + return @regExpSearchFast.@call(regexp, strArg); + + // 1. Let rx be the this value. + // 2. If Type(rx) is not Object, throw a TypeError exception. + if (!@isObject(this)) + throw new @TypeError("RegExp.prototype.@@search requires that |this| be an Object"); + + // 3. Let S be ? ToString(string). + let str = @toString(strArg) + + // 4. Let previousLastIndex be ? Get(rx, "lastIndex"). + let previousLastIndex = regexp.lastIndex; + // 5. Perform ? Set(rx, "lastIndex", 0, true). + regexp.lastIndex = 0; + // 6. Let result be ? RegExpExec(rx, S). + let result = @regExpExec(regexp, str); + // 7. Perform ? Set(rx, "lastIndex", previousLastIndex, true). + regexp.lastIndex = previousLastIndex; + // 8. If result is null, return -1. + if (result === null) + return -1; + // 9. Return ? Get(result, "index"). + return result.index; +} + +@globalPrivate +function hasObservableSideEffectsForRegExpSplit(regexp) { + // This is accessed by the RegExpExec internal function. + let regexpExec = @tryGetById(regexp, "exec"); + if (regexpExec !== @regExpBuiltinExec) + return true; + + // This is accessed by step 5 below. + let regexpFlags = @tryGetById(regexp, "flags"); + if (regexpFlags !== @regExpProtoFlagsGetter) + return true; + + // These are accessed by the builtin flags getter. + let regexpGlobal = @tryGetById(regexp, "global"); + if (regexpGlobal !== @regExpProtoGlobalGetter) + return true; + let regexpIgnoreCase = @tryGetById(regexp, "ignoreCase"); + if (regexpIgnoreCase !== @regExpProtoIgnoreCaseGetter) + return true; + let regexpMultiline = @tryGetById(regexp, "multiline"); + if (regexpMultiline !== @regExpProtoMultilineGetter) + return true; + let regexpSticky = @tryGetById(regexp, "sticky"); + if (regexpSticky !== @regExpProtoStickyGetter) + return true; + let regexpUnicode = @tryGetById(regexp, "unicode"); + if (regexpUnicode !== @regExpProtoUnicodeGetter) + return true; + + // This is accessed by the RegExp species constructor. + let regexpSource = @tryGetById(regexp, "source"); + if (regexpSource !== @regExpProtoSourceGetter) + return true; + + return !@isRegExpObject(regexp); +} + +// ES 21.2.5.11 RegExp.prototype[@@split](string, limit) +function split(string, limit) +{ + "use strict"; + + // 1. Let rx be the this value. + // 2. If Type(rx) is not Object, throw a TypeError exception. + if (!@isObject(this)) + throw new @TypeError("RegExp.prototype.@@split requires that |this| be an Object"); + let regexp = this; + + // 3. Let S be ? ToString(string). + let str = @toString(string); + + // 4. Let C be ? SpeciesConstructor(rx, %RegExp%). + let speciesConstructor = @speciesConstructor(regexp, @RegExp); + + if (speciesConstructor === @RegExp && !@hasObservableSideEffectsForRegExpSplit(regexp)) + return @regExpSplitFast.@call(regexp, str, limit); + + // 5. Let flags be ? ToString(? Get(rx, "flags")). + let flags = @toString(regexp.flags); + + // 6. If flags contains "u", let unicodeMatching be true. + // 7. Else, let unicodeMatching be false. + let unicodeMatching = @stringIncludesInternal.@call(flags, "u"); + // 8. If flags contains "y", let newFlags be flags. + // 9. Else, let newFlags be the string that is the concatenation of flags and "y". + let newFlags = @stringIncludesInternal.@call(flags, "y") ? flags : flags + "y"; + + // 10. Let splitter be ? Construct(C, « rx, newFlags »). + let splitter = new speciesConstructor(regexp, newFlags); + + // We need to check again for RegExp subclasses that will fail the speciesConstructor test + // but can still use the fast path after we invoke the constructor above. + if (!@hasObservableSideEffectsForRegExpSplit(splitter)) + return @regExpSplitFast.@call(splitter, str, limit); + + // 11. Let A be ArrayCreate(0). + // 12. Let lengthA be 0. + let result = []; + + // 13. If limit is undefined, let lim be 2^32-1; else let lim be ? ToUint32(limit). + limit = (limit === @undefined) ? 0xffffffff : limit >>> 0; + + // 16. If lim = 0, return A. + if (!limit) + return result; + + // 14. [Defered from above] Let size be the number of elements in S. + let size = str.length; + + // 17. If size = 0, then + if (!size) { + // a. Let z be ? RegExpExec(splitter, S). + let z = @regExpExec(splitter, str); + // b. If z is not null, return A. + if (z != null) + return result; + // c. Perform ! CreateDataProperty(A, "0", S). + @putByValDirect(result, 0, str); + // d. Return A. + return result; + } + + // 15. [Defered from above] Let p be 0. + let position = 0; + // 18. Let q be p. + let matchPosition = 0; + + // 19. Repeat, while q < size + while (matchPosition < size) { + // a. Perform ? Set(splitter, "lastIndex", q, true). + splitter.lastIndex = matchPosition; + // b. Let z be ? RegExpExec(splitter, S). + let matches = @regExpExec(splitter, str); + // c. If z is null, let q be AdvanceStringIndex(S, q, unicodeMatching). + if (matches === null) + matchPosition = @advanceStringIndex(str, matchPosition, unicodeMatching); + // d. Else z is not null, + else { + // i. Let e be ? ToLength(? Get(splitter, "lastIndex")). + let endPosition = @toLength(splitter.lastIndex); + // ii. Let e be min(e, size). + endPosition = (endPosition <= size) ? endPosition : size; + // iii. If e = p, let q be AdvanceStringIndex(S, q, unicodeMatching). + if (endPosition === position) + matchPosition = @advanceStringIndex(str, matchPosition, unicodeMatching); + // iv. Else e != p, + else { + // 1. Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through q (exclusive). + let subStr = @stringSubstrInternal.@call(str, position, matchPosition - position); + // 2. Perform ! CreateDataProperty(A, ! ToString(lengthA), T). + // 3. Let lengthA be lengthA + 1. + @putByValDirect(result, result.length, subStr); + // 4. If lengthA = lim, return A. + if (result.length == limit) + return result; + + // 5. Let p be e. + position = endPosition; + // 6. Let numberOfCaptures be ? ToLength(? Get(z, "length")). + // 7. Let numberOfCaptures be max(numberOfCaptures-1, 0). + let numberOfCaptures = matches.length > 1 ? matches.length - 1 : 0; + + // 8. Let i be 1. + let i = 1; + // 9. Repeat, while i <= numberOfCaptures, + while (i <= numberOfCaptures) { + // a. Let nextCapture be ? Get(z, ! ToString(i)). + let nextCapture = matches[i]; + // b. Perform ! CreateDataProperty(A, ! ToString(lengthA), nextCapture). + // d. Let lengthA be lengthA + 1. + @putByValDirect(result, result.length, nextCapture); + // e. If lengthA = lim, return A. + if (result.length == limit) + return result; + // c. Let i be i + 1. + i++; + } + // 10. Let q be p. + matchPosition = position; + } + } + } + // 20. Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through size (exclusive). + let remainingStr = @stringSubstrInternal.@call(str, position, size); + // 21. Perform ! CreateDataProperty(A, ! ToString(lengthA), T). + @putByValDirect(result, result.length, remainingStr); + // 22. Return A. + return result; +} + +// ES 21.2.5.13 RegExp.prototype.test(string) +@intrinsic=RegExpTestIntrinsic +function test(strArg) +{ + "use strict"; + + let regexp = this; + + // Check for observable side effects and call the fast path if there aren't any. + if (@isRegExpObject(regexp) && @tryGetById(regexp, "exec") === @regExpBuiltinExec) + return @regExpTestFast.@call(regexp, strArg); + + // 1. Let R be the this value. + // 2. If Type(R) is not Object, throw a TypeError exception. + if (!@isObject(regexp)) + throw new @TypeError("RegExp.prototype.test requires that |this| be an Object"); + + // 3. Let string be ? ToString(S). + let str = @toString(strArg); + + // 4. Let match be ? RegExpExec(R, string). + let match = @regExpExec(regexp, str); + + // 5. If match is not null, return true; else return false. + if (match !== null) + return true; + return false; +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/StringPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/StringPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/StringPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/StringPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,6 +1,7 @@ /* * Copyright (C) 2015 Andy VanWagoner . * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,8 +25,216 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// @conditional=ENABLE(INTL) +function match(regexp) +{ + "use strict"; + + if (this == null) + throw new @TypeError("String.prototype.match requires that |this| not be null or undefined"); + + if (regexp != null) { + var matcher = regexp.@matchSymbol; + if (matcher != @undefined) + return matcher.@call(regexp, this); + } + + let thisString = @toString(this); + let createdRegExp = @regExpCreate(regexp, @undefined); + return createdRegExp.@matchSymbol(thisString); +} + +@globalPrivate +function repeatSlowPath(string, count) +{ + "use strict"; + + // Return an empty string. + if (count === 0 || string.length === 0) + return ""; + + // Return the original string. + if (count === 1) + return string; + + if (string.length * count > @MAX_STRING_LENGTH) + throw new @Error("Out of memory"); + + // Bit operation onto |count| is safe because |count| should be within Int32 range, + // Repeat log N times to generate the repeated string rope. + var result = ""; + var operand = string; + while (true) { + if (count & 1) + result += operand; + count >>= 1; + if (!count) + return result; + operand += operand; + } +} + +@globalPrivate +function repeatCharactersSlowPath(string, count) +{ + "use strict"; + var repeatCount = (count / string.length) | 0; + var remainingCharacters = count - repeatCount * string.length; + var result = ""; + var operand = string; + // Bit operation onto |repeatCount| is safe because |repeatCount| should be within Int32 range, + // Repeat log N times to generate the repeated string rope. + while (true) { + if (repeatCount & 1) + result += operand; + repeatCount >>= 1; + if (!repeatCount) + break; + operand += operand; + } + if (remainingCharacters) + result += @stringSubstrInternal.@call(string, 0, remainingCharacters); + return result; +} + + +function repeat(count) +{ + "use strict"; + + if (this == null) + throw new @TypeError("String.prototype.repeat requires that |this| not be null or undefined"); + + var string = @toString(this); + count = @toInteger(count); + + if (count < 0 || count === @Infinity) + throw new @RangeError("String.prototype.repeat argument must be greater than or equal to 0 and not be Infinity"); + + if (string.length === 1) { + var result = @repeatCharacter(string, count); + if (result !== null) + return result; + } + + return @repeatSlowPath(string, count); +} + +function padStart(maxLength/*, fillString*/) +{ + "use strict"; + + if (this == null) + throw new @TypeError("String.prototype.padStart requires that |this| not be null or undefined"); + + var string = @toString(this); + maxLength = @toLength(maxLength); + + var stringLength = string.length; + if (maxLength <= stringLength) + return string; + + var filler; + var fillString = arguments[1]; + if (fillString === @undefined) + filler = " "; + else { + filler = @toString(fillString); + if (filler === "") + return string; + } + if (maxLength > @MAX_STRING_LENGTH) + throw new @Error("Out of memory"); + + var fillLength = maxLength - stringLength; + var truncatedStringFiller; + + if (filler.length === 1) + truncatedStringFiller = @repeatCharacter(filler, fillLength); + else + truncatedStringFiller = @repeatCharactersSlowPath(filler, fillLength); + return truncatedStringFiller + string; +} + +function padEnd(maxLength/*, fillString*/) +{ + "use strict"; + + if (this == null) + throw new @TypeError("String.prototype.padEnd requires that |this| not be null or undefined"); + + var string = @toString(this); + maxLength = @toLength(maxLength); + + var stringLength = string.length; + if (maxLength <= stringLength) + return string; + + var filler; + var fillString = arguments[1]; + if (fillString === @undefined) + filler = " "; + else { + filler = @toString(fillString); + if (filler === "") + return string; + } + + if (maxLength > @MAX_STRING_LENGTH) + throw new @Error("Out of memory"); + + var fillLength = maxLength - stringLength; + var truncatedStringFiller; + + if (filler.length === 1) + truncatedStringFiller = @repeatCharacter(filler, fillLength); + else + truncatedStringFiller = @repeatCharactersSlowPath(filler, fillLength); + return string + truncatedStringFiller; +} + +@globalPrivate +function hasObservableSideEffectsForStringReplace(regexp, replacer) { + if (replacer !== @regExpPrototypeSymbolReplace) + return true; + + let regexpExec = @tryGetById(regexp, "exec"); + if (regexpExec !== @regExpBuiltinExec) + return true; + + let regexpGlobal = @tryGetById(regexp, "global"); + if (regexpGlobal !== @regExpProtoGlobalGetter) + return true; + + let regexpUnicode = @tryGetById(regexp, "unicode"); + if (regexpUnicode !== @regExpProtoUnicodeGetter) + return true; + + return !@isRegExpObject(regexp); +} + +@intrinsic=StringPrototypeReplaceIntrinsic +function replace(search, replace) +{ + "use strict"; + + if (this == null) + throw new @TypeError("String.prototype.replace requires that |this| not be null or undefined"); + + if (search != null) { + let replacer = search.@replaceSymbol; + if (replacer !== @undefined) { + if (!@hasObservableSideEffectsForStringReplace(search, replacer)) + return @toString(this).@replaceUsingRegExp(search, replace); + return replacer.@call(search, this, replace); + } + } + + let thisString = @toString(this); + let searchString = @toString(search); + return thisString.@replaceUsingStringSearch(searchString, replace); +} + function localeCompare(that/*, locales, options */) { "use strict"; @@ -34,11 +243,8 @@ // http://ecma-international.org/publications/standards/Ecma-402.htm // 1. Let O be RequireObjectCoercible(this value). - if (this === null) - throw new @TypeError("String.prototype.localeCompare requires that |this| not be null"); - - if (this === @undefined) - throw new @TypeError("String.prototype.localeCompare requires that |this| not be undefined"); + if (this == null) + throw new @TypeError("String.prototype.localeCompare requires that |this| not be null or undefined"); // 2. Let S be ToString(O). // 3. ReturnIfAbrupt(S). @@ -64,19 +270,32 @@ { "use strict"; - if (this == null) { - if (this === null) - throw new @TypeError("String.prototype.search requires that |this| not be null"); - throw new @TypeError("String.prototype.search requires that |this| not be undefined"); - } + if (this == null) + throw new @TypeError("String.prototype.search requires that |this| not be null or undefined"); if (regexp != null) { - var searcher = regexp[@symbolSearch]; - if (searcher !== @undefined) + var searcher = regexp.@searchSymbol; + if (searcher != @undefined) return searcher.@call(regexp, this); } var thisString = @toString(this); - var createdRegExp = new @RegExp(regexp, @undefined); - return createdRegExp[@symbolSearch](thisString); + var createdRegExp = @regExpCreate(regexp, @undefined); + return createdRegExp.@searchSymbol(thisString); +} + +function split(separator, limit) +{ + "use strict"; + + if (this == null) + throw new @TypeError("String.prototype.split requires that |this| not be null or undefined"); + + if (separator != null) { + var splitter = separator.@splitSymbol; + if (splitter != @undefined) + return splitter.@call(separator, this, limit); + } + + return @stringSplitFast.@call(this, separator, limit); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/TypedArrayConstructor.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/TypedArrayConstructor.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/TypedArrayConstructor.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/TypedArrayConstructor.js 2016-11-03 07:04:20.000000000 +0000 @@ -34,7 +34,7 @@ let len = arguments.length; let constructFunction = this.@allocateTypedArray; if (constructFunction === @undefined) - throw new @TypeError("TypedArray.from requires its this argument to subclass a TypedArray constructor"); + throw new @TypeError("TypedArray.of requires its this argument to subclass a TypedArray constructor"); let result = constructFunction(len); @@ -63,7 +63,7 @@ if (items == null) throw new @TypeError("TypedArray.from requires an array-like object - not null or undefined"); - let iteratorMethod = items[@symbolIterator]; + let iteratorMethod = items.@iteratorSymbol; if (iteratorMethod != null) { if (typeof iteratorMethod !== "function") throw new @TypeError("TypedArray.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function"); @@ -76,12 +76,8 @@ // Since for-of loop once more looks up the @@iterator property of a given iterable, // it could be observable if the user defines a getter for @@iterator. // To avoid this situation, we define a wrapper object that @@iterator just returns a given iterator. - let wrapper = { - [@symbolIterator]() { - return iterator; - } - }; - + let wrapper = {}; + wrapper.@iteratorSymbol = function() { return iterator; } for (let value of wrapper) { if (mapFn) @@ -126,56 +122,47 @@ return result; } -function allocateInt8Array(length) { - +function allocateInt8Array(length) +{ return new @Int8Array(length); - } -function allocateInt16Array(length) { - - return new @Int16Array(length); - +function allocateInt16Array(length) +{ + return new @Int16Array(length); } -function allocateInt32Array(length) { - - return new @Int32Array(length); - +function allocateInt32Array(length) +{ + return new @Int32Array(length); } -function allocateUint32Array(length) { - +function allocateUint32Array(length) +{ return new @Uint32Array(length); - } -function allocateUint16Array(length) { - - return new @Uint16Array(length); - +function allocateUint16Array(length) +{ + return new @Uint16Array(length); } -function allocateUint8Array(length) { - - return new @Uint8Array(length); - +function allocateUint8Array(length) +{ + return new @Uint8Array(length); } -function allocateUint8ClampedArray(length) { - +function allocateUint8ClampedArray(length) +{ return new @Uint8ClampedArray(length); - } -function allocateFloat32Array(length) { - +function allocateFloat32Array(length) +{ return new @Float32Array(length); - } -function allocateFloat64Array(length) { - +function allocateFloat64Array(length) +{ return new @Float64Array(length); - } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/TypedArrayPrototype.js webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/TypedArrayPrototype.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/builtins/TypedArrayPrototype.js 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/builtins/TypedArrayPrototype.js 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,9 +23,72 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Note that the intrisic @typedArrayLength checks the that the argument passed is a typed array +// Note that the intrisic @typedArrayLength checks that the argument passed is a typed array // and throws if it is not. + +// Typed Arrays have their own species constructor function since they need +// to look up their default constructor, which is expensive. If we used the +// normal speciesConstructor helper we would need to look up the default +// constructor every time. +@globalPrivate +function typedArraySpeciesConstructor(value) +{ + "use strict"; + let constructor = value.constructor; + if (constructor === @undefined) + return @typedArrayGetOriginalConstructor(value); + + if (!@isObject(constructor)) + throw new @TypeError("|this|.constructor is not an Object or undefined"); + + constructor = constructor.@speciesSymbol; + if (constructor == null) + return @typedArrayGetOriginalConstructor(value); + // The lack of an @isConstructor(constructor) check here is not observable because + // the first thing we will do with the value is attempt to construct the result with it. + // If any user of this function does not immediately construct the result they need to + // verify that the result is a constructor. + return constructor; +} + +@globalPrivate +function typedArrayClampArgumentToStartOrEnd(value, length, undefinedValue) +{ + "use strict"; + + if (value === @undefined) + return undefinedValue; + + let int = @toInteger(value); + if (int < 0) { + int += length; + return int < 0 ? 0 : int; + } + return int > length ? length : int; +} + +function values() +{ + "use strict"; + @typedArrayLength(this); + return new @createArrayIterator(this, "value", @arrayIteratorValueNext); +} + +function keys() +{ + "use strict"; + @typedArrayLength(this); + return new @createArrayIterator(this, "key", @arrayIteratorKeyNext); +} + +function entries() +{ + "use strict"; + @typedArrayLength(this); + return new @createArrayIterator(this, "key+value", @arrayIteratorKeyValueNext); +} + function every(callback /*, thisArg */) { "use strict"; @@ -43,6 +106,29 @@ return true; } +function fill(value /* [, start [, end]] */) +{ + "use strict"; + + let length = @typedArrayLength(this); + let start; + let end; + + if (arguments.length > 1) { + start = arguments[1]; + if (arguments.length > 2) { + end = arguments[2]; + } + } + + start = @typedArrayClampArgumentToStartOrEnd(start, length, 0); + end = @typedArrayClampArgumentToStartOrEnd(end, length, length); + + for (let i = start; i < end; i++) + this[i] = value; + return this; +} + function find(callback /* [, thisArg] */) { "use strict"; @@ -172,6 +258,23 @@ return this; } +function subarray(begin, end) +{ + "use strict"; + + if (!@isTypedArrayView(this)) + throw new @TypeError("|this| should be a typed array view"); + + let start = @toInteger(begin); + let finish; + if (end !== @undefined) + finish = @toInteger(end); + + let constructor = @typedArraySpeciesConstructor(this); + + return @typedArraySubarrayCreate.@call(this, start, finish, constructor); +} + function reduce(callback /* [, initialValue] */) { // 22.2.3.19 @@ -233,8 +336,23 @@ throw new @TypeError("TypedArray.prototype.map callback must be a function"); var thisArg = arguments.length > 1 ? arguments[1] : @undefined; - // FIXME: This should be a species constructor. - var result = new this.constructor(length); + + // Do species construction + var constructor = this.constructor; + var result; + if (constructor === @undefined) + result = new (@typedArrayGetOriginalConstructor(this))(length); + else { + var speciesConstructor = @Object(constructor).@speciesSymbol; + if (speciesConstructor === null || speciesConstructor === @undefined) + result = new (@typedArrayGetOriginalConstructor(this))(length); + else { + result = new speciesConstructor(length); + // typedArrayLength throws if it doesn't get a view. + @typedArrayLength(result); + } + } + for (var i = 0; i < length; i++) { var mappedValue = callback.@call(thisArg, this[i], i, this); result[i] = mappedValue; @@ -252,7 +370,6 @@ throw new @TypeError("TypedArray.prototype.filter callback must be a function"); var thisArg = arguments.length > 1 ? arguments[1] : @undefined; - var kept = []; for (var i = 0; i < length; i++) { @@ -261,8 +378,21 @@ kept.@push(value); } - // FIXME: This should be a species constructor. - var result = new this.constructor(kept.length); + var constructor = this.constructor; + var result; + var resultLength = kept.length; + if (constructor === @undefined) + result = new (@typedArrayGetOriginalConstructor(this))(resultLength); + else { + var speciesConstructor = @Object(constructor).@speciesSymbol; + if (speciesConstructor === null || speciesConstructor === @undefined) + result = new (@typedArrayGetOriginalConstructor(this))(resultLength); + else { + result = new speciesConstructor(resultLength); + // typedArrayLength throws if it doesn't get a view. + @typedArrayLength(result); + } + } for (var i = 0; i < kept.length; i++) result[i] = kept[i]; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -26,8 +26,7 @@ #include "config.h" #include "AdaptiveInferredPropertyValueWatchpointBase.h" -#include "JSCellInlines.h" -#include "StructureInlines.h" +#include "JSCInlines.h" namespace JSC { @@ -50,10 +49,6 @@ void AdaptiveInferredPropertyValueWatchpointBase::fire(const FireDetail& detail) { - // We need to defer GC here otherwise we might trigger a GC that could destroy the owner - // CodeBlock. In particular, this can happen when we add rare data to a structure when - // we EnsureWatchability. - DeferGCForAWhile defer(*Heap::heap(m_key.object())); // One of the watchpoints fired, but the other one didn't. Make sure that neither of them are // in any set anymore. This simplifies things by allowing us to reinstall the watchpoints // wherever from scratch. diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h 2016-11-03 07:04:20.000000000 +0000 @@ -54,13 +54,13 @@ public: StructureWatchpoint() { } protected: - virtual void fireInternal(const FireDetail&) override; + void fireInternal(const FireDetail&) override; }; class PropertyWatchpoint : public Watchpoint { public: PropertyWatchpoint() { } protected: - virtual void fireInternal(const FireDetail&) override; + void fireInternal(const FireDetail&) override; }; void fire(const FireDetail&); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ArithProfile.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ArithProfile.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ArithProfile.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ArithProfile.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ArithProfile.h" + +#include "CCallHelpers.h" +#include "JSCInlines.h" + +namespace JSC { + +#if ENABLE(JIT) +void ArithProfile::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode) +{ + if (!shouldEmitSetDouble() && !shouldEmitSetNonNumber()) + return; + + CCallHelpers::Jump isInt32 = jit.branchIfInt32(regs, mode); + CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode); + emitSetDouble(jit); + CCallHelpers::Jump done = jit.jump(); + notDouble.link(&jit); + emitSetNonNumber(jit); + done.link(&jit); + isInt32.link(&jit); +} + +bool ArithProfile::shouldEmitSetDouble() const +{ + uint32_t mask = ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble; + return (m_bits & mask) != mask; +} + +void ArithProfile::emitSetDouble(CCallHelpers& jit) +{ + if (shouldEmitSetDouble()) + jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int32Overflow | ArithProfile::Int52Overflow | ArithProfile::NegZeroDouble | ArithProfile::NonNegZeroDouble), CCallHelpers::AbsoluteAddress(addressOfBits())); +} + +bool ArithProfile::shouldEmitSetNonNumber() const +{ + uint32_t mask = ArithProfile::NonNumber; + return (m_bits & mask) != mask; +} + +void ArithProfile::emitSetNonNumber(CCallHelpers& jit) +{ + if (shouldEmitSetNonNumber()) + jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NonNumber), CCallHelpers::AbsoluteAddress(addressOfBits())); +} +#endif // ENABLE(JIT) + +} // namespace JSC + +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, const ArithProfile& profile) +{ + const char* separator = ""; + + out.print("Result:<"); + if (!profile.didObserveNonInt32()) { + out.print("Int32"); + separator = "|"; + } else { + if (profile.didObserveNegZeroDouble()) { + out.print(separator, "NegZeroDouble"); + separator = "|"; + } + if (profile.didObserveNonNegZeroDouble()) { + out.print(separator, "NonNegZeroDouble"); + separator = "|"; + } + if (profile.didObserveNonNumber()) { + out.print(separator, "NonNumber"); + separator = "|"; + } + if (profile.didObserveInt32Overflow()) { + out.print(separator, "Int32Overflow"); + separator = "|"; + } + if (profile.didObserveInt52Overflow()) { + out.print(separator, "Int52Overflow"); + separator = "|"; + } + } + if (profile.tookSpecialFastPath()) + out.print(separator, "Took special fast path."); + out.print(">"); + + out.print(" LHS ObservedType:<"); + out.print(profile.lhsObservedType()); + out.print("> RHS ObservedType:<"); + out.print(profile.rhsObservedType()); + out.print(">"); + + out.print(" LHS ResultType:<", RawPointer(bitwise_cast(static_cast(profile.lhsResultType().bits())))); + out.print("> RHS ResultType:<", RawPointer(bitwise_cast(static_cast(profile.rhsResultType().bits())))); + out.print(">"); +} + +void printInternal(PrintStream& out, const JSC::ObservedType& observedType) +{ + const char* separator = ""; + if (observedType.sawInt32()) { + out.print(separator, "Int32"); + separator = "|"; + } + if (observedType.sawNumber()) { + out.print(separator, "Number"); + separator = "|"; + } + if (observedType.sawNonNumber()) { + out.print(separator, "NonNumber"); + separator = "|"; + } +} + +} // namespace WTF diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ArithProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ArithProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ArithProfile.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ArithProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "GPRInfo.h" +#include "JSCJSValue.h" +#include "ResultType.h" +#include "TagRegistersMode.h" + +namespace JSC { + +class CCallHelpers; + +struct ObservedType { + ObservedType(uint8_t bits = TypeEmpty) + : m_bits(bits) + { } + + bool sawInt32() const { return m_bits & TypeInt32; } + bool isOnlyInt32() const { return m_bits == TypeInt32; } + bool sawNumber() const { return m_bits & TypeNumber; } + bool isOnlyNumber() const { return m_bits == TypeNumber; } + bool sawNonNumber() const { return m_bits & TypeNonNumber; } + bool isOnlyNonNumber() const { return m_bits == TypeNonNumber; } + bool isEmpty() const { return !m_bits; } + uint8_t bits() const { return m_bits; } + + ObservedType withInt32() const { return ObservedType(m_bits | TypeInt32); } + ObservedType withNumber() const { return ObservedType(m_bits | TypeNumber); } + ObservedType withNonNumber() const { return ObservedType(m_bits | TypeNonNumber); } + ObservedType withoutNonNumber() const { return ObservedType(m_bits & ~TypeNonNumber); } + + bool operator==(const ObservedType& other) const { return m_bits == other.m_bits; } + + static const uint8_t TypeEmpty = 0x0; + static const uint8_t TypeInt32 = 0x1; + static const uint8_t TypeNumber = 0x02; + static const uint8_t TypeNonNumber = 0x04; + + static const uint32_t numBitsNeeded = 3; + +private: + uint8_t m_bits; +}; + +struct ArithProfile { +private: + static const uint32_t numberOfFlagBits = 5; + static const uint32_t rhsResultTypeShift = numberOfFlagBits; + static const uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded; + static const uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded; + static const uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded; + + static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here."); + static const uint32_t clearRhsObservedTypeBitMask = static_cast(~((1 << rhsObservedTypeShift) | (1 << (rhsObservedTypeShift + 1)) | (1 << (rhsObservedTypeShift + 2)))); + static const uint32_t clearLhsObservedTypeBitMask = static_cast(~((1 << lhsObservedTypeShift) | (1 << (lhsObservedTypeShift + 1)) | (1 << (lhsObservedTypeShift + 2)))); + + static const uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1; + static const uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1; +public: + static const uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded); + static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded) <= (sizeof(uint32_t) * 8) - 1, "Should fit in a uint32_t."); + static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect."); + static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect."); + static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit."); + + ArithProfile(ResultType lhs, ResultType rhs) + { + m_bits = (lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift); + ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits()); + ASSERT(lhsObservedType().isEmpty()); + ASSERT(rhsObservedType().isEmpty()); + } + ArithProfile() { } + + static ArithProfile fromInt(uint32_t bits) + { + ArithProfile result; + result.m_bits = bits; + return result; + } + + enum ObservedResults { + NonNegZeroDouble = 1 << 0, + NegZeroDouble = 1 << 1, + NonNumber = 1 << 2, + Int32Overflow = 1 << 3, + Int52Overflow = 1 << 4, + }; + + ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); } + ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); } + + ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); } + ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); } + void setLhsObservedType(ObservedType type) + { + uint32_t bits = m_bits; + bits &= clearLhsObservedTypeBitMask; + bits |= type.bits() << lhsObservedTypeShift; + m_bits = bits; + ASSERT(lhsObservedType() == type); + } + + void setRhsObservedType(ObservedType type) + { + uint32_t bits = m_bits; + bits &= clearRhsObservedTypeBitMask; + bits |= type.bits() << rhsObservedTypeShift; + m_bits = bits; + ASSERT(rhsObservedType() == type); + } + + bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; } + + bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); } + bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); } + bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); } + bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); } + bool didObserveNonNumber() const { return hasBits(NonNumber); } + bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); } + bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); } + + void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); } + void setObservedNegZeroDouble() { setBit(NegZeroDouble); } + void setObservedNonNumber() { setBit(NonNumber); } + void setObservedInt32Overflow() { setBit(Int32Overflow); } + void setObservedInt52Overflow() { setBit(Int52Overflow); } + + void* addressOfBits() { return &m_bits; } + + void observeResult(JSValue value) + { + if (value.isInt32()) + return; + if (value.isNumber()) { + m_bits |= Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble; + return; + } + m_bits |= NonNumber; + } + + void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); } + void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); } + void lhsSawNonNumber() { setLhsObservedType(lhsObservedType().withNonNumber()); } + void rhsSawInt32() { setRhsObservedType(rhsObservedType().withInt32()); } + void rhsSawNumber() { setRhsObservedType(rhsObservedType().withNumber()); } + void rhsSawNonNumber() { setRhsObservedType(rhsObservedType().withNonNumber()); } + + void observeLHSAndRHS(JSValue lhs, JSValue rhs) + { + ArithProfile newProfile = *this; + if (lhs.isNumber()) { + if (lhs.isInt32()) + newProfile.lhsSawInt32(); + else + newProfile.lhsSawNumber(); + } else + newProfile.lhsSawNonNumber(); + + if (rhs.isNumber()) { + if (rhs.isInt32()) + newProfile.rhsSawInt32(); + else + newProfile.rhsSawNumber(); + } else + newProfile.rhsSawNonNumber(); + + m_bits = newProfile.bits(); + } + +#if ENABLE(JIT) + // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a + // double. Sets NonNumber if it sees a non-number. + void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters); + + // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble). + bool shouldEmitSetDouble() const; + void emitSetDouble(CCallHelpers&); + + // Sets NonNumber. + void emitSetNonNumber(CCallHelpers&); + bool shouldEmitSetNonNumber() const; +#endif // ENABLE(JIT) + + uint32_t bits() const { return m_bits; } + +private: + bool hasBits(int mask) const { return m_bits & mask; } + void setBit(int mask) { m_bits |= mask; } + + uint32_t m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it. +}; + +} // namespace JSC + +namespace WTF { + +void printInternal(PrintStream&, const JSC::ArithProfile&); +void printInternal(PrintStream&, const JSC::ObservedType&); + +} // namespace WTF diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ArrayProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ArrayProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ArrayProfile.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ArrayProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,7 +29,6 @@ #include "ConcurrentJITLock.h" #include "JSArray.h" #include "Structure.h" -#include #include namespace JSC { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -27,6 +27,7 @@ #include "BytecodeBasicBlock.h" #include "CodeBlock.h" +#include "InterpreterInlines.h" #include "JSCInlines.h" #include "PreciseJumpTargets.h" @@ -34,69 +35,10 @@ void BytecodeBasicBlock::shrinkToFit() { - m_bytecodeOffsets.shrinkToFit(); + m_offsets.shrinkToFit(); m_successors.shrinkToFit(); } -static bool isBranch(OpcodeID opcodeID) -{ - switch (opcodeID) { - case op_jmp: - case op_jtrue: - case op_jfalse: - case op_jeq_null: - case op_jneq_null: - case op_jneq_ptr: - case op_jless: - case op_jlesseq: - case op_jgreater: - case op_jgreatereq: - case op_jnless: - case op_jnlesseq: - case op_jngreater: - case op_jngreatereq: - case op_switch_imm: - case op_switch_char: - case op_switch_string: - case op_save: - return true; - default: - return false; - } -} - -static bool isUnconditionalBranch(OpcodeID opcodeID) -{ - switch (opcodeID) { - case op_jmp: - return true; - default: - return false; - } -} - -static bool isTerminal(OpcodeID opcodeID) -{ - switch (opcodeID) { - case op_ret: - case op_end: - return true; - default: - return false; - } -} - -static bool isThrow(OpcodeID opcodeID) -{ - switch (opcodeID) { - case op_throw: - case op_throw_static_error: - return true; - default: - return false; - } -} - static bool isJumpTarget(OpcodeID opcodeID, const Vector& jumpTargets, unsigned bytecodeOffset) { if (opcodeID == op_catch) @@ -105,15 +47,20 @@ return std::binary_search(jumpTargets.begin(), jumpTargets.end(), bytecodeOffset); } -static void linkBlocks(BytecodeBasicBlock* predecessor, BytecodeBasicBlock* successor) -{ - predecessor->addSuccessor(successor); -} - -void computeBytecodeBasicBlocks(CodeBlock* codeBlock, Vector>& basicBlocks) +template +void BytecodeBasicBlock::computeImpl(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector>& basicBlocks) { Vector jumpTargets; - computePreciseJumpTargets(codeBlock, jumpTargets); + computePreciseJumpTargets(codeBlock, instructionsBegin, instructionCount, jumpTargets); + + auto appendBlock = [&] (std::unique_ptr&& block) { + block->m_index = basicBlocks.size(); + basicBlocks.append(WTFMove(block)); + }; + + auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) { + from->addSuccessor(to); + }; // Create the entry and exit basic blocks. basicBlocks.reserveCapacity(jumpTargets.size() + 2); @@ -122,19 +69,17 @@ auto firstBlock = std::make_unique(0, 0); linkBlocks(entry.get(), firstBlock.get()); - basicBlocks.append(WTFMove(entry)); + appendBlock(WTFMove(entry)); BytecodeBasicBlock* current = firstBlock.get(); - basicBlocks.append(WTFMove(firstBlock)); + appendBlock(WTFMove(firstBlock)); auto exit = std::make_unique(BytecodeBasicBlock::ExitBlock); bool nextInstructionIsLeader = false; Interpreter* interpreter = codeBlock->vm()->interpreter; - Instruction* instructionsBegin = codeBlock->instructions().begin(); - unsigned instructionCount = codeBlock->instructions().size(); for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) { - OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); + OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); unsigned opcodeLength = opcodeLengths[opcodeID]; bool createdBlock = false; @@ -142,7 +87,7 @@ if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) { auto newBlock = std::make_unique(bytecodeOffset, opcodeLength); current = newBlock.get(); - basicBlocks.append(WTFMove(newBlock)); + appendBlock(WTFMove(newBlock)); createdBlock = true; nextInstructionIsLeader = false; bytecodeOffset += opcodeLength; @@ -156,7 +101,7 @@ continue; // Otherwise, just add to the length of the current block. - current->addBytecodeLength(opcodeLength); + current->addLength(opcodeLength); bytecodeOffset += opcodeLength; } @@ -168,13 +113,12 @@ continue; bool fallsThrough = true; - for (unsigned bytecodeOffset = block->leaderBytecodeOffset(); bytecodeOffset < block->leaderBytecodeOffset() + block->totalBytecodeLength();) { - const Instruction& currentInstruction = instructionsBegin[bytecodeOffset]; - OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction.u.opcode); + for (unsigned bytecodeOffset = block->leaderOffset(); bytecodeOffset < block->leaderOffset() + block->totalLength();) { + OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); unsigned opcodeLength = opcodeLengths[opcodeID]; // If we found a terminal bytecode, link to the exit block. if (isTerminal(opcodeID)) { - ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength()); + ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength()); linkBlocks(block, exit.get()); fallsThrough = false; break; @@ -184,8 +128,8 @@ // If there isn't one, treat this throw as a terminal. This is true even if we have a finally // block because the finally block will create its own catch, which will generate a HandlerInfo. if (isThrow(opcodeID)) { - ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength()); - HandlerInfo* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset); + ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength()); + auto* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset); fallsThrough = false; if (!handler) { linkBlocks(block, exit.get()); @@ -193,7 +137,7 @@ } for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); - if (handler->target == otherBlock->leaderBytecodeOffset()) { + if (handler->target == otherBlock->leaderOffset()) { linkBlocks(block, otherBlock); break; } @@ -203,13 +147,13 @@ // If we found a branch, link to the block(s) that we jump to. if (isBranch(opcodeID)) { - ASSERT(bytecodeOffset + opcodeLength == block->leaderBytecodeOffset() + block->totalBytecodeLength()); + ASSERT(bytecodeOffset + opcodeLength == block->leaderOffset() + block->totalLength()); Vector bytecodeOffsetsJumpedTo; - findJumpTargetsForBytecodeOffset(codeBlock, bytecodeOffset, bytecodeOffsetsJumpedTo); + findJumpTargetsForBytecodeOffset(codeBlock, instructionsBegin, bytecodeOffset, bytecodeOffsetsJumpedTo); for (unsigned i = 0; i < basicBlocks.size(); i++) { BytecodeBasicBlock* otherBlock = basicBlocks[i].get(); - if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderBytecodeOffset())) + if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset())) linkBlocks(block, otherBlock); } @@ -229,10 +173,20 @@ } } - basicBlocks.append(WTFMove(exit)); + appendBlock(WTFMove(exit)); for (auto& basicBlock : basicBlocks) basicBlock->shrinkToFit(); } +void BytecodeBasicBlock::compute(CodeBlock* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector>& basicBlocks) +{ + computeImpl(codeBlock, instructionsBegin, instructionCount, basicBlocks); +} + +void BytecodeBasicBlock::compute(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector>& basicBlocks) +{ + BytecodeBasicBlock::computeImpl(codeBlock, instructionsBegin, instructionCount, basicBlocks); +} + } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -28,13 +28,14 @@ #include #include -#include -#include #include namespace JSC { class CodeBlock; +class UnlinkedCodeBlock; +struct Instruction; +struct UnlinkedInstruction; class BytecodeBasicBlock { WTF_MAKE_FAST_ALLOCATED; @@ -44,51 +45,59 @@ BytecodeBasicBlock(SpecialBlockType); void shrinkToFit(); - bool isEntryBlock() { return !m_leaderBytecodeOffset && !m_totalBytecodeLength; } - bool isExitBlock() { return m_leaderBytecodeOffset == UINT_MAX && m_totalBytecodeLength == UINT_MAX; } + bool isEntryBlock() { return !m_leaderOffset && !m_totalLength; } + bool isExitBlock() { return m_leaderOffset == UINT_MAX && m_totalLength == UINT_MAX; } - unsigned leaderBytecodeOffset() { return m_leaderBytecodeOffset; } - unsigned totalBytecodeLength() { return m_totalBytecodeLength; } + unsigned leaderOffset() { return m_leaderOffset; } + unsigned totalLength() { return m_totalLength; } - Vector& bytecodeOffsets() { return m_bytecodeOffsets; } - void addBytecodeLength(unsigned); + const Vector& offsets() const { return m_offsets; } - Vector& successors() { return m_successors; } - void addSuccessor(BytecodeBasicBlock* block) { m_successors.append(block); } + const Vector& successors() const { return m_successors; } FastBitVector& in() { return m_in; } FastBitVector& out() { return m_out; } + unsigned index() const { return m_index; } + + static void compute(CodeBlock*, Instruction* instructionsBegin, unsigned instructionCount, Vector>&); + static void compute(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector>&); + private: - unsigned m_leaderBytecodeOffset; - unsigned m_totalBytecodeLength; + template static void computeImpl(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector>& basicBlocks); + + void addSuccessor(BytecodeBasicBlock* block) { m_successors.append(block); } + + void addLength(unsigned); - Vector m_bytecodeOffsets; + unsigned m_leaderOffset; + unsigned m_totalLength; + unsigned m_index; + + Vector m_offsets; Vector m_successors; FastBitVector m_in; FastBitVector m_out; }; -void computeBytecodeBasicBlocks(CodeBlock*, Vector>&); - inline BytecodeBasicBlock::BytecodeBasicBlock(unsigned start, unsigned length) - : m_leaderBytecodeOffset(start) - , m_totalBytecodeLength(length) + : m_leaderOffset(start) + , m_totalLength(length) { - m_bytecodeOffsets.append(m_leaderBytecodeOffset); + m_offsets.append(m_leaderOffset); } inline BytecodeBasicBlock::BytecodeBasicBlock(BytecodeBasicBlock::SpecialBlockType blockType) - : m_leaderBytecodeOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX) - , m_totalBytecodeLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX) + : m_leaderOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX) + , m_totalLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX) { } -inline void BytecodeBasicBlock::addBytecodeLength(unsigned bytecodeLength) +inline void BytecodeBasicBlock::addLength(unsigned bytecodeLength) { - m_bytecodeOffsets.append(m_leaderBytecodeOffset + m_totalBytecodeLength); - m_totalBytecodeLength += bytecodeLength; + m_offsets.append(m_leaderOffset + m_totalLength); + m_totalLength += bytecodeLength; } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeConventions.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeConventions.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeConventions.h 2013-08-03 16:10:38.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeConventions.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,7 +27,7 @@ #define BytecodeConventions_h // Register numbers used in bytecode operations have different meaning according to their ranges: -// 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see JSStack.h. +// 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame. // 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe. // 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock. static const int FirstConstantRegisterIndex = 0x40000000; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BytecodeGeneratorification.h" + +#include "BytecodeLivenessAnalysisInlines.h" +#include "BytecodeRewriter.h" +#include "BytecodeUseDef.h" +#include "IdentifierInlines.h" +#include "InterpreterInlines.h" +#include "JSCInlines.h" +#include "JSCJSValueInlines.h" +#include "JSGeneratorFunction.h" +#include "StrongInlines.h" +#include "UnlinkedCodeBlock.h" +#include + +namespace JSC { + +struct YieldData { + size_t point { 0 }; + int argument { 0 }; + FastBitVector liveness; +}; + +class BytecodeGeneratorification { +public: + typedef Vector Yields; + + BytecodeGeneratorification(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex) + : m_graph(codeBlock, instructions) + , m_generatorFrameSymbolTable(*codeBlock->vm(), generatorFrameSymbolTable) + , m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex) + { + for (BytecodeBasicBlock* block : m_graph) { + for (unsigned bytecodeOffset : block->offsets()) { + const UnlinkedInstruction* pc = &m_graph.instructions()[bytecodeOffset]; + switch (pc->u.opcode) { + case op_enter: { + m_enterPoint = bytecodeOffset; + break; + } + + case op_yield: { + unsigned liveCalleeLocalsIndex = pc[2].u.index; + if (liveCalleeLocalsIndex >= m_yields.size()) + m_yields.resize(liveCalleeLocalsIndex + 1); + YieldData& data = m_yields[liveCalleeLocalsIndex]; + data.point = bytecodeOffset; + data.argument = pc[3].u.operand; + break; + } + + default: + break; + } + } + } + } + + struct Storage { + Identifier identifier; + unsigned identifierIndex; + ScopeOffset scopeOffset; + }; + + void run(); + + BytecodeGraph& graph() { return m_graph; } + + const Yields& yields() const + { + return m_yields; + } + + Yields& yields() + { + return m_yields; + } + + unsigned enterPoint() const + { + return m_enterPoint; + } + +private: + Storage storageForGeneratorLocal(unsigned index) + { + // We assign a symbol to a register. There is one-on-one corresponding between a register and a symbol. + // By doing so, we allocate the specific storage to save the given register. + // This allow us not to save all the live registers even if the registers are not overwritten from the previous resuming time. + // It means that, the register can be retrieved even if the immediate previous op_save does not save it. + + if (m_storages.size() <= index) + m_storages.resize(index + 1); + if (Optional storage = m_storages[index]) + return *storage; + + UnlinkedCodeBlock* codeBlock = m_graph.codeBlock(); + Identifier identifier = Identifier::fromUid(PrivateName()); + unsigned identifierIndex = codeBlock->numberOfIdentifiers(); + codeBlock->addIdentifier(identifier); + ScopeOffset scopeOffset = m_generatorFrameSymbolTable->takeNextScopeOffset(NoLockingNecessary); + m_generatorFrameSymbolTable->set(NoLockingNecessary, identifier.impl(), SymbolTableEntry(VarOffset(scopeOffset))); + + Storage storage = { + identifier, + identifierIndex, + scopeOffset + }; + m_storages[index] = storage; + return storage; + } + + unsigned m_enterPoint { 0 }; + BytecodeGraph m_graph; + Vector> m_storages; + Yields m_yields; + Strong m_generatorFrameSymbolTable; + int m_generatorFrameSymbolTableIndex; +}; + +class GeneratorLivenessAnalysis : public BytecodeLivenessPropagation { +public: + GeneratorLivenessAnalysis(BytecodeGeneratorification& generatorification) + : m_generatorification(generatorification) + { + } + + template + void computeDefsForBytecodeOffset(UnlinkedCodeBlock* codeBlock, OpcodeID opcodeID, UnlinkedInstruction* instruction, FastBitVector&, const Functor& functor) + { + JSC::computeDefsForBytecodeOffset(codeBlock, opcodeID, instruction, functor); + } + + template + void computeUsesForBytecodeOffset(UnlinkedCodeBlock* codeBlock, OpcodeID opcodeID, UnlinkedInstruction* instruction, FastBitVector&, const Functor& functor) + { + JSC::computeUsesForBytecodeOffset(codeBlock, opcodeID, instruction, functor); + } + + void run() + { + // Perform modified liveness analysis to determine which locals are live at the merge points. + // This produces the conservative results for the question, "which variables should be saved and resumed?". + + runLivenessFixpoint(m_generatorification.graph()); + + for (YieldData& data : m_generatorification.yields()) + data.liveness = getLivenessInfoAtBytecodeOffset(m_generatorification.graph(), data.point + opcodeLength(op_yield)); + } + +private: + BytecodeGeneratorification& m_generatorification; +}; + +void BytecodeGeneratorification::run() +{ + // We calculate the liveness at each merge point. This gives us the information which registers should be saved and resumed conservatively. + + { + GeneratorLivenessAnalysis pass(*this); + pass.run(); + } + + UnlinkedCodeBlock* codeBlock = m_graph.codeBlock(); + BytecodeRewriter rewriter(m_graph); + + // Setup the global switch for the generator. + { + unsigned nextToEnterPoint = enterPoint() + opcodeLength(op_enter); + unsigned switchTableIndex = m_graph.codeBlock()->numberOfSwitchJumpTables(); + VirtualRegister state = virtualRegisterForArgument(static_cast(JSGeneratorFunction::GeneratorArgument::State)); + auto& jumpTable = m_graph.codeBlock()->addSwitchJumpTable(); + jumpTable.min = 0; + jumpTable.branchOffsets.resize(m_yields.size() + 1); + jumpTable.branchOffsets.fill(0); + jumpTable.add(0, nextToEnterPoint); + for (unsigned i = 0; i < m_yields.size(); ++i) + jumpTable.add(i + 1, m_yields[i].point); + + rewriter.insertFragmentBefore(nextToEnterPoint, [&](BytecodeRewriter::Fragment& fragment) { + fragment.appendInstruction(op_switch_imm, switchTableIndex, nextToEnterPoint, state.offset()); + }); + } + + for (const YieldData& data : m_yields) { + VirtualRegister scope = virtualRegisterForArgument(static_cast(JSGeneratorFunction::GeneratorArgument::Frame)); + + // Emit save sequence. + rewriter.insertFragmentBefore(data.point, [&](BytecodeRewriter::Fragment& fragment) { + data.liveness.forEachSetBit([&](size_t index) { + VirtualRegister operand = virtualRegisterForLocal(index); + Storage storage = storageForGeneratorLocal(index); + + fragment.appendInstruction( + op_put_to_scope, + scope.offset(), // scope + storage.identifierIndex, // identifier + operand.offset(), // value + GetPutInfo(DoNotThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand(), // info + m_generatorFrameSymbolTableIndex, // symbol table constant index + storage.scopeOffset.offset() // scope offset + ); + }); + + // Insert op_ret just after save sequence. + fragment.appendInstruction(op_ret, data.argument); + }); + + // Emit resume sequence. + rewriter.insertFragmentAfter(data.point, [&](BytecodeRewriter::Fragment& fragment) { + data.liveness.forEachSetBit([&](size_t index) { + VirtualRegister operand = virtualRegisterForLocal(index); + Storage storage = storageForGeneratorLocal(index); + + UnlinkedValueProfile profile = codeBlock->addValueProfile(); + fragment.appendInstruction( + op_get_from_scope, + operand.offset(), // dst + scope.offset(), // scope + storage.identifierIndex, // identifier + GetPutInfo(DoNotThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand(), // info + 0, // local scope depth + storage.scopeOffset.offset(), // scope offset + profile // profile + ); + }); + }); + + // Clip the unnecessary bytecodes. + rewriter.removeBytecode(data.point); + } + + rewriter.execute(); +} + +void performGeneratorification(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex) +{ + BytecodeGeneratorification pass(codeBlock, instructions, generatorFrameSymbolTable, generatorFrameSymbolTableIndex); + pass.run(); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "UnlinkedCodeBlock.h" + +namespace JSC { + +class SymbolTable; + +void performGeneratorification(UnlinkedCodeBlock*, UnlinkedCodeBlock::UnpackedInstructions&, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex); + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeGraph.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeGraph.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeGraph.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeGraph.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "BytecodeBasicBlock.h" +#include +#include +#include + +namespace JSC { + +class BytecodeBasicBlock; + +template +class BytecodeGraph { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(BytecodeGraph); +public: + typedef Block CodeBlock; + typedef typename Block::Instruction Instruction; + typedef Vector> BasicBlocksVector; + + typedef WTF::IndexedContainerIterator> iterator; + + inline BytecodeGraph(Block*, typename Block::UnpackedInstructions&); + + Block* codeBlock() const { return m_codeBlock; } + + typename Block::UnpackedInstructions& instructions() { return m_instructions; } + + WTF::IteratorRange basicBlocksInReverseOrder() + { + return WTF::makeIteratorRange(m_basicBlocks.rbegin(), m_basicBlocks.rend()); + } + + static bool blockContainsBytecodeOffset(BytecodeBasicBlock* block, unsigned bytecodeOffset) + { + unsigned leaderOffset = block->leaderOffset(); + return bytecodeOffset >= leaderOffset && bytecodeOffset < leaderOffset + block->totalLength(); + } + + BytecodeBasicBlock* findBasicBlockForBytecodeOffset(unsigned bytecodeOffset) + { + /* + for (unsigned i = 0; i < m_basicBlocks.size(); i++) { + if (blockContainsBytecodeOffset(m_basicBlocks[i].get(), bytecodeOffset)) + return m_basicBlocks[i].get(); + } + return 0; + */ + + std::unique_ptr* basicBlock = approximateBinarySearch, unsigned>(m_basicBlocks, m_basicBlocks.size(), bytecodeOffset, [] (std::unique_ptr* basicBlock) { return (*basicBlock)->leaderOffset(); }); + // We found the block we were looking for. + if (blockContainsBytecodeOffset((*basicBlock).get(), bytecodeOffset)) + return (*basicBlock).get(); + + // Basic block is to the left of the returned block. + if (bytecodeOffset < (*basicBlock)->leaderOffset()) { + ASSERT(basicBlock - 1 >= m_basicBlocks.data()); + ASSERT(blockContainsBytecodeOffset(basicBlock[-1].get(), bytecodeOffset)); + return basicBlock[-1].get(); + } + + // Basic block is to the right of the returned block. + ASSERT(&basicBlock[1] <= &m_basicBlocks.last()); + ASSERT(blockContainsBytecodeOffset(basicBlock[1].get(), bytecodeOffset)); + return basicBlock[1].get(); + } + + BytecodeBasicBlock* findBasicBlockWithLeaderOffset(unsigned leaderOffset) + { + return (*tryBinarySearch, unsigned>(m_basicBlocks, m_basicBlocks.size(), leaderOffset, [] (std::unique_ptr* basicBlock) { return (*basicBlock)->leaderOffset(); })).get(); + } + + unsigned size() const { return m_basicBlocks.size(); } + BytecodeBasicBlock* at(unsigned index) const { return m_basicBlocks[index].get(); } + BytecodeBasicBlock* operator[](unsigned index) const { return at(index); } + + iterator begin() const { return iterator(*this, 0); } + iterator end() const { return iterator(*this, size()); } + BytecodeBasicBlock* first() { return at(0); } + BytecodeBasicBlock* last() { return at(size() - 1); } + +private: + Block* m_codeBlock; + BasicBlocksVector m_basicBlocks; + typename Block::UnpackedInstructions& m_instructions; +}; + + +template +BytecodeGraph::BytecodeGraph(Block* codeBlock, typename Block::UnpackedInstructions& instructions) + : m_codeBlock(codeBlock) + , m_instructions(instructions) +{ + ASSERT(m_codeBlock); + BytecodeBasicBlock::compute(m_codeBlock, instructions.begin(), instructions.size(), m_basicBlocks); + ASSERT(m_basicBlocks.size()); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Yusuke Suzuki . + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,16 +26,20 @@ #include "config.h" #include "BytecodeIntrinsicRegistry.h" + +#include "ArrayIteratorPrototype.h" +#include "BuiltinNames.h" #include "BytecodeGenerator.h" -#include "JSArrayIterator.h" #include "JSCJSValueInlines.h" +#include "JSGeneratorFunction.h" +#include "JSModuleLoader.h" #include "JSPromise.h" #include "Nodes.h" #include "StrongInlines.h" namespace JSC { -#define INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET(name) m_bytecodeIntrinsicMap.add(vm.propertyNames->name##PrivateName.impl(), &BytecodeIntrinsicNode::emit_intrinsic_##name); +#define INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET(name) m_bytecodeIntrinsicMap.add(vm.propertyNames->builtinNames().name##PrivateName().impl(), &BytecodeIntrinsicNode::emit_intrinsic_##name); BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm) : m_vm(vm) @@ -44,14 +49,26 @@ JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(INITIALIZE_BYTECODE_INTRINSIC_NAMES_TO_SET) m_undefined.set(m_vm, jsUndefined()); - m_arrayIterationKindKey.set(m_vm, jsNumber(ArrayIterateKey)); - m_arrayIterationKindValue.set(m_vm, jsNumber(ArrayIterateValue)); - m_arrayIterationKindKeyValue.set(m_vm, jsNumber(ArrayIterateKeyValue)); + m_Infinity.set(m_vm, jsDoubleNumber(std::numeric_limits::infinity())); + m_iterationKindKey.set(m_vm, jsNumber(IterateKey)); + m_iterationKindValue.set(m_vm, jsNumber(IterateValue)); + m_iterationKindKeyValue.set(m_vm, jsNumber(IterateKeyValue)); + m_MAX_STRING_LENGTH.set(m_vm, jsNumber(JSString::MaxLength)); + m_MAX_SAFE_INTEGER.set(m_vm, jsDoubleNumber(maxSafeInteger())); + m_ModuleFetch.set(m_vm, jsNumber(static_cast(JSModuleLoader::Status::Fetch))); + m_ModuleTranslate.set(m_vm, jsNumber(static_cast(JSModuleLoader::Status::Translate))); + m_ModuleInstantiate.set(m_vm, jsNumber(static_cast(JSModuleLoader::Status::Instantiate))); + m_ModuleSatisfy.set(m_vm, jsNumber(static_cast(JSModuleLoader::Status::Satisfy))); + m_ModuleLink.set(m_vm, jsNumber(static_cast(JSModuleLoader::Status::Link))); + m_ModuleReady.set(m_vm, jsNumber(static_cast(JSModuleLoader::Status::Ready))); m_promiseStatePending.set(m_vm, jsNumber(static_cast(JSPromise::Status::Pending))); m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast(JSPromise::Status::Fulfilled))); m_promiseStateRejected.set(m_vm, jsNumber(static_cast(JSPromise::Status::Rejected))); - m_symbolIterator.set(m_vm, Symbol::create(m_vm, static_cast(*m_vm.propertyNames->iteratorSymbol.impl()))); - m_symbolSearch.set(m_vm, Symbol::create(m_vm, static_cast(*m_vm.propertyNames->searchSymbol.impl()))); + m_GeneratorResumeModeNormal.set(m_vm, jsNumber(static_cast(JSGeneratorFunction::GeneratorResumeMode::NormalMode))); + m_GeneratorResumeModeThrow.set(m_vm, jsNumber(static_cast(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))); + m_GeneratorResumeModeReturn.set(m_vm, jsNumber(static_cast(JSGeneratorFunction::GeneratorResumeMode::ReturnMode))); + m_GeneratorStateCompleted.set(m_vm, jsNumber(static_cast(JSGeneratorFunction::GeneratorState::Completed))); + m_GeneratorStateExecuting.set(m_vm, jsNumber(static_cast(JSGeneratorFunction::GeneratorState::Executing))); } BytecodeIntrinsicNode::EmitterType BytecodeIntrinsicRegistry::lookup(const Identifier& ident) const diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Yusuke Suzuki . + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,7 +28,6 @@ #define BytecodeIntrinsicRegistry_h #include "Identifier.h" -#include #include namespace JSC { @@ -39,21 +39,40 @@ class Identifier; #define JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \ + macro(argumentCount) \ macro(assert) \ macro(isObject) \ + macro(isJSArray) \ + macro(tailCallForwardArguments) \ + macro(tryGetById) \ macro(putByValDirect) \ - macro(toString) + macro(toNumber) \ + macro(toString) \ + macro(newArrayWithSize) \ #define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \ macro(undefined) \ - macro(arrayIterationKindKey) \ - macro(arrayIterationKindValue) \ - macro(arrayIterationKindKeyValue) \ + macro(Infinity) \ + macro(iterationKindKey) \ + macro(iterationKindValue) \ + macro(iterationKindKeyValue) \ + macro(MAX_STRING_LENGTH) \ + macro(MAX_SAFE_INTEGER) \ + macro(ModuleFetch) \ + macro(ModuleTranslate) \ + macro(ModuleInstantiate) \ + macro(ModuleSatisfy) \ + macro(ModuleLink) \ + macro(ModuleReady) \ macro(promiseStatePending) \ macro(promiseStateFulfilled) \ macro(promiseStateRejected) \ - macro(symbolIterator) \ - macro(symbolSearch) + macro(GeneratorResumeModeNormal) \ + macro(GeneratorResumeModeThrow) \ + macro(GeneratorResumeModeReturn) \ + macro(GeneratorStateCompleted) \ + macro(GeneratorStateExecuting) \ + class BytecodeIntrinsicRegistry { WTF_MAKE_NONCOPYABLE(BytecodeIntrinsicRegistry); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeList.json webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeList.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeList.json 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeList.json 2016-11-03 07:04:20.000000000 +0000 @@ -7,8 +7,9 @@ { "name" : "op_get_scope", "length" : 2 }, { "name" : "op_create_direct_arguments", "length" : 2 }, { "name" : "op_create_scoped_arguments", "length" : 3 }, - { "name" : "op_create_out_of_band_arguments", "length" : 2 }, + { "name" : "op_create_cloned_arguments", "length" : 2 }, { "name" : "op_create_this", "length" : 5 }, + { "name" : "op_argument_count", "length" : 2 }, { "name" : "op_to_this", "length" : 4 }, { "name" : "op_check_tdz", "length" : 2 }, { "name" : "op_new_object", "length" : 4 }, @@ -30,7 +31,7 @@ { "name" : "op_greatereq", "length" : 4 }, { "name" : "op_inc", "length" : 2 }, { "name" : "op_dec", "length" : 2 }, - { "name" : "op_to_number", "length" : 3 }, + { "name" : "op_to_number", "length" : 4 }, { "name" : "op_to_string", "length" : 3 }, { "name" : "op_negate", "length" : 3 }, { "name" : "op_add", "length" : 5 }, @@ -38,6 +39,7 @@ { "name" : "op_div", "length" : 5 }, { "name" : "op_mod", "length" : 4 }, { "name" : "op_sub", "length" : 5 }, + { "name" : "op_pow", "length" : 4 }, { "name" : "op_lshift", "length" : 4 }, { "name" : "op_rshift", "length" : 4 }, { "name" : "op_urshift", "length" : 4 }, @@ -49,20 +51,29 @@ { "name" : "op_instanceof", "length" : 4 }, { "name" : "op_instanceof_custom", "length" : 5 }, { "name" : "op_typeof", "length" : 3 }, + { "name" : "op_is_empty", "length" : 3 }, { "name" : "op_is_undefined", "length" : 3 }, { "name" : "op_is_boolean", "length" : 3 }, { "name" : "op_is_number", "length" : 3 }, { "name" : "op_is_string", "length" : 3 }, + { "name" : "op_is_jsarray", "length" : 3 }, { "name" : "op_is_object", "length" : 3 }, { "name" : "op_is_object_or_null", "length" : 3 }, { "name" : "op_is_function", "length" : 3 }, { "name" : "op_in", "length" : 4 }, - { "name" : "op_get_by_id", "length" : 9 }, { "name" : "op_get_array_length", "length" : 9 }, + { "name" : "op_get_by_id", "length" : 9 }, + { "name" : "op_get_by_id_proto_load", "length" : 9 }, + { "name" : "op_get_by_id_unset", "length" : 9 }, + { "name" : "op_get_by_id_with_this", "length" : 6 }, + { "name" : "op_get_by_val_with_this", "length" : 6 }, + { "name" : "op_try_get_by_id", "length" : 5 }, { "name" : "op_put_by_id", "length" : 9 }, + { "name" : "op_put_by_id_with_this", "length" : 5 }, { "name" : "op_del_by_id", "length" : 4 }, { "name" : "op_get_by_val", "length" : 6 }, { "name" : "op_put_by_val", "length" : 5 }, + { "name" : "op_put_by_val_with_this", "length" : 5 }, { "name" : "op_put_by_val_direct", "length" : 5 }, { "name" : "op_del_by_val", "length" : 4 }, { "name" : "op_put_by_index", "length" : 4 }, @@ -76,7 +87,7 @@ { "name" : "op_jfalse", "length" : 3 }, { "name" : "op_jeq_null", "length" : 3 }, { "name" : "op_jneq_null", "length" : 3 }, - { "name" : "op_jneq_ptr", "length" : 4 }, + { "name" : "op_jneq_ptr", "length" : 5 }, { "name" : "op_jless", "length" : 4 }, { "name" : "op_jlesseq", "length" : 4 }, { "name" : "op_jgreater", "length" : 4 }, @@ -93,12 +104,13 @@ { "name" : "op_new_func_exp", "length" : 4 }, { "name" : "op_new_generator_func", "length" : 4 }, { "name" : "op_new_generator_func_exp", "length" : 4 }, - { "name" : "op_new_arrow_func_exp", "length" : 4 }, + { "name" : "op_set_function_name", "length" : 3 }, { "name" : "op_call", "length" : 9 }, { "name" : "op_tail_call", "length" : 9 }, { "name" : "op_call_eval", "length" : 9 }, { "name" : "op_call_varargs", "length" : 9 }, { "name" : "op_tail_call_varargs", "length" : 9 }, + { "name" : "op_tail_call_forward_arguments", "length" : 9 }, { "name" : "op_ret", "length" : 2 }, { "name" : "op_construct", "length" : 9 }, { "name" : "op_construct_varargs", "length" : 9 }, @@ -116,8 +128,6 @@ { "name" : "op_throw", "length" : 2 }, { "name" : "op_throw_static_error", "length" : 3 }, { "name" : "op_debug", "length" : 3 }, - { "name" : "op_profile_will_call", "length" : 2 }, - { "name" : "op_profile_did_call", "length" : 2 }, { "name" : "op_end", "length" : 2 }, { "name" : "op_profile_type", "length" : 6 }, { "name" : "op_profile_control_flow", "length" : 2 }, @@ -131,11 +141,12 @@ { "name" : "op_enumerator_generic_pname", "length" : 4 }, { "name" : "op_to_index_string", "length" : 3 }, { "name" : "op_assert", "length" : 3 }, - { "name" : "op_copy_rest", "length": 4 }, + { "name" : "op_create_rest", "length": 4 }, { "name" : "op_get_rest_length", "length": 3 }, - { "name" : "op_save", "length" : 4 }, - { "name" : "op_resume", "length" : 3 }, - { "name" : "op_watchdog", "length" : 1 } + { "name" : "op_yield", "length" : 4 }, + { "name" : "op_watchdog", "length" : 1 }, + { "name" : "op_log_shadow_chicken_prologue", "length" : 2}, + { "name" : "op_log_shadow_chicken_tail", "length" : 3} ] }, { @@ -157,7 +168,8 @@ { "name" : "llint_cloop_did_return_from_js_8" }, { "name" : "llint_cloop_did_return_from_js_9" }, { "name" : "llint_cloop_did_return_from_js_10" }, - { "name" : "llint_cloop_did_return_from_js_11" } + { "name" : "llint_cloop_did_return_from_js_11" }, + { "name" : "llint_cloop_did_return_from_js_12" } ] }, { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -31,190 +31,37 @@ #include "BytecodeUseDef.h" #include "CodeBlock.h" #include "FullBytecodeLiveness.h" +#include "InterpreterInlines.h" #include "PreciseJumpTargets.h" namespace JSC { BytecodeLivenessAnalysis::BytecodeLivenessAnalysis(CodeBlock* codeBlock) - : m_codeBlock(codeBlock) + : m_graph(codeBlock, codeBlock->instructions()) { - ASSERT(m_codeBlock); compute(); } -static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand) +template +void BytecodeLivenessAnalysis::computeDefsForBytecodeOffset(CodeBlock* codeBlock, OpcodeID opcodeID, Instruction* instruction, FastBitVector&, const Functor& functor) { - if (codeBlock->isConstantRegisterIndex(operand)) - return false; - - VirtualRegister virtualReg(operand); - return virtualReg.isLocal(); -} - -static unsigned getLeaderOffsetForBasicBlock(std::unique_ptr* basicBlock) -{ - return (*basicBlock)->leaderBytecodeOffset(); -} - -static BytecodeBasicBlock* findBasicBlockWithLeaderOffset(Vector>& basicBlocks, unsigned leaderOffset) -{ - return (*tryBinarySearch, unsigned>(basicBlocks, basicBlocks.size(), leaderOffset, getLeaderOffsetForBasicBlock)).get(); -} - -static bool blockContainsBytecodeOffset(BytecodeBasicBlock* block, unsigned bytecodeOffset) -{ - unsigned leaderOffset = block->leaderBytecodeOffset(); - return bytecodeOffset >= leaderOffset && bytecodeOffset < leaderOffset + block->totalBytecodeLength(); -} - -static BytecodeBasicBlock* findBasicBlockForBytecodeOffset(Vector>& basicBlocks, unsigned bytecodeOffset) -{ -/* - for (unsigned i = 0; i < basicBlocks.size(); i++) { - if (blockContainsBytecodeOffset(basicBlocks[i].get(), bytecodeOffset)) - return basicBlocks[i].get(); - } - return 0; -*/ - std::unique_ptr* basicBlock = approximateBinarySearch, unsigned>( - basicBlocks, basicBlocks.size(), bytecodeOffset, getLeaderOffsetForBasicBlock); - // We found the block we were looking for. - if (blockContainsBytecodeOffset((*basicBlock).get(), bytecodeOffset)) - return (*basicBlock).get(); - - // Basic block is to the left of the returned block. - if (bytecodeOffset < (*basicBlock)->leaderBytecodeOffset()) { - ASSERT(basicBlock - 1 >= basicBlocks.data()); - ASSERT(blockContainsBytecodeOffset(basicBlock[-1].get(), bytecodeOffset)); - return basicBlock[-1].get(); - } - - // Basic block is to the right of the returned block. - ASSERT(&basicBlock[1] <= &basicBlocks.last()); - ASSERT(blockContainsBytecodeOffset(basicBlock[1].get(), bytecodeOffset)); - return basicBlock[1].get(); -} - -// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes -// exception handlers in the uses. -template -static void stepOverInstruction(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector>& basicBlocks, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def) -{ - // This abstractly execute the instruction in reverse. Instructions logically first use operands and - // then define operands. This logical ordering is necessary for operations that use and def the same - // operand, like: - // - // op_add loc1, loc1, loc2 - // - // The use of loc1 happens before the def of loc1. That's a semantic requirement since the add - // operation cannot travel forward in time to read the value that it will produce after reading that - // value. Since we are executing in reverse, this means that we must do defs before uses (reverse of - // uses before defs). - // - // Since this is a liveness analysis, this ordering ends up being particularly important: if we did - // uses before defs, then the add operation above would appear to not have loc1 live, since we'd - // first add it to the out set (the use), and then we'd remove it (the def). - - computeDefsForBytecodeOffset( - codeBlock, block, bytecodeOffset, - [&] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) { - if (isValidRegisterForLiveness(codeBlock, operand)) - def(VirtualRegister(operand).toLocal()); - }); - - computeUsesForBytecodeOffset( - codeBlock, block, bytecodeOffset, - [&] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) { - if (isValidRegisterForLiveness(codeBlock, operand)) - use(VirtualRegister(operand).toLocal()); - }); - - // If we have an exception handler, we want the live-in variables of the - // exception handler block to be included in the live-in of this particular bytecode. - if (HandlerInfo* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset)) { - BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler->target); - ASSERT(handlerBlock); - handlerBlock->in().forEachSetBit(use); - } + JSC::computeDefsForBytecodeOffset(codeBlock, opcodeID, instruction, functor); } -static void stepOverInstruction(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector>& basicBlocks, unsigned bytecodeOffset, FastBitVector& out) +template +void BytecodeLivenessAnalysis::computeUsesForBytecodeOffset(CodeBlock* codeBlock, OpcodeID opcodeID, Instruction* instruction, FastBitVector&, const Functor& functor) { - stepOverInstruction( - codeBlock, block, basicBlocks, bytecodeOffset, - [&] (unsigned bitIndex) { - // This is the use functor, so we set the bit. - out.set(bitIndex); - }, - [&] (unsigned bitIndex) { - // This is the def functor, so we clear the bit. - out.clear(bitIndex); - }); -} - -static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector>& basicBlocks, unsigned targetOffset, FastBitVector& result) -{ - ASSERT(!block->isExitBlock()); - ASSERT(!block->isEntryBlock()); - - FastBitVector out = block->out(); - - for (int i = block->bytecodeOffsets().size() - 1; i >= 0; i--) { - unsigned bytecodeOffset = block->bytecodeOffsets()[i]; - if (targetOffset > bytecodeOffset) - break; - - stepOverInstruction(codeBlock, block, basicBlocks, bytecodeOffset, out); - } - - result.set(out); -} - -static void computeLocalLivenessForBlock(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector>& basicBlocks) -{ - if (block->isExitBlock() || block->isEntryBlock()) - return; - computeLocalLivenessForBytecodeOffset(codeBlock, block, basicBlocks, block->leaderBytecodeOffset(), block->in()); -} - -void BytecodeLivenessAnalysis::runLivenessFixpoint() -{ - UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock->unlinkedCodeBlock(); - unsigned numberOfVariables = unlinkedCodeBlock->m_numCalleeLocals; - - for (unsigned i = 0; i < m_basicBlocks.size(); i++) { - BytecodeBasicBlock* block = m_basicBlocks[i].get(); - block->in().resize(numberOfVariables); - block->out().resize(numberOfVariables); - } - - bool changed; - m_basicBlocks.last()->in().clearAll(); - m_basicBlocks.last()->out().clearAll(); - FastBitVector newOut; - newOut.resize(m_basicBlocks.last()->out().numBits()); - do { - changed = false; - for (unsigned i = m_basicBlocks.size() - 1; i--;) { - BytecodeBasicBlock* block = m_basicBlocks[i].get(); - newOut.clearAll(); - for (unsigned j = 0; j < block->successors().size(); j++) - newOut.merge(block->successors()[j]->in()); - bool outDidChange = block->out().setAndCheck(newOut); - computeLocalLivenessForBlock(m_codeBlock, block, m_basicBlocks); - changed |= outDidChange; - } - } while (changed); + JSC::computeUsesForBytecodeOffset(codeBlock, opcodeID, instruction, functor); } void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector& result) { - BytecodeBasicBlock* block = findBasicBlockForBytecodeOffset(m_basicBlocks, bytecodeOffset); + BytecodeBasicBlock* block = m_graph.findBasicBlockForBytecodeOffset(bytecodeOffset); ASSERT(block); ASSERT(!block->isEntryBlock()); ASSERT(!block->isExitBlock()); result.resize(block->out().numBits()); - computeLocalLivenessForBytecodeOffset(m_codeBlock, block, m_basicBlocks, bytecodeOffset, result); + computeLocalLivenessForBytecodeOffset(m_graph, block, bytecodeOffset, result); } bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset) @@ -236,19 +83,19 @@ void BytecodeLivenessAnalysis::computeFullLiveness(FullBytecodeLiveness& result) { FastBitVector out; + CodeBlock* codeBlock = m_graph.codeBlock(); - result.m_map.resize(m_codeBlock->instructions().size()); + result.m_map.resize(codeBlock->instructions().size()); - for (unsigned i = m_basicBlocks.size(); i--;) { - BytecodeBasicBlock* block = m_basicBlocks[i].get(); + for (std::unique_ptr& block : m_graph.basicBlocksInReverseOrder()) { if (block->isEntryBlock() || block->isExitBlock()) continue; out = block->out(); - for (unsigned i = block->bytecodeOffsets().size(); i--;) { - unsigned bytecodeOffset = block->bytecodeOffsets()[i]; - stepOverInstruction(m_codeBlock, block, m_basicBlocks, bytecodeOffset, out); + for (unsigned i = block->offsets().size(); i--;) { + unsigned bytecodeOffset = block->offsets()[i]; + stepOverInstruction(m_graph, bytecodeOffset, out); result.m_map[bytecodeOffset] = out; } } @@ -258,20 +105,20 @@ { FastBitVector out; - result.m_codeBlock = m_codeBlock; - result.m_killSets = std::make_unique(m_codeBlock->instructions().size()); + CodeBlock* codeBlock = m_graph.codeBlock(); + result.m_codeBlock = codeBlock; + result.m_killSets = std::make_unique(codeBlock->instructions().size()); - for (unsigned i = m_basicBlocks.size(); i--;) { - BytecodeBasicBlock* block = m_basicBlocks[i].get(); + for (std::unique_ptr& block : m_graph.basicBlocksInReverseOrder()) { if (block->isEntryBlock() || block->isExitBlock()) continue; out = block->out(); - for (unsigned i = block->bytecodeOffsets().size(); i--;) { - unsigned bytecodeOffset = block->bytecodeOffsets()[i]; + for (unsigned i = block->offsets().size(); i--;) { + unsigned bytecodeOffset = block->offsets()[i]; stepOverInstruction( - m_codeBlock, block, m_basicBlocks, bytecodeOffset, + m_graph, bytecodeOffset, out, [&] (unsigned index) { // This is for uses. if (out.get(index)) @@ -289,11 +136,13 @@ void BytecodeLivenessAnalysis::dumpResults() { - Interpreter* interpreter = m_codeBlock->vm()->interpreter; - Instruction* instructionsBegin = m_codeBlock->instructions().begin(); - for (unsigned i = 0; i < m_basicBlocks.size(); i++) { - BytecodeBasicBlock* block = m_basicBlocks[i].get(); - dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i, block, block->leaderBytecodeOffset(), block->totalBytecodeLength()); + CodeBlock* codeBlock = m_graph.codeBlock(); + dataLog("\nDumping bytecode liveness for ", *codeBlock, ":\n"); + Interpreter* interpreter = codeBlock->vm()->interpreter; + Instruction* instructionsBegin = codeBlock->instructions().begin(); + unsigned i = 0; + for (BytecodeBasicBlock* block : m_graph) { + dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i++, block, block->leaderOffset(), block->totalLength()); dataLogF("Successors: "); for (unsigned j = 0; j < block->successors().size(); j++) { BytecodeBasicBlock* successor = block->successors()[j]; @@ -308,7 +157,7 @@ dataLogF("Exit block: %p\n", block); continue; } - for (unsigned bytecodeOffset = block->leaderBytecodeOffset(); bytecodeOffset < block->leaderBytecodeOffset() + block->totalBytecodeLength();) { + for (unsigned bytecodeOffset = block->leaderOffset(); bytecodeOffset < block->leaderOffset() + block->totalLength();) { const Instruction* currentInstruction = &instructionsBegin[bytecodeOffset]; dataLogF("Live variables: "); @@ -318,7 +167,7 @@ dataLogF("%u ", j); } dataLogF("\n"); - m_codeBlock->dumpBytecode(WTF::dataFile(), m_codeBlock->globalObject()->globalExec(), instructionsBegin, currentInstruction); + codeBlock->dumpBytecode(WTF::dataFile(), codeBlock->globalObject()->globalExec(), instructionsBegin, currentInstruction); OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); unsigned opcodeLength = opcodeLengths[opcodeID]; @@ -337,9 +186,7 @@ void BytecodeLivenessAnalysis::compute() { - computeBytecodeBasicBlocks(m_codeBlock, m_basicBlocks); - ASSERT(m_basicBlocks.size()); - runLivenessFixpoint(); + runLivenessFixpoint(m_graph); if (Options::dumpBytecodeLivenessResults()) dumpResults(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,10 +23,11 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BytecodeLivenessAnalysis_h -#define BytecodeLivenessAnalysis_h +#pragma once #include "BytecodeBasicBlock.h" +#include "BytecodeGraph.h" +#include "CodeBlock.h" #include #include #include @@ -34,13 +35,29 @@ namespace JSC { class BytecodeKills; -class CodeBlock; class FullBytecodeLiveness; -class BytecodeLivenessAnalysis { +template +class BytecodeLivenessPropagation { +protected: + template void stepOverInstruction(Graph&, unsigned bytecodeOffset, FastBitVector& out, const UseFunctor&, const DefFunctor&); + + template void stepOverInstruction(Graph&, unsigned bytecodeOffset, FastBitVector& out); + + template bool computeLocalLivenessForBytecodeOffset(Graph&, BytecodeBasicBlock*, unsigned targetOffset, FastBitVector& result); + + template bool computeLocalLivenessForBlock(Graph&, BytecodeBasicBlock*); + + template FastBitVector getLivenessInfoAtBytecodeOffset(Graph&, unsigned bytecodeOffset); + + template void runLivenessFixpoint(Graph&); +}; + +class BytecodeLivenessAnalysis : private BytecodeLivenessPropagation { WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(BytecodeLivenessAnalysis); public: + friend class BytecodeLivenessPropagation; BytecodeLivenessAnalysis(CodeBlock*); bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset); @@ -51,19 +68,19 @@ private: void compute(); - void runLivenessFixpoint(); void dumpResults(); void getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&); - CodeBlock* m_codeBlock; - Vector> m_basicBlocks; + template void computeDefsForBytecodeOffset(CodeBlock*, OpcodeID, Instruction*, FastBitVector&, const Functor&); + template void computeUsesForBytecodeOffset(CodeBlock*, OpcodeID, Instruction*, FastBitVector&, const Functor&); + + BytecodeGraph m_graph; }; inline bool operandIsAlwaysLive(int operand); inline bool operandThatIsNotAlwaysLiveIsLive(const FastBitVector& out, int operand); inline bool operandIsLive(const FastBitVector& out, int operand); +inline bool isValidRegisterForLiveness(int operand); } // namespace JSC - -#endif // BytecodeLivenessAnalysis_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,11 +23,12 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BytecodeLivenessAnalysisInlines_h -#define BytecodeLivenessAnalysisInlines_h +#pragma once +#include "BytecodeGraph.h" #include "BytecodeLivenessAnalysis.h" #include "CodeBlock.h" +#include "Interpreter.h" #include "Operations.h" namespace JSC { @@ -50,7 +51,151 @@ return operandIsAlwaysLive(operand) || operandThatIsNotAlwaysLiveIsLive(out, operand); } -} // namespace JSC +inline bool isValidRegisterForLiveness(int operand) +{ + VirtualRegister virtualReg(operand); + if (virtualReg.isConstant()) + return false; + return virtualReg.isLocal(); +} + +// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes +// exception handlers in the uses. +template +template +inline void BytecodeLivenessPropagation::stepOverInstruction(Graph& graph, unsigned bytecodeOffset, FastBitVector& out, const UseFunctor& use, const DefFunctor& def) +{ + // This abstractly execute the instruction in reverse. Instructions logically first use operands and + // then define operands. This logical ordering is necessary for operations that use and def the same + // operand, like: + // + // op_add loc1, loc1, loc2 + // + // The use of loc1 happens before the def of loc1. That's a semantic requirement since the add + // operation cannot travel forward in time to read the value that it will produce after reading that + // value. Since we are executing in reverse, this means that we must do defs before uses (reverse of + // uses before defs). + // + // Since this is a liveness analysis, this ordering ends up being particularly important: if we did + // uses before defs, then the add operation above would appear to not have loc1 live, since we'd + // first add it to the out set (the use), and then we'd remove it (the def). + + auto* codeBlock = graph.codeBlock(); + Interpreter* interpreter = codeBlock->vm()->interpreter; + auto* instructionsBegin = graph.instructions().begin(); + auto* instruction = &instructionsBegin[bytecodeOffset]; + OpcodeID opcodeID = interpreter->getOpcodeID(*instruction); + + static_cast(this)->computeDefsForBytecodeOffset( + codeBlock, opcodeID, instruction, out, + [&] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) { + if (isValidRegisterForLiveness(operand)) + def(VirtualRegister(operand).toLocal()); + }); + + static_cast(this)->computeUsesForBytecodeOffset( + codeBlock, opcodeID, instruction, out, + [&] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) { + if (isValidRegisterForLiveness(operand)) + use(VirtualRegister(operand).toLocal()); + }); + + // If we have an exception handler, we want the live-in variables of the + // exception handler block to be included in the live-in of this particular bytecode. + if (auto* handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset)) { + BytecodeBasicBlock* handlerBlock = graph.findBasicBlockWithLeaderOffset(handler->target); + ASSERT(handlerBlock); + handlerBlock->in().forEachSetBit(use); + } +} + +template +template +inline void BytecodeLivenessPropagation::stepOverInstruction(Graph& graph, unsigned bytecodeOffset, FastBitVector& out) +{ + stepOverInstruction( + graph, bytecodeOffset, out, + [&] (unsigned bitIndex) { + // This is the use functor, so we set the bit. + out.set(bitIndex); + }, + [&] (unsigned bitIndex) { + // This is the def functor, so we clear the bit. + out.clear(bitIndex); + }); +} + +template +template +inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset(Graph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result) +{ + ASSERT(!block->isExitBlock()); + ASSERT(!block->isEntryBlock()); + + FastBitVector out = block->out(); -#endif // BytecodeLivenessAnalysisInlines_h + for (int i = block->offsets().size() - 1; i >= 0; i--) { + unsigned bytecodeOffset = block->offsets()[i]; + if (targetOffset > bytecodeOffset) + break; + stepOverInstruction(graph, bytecodeOffset, out); + } + return result.setAndCheck(out); +} + +template +template +inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(Graph& graph, BytecodeBasicBlock* block) +{ + if (block->isExitBlock() || block->isEntryBlock()) + return false; + return computeLocalLivenessForBytecodeOffset(graph, block, block->leaderOffset(), block->in()); +} + +template +template +inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset(Graph& graph, unsigned bytecodeOffset) +{ + BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(bytecodeOffset); + ASSERT(block); + ASSERT(!block->isEntryBlock()); + ASSERT(!block->isExitBlock()); + FastBitVector out; + out.resize(block->out().numBits()); + computeLocalLivenessForBytecodeOffset(graph, block, bytecodeOffset, out); + return out; +} + +template +template +inline void BytecodeLivenessPropagation::runLivenessFixpoint(Graph& graph) +{ + auto* codeBlock = graph.codeBlock(); + unsigned numberOfVariables = codeBlock->numCalleeLocals(); + for (BytecodeBasicBlock* block : graph) { + block->in().resize(numberOfVariables); + block->out().resize(numberOfVariables); + block->in().clearAll(); + block->out().clearAll(); + } + + bool changed; + BytecodeBasicBlock* lastBlock = graph.last(); + lastBlock->in().clearAll(); + lastBlock->out().clearAll(); + FastBitVector newOut; + newOut.resize(lastBlock->out().numBits()); + do { + changed = false; + for (std::unique_ptr& block : graph.basicBlocksInReverseOrder()) { + newOut.clearAll(); + for (BytecodeBasicBlock* successor : block->successors()) + newOut.merge(successor->in()); + block->out().set(newOut); + changed |= computeLocalLivenessForBlock(graph, block.get()); + } + } while (changed); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BytecodeRewriter.h" + +#include "HeapInlines.h" +#include "PreciseJumpTargetsInlines.h" +#include + +namespace JSC { + +void BytecodeRewriter::applyModification() +{ + for (size_t insertionIndex = m_insertions.size(); insertionIndex--;) { + Insertion& insertion = m_insertions[insertionIndex]; + if (insertion.type == Insertion::Type::Remove) + m_graph.instructions().remove(insertion.index.bytecodeOffset, insertion.length()); + else { + if (insertion.includeBranch == IncludeBranch::Yes) { + int finalOffset = insertion.index.bytecodeOffset + calculateDifference(m_insertions.begin(), m_insertions.begin() + insertionIndex); + adjustJumpTargetsInFragment(finalOffset, insertion); + } + m_graph.instructions().insertVector(insertion.index.bytecodeOffset, insertion.instructions); + } + } + m_insertions.clear(); +} + +void BytecodeRewriter::execute() +{ + WTF::bubbleSort(m_insertions.begin(), m_insertions.end(), [] (const Insertion& lhs, const Insertion& rhs) { + return lhs.index < rhs.index; + }); + + UnlinkedCodeBlock* codeBlock = m_graph.codeBlock(); + codeBlock->applyModification(*this); +} + +void BytecodeRewriter::adjustJumpTargetsInFragment(unsigned finalOffset, Insertion& insertion) +{ + auto& fragment = insertion.instructions; + UnlinkedInstruction* instructionsBegin = fragment.data(); + for (unsigned fragmentOffset = 0, fragmentCount = fragment.size(); fragmentOffset < fragmentCount;) { + UnlinkedInstruction& instruction = fragment[fragmentOffset]; + OpcodeID opcodeID = instruction.u.opcode; + if (isBranch(opcodeID)) { + unsigned bytecodeOffset = finalOffset + fragmentOffset; + UnlinkedCodeBlock* codeBlock = m_graph.codeBlock(); + extractStoredJumpTargetsForBytecodeOffset(codeBlock, codeBlock->vm()->interpreter, instructionsBegin, fragmentOffset, [&](int32_t& label) { + int absoluteOffset = adjustAbsoluteOffset(label); + label = absoluteOffset - static_cast(bytecodeOffset); + }); + } + fragmentOffset += opcodeLength(opcodeID); + } +} + +void BytecodeRewriter::insertImpl(InsertionPoint insertionPoint, IncludeBranch includeBranch, Vector&& fragment) +{ + ASSERT(insertionPoint.position == Position::Before || insertionPoint.position == Position::After); + m_insertions.append(Insertion { + insertionPoint, + Insertion::Type::Insert, + includeBranch, + 0, + WTFMove(fragment) + }); +} + +int BytecodeRewriter::adjustJumpTarget(InsertionPoint startPoint, InsertionPoint jumpTargetPoint) +{ + if (startPoint < jumpTargetPoint) { + int jumpTarget = jumpTargetPoint.bytecodeOffset; + auto start = std::lower_bound(m_insertions.begin(), m_insertions.end(), startPoint, [&] (const Insertion& insertion, InsertionPoint startPoint) { + return insertion.index < startPoint; + }); + if (start != m_insertions.end()) { + auto end = std::lower_bound(m_insertions.begin(), m_insertions.end(), jumpTargetPoint, [&] (const Insertion& insertion, InsertionPoint jumpTargetPoint) { + return insertion.index < jumpTargetPoint; + }); + jumpTarget += calculateDifference(start, end); + } + return jumpTarget - startPoint.bytecodeOffset; + } + + if (startPoint == jumpTargetPoint) + return 0; + + return -adjustJumpTarget(jumpTargetPoint, startPoint); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeRewriter.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeRewriter.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeRewriter.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeRewriter.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "BytecodeGraph.h" +#include "Bytecodes.h" +#include "Opcode.h" +#include "UnlinkedCodeBlock.h" +#include + +namespace JSC { + +// BytecodeRewriter offers the ability to insert and remove the bytecodes including jump operations. +// +// We use the original bytecode offsets as labels. When you emit some jumps, you can specify the jump target by +// using the original bytecode offsets. These bytecode offsets are later converted appropriate values by the +// rewriter. And we also use the labels to represents the position the new bytecodes inserted. +// +// | [bytecode] | [bytecode] | +// offsets A B C +// +// We can use the above "A", "B", and "C" offsets as labels. And the rewriter has the ability to insert bytecode fragments +// before and after the label. For example, if you insert the fragment after "B", the layout becomes like this. +// +// | [bytecode] | [fragment] [bytecode] | +// offsets A B C +// +// And even if you remove some original bytecodes, the offset remains as labels. For example, when you remove the A's bytecode, +// the layout becomes like this. +// +// | | [bytecode] | +// offsets A B C +// +// And still you can insert fragments before and after "A". +// +// | [fragment] | [bytecode] | +// offsets A B C +// +// We can insert bytecode fragments "Before" and "After" the labels. This inserted position, either "Before" and "After", +// has effect when the label is involved with jumps. For example, when you have jump to the position "B", +// +// | [bytecode] | [bytecode] | +// offsets A B C +// ^ +// jump to here. +// +// and you insert the bytecode before/after "B", +// +// | [bytecode] [before] | [after] [bytecode] | +// offsets A B C +// ^ +// jump to here. +// +// as you can see, the execution jumping into "B" does not execute [before] code. +class BytecodeRewriter { +WTF_MAKE_NONCOPYABLE(BytecodeRewriter); +public: + enum class Position : int8_t { + EntryPoint = -2, + Before = -1, + LabelPoint = 0, + After = 1, + OriginalBytecodePoint = 2, + }; + + enum class IncludeBranch : uint8_t { + No = 0, + Yes = 1, + }; + + struct InsertionPoint { + int bytecodeOffset; + Position position; + + InsertionPoint(int offset, Position pos) + : bytecodeOffset(offset) + , position(pos) + { + } + + bool operator<(const InsertionPoint& other) const + { + if (bytecodeOffset == other.bytecodeOffset) + return position < other.position; + return bytecodeOffset < other.bytecodeOffset; + } + + bool operator==(const InsertionPoint& other) const + { + return bytecodeOffset == other.bytecodeOffset && position == other.position; + } + }; + +private: + struct Insertion { + enum class Type : uint8_t { Insert = 0, Remove = 1, }; + + size_t length() const + { + if (type == Type::Remove) + return removeLength; + return instructions.size(); + } + + InsertionPoint index; + Type type; + IncludeBranch includeBranch; + size_t removeLength; + Vector instructions; + }; + +public: + class Fragment { + WTF_MAKE_NONCOPYABLE(Fragment); + public: + Fragment(Vector& fragment, IncludeBranch& includeBranch) + : m_fragment(fragment) + , m_includeBranch(includeBranch) + { + } + + template + void appendInstruction(OpcodeID opcodeID, Args... args) + { + if (isBranch(opcodeID)) + m_includeBranch = IncludeBranch::Yes; + + UnlinkedInstruction instructions[sizeof...(args) + 1] = { + UnlinkedInstruction(opcodeID), + UnlinkedInstruction(args)... + }; + m_fragment.append(instructions, sizeof...(args) + 1); + } + + private: + Vector& m_fragment; + IncludeBranch& m_includeBranch; + }; + + BytecodeRewriter(BytecodeGraph& graph) + : m_graph(graph) + { + } + + template + void insertFragmentBefore(unsigned bytecodeOffset, Function function) + { + IncludeBranch includeBranch = IncludeBranch::No; + Vector instructions; + Fragment fragment(instructions, includeBranch); + function(fragment); + insertImpl(InsertionPoint(bytecodeOffset, Position::Before), includeBranch, WTFMove(instructions)); + } + + template + void insertFragmentAfter(unsigned bytecodeOffset, Function function) + { + IncludeBranch includeBranch = IncludeBranch::No; + Vector instructions; + Fragment fragment(instructions, includeBranch); + function(fragment); + insertImpl(InsertionPoint(bytecodeOffset, Position::After), includeBranch, WTFMove(instructions)); + } + + void removeBytecode(unsigned bytecodeOffset) + { + m_insertions.append(Insertion { InsertionPoint(bytecodeOffset, Position::OriginalBytecodePoint), Insertion::Type::Remove, IncludeBranch::No, opcodeLength(m_graph.instructions()[bytecodeOffset].u.opcode), { } }); + } + + void execute(); + + BytecodeGraph& graph() { return m_graph; } + + int adjustAbsoluteOffset(int absoluteOffset) + { + return adjustJumpTarget(InsertionPoint(0, Position::EntryPoint), InsertionPoint(absoluteOffset, Position::LabelPoint)); + } + + int adjustJumpTarget(int originalBytecodeOffset, int originalJumpTarget) + { + return adjustJumpTarget(InsertionPoint(originalBytecodeOffset, Position::LabelPoint), InsertionPoint(originalJumpTarget, Position::LabelPoint)); + } + +private: + void insertImpl(InsertionPoint, IncludeBranch, Vector&& fragment); + + friend class UnlinkedCodeBlock; + void applyModification(); + void adjustJumpTargetsInFragment(unsigned finalOffset, Insertion&); + + int adjustJumpTarget(InsertionPoint startPoint, InsertionPoint jumpTargetPoint); + template int calculateDifference(Iterator begin, Iterator end); + + BytecodeGraph& m_graph; + Vector m_insertions; +}; + +template +inline int BytecodeRewriter::calculateDifference(Iterator begin, Iterator end) +{ + int result = 0; + for (; begin != end; ++begin) { + if (begin->type == Insertion::Type::Remove) + result -= begin->length(); + else + result += begin->length(); + } + return result; +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeUseDef.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeUseDef.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/BytecodeUseDef.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/BytecodeUseDef.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,17 +27,16 @@ #define BytecodeUseDef_h #include "CodeBlock.h" +#include "Interpreter.h" namespace JSC { -template -void computeUsesForBytecodeOffset( - CodeBlock* codeBlock, BytecodeBasicBlock* block, unsigned bytecodeOffset, const Functor& functor) +template +void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instruction* instruction, const Functor& functor) { - Interpreter* interpreter = codeBlock->vm()->interpreter; - Instruction* instructionsBegin = codeBlock->instructions().begin(); - Instruction* instruction = &instructionsBegin[bytecodeOffset]; - OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); + if (opcodeID != op_enter && codeBlock->wasCompiledWithDebuggingOpcodes() && codeBlock->scopeRegister().isValid()) + functor(codeBlock, instruction, opcodeID, codeBlock->scopeRegister().offset()); + switch (opcodeID) { // No uses. case op_new_regexp: @@ -49,10 +48,11 @@ case op_jmp: case op_new_object: case op_enter: + case op_argument_count: case op_catch: case op_profile_control_flow: case op_create_direct_arguments: - case op_create_out_of_band_arguments: + case op_create_cloned_arguments: case op_get_rest_length: case op_watchdog: return; @@ -60,8 +60,6 @@ case op_get_scope: case op_to_this: case op_check_tdz: - case op_profile_will_call: - case op_profile_did_call: case op_profile_type: case op_throw: case op_end: @@ -72,7 +70,7 @@ case op_jneq_null: case op_dec: case op_inc: - case op_resume: { + case op_log_shadow_chicken_prologue: { ASSERT(opcodeLengths[opcodeID] > 1); functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); return; @@ -85,7 +83,8 @@ case op_jngreater: case op_jngreatereq: case op_jless: - case op_copy_rest: { + case op_set_function_name: + case op_log_shadow_chicken_tail: { ASSERT(opcodeLengths[opcodeID] > 2); functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); @@ -108,6 +107,21 @@ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); return; } + case op_put_by_id_with_this: { + ASSERT(opcodeLengths[opcodeID] > 4); + functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); + return; + } + case op_put_by_val_with_this: { + ASSERT(opcodeLengths[opcodeID] > 4); + functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); + return; + } case op_put_getter_by_id: case op_put_setter_by_id: { ASSERT(opcodeLengths[opcodeID] > 4); @@ -134,19 +148,23 @@ case op_get_enumerable_length: case op_new_func_exp: case op_new_generator_func_exp: - case op_new_arrow_func_exp: case op_to_index_string: case op_create_lexical_environment: case op_resolve_scope: case op_get_from_scope: case op_to_primitive: + case op_try_get_by_id: case op_get_by_id: + case op_get_by_id_proto_load: + case op_get_by_id_unset: case op_get_array_length: case op_typeof: + case op_is_empty: case op_is_undefined: case op_is_boolean: case op_is_number: case op_is_string: + case op_is_jsarray: case op_is_object: case op_is_object_or_null: case op_is_function: @@ -165,6 +183,7 @@ case op_new_generator_func: case op_get_parent_scope: case op_create_scoped_arguments: + case op_create_rest: case op_get_from_arguments: { ASSERT(opcodeLengths[opcodeID] > 2); functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); @@ -183,6 +202,7 @@ case op_div: case op_mod: case op_sub: + case op_pow: case op_lshift: case op_rshift: case op_urshift: @@ -198,12 +218,21 @@ case op_neq: case op_eq: case op_push_with_scope: - case op_del_by_val: { + case op_get_by_id_with_this: + case op_del_by_val: + case op_tail_call_forward_arguments: { ASSERT(opcodeLengths[opcodeID] > 3); functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); return; } + case op_get_by_val_with_this: { + ASSERT(opcodeLengths[opcodeID] > 4); + functor(codeBlock, instruction, opcodeID, instruction[2].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); + functor(codeBlock, instruction, opcodeID, instruction[4].u.operand); + return; + } case op_instanceof_custom: case op_has_structure_property: case op_construct_varargs: @@ -248,22 +277,13 @@ int lastArg = registerOffset + CallFrame::thisArgumentOffset(); for (int i = 0; i < argCount; i++) functor(codeBlock, instruction, opcodeID, lastArg + i); + if (opcodeID == op_call_eval) + functor(codeBlock, instruction, opcodeID, codeBlock->scopeRegister().offset()); return; } - case op_save: { + case op_yield: { functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); - unsigned mergePointBytecodeOffset = bytecodeOffset + instruction[3].u.operand; - BytecodeBasicBlock* mergePointBlock = nullptr; - for (BytecodeBasicBlock* successor : block->successors()) { - if (successor->leaderBytecodeOffset() == mergePointBytecodeOffset) { - mergePointBlock = successor; - break; - } - } - ASSERT(mergePointBlock); - mergePointBlock->in().forEachSetBit([&](unsigned local) { - functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(local).offset()); - }); + functor(codeBlock, instruction, opcodeID, instruction[3].u.operand); return; } default: @@ -272,23 +292,15 @@ } } -template -void computeDefsForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, unsigned bytecodeOffset, const Functor& functor) +template +void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instruction* instruction, const Functor& functor) { - Interpreter* interpreter = codeBlock->vm()->interpreter; - Instruction* instructionsBegin = codeBlock->instructions().begin(); - Instruction* instruction = &instructionsBegin[bytecodeOffset]; - OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); switch (opcodeID) { // These don't define anything. - case op_copy_rest: case op_put_to_scope: case op_end: - case op_profile_will_call: - case op_profile_did_call: case op_throw: case op_throw_static_error: - case op_save: case op_assert: case op_debug: case op_ret: @@ -311,6 +323,8 @@ case op_switch_char: case op_switch_string: case op_put_by_id: + case op_put_by_id_with_this: + case op_put_by_val_with_this: case op_put_getter_by_id: case op_put_setter_by_id: case op_put_getter_setter_by_id: @@ -322,12 +336,17 @@ case op_profile_type: case op_profile_control_flow: case op_put_to_arguments: + case op_set_function_name: case op_watchdog: + case op_log_shadow_chicken_prologue: + case op_log_shadow_chicken_tail: + case op_yield: #define LLINT_HELPER_OPCODES(opcode, length) case opcode: FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); #undef LLINT_HELPER_OPCODES return; // These all have a single destination for the first argument. + case op_argument_count: case op_to_index_string: case op_get_enumerable_length: case op_has_indexed_property: @@ -352,26 +371,33 @@ case op_new_func_exp: case op_new_generator_func: case op_new_generator_func_exp: - case op_new_arrow_func_exp: case op_call_varargs: case op_tail_call_varargs: + case op_tail_call_forward_arguments: case op_construct_varargs: case op_get_from_scope: case op_call: case op_tail_call: case op_call_eval: case op_construct: + case op_try_get_by_id: case op_get_by_id: + case op_get_by_id_proto_load: + case op_get_by_id_unset: + case op_get_by_id_with_this: + case op_get_by_val_with_this: case op_get_array_length: case op_overrides_has_instance: case op_instanceof: case op_instanceof_custom: case op_get_by_val: case op_typeof: + case op_is_empty: case op_is_undefined: case op_is_boolean: case op_is_number: case op_is_string: + case op_is_jsarray: case op_is_object: case op_is_object_or_null: case op_is_function: @@ -384,6 +410,7 @@ case op_div: case op_mod: case op_sub: + case op_pow: case op_lshift: case op_rshift: case op_urshift: @@ -410,11 +437,12 @@ case op_get_scope: case op_create_direct_arguments: case op_create_scoped_arguments: - case op_create_out_of_band_arguments: + case op_create_cloned_arguments: case op_del_by_id: case op_del_by_val: case op_unsigned: case op_get_from_arguments: + case op_create_rest: case op_get_rest_length: { ASSERT(opcodeLengths[opcodeID] > 1); functor(codeBlock, instruction, opcodeID, instruction[1].u.operand); @@ -431,13 +459,6 @@ functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset()); return; } - case op_resume: { - RELEASE_ASSERT(block->successors().size() == 1); - block->successors()[0]->in().forEachSetBit([&](unsigned local) { - functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(local).offset()); - }); - return; - } } } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ByValInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ByValInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ByValInfo.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ByValInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -32,12 +32,15 @@ #include "IndexingType.h" #include "JITStubRoutine.h" #include "Structure.h" -#include "StructureStubInfo.h" namespace JSC { +class Symbol; + #if ENABLE(JIT) +class StructureStubInfo; + enum JITArrayMode { JITInt32, JITDouble, @@ -204,10 +207,11 @@ struct ByValInfo { ByValInfo() { } - ByValInfo(unsigned bytecodeIndex, CodeLocationJump notIndexJump, CodeLocationJump badTypeJump, JITArrayMode arrayMode, ArrayProfile* arrayProfile, int16_t badTypeJumpToDone, int16_t badTypeJumpToNextHotPath, int16_t returnAddressToSlowPath) + ByValInfo(unsigned bytecodeIndex, CodeLocationJump notIndexJump, CodeLocationJump badTypeJump, CodeLocationLabel exceptionHandler, JITArrayMode arrayMode, ArrayProfile* arrayProfile, int16_t badTypeJumpToDone, int16_t badTypeJumpToNextHotPath, int16_t returnAddressToSlowPath) : bytecodeIndex(bytecodeIndex) , notIndexJump(notIndexJump) , badTypeJump(badTypeJump) + , exceptionHandler(exceptionHandler) , arrayMode(arrayMode) , arrayProfile(arrayProfile) , badTypeJumpToDone(badTypeJumpToDone) @@ -223,6 +227,7 @@ unsigned bytecodeIndex; CodeLocationJump notIndexJump; CodeLocationJump badTypeJump; + CodeLocationLabel exceptionHandler; JITArrayMode arrayMode; // The array mode that was baked into the inline JIT code. ArrayProfile* arrayProfile; int16_t badTypeJumpToDone; @@ -231,6 +236,7 @@ unsigned slowPathCount; RefPtr stubRoutine; Identifier cachedId; + WriteBarrier cachedSymbol; StructureStubInfo* stubInfo; bool tookSlowPath : 1; bool seen : 1; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -30,13 +30,29 @@ #include "DFGOperations.h" #include "DFGThunks.h" #include "JSCInlines.h" +#include "Opcode.h" #include "Repatch.h" #include -#include #if ENABLE(JIT) namespace JSC { +CallLinkInfo::CallType CallLinkInfo::callTypeFor(OpcodeID opcodeID) +{ + if (opcodeID == op_call || opcodeID == op_call_eval) + return Call; + if (opcodeID == op_call_varargs) + return CallVarargs; + if (opcodeID == op_construct) + return Construct; + if (opcodeID == op_construct_varargs) + return ConstructVarargs; + if (opcodeID == op_tail_call) + return TailCall; + ASSERT(opcodeID == op_tail_call_varargs || op_tail_call_forward_arguments); + return TailCallVarargs; +} + CallLinkInfo::CallLinkInfo() : m_hasSeenShouldRepatch(false) , m_hasSeenClosure(false) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkInfo.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,7 +31,6 @@ #include "CodeSpecializationKind.h" #include "JITWriteBarrier.h" #include "JSFunction.h" -#include "Opcode.h" #include "PolymorphicCallStubRoutine.h" #include "WriteBarrier.h" #include @@ -40,26 +39,13 @@ #if ENABLE(JIT) +enum OpcodeID : unsigned; struct CallFrameShuffleData; class CallLinkInfo : public BasicRawSentinelNode { public: enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs, TailCall, TailCallVarargs }; - static CallType callTypeFor(OpcodeID opcodeID) - { - if (opcodeID == op_call || opcodeID == op_call_eval) - return Call; - if (opcodeID == op_call_varargs) - return CallVarargs; - if (opcodeID == op_construct) - return Construct; - if (opcodeID == op_construct_varargs) - return ConstructVarargs; - if (opcodeID == op_tail_call) - return TailCall; - ASSERT(opcodeID == op_tail_call_varargs); - return TailCallVarargs; - } + static CallType callTypeFor(OpcodeID opcodeID); static bool isVarargsCallType(CallType callType) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -30,6 +30,7 @@ #include "CodeBlock.h" #include "DFGJITCode.h" #include "InlineCallFrame.h" +#include "Interpreter.h" #include "LLIntCallLinkInfo.h" #include "JSCInlines.h" #include @@ -342,6 +343,9 @@ if (m_couldTakeSlowPath) out.print(comma, "Could Take Slow Path"); + if (m_isBasedOnStub) + out.print(comma, "Based On Stub"); + if (!m_variants.isEmpty()) out.print(comma, listDump(m_variants)); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkStatus.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkStatus.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CallLinkStatus.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CallLinkStatus.h 2016-11-03 07:04:20.000000000 +0000 @@ -101,6 +101,8 @@ bool couldTakeSlowPath() const { return m_couldTakeSlowPath; } + void setCouldTakeSlowPath(bool value) { m_couldTakeSlowPath = value; } + CallVariantList variants() const { return m_variants; } unsigned size() const { return m_variants.size(); } CallVariant at(unsigned i) const { return m_variants[i]; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeBlock.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeBlock.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeBlock.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeBlock.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2010, 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008-2010, 2012-2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * * Redistribution and use in source and binary forms, with or without @@ -30,8 +30,10 @@ #include "config.h" #include "CodeBlock.h" +#include "ArithProfile.h" #include "BasicBlockLocation.h" #include "BytecodeGenerator.h" +#include "BytecodeLivenessAnalysis.h" #include "BytecodeUseDef.h" #include "CallLinkStatus.h" #include "DFGCapabilities.h" @@ -45,11 +47,14 @@ #include "InlineCallFrame.h" #include "Interpreter.h" #include "JIT.h" +#include "JITMathIC.h" #include "JSCJSValue.h" #include "JSFunction.h" #include "JSLexicalEnvironment.h" #include "JSModuleEnvironment.h" +#include "LLIntData.h" #include "LLIntEntrypoint.h" +#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" #include "LowLevelInterpreter.h" #include "JSCInlines.h" #include "PCToCodeOriginMap.h" @@ -59,11 +64,14 @@ #include "Repatch.h" #include "SlotVisitorInlines.h" #include "StackVisitor.h" +#include "StructureStubInfo.h" #include "TypeLocationCache.h" #include "TypeProfiler.h" #include "UnlinkedInstructionStream.h" +#include "VMInlines.h" #include #include +#include #include #include #include @@ -229,10 +237,14 @@ out.print(" (NeverInline)"); if (ownerScriptExecutable()->neverOptimize()) out.print(" (NeverOptimize)"); + else if (ownerScriptExecutable()->neverFTLOptimize()) + out.print(" (NeverFTLOptimize)"); if (ownerScriptExecutable()->didTryToEnterInLoop()) out.print(" (DidTryToEnterInLoop)"); if (ownerScriptExecutable()->isStrictMode()) out.print(" (StrictMode)"); + if (m_didFailJITCompilation) + out.print(" (JITFail)"); if (this->jitType() == JITCode::BaselineJIT && m_didFailFTLCompilation) out.print(" (FTLFail)"); if (this->jitType() == JITCode::BaselineJIT && m_hasBeenCompiledWithFTL) @@ -274,6 +286,10 @@ postfix[index++] = 'i'; if (regExp->multiline()) postfix[index] = 'm'; + if (regExp->sticky()) + postfix[index++] = 'y'; + if (regExp->unicode()) + postfix[index++] = 'u'; return toCString("/", regExp->pattern().impl(), postfix); } @@ -337,6 +353,12 @@ case op_get_by_id: op = "get_by_id"; break; + case op_get_by_id_proto_load: + op = "get_by_id_proto_load"; + break; + case op_get_by_id_unset: + op = "get_by_id_unset"; + break; case op_get_array_length: op = "array_length"; break; @@ -397,6 +419,8 @@ out.printf(" llint("); dumpStructure(out, "struct", structure, ident); out.printf(")"); + if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_by_id_proto_load) + out.printf(" proto(%p)", instruction[6].u.pointer); } #if ENABLE(JIT) @@ -422,6 +446,9 @@ case CacheType::Unset: out.printf("unset"); break; + case CacheType::ArrayLength: + out.printf("ArrayLength"); + break; default: RELEASE_ASSERT_NOT_REACHED(); break; @@ -507,7 +534,8 @@ int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; printLocationAndOp(out, exec, location, it, op); - out.printf("%s, %s, %d, %d", registerName(dst).data(), registerName(func).data(), argCount, registerOffset); + out.print(registerName(dst), ", ", registerName(func), ", ", argCount, ", ", registerOffset); + out.print(" (this at ", virtualRegisterForArgument(0, -registerOffset), ")"); if (cacheDumpMode == DumpCaches) { LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo; if (callLinkInfo->lastSeenCallee) { @@ -587,6 +615,7 @@ static_cast(instructions().size()), static_cast(instructions().size() * sizeof(Instruction)), m_numParameters, m_numCalleeLocals, m_numVars); + out.print("; scope at ", scopeRegister()); out.printf("\n"); StubInfoMap stubInfos; @@ -670,18 +699,6 @@ } while (i < m_rareData->m_stringSwitchJumpTables.size()); } - if (m_rareData && !m_rareData->m_liveCalleeLocalsAtYield.isEmpty()) { - out.printf("\nLive Callee Locals:\n"); - unsigned i = 0; - do { - const FastBitVector& liveness = m_rareData->m_liveCalleeLocalsAtYield[i]; - out.printf(" live%1u = ", i); - liveness.dump(out); - out.printf("\n"); - ++i; - } while (i < m_rareData->m_liveCalleeLocalsAtYield.size()); - } - out.printf("\n"); } @@ -745,7 +762,7 @@ out.print(name, profile->m_counter); } -void CodeBlock::dumpResultProfile(PrintStream& out, ResultProfile* profile, bool& hasPrintedProfiling) +void CodeBlock::dumpArithProfile(PrintStream& out, ArithProfile* profile, bool& hasPrintedProfiling) { if (!profile) return; @@ -795,17 +812,22 @@ out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); break; } - case op_create_out_of_band_arguments: { + case op_create_cloned_arguments: { int r0 = (++it)->u.operand; - printLocationAndOp(out, exec, location, it, "create_out_of_band_arguments"); + printLocationAndOp(out, exec, location, it, "create_cloned_arguments"); out.printf("%s", registerName(r0).data()); break; } - case op_copy_rest: { + case op_argument_count: { + int r0 = (++it)->u.operand; + printLocationOpAndRegisterOperand(out, exec, location, it, "argument_count", r0); + break; + } + case op_create_rest: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; unsigned argumentOffset = (++it)->u.unsignedValue; - printLocationAndOp(out, exec, location, it, "copy_rest"); + printLocationAndOp(out, exec, location, it, "create_rest"); out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data()); out.printf("ArgumentsOffset: %u", argumentOffset); break; @@ -965,6 +987,7 @@ } case op_to_number: { printUnaryOp(out, exec, location, it, "to_number"); + dumpValueProfiling(out, it, hasPrintedProfiling); break; } case op_to_string: { @@ -994,6 +1017,10 @@ printBinaryOp(out, exec, location, it, "mod"); break; } + case op_pow: { + printBinaryOp(out, exec, location, it, "pow"); + break; + } case op_sub: { printBinaryOp(out, exec, location, it, "sub"); ++it; @@ -1059,6 +1086,10 @@ printUnaryOp(out, exec, location, it, "typeof"); break; } + case op_is_empty: { + printUnaryOp(out, exec, location, it, "is_empty"); + break; + } case op_is_undefined: { printUnaryOp(out, exec, location, it, "is_undefined"); break; @@ -1075,6 +1106,10 @@ printUnaryOp(out, exec, location, it, "is_string"); break; } + case op_is_jsarray: { + printUnaryOp(out, exec, location, it, "is_jsarray"); + break; + } case op_is_object: { printUnaryOp(out, exec, location, it, "is_object"); break; @@ -1091,18 +1126,67 @@ printBinaryOp(out, exec, location, it, "in"); break; } + case op_try_get_by_id: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int id0 = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "try_get_by_id"); + out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data()); + dumpValueProfiling(out, it, hasPrintedProfiling); + break; + } case op_get_by_id: + case op_get_by_id_proto_load: + case op_get_by_id_unset: case op_get_array_length: { printGetByIdOp(out, exec, location, it); printGetByIdCacheStatus(out, exec, location, stubInfos); dumpValueProfiling(out, it, hasPrintedProfiling); break; } + case op_get_by_id_with_this: { + printLocationAndOp(out, exec, location, it, "get_by_id_with_this"); + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + int id0 = (++it)->u.operand; + out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), idName(id0, identifier(id0)).data()); + dumpValueProfiling(out, it, hasPrintedProfiling); + break; + } + case op_get_by_val_with_this: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + int r3 = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "get_by_val_with_this"); + out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data()); + dumpValueProfiling(out, it, hasPrintedProfiling); + break; + } case op_put_by_id: { printPutByIdOp(out, exec, location, it, "put_by_id"); printPutByIdCacheStatus(out, location, stubInfos); break; } + case op_put_by_id_with_this: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int id0 = (++it)->u.operand; + int r2 = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "put_by_id_with_this"); + out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data(), registerName(r2).data()); + break; + } + case op_put_by_val_with_this: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + int r3 = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "put_by_val_with_this"); + out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data()); + break; + } case op_put_getter_by_id: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; @@ -1229,6 +1313,7 @@ int offset = (++it)->u.operand; printLocationAndOp(out, exec, location, it, "jneq_ptr"); out.printf("%s, %d (%p), %d(->%d)", registerName(r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset); + ++it; break; } case op_jless: { @@ -1303,6 +1388,19 @@ printLocationAndOp(out, exec, location, it, "watchdog"); break; } + case op_log_shadow_chicken_prologue: { + int r0 = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "log_shadow_chicken_prologue"); + out.printf("%s", registerName(r0).data()); + break; + } + case op_log_shadow_chicken_tail: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "log_shadow_chicken_tail"); + out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); + break; + } case op_switch_imm: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; @@ -1343,14 +1441,6 @@ out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0); break; } - case op_new_arrow_func_exp: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int f0 = (++it)->u.operand; - printLocationAndOp(out, exec, location, it, "op_new_arrow_func_exp"); - out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0); - break; - } case op_new_func_exp: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; @@ -1367,6 +1457,13 @@ out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0); break; } + case op_set_function_name: { + int funcReg = (++it)->u.operand; + int nameReg = (++it)->u.operand; + printLocationAndOp(out, exec, location, it, "set_function_name"); + out.printf("%s, %s", registerName(funcReg).data(), registerName(nameReg).data()); + break; + } case op_call: { printCallOp(out, exec, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos); break; @@ -1382,7 +1479,8 @@ case op_construct_varargs: case op_call_varargs: - case op_tail_call_varargs: { + case op_tail_call_varargs: + case op_tail_call_forward_arguments: { int result = (++it)->u.operand; int callee = (++it)->u.operand; int thisValue = (++it)->u.operand; @@ -1390,7 +1488,19 @@ int firstFreeRegister = (++it)->u.operand; int varArgOffset = (++it)->u.operand; ++it; - printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : opcode == op_construct_varargs ? "construct_varargs" : "tail_call_varargs"); + const char* opName; + if (opcode == op_call_varargs) + opName = "call_varargs"; + else if (opcode == op_construct_varargs) + opName = "construct_varargs"; + else if (opcode == op_tail_call_varargs) + opName = "tail_call_varargs"; + else if (opcode == op_tail_call_forward_arguments) + opName = "tail_call_forward_arguments"; + else + RELEASE_ASSERT_NOT_REACHED(); + + printLocationAndOp(out, exec, location, it, opName); out.printf("%s, %s, %s, %s, %d, %d", registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset); dumpValueProfiling(out, it, hasPrintedProfiling); break; @@ -1555,27 +1665,6 @@ out.printf("%s, %d", debugHookName(debugHookID), hasBreakpointFlag); break; } - case op_save: { - int generator = (++it)->u.operand; - unsigned liveCalleeLocalsIndex = (++it)->u.unsignedValue; - int offset = (++it)->u.operand; - const FastBitVector& liveness = m_rareData->m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex]; - printLocationAndOp(out, exec, location, it, "save"); - out.printf("%s, ", registerName(generator).data()); - liveness.dump(out); - out.printf("(@live%1u), %d(->%d)", liveCalleeLocalsIndex, offset, location + offset); - break; - } - case op_resume: { - int generator = (++it)->u.operand; - unsigned liveCalleeLocalsIndex = (++it)->u.unsignedValue; - const FastBitVector& liveness = m_rareData->m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex]; - printLocationAndOp(out, exec, location, it, "resume"); - out.printf("%s, ", registerName(generator).data()); - liveness.dump(out); - out.printf("(@live%1u)", liveCalleeLocalsIndex); - break; - } case op_assert: { int condition = (++it)->u.operand; int line = (++it)->u.operand; @@ -1583,16 +1672,6 @@ out.printf("%s, %d", registerName(condition).data(), line); break; } - case op_profile_will_call: { - int function = (++it)->u.operand; - printLocationOpAndRegisterOperand(out, exec, location, it, "profile_will_call", function); - break; - } - case op_profile_did_call: { - int function = (++it)->u.operand; - printLocationOpAndRegisterOperand(out, exec, location, it, "profile_did_call", function); - break; - } case op_end: { int r0 = (++it)->u.operand; printLocationOpAndRegisterOperand(out, exec, location, it, "end", r0); @@ -1664,7 +1743,9 @@ } dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling); - dumpResultProfile(out, resultProfileForBytecodeOffset(location), hasPrintedProfiling); + { + dumpArithProfile(out, arithProfileForBytecodeOffset(location), hasPrintedProfiling); + } #if ENABLE(DFG_JIT) Vector exitSites = exitProfile().exitSitesFor(location); @@ -1724,7 +1805,7 @@ { } - virtual void dump(PrintStream& out) const override + void dump(PrintStream& out) const override { out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast(m_codeBlock->ownerExecutable())), " for ", m_ident); } @@ -1745,6 +1826,7 @@ #if ENABLE(JIT) , m_capabilityLevelState(DFG::CapabilityLevelNotSet) #endif + , m_didFailJITCompilation(false) , m_didFailFTLCompilation(false) , m_hasBeenCompiledWithFTL(false) , m_isConstructor(other.m_isConstructor) @@ -1794,10 +1876,9 @@ m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers; m_rareData->m_switchJumpTables = other.m_rareData->m_switchJumpTables; m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables; - m_rareData->m_liveCalleeLocalsAtYield = other.m_rareData->m_liveCalleeLocalsAtYield; } - heap()->m_codeBlocks.add(this); + heap()->m_codeBlocks->add(this); } CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, @@ -1810,6 +1891,7 @@ #if ENABLE(JIT) , m_capabilityLevelState(DFG::CapabilityLevelNotSet) #endif + , m_didFailJITCompilation(false) , m_didFailFTLCompilation(false) , m_hasBeenCompiledWithFTL(false) , m_isConstructor(unlinkedCodeBlock->isConstructor()) @@ -1858,31 +1940,6 @@ m_constantRegisters[registerIndex].set(*m_vm, this, m_globalObject->jsCellForLinkTimeConstant(type)); } -#if !ASSERT_DISABLED - HashSet, WTF::UnsignedWithZeroKeyHashTraits> clonedConstantSymbolTables; -#endif - { -#if !ASSERT_DISABLED - HashSet clonedSymbolTables; -#endif - bool hasTypeProfiler = !!vm.typeProfiler(); - for (unsigned i = 0; i < m_constantRegisters.size(); i++) { - if (m_constantRegisters[i].get().isEmpty()) - continue; - if (SymbolTable* symbolTable = jsDynamicCast(m_constantRegisters[i].get())) { - ASSERT(clonedSymbolTables.add(symbolTable).isNewEntry); - if (hasTypeProfiler) { - ConcurrentJITLocker locker(symbolTable->m_lock); - symbolTable->prepareForTypeProfiling(locker); - } - m_constantRegisters[i].set(*m_vm, this, symbolTable->cloneScopePart(*m_vm)); -#if !ASSERT_DISABLED - clonedConstantSymbolTables.add(i + FirstConstantRegisterIndex); -#endif - } - } - } - // We already have the cloned symbol table for the module environment since we need to instantiate // the module environments before linking the code block. We replace the stored symbol table with the already cloned one. if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast(unlinkedCodeBlock)) { @@ -1940,7 +1997,7 @@ UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end(); for (; ptr != end; ++ptr) { OffsetLocation offset; - offset.branchOffset = ptr->value; + offset.branchOffset = ptr->value.branchOffset; m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset); } } @@ -1980,11 +2037,17 @@ // Bookkeep the strongly referenced module environments. HashSet stronglyReferencedModuleEnvironments; - // Bookkeep the merge point bytecode offsets. - Vector mergePointBytecodeOffsets; - RefCountedArray instructions(instructionCount); + unsigned valueProfileCount = 0; + auto linkValueProfile = [&](unsigned bytecodeOffset, unsigned opLength) { + unsigned valueProfileIndex = valueProfileCount++; + ValueProfile* profile = &m_valueProfiles[valueProfileIndex]; + ASSERT(profile->m_bytecodeOffset == -1); + profile->m_bytecodeOffset = bytecodeOffset; + instructions[bytecodeOffset + opLength - 1] = profile; + }; + for (unsigned i = 0; !instructionReader.atEnd(); ) { const UnlinkedInstruction* pc = instructionReader.next(); @@ -2006,6 +2069,7 @@ } case op_call_varargs: case op_tail_call_varargs: + case op_tail_call_forward_arguments: case op_construct_varargs: case op_get_by_val: { int arrayProfileIndex = pc[opLength - 2].u.operand; @@ -2016,11 +2080,12 @@ } case op_get_direct_pname: case op_get_by_id: - case op_get_from_arguments: { - ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; - ASSERT(profile->m_bytecodeOffset == -1); - profile->m_bytecodeOffset = i; - instructions[i + opLength - 1] = profile; + case op_get_by_id_with_this: + case op_try_get_by_id: + case op_get_by_val_with_this: + case op_get_from_arguments: + case op_to_number: { + linkValueProfile(i, opLength); break; } case op_put_by_val: { @@ -2057,10 +2122,7 @@ case op_call: case op_tail_call: case op_call_eval: { - ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; - ASSERT(profile->m_bytecodeOffset == -1); - profile->m_bytecodeOffset = i; - instructions[i + opLength - 1] = profile; + linkValueProfile(i, opLength); int arrayProfileIndex = pc[opLength - 2].u.operand; m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i); instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex]; @@ -2069,30 +2131,19 @@ } case op_construct: { instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand]; - ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; - ASSERT(profile->m_bytecodeOffset == -1); - profile->m_bytecodeOffset = i; - instructions[i + opLength - 1] = profile; + linkValueProfile(i, opLength); break; } case op_get_array_length: CRASH(); -#if !ASSERT_DISABLED - case op_create_lexical_environment: { - int symbolTableIndex = pc[3].u.operand; - ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex)); - break; - } -#endif - case op_resolve_scope: { const Identifier& ident = identifier(pc[3].u.operand); ResolveType type = static_cast(pc[4].u.operand); RELEASE_ASSERT(type != LocalClosureVar); int localScopeDepth = pc[5].u.operand; - ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, NotInitialization); + ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization); instructions[i + 4].u.operand = op.type; instructions[i + 5].u.operand = op.depth; if (op.lexicalEnvironment) { @@ -2111,10 +2162,7 @@ } case op_get_from_scope: { - ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; - ASSERT(profile->m_bytecodeOffset == -1); - profile->m_bytecodeOffset = i; - instructions[i + opLength - 1] = profile; + linkValueProfile(i, opLength); // get_from_scope dst, scope, id, GetPutInfo, Structure, Operand @@ -2122,14 +2170,14 @@ instructions[i + 5].u.pointer = nullptr; GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand); - ASSERT(getPutInfo.initializationMode() == NotInitialization); + ASSERT(!isInitialization(getPutInfo.initializationMode())); if (getPutInfo.resolveType() == LocalClosureVar) { instructions[i + 4] = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand(); break; } const Identifier& ident = identifier(pc[3].u.operand); - ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), NotInitialization); + ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), InitializationMode::NotInitialization); instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand(); if (op.type == ModuleVar) @@ -2149,7 +2197,6 @@ // Only do watching if the property we're putting to is not anonymous. if (static_cast(pc[2].u.operand) != UINT_MAX) { int symbolTableIndex = pc[5].u.operand; - ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex)); SymbolTable* symbolTable = jsCast(getConstant(symbolTableIndex)); const Identifier& ident = identifier(pc[2].u.operand); ConcurrentJITLocker locker(symbolTable->m_lock); @@ -2172,7 +2219,7 @@ instructions[i + 5].u.watchpointSet = op.watchpointSet; else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) { if (op.watchpointSet) - op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident)); + op.watchpointSet->invalidate(vm, PutToScopeFireDetail(this, ident)); } else if (op.structure) instructions[i + 5].u.structure.set(vm, this, op.structure); instructions[i + 6].u.pointer = reinterpret_cast(op.operand); @@ -2199,7 +2246,7 @@ ResolveType type = static_cast(pc[5].u.operand); // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because // we're abstractly "read"ing from a JSScope. - ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, NotInitialization); + ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization); if (op.type == ClosureVar || op.type == ModuleVar) symbolTable = op.lexicalEnvironment->symbolTable(); @@ -2220,7 +2267,6 @@ } case ProfileTypeBytecodeLocallyResolved: { int symbolTableIndex = pc[2].u.operand; - ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex)); SymbolTable* symbolTable = jsCast(getConstant(symbolTableIndex)); const Identifier& ident = identifier(pc[4].u.operand); ConcurrentJITLocker locker(symbolTable->m_lock); @@ -2273,15 +2319,6 @@ break; } - case op_save: { - unsigned liveCalleeLocalsIndex = pc[2].u.index; - int offset = pc[3].u.operand; - if (liveCalleeLocalsIndex >= mergePointBytecodeOffsets.size()) - mergePointBytecodeOffsets.resize(liveCalleeLocalsIndex + 1); - mergePointBytecodeOffsets[liveCalleeLocalsIndex] = i + offset; - break; - } - default: break; } @@ -2293,20 +2330,6 @@ m_instructions = WTFMove(instructions); - // Perform bytecode liveness analysis to determine which locals are live and should be resumed when executing op_resume. - if (unlinkedCodeBlock->parseMode() == SourceParseMode::GeneratorBodyMode) { - if (size_t count = mergePointBytecodeOffsets.size()) { - createRareDataIfNecessary(); - BytecodeLivenessAnalysis liveness(this); - m_rareData->m_liveCalleeLocalsAtYield.grow(count); - size_t liveCalleeLocalsIndex = 0; - for (size_t bytecodeOffset : mergePointBytecodeOffsets) { - m_rareData->m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex] = liveness.getLivenessInfoAtBytecodeOffset(bytecodeOffset); - ++liveCalleeLocalsIndex; - } - } - } - // Set optimization thresholds only after m_instructions is initialized, since these // rely on the instruction count (and are in theory permitted to also inspect the // instruction stream to more accurate assess the cost of tier-up). @@ -2321,7 +2344,7 @@ if (Options::dumpGeneratedBytecodes()) dumpBytecode(); - heap()->m_codeBlocks.add(this); + heap()->m_codeBlocks->add(this); heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction)); } @@ -2335,6 +2358,7 @@ #if ENABLE(JIT) , m_capabilityLevelState(DFG::CannotCompile) #endif + , m_didFailJITCompilation(false) , m_didFailFTLCompilation(false) , m_hasBeenCompiledWithFTL(false) , m_isConstructor(false) @@ -2357,7 +2381,7 @@ { Base::finishCreation(vm); - heap()->m_codeBlocks.add(this); + heap()->m_codeBlocks->add(this); } #endif @@ -2365,7 +2389,10 @@ { if (m_vm->m_perBytecodeProfiler) m_vm->m_perBytecodeProfiler->notifyDestruction(this); - + + if (unlinkedCodeBlock()->didOptimize() == MixedTriState) + unlinkedCodeBlock()->setDidOptimize(FalseTriState); + #if ENABLE(VERBOSE_VALUE_PROFILE) dumpValueProfiles(); #endif @@ -2391,6 +2418,36 @@ #endif // ENABLE(JIT) } +void CodeBlock::setConstantRegisters(const Vector>& constants, const Vector& constantsSourceCodeRepresentation) +{ + ASSERT(constants.size() == constantsSourceCodeRepresentation.size()); + size_t count = constants.size(); + m_constantRegisters.resizeToFit(count); + bool hasTypeProfiler = !!m_vm->typeProfiler(); + for (size_t i = 0; i < count; i++) { + JSValue constant = constants[i].get(); + + if (!constant.isEmpty()) { + if (SymbolTable* symbolTable = jsDynamicCast(constant)) { + if (hasTypeProfiler) { + ConcurrentJITLocker locker(symbolTable->m_lock); + symbolTable->prepareForTypeProfiling(locker); + } + + SymbolTable* clone = symbolTable->cloneScopePart(*m_vm); + if (wasCompiledWithDebuggingOpcodes()) + clone->setRareDataCodeBlock(this); + + constant = clone; + } + } + + m_constantRegisters[i].set(*m_vm, this, constant); + } + + m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation; +} + void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative) { m_alternative.set(vm, this, alternative); @@ -2428,7 +2485,7 @@ if (!setByMe) return; - if (Heap::isMarked(this)) + if (Heap::isMarkedConcurrently(this)) return; if (shouldVisitStrongly()) { @@ -2536,18 +2593,60 @@ return !Heap::isMarked(this); } +static std::chrono::milliseconds timeToLive(JITCode::JITType jitType) +{ + if (UNLIKELY(Options::useEagerCodeBlockJettisonTiming())) { + switch (jitType) { + case JITCode::InterpreterThunk: + return std::chrono::milliseconds(10); + case JITCode::BaselineJIT: + return std::chrono::milliseconds(10 + 20); + case JITCode::DFGJIT: + return std::chrono::milliseconds(40); + case JITCode::FTLJIT: + return std::chrono::milliseconds(120); + default: + return std::chrono::milliseconds::max(); + } + } + + switch (jitType) { + case JITCode::InterpreterThunk: + return std::chrono::duration_cast(std::chrono::seconds(5)); + case JITCode::BaselineJIT: + // Effectively 10 additional seconds, since BaselineJIT and + // InterpreterThunk share a CodeBlock. + return std::chrono::duration_cast(std::chrono::seconds(5 + 10)); + case JITCode::DFGJIT: + return std::chrono::duration_cast(std::chrono::seconds(20)); + case JITCode::FTLJIT: + return std::chrono::duration_cast(std::chrono::seconds(60)); + default: + return std::chrono::milliseconds::max(); + } +} + bool CodeBlock::shouldJettisonDueToOldAge() { - return false; + if (Heap::isMarkedConcurrently(this)) + return false; + + if (UNLIKELY(Options::forceCodeBlockToJettisonDueToOldAge())) + return true; + + if (timeSinceCreation() < timeToLive(jitType())) + return false; + + return true; } #if ENABLE(DFG_JIT) static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition) { - if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get())) + if (transition.m_codeOrigin && !Heap::isMarkedConcurrently(transition.m_codeOrigin.get())) return false; - if (!Heap::isMarked(transition.m_from.get())) + if (!Heap::isMarkedConcurrently(transition.m_from.get())) return false; return true; @@ -2578,7 +2677,7 @@ m_vm->heap.structureIDTable().get(oldStructureID); Structure* newStructure = m_vm->heap.structureIDTable().get(newStructureID); - if (Heap::isMarked(oldStructure)) + if (Heap::isMarkedConcurrently(oldStructure)) visitor.appendUnbarrieredReadOnlyPointer(newStructure); else allAreMarkedSoFar = false; @@ -2592,32 +2691,16 @@ #if ENABLE(JIT) if (JITCode::isJIT(jitType())) { - for (Bag::iterator iter = m_stubInfos.begin(); !!iter; ++iter) { - StructureStubInfo& stubInfo = **iter; - if (stubInfo.cacheType != CacheType::Stub) - continue; - PolymorphicAccess* list = stubInfo.u.stub; - JSCell* origin = stubInfo.codeOrigin.codeOriginOwner(); - if (origin && !Heap::isMarked(origin)) { - allAreMarkedSoFar = false; - continue; - } - for (unsigned j = list->size(); j--;) { - const AccessCase& access = list->at(j); - if (access.type() != AccessCase::Transition) - continue; - if (Heap::isMarked(access.structure())) - visitor.appendUnbarrieredReadOnlyPointer(access.newStructure()); - else - allAreMarkedSoFar = false; - } - } + for (Bag::iterator iter = m_stubInfos.begin(); !!iter; ++iter) + allAreMarkedSoFar &= (*iter)->propagateTransitions(visitor); } #endif // ENABLE(JIT) #if ENABLE(DFG_JIT) if (JITCode::isOptimizingJIT(jitType())) { DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); + for (auto& weakReference : dfgCommon->weakStructureReferences) + allAreMarkedSoFar &= weakReference->markIfCheap(visitor); for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) { if (shouldMarkTransition(dfgCommon->transitions[i])) { @@ -2666,14 +2749,14 @@ // GC we still have not proved liveness, then this code block is toast. bool allAreLiveSoFar = true; for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) { - if (!Heap::isMarked(dfgCommon->weakReferences[i].get())) { + if (!Heap::isMarkedConcurrently(dfgCommon->weakReferences[i].get())) { allAreLiveSoFar = false; break; } } if (allAreLiveSoFar) { for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) { - if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) { + if (!Heap::isMarkedConcurrently(dfgCommon->weakStructureReferences[i].get())) { allAreLiveSoFar = false; break; } @@ -2702,6 +2785,14 @@ codeBlock->determineLiveness(visitor); } +void CodeBlock::clearLLIntGetByIdCache(Instruction* instruction) +{ + instruction[0].u.opcode = LLInt::getOpcode(op_get_by_id); + instruction[4].u.pointer = nullptr; + instruction[5].u.pointer = nullptr; + instruction[6].u.pointer = nullptr; +} + void CodeBlock::finalizeLLIntInlineCaches() { #if ENABLE(WEBASSEMBLY) @@ -2714,14 +2805,15 @@ for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]]; switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { - case op_get_by_id: { + case op_get_by_id: + case op_get_by_id_proto_load: + case op_get_by_id_unset: { StructureID oldStructureID = curInstruction[4].u.structureID; if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) break; if (Options::verboseOSR()) dataLogF("Clearing LLInt property access.\n"); - curInstruction[4].u.structureID = 0; - curInstruction[5].u.operand = 0; + clearLLIntGetByIdCache(curInstruction); break; } case op_put_by_id: { @@ -2795,6 +2887,12 @@ } } + // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set + // then cleared the cache without GCing in between. + m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool { + return !Heap::isMarked(pair.key); + }); + for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) { if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) { if (Options::verboseOSR()) @@ -2848,7 +2946,8 @@ void CodeBlock::getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result) { #if ENABLE(JIT) - toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result); + if (JITCode::isJIT(jitType())) + toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result); #else UNUSED_PARAM(result); #endif @@ -2863,7 +2962,8 @@ void CodeBlock::getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result) { #if ENABLE(JIT) - toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result); + if (JITCode::isJIT(jitType())) + toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result); #else UNUSED_PARAM(result); #endif @@ -2878,8 +2978,10 @@ void CodeBlock::getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result) { #if ENABLE(JIT) - for (auto* byValInfo : m_byValInfos) - result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo); + if (JITCode::isJIT(jitType())) { + for (auto* byValInfo : m_byValInfos) + result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo); + } #else UNUSED_PARAM(result); #endif @@ -2898,6 +3000,21 @@ return m_stubInfos.add(accessType); } +JITAddIC* CodeBlock::addJITAddIC() +{ + return m_addICs.add(); +} + +JITMulIC* CodeBlock::addJITMulIC() +{ + return m_mulICs.add(); +} + +JITSubIC* CodeBlock::addJITSubIC() +{ + return m_subICs.add(); +} + StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin) { for (StructureStubInfo* stubInfo : m_stubInfos) { @@ -2927,6 +3044,24 @@ } return nullptr; } + +void CodeBlock::resetJITData() +{ + RELEASE_ASSERT(!JITCode::isJIT(jitType())); + ConcurrentJITLocker locker(m_lock); + + // We can clear these because no other thread will have references to any stub infos, call + // link infos, or by val infos if we don't have JIT code. Attempts to query these data + // structures using the concurrent API (getStubInfoMap and friends) will return nothing if we + // don't have JIT code. + m_stubInfos.clear(); + m_callLinkInfos.clear(); + m_byValInfos.clear(); + + // We can clear this because the DFG's queries to these data structures are guarded by whether + // there is JIT code. + m_rareCaseProfiles.clear(); +} #endif void CodeBlock::visitOSRExitTargets(SlotVisitor& visitor) @@ -2964,6 +3099,11 @@ for (unsigned i = 0; i < m_objectAllocationProfiles.size(); ++i) m_objectAllocationProfiles[i].visitAggregate(visitor); +#if ENABLE(JIT) + for (ByValInfo* byValInfo : m_byValInfos) + visitor.append(&byValInfo->cachedSymbol); +#endif + #if ENABLE(DFG_JIT) if (JITCode::isOptimizingJIT(jitType())) visitOSRExitTargets(visitor); @@ -3054,21 +3194,7 @@ { if (!m_rareData) return 0; - - Vector& exceptionHandlers = m_rareData->m_exceptionHandlers; - for (size_t i = 0; i < exceptionHandlers.size(); ++i) { - HandlerInfo& handler = exceptionHandlers[i]; - if ((requiredHandler == RequiredHandler::CatchHandler) && !handler.isCatchHandler()) - continue; - - // Handlers are ordered innermost first, so the first handler we encounter - // that contains the source address is the correct handler to use. - // This index used is either the BytecodeOffset or a CallSiteIndex. - if (handler.start <= index && handler.end > index) - return &handler; - } - - return 0; + return HandlerInfo::handlerForIndex(m_rareData->m_exceptionHandlers, index, requiredHandler); } CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite) @@ -3121,7 +3247,7 @@ return column; } -void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) +void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const { m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column); divot += m_sourceOffset; @@ -3152,8 +3278,9 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) { + ConcurrentJITLocker locker(m_lock); + m_rareCaseProfiles.shrinkToFit(); - m_resultProfiles.shrinkToFit(); if (shrinkMode == EarlyShrink) { m_constantRegisters.shrinkToFit(); @@ -3162,7 +3289,6 @@ if (m_rareData) { m_rareData->m_switchJumpTables.shrinkToFit(); m_rareData->m_stringSwitchJumpTables.shrinkToFit(); - m_rareData->m_liveCalleeLocalsAtYield.shrinkToFit(); } } // else don't shrink these, because we would have already pointed pointers into these tables. } @@ -3266,6 +3392,8 @@ UNUSED_PARAM(mode); UNUSED_PARAM(detail); #endif + + CODEBLOCK_LOG_EVENT(this, "jettison", ("due to ", reason, ", counting = ", mode == CountReoptimization, ", detail = ", pointerDump(detail))); RELEASE_ASSERT(reason != Profiler::NotJettisoned); @@ -3318,7 +3446,7 @@ // This accomplishes (1), and does its own book-keeping about whether it has already happened. if (!jitCode()->dfgCommon()->invalidate()) { // We've already been invalidated. - RELEASE_ASSERT(this != replacement()); + RELEASE_ASSERT(this != replacement() || (m_vm->heap.isCollecting() && !Heap::isMarked(ownerScriptExecutable()))); return; } } @@ -3348,6 +3476,11 @@ tallyFrequentExitSites(); #endif // ENABLE(DFG_JIT) + // Jettison can happen during GC. We don't want to install code to a dead executable + // because that would add a dead object to the remembered set. + if (m_vm->heap.isCollecting() && !Heap::isMarked(ownerScriptExecutable())) + return; + // This accomplishes (2). ownerScriptExecutable()->installCode( m_globalObject->vm(), alternative(), codeType(), specializationKind()); @@ -3375,7 +3508,7 @@ , m_didRecurse(false) { } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { CallFrame* currentCallFrame = visitor->callFrame(); @@ -3400,9 +3533,9 @@ private: CallFrame* m_startCallFrame; CodeBlock* m_codeBlock; - unsigned m_depthToCheck; - bool m_foundStartCallFrame; - bool m_didRecurse; + mutable unsigned m_depthToCheck; + mutable bool m_foundStartCallFrame; + mutable bool m_didRecurse; }; void CodeBlock::noticeIncomingCall(ExecState* callerFrame) @@ -3807,7 +3940,7 @@ } #endif -ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset) +ArrayProfile* CodeBlock::getArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset) { for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) { if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset) @@ -3816,12 +3949,36 @@ return 0; } -ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset) +ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset) +{ + ConcurrentJITLocker locker(m_lock); + return getArrayProfile(locker, bytecodeOffset); +} + +ArrayProfile* CodeBlock::addArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset) +{ + m_arrayProfiles.append(ArrayProfile(bytecodeOffset)); + return &m_arrayProfiles.last(); +} + +ArrayProfile* CodeBlock::addArrayProfile(unsigned bytecodeOffset) +{ + ConcurrentJITLocker locker(m_lock); + return addArrayProfile(locker, bytecodeOffset); +} + +ArrayProfile* CodeBlock::getOrAddArrayProfile(const ConcurrentJITLocker& locker, unsigned bytecodeOffset) { - ArrayProfile* result = getArrayProfile(bytecodeOffset); + ArrayProfile* result = getArrayProfile(locker, bytecodeOffset); if (result) return result; - return addArrayProfile(bytecodeOffset); + return addArrayProfile(locker, bytecodeOffset); +} + +ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset) +{ + ConcurrentJITLocker locker(m_lock); + return getOrAddArrayProfile(locker, bytecodeOffset); } #if ENABLE(DFG_JIT) @@ -3998,11 +4155,6 @@ RareCaseProfile* profile = rareCaseProfile(i); dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); } - dataLog("ResultProfile for ", *this, ":\n"); - for (unsigned i = 0; i < numberOfResultProfiles(); ++i) { - const ResultProfile& profile = *resultProfile(i); - dataLog(" bc = ", profile.bytecodeOffset(), ": ", profile, "\n"); - } } #endif // ENABLE(VERBOSE_VALUE_PROFILE) @@ -4042,12 +4194,12 @@ if (!m_vm) return 0; - if (!m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT) + if (!*m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT) return 0; // It's as good of a prediction as we'll get. // Be conservative: return a size that will be an overestimation 84% of the time. - double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() + - m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation(); + double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT->mean() + + m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT->standardDeviation(); // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing // here is OK, since this whole method is just a heuristic. @@ -4118,14 +4270,9 @@ ValueProfile* CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset) { - ValueProfile* result = binarySearch( - m_valueProfiles, m_valueProfiles.size(), bytecodeOffset, - getValueProfileBytecodeOffset); - ASSERT(result->m_bytecodeOffset != -1); - ASSERT(instructions()[bytecodeOffset + opcodeLength( - m_vm->interpreter->getOpcodeID( - instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result); - return result; + OpcodeID opcodeID = m_vm->interpreter->getOpcodeID(instructions()[bytecodeOffset].u.opcode); + unsigned length = opcodeLength(opcodeID); + return instructions()[bytecodeOffset + length - 1].u.profile; } void CodeBlock::validate() @@ -4184,6 +4331,12 @@ jettison(Profiler::JettisonDueToDebuggerStepping); } +RareCaseProfile* CodeBlock::addRareCaseProfile(int bytecodeOffset) +{ + m_rareCaseProfiles.append(RareCaseProfile(bytecodeOffset)); + return &m_rareCaseProfiles.last(); +} + RareCaseProfile* CodeBlock::rareCaseProfileForBytecodeOffset(int bytecodeOffset) { return tryBinarySearch( @@ -4199,14 +4352,55 @@ return 0; } -ResultProfile* CodeBlock::resultProfileForBytecodeOffset(int bytecodeOffset) +ArithProfile* CodeBlock::arithProfileForBytecodeOffset(int bytecodeOffset) { - if (!m_bytecodeOffsetToResultProfileIndexMap) - return nullptr; - auto iterator = m_bytecodeOffsetToResultProfileIndexMap->find(bytecodeOffset); - if (iterator == m_bytecodeOffsetToResultProfileIndexMap->end()) + auto opcodeID = vm()->interpreter->getOpcodeID(instructions()[bytecodeOffset].u.opcode); + switch (opcodeID) { + case op_bitor: + case op_bitand: + case op_bitxor: + case op_add: + case op_mul: + case op_sub: + case op_div: + break; + default: return nullptr; - return &m_resultProfiles[iterator->value]; + } + + return &arithProfileForPC(instructions().begin() + bytecodeOffset); +} + +ArithProfile& CodeBlock::arithProfileForPC(Instruction* pc) +{ + if (!ASSERT_DISABLED) { + ASSERT(pc >= instructions().begin() && pc < instructions().end()); + auto opcodeID = vm()->interpreter->getOpcodeID(pc[0].u.opcode); + switch (opcodeID) { + case op_bitor: + case op_bitand: + case op_bitxor: + case op_add: + case op_mul: + case op_sub: + case op_div: + break; + default: + ASSERT_NOT_REACHED(); + } + } + + return *bitwise_cast(&pc[4].u.operand); +} + +bool CodeBlock::couldTakeSpecialFastCase(int bytecodeOffset) +{ + if (!hasBaselineJITProfiling()) + return false; + ArithProfile* profile = arithProfileForBytecodeOffset(bytecodeOffset); + if (!profile) + return false; + return profile->tookSpecialFastPath(); } #if ENABLE(JIT) @@ -4313,4 +4507,110 @@ } #endif // ENABLE(JIT) +Optional CodeBlock::bytecodeOffsetFromCallSiteIndex(CallSiteIndex callSiteIndex) +{ + Optional bytecodeOffset; + JITCode::JITType jitType = this->jitType(); + if (jitType == JITCode::InterpreterThunk || jitType == JITCode::BaselineJIT) { +#if USE(JSVALUE64) + bytecodeOffset = callSiteIndex.bits(); +#else + Instruction* instruction = bitwise_cast(callSiteIndex.bits()); + bytecodeOffset = instruction - instructions().begin(); +#endif + } else if (jitType == JITCode::DFGJIT || jitType == JITCode::FTLJIT) { +#if ENABLE(DFG_JIT) + RELEASE_ASSERT(canGetCodeOrigin(callSiteIndex)); + CodeOrigin origin = codeOrigin(callSiteIndex); + bytecodeOffset = origin.bytecodeIndex; +#else + RELEASE_ASSERT_NOT_REACHED(); +#endif + } + + return bytecodeOffset; +} + +int32_t CodeBlock::thresholdForJIT(int32_t threshold) +{ + switch (unlinkedCodeBlock()->didOptimize()) { + case MixedTriState: + return threshold; + case FalseTriState: + return threshold * 4; + case TrueTriState: + return threshold / 2; + } + ASSERT_NOT_REACHED(); + return threshold; +} + +void CodeBlock::jitAfterWarmUp() +{ + m_llintExecuteCounter.setNewThreshold(thresholdForJIT(Options::thresholdForJITAfterWarmUp()), this); +} + +void CodeBlock::jitSoon() +{ + m_llintExecuteCounter.setNewThreshold(thresholdForJIT(Options::thresholdForJITSoon()), this); +} + +void CodeBlock::dumpMathICStats() +{ +#if ENABLE(MATH_IC_STATS) + double numAdds = 0.0; + double totalAddSize = 0.0; + double numMuls = 0.0; + double totalMulSize = 0.0; + double numSubs = 0.0; + double totalSubSize = 0.0; + + auto countICs = [&] (CodeBlock* codeBlock) { + for (JITAddIC* addIC : codeBlock->m_addICs) { + numAdds++; + totalAddSize += addIC->codeSize(); + } + + for (JITMulIC* mulIC : codeBlock->m_mulICs) { + numMuls++; + totalMulSize += mulIC->codeSize(); + } + + for (JITSubIC* subIC : codeBlock->m_subICs) { + numSubs++; + totalSubSize += subIC->codeSize(); + } + + return false; + }; + heap()->forEachCodeBlock(countICs); + + dataLog("Num Adds: ", numAdds, "\n"); + dataLog("Total Add size in bytes: ", totalAddSize, "\n"); + dataLog("Average Add size: ", totalAddSize / numAdds, "\n"); + dataLog("\n"); + dataLog("Num Muls: ", numMuls, "\n"); + dataLog("Total Mul size in bytes: ", totalMulSize, "\n"); + dataLog("Average Mul size: ", totalMulSize / numMuls, "\n"); + dataLog("\n"); + dataLog("Num Subs: ", numSubs, "\n"); + dataLog("Total Sub size in bytes: ", totalSubSize, "\n"); + dataLog("Average Sub size: ", totalSubSize / numSubs, "\n"); + + dataLog("-----------------------\n"); +#endif +} + +BytecodeLivenessAnalysis& CodeBlock::livenessAnalysisSlow() +{ + std::unique_ptr analysis = std::make_unique(this); + { + ConcurrentJITLocker locker(m_lock); + if (!m_livenessAnalysis) + m_livenessAnalysis = WTFMove(analysis); + return *m_livenessAnalysis; + } +} + + } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeBlock.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008-2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * * Redistribution and use in source and binary forms, with or without @@ -33,7 +33,6 @@ #include "ArrayProfile.h" #include "ByValInfo.h" #include "BytecodeConventions.h" -#include "BytecodeLivenessAnalysis.h" #include "CallLinkInfo.h" #include "CallReturnOffsetToBytecodeOffset.h" #include "CodeBlockHash.h" @@ -51,19 +50,19 @@ #include "HandlerInfo.h" #include "Instruction.h" #include "JITCode.h" +#include "JITMathICForwards.h" #include "JITWriteBarrier.h" #include "JSCell.h" #include "JSGlobalObject.h" #include "JumpTable.h" #include "LLIntCallLinkInfo.h" +#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" #include "LazyOperandValueProfile.h" #include "ObjectAllocationProfile.h" #include "Options.h" -#include "ProfilerCompilation.h" #include "ProfilerJettisonReason.h" #include "PutPropertySlot.h" #include "RegExpObject.h" -#include "StructureStubInfo.h" #include "UnconditionalFinalizer.h" #include "ValueProfile.h" #include "VirtualRegister.h" @@ -79,12 +78,21 @@ namespace JSC { +class BytecodeLivenessAnalysis; class ExecState; +class JITAddGenerator; +class JSModuleEnvironment; class LLIntOffsetsExtractor; +class PCToCodeOriginMap; class RegisterAtOffsetList; +class StructureStubInfo; class TypeLocation; -class JSModuleEnvironment; -class PCToCodeOriginMap; + +enum class AccessType : int8_t; + +struct ArithProfile; + +typedef HashMap StubInfoMap; enum ReoptimizationMode { DontCountReoptimization, CountReoptimization }; @@ -95,11 +103,11 @@ friend class LLIntOffsetsExtractor; class UnconditionalFinalizer : public JSC::UnconditionalFinalizer { - virtual void finalizeUnconditionally() override; + void finalizeUnconditionally() override; }; class WeakReferenceHarvester : public JSC::WeakReferenceHarvester { - virtual void visitWeakReferences(SlotVisitor&) override; + void visitWeakReferences(SlotVisitor&) override; }; public: @@ -137,7 +145,7 @@ CString sourceCodeForTools() const; // Not quite the actual source we parsed; this will do things like prefix the source for a function with a reified signature. CString sourceCodeOnOneLine() const; // As sourceCodeForTools(), but replaces all whitespace runs with a single space. void dumpAssumingJITType(PrintStream&, JITCode::JITType) const; - void dump(PrintStream&) const; + JS_EXPORT_PRIVATE void dump(PrintStream&) const; int numParameters() const { return m_numParameters; } void setNumParameters(int newValue); @@ -197,6 +205,8 @@ void printStructures(PrintStream&, const Instruction*); void printStructure(PrintStream&, const char* name, const Instruction*, int operand); + void dumpMathICStats(); + bool isStrictMode() const { return m_isStrictMode; } ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; } @@ -216,17 +226,15 @@ return index >= m_numVars; } - enum class RequiredHandler { - CatchHandler, - AnyHandler - }; HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler); HandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler); void removeExceptionHandlerForCallSite(CallSiteIndex); unsigned lineNumberForBytecodeOffset(unsigned bytecodeOffset); unsigned columnNumberForBytecodeOffset(unsigned bytecodeOffset); void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, - int& startOffset, int& endOffset, unsigned& line, unsigned& column); + int& startOffset, int& endOffset, unsigned& line, unsigned& column) const; + + Optional bytecodeOffsetFromCallSiteIndex(CallSiteIndex); void getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result); void getStubInfoMap(StubInfoMap& result); @@ -239,6 +247,9 @@ #if ENABLE(JIT) StructureStubInfo* addStubInfo(AccessType); + JITAddIC* addJITAddIC(); + JITMulIC* addJITMulIC(); + JITSubIC* addJITSubIC(); Bag::iterator stubInfoBegin() { return m_stubInfos.begin(); } Bag::iterator stubInfoEnd() { return m_stubInfos.end(); } @@ -256,6 +267,13 @@ // that there had been inlining. Chances are if you want to use this, you're really // looking for a CallLinkInfoMap to amortize the cost of calling this. CallLinkInfo* getCallLinkInfoForBytecodeIndex(unsigned bytecodeIndex); + + // We call this when we want to reattempt compiling something with the baseline JIT. Ideally + // the baseline JIT would not add data to CodeBlock, but instead it would put its data into + // a newly created JITCode, which could be thrown away if we bail on JIT compilation. Then we + // would be able to get rid of this silly function. + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=159061 + void resetJITData(); #endif // ENABLE(JIT) void unlinkIncomingCalls(); @@ -275,6 +293,8 @@ { return m_jitCodeMap.get(); } + + static void clearLLIntGetByIdCache(Instruction*); unsigned bytecodeOffset(Instruction* returnAddress) { @@ -282,6 +302,9 @@ return static_cast(returnAddress) - instructions().begin(); } + typedef JSC::Instruction Instruction; + typedef RefCountedArray& UnpackedInstructions; + unsigned numberOfInstructions() const { return m_instructions.size(); } RefCountedArray& instructions() { return m_instructions; } const RefCountedArray& instructions() const { return m_instructions; } @@ -335,8 +358,7 @@ ExecutableBase* ownerExecutable() const { return m_ownerExecutable.get(); } ScriptExecutable* ownerScriptExecutable() const { return jsCast(m_ownerExecutable.get()); } - void setVM(VM* vm) { m_vm = vm; } - VM* vm() { return m_vm; } + VM* vm() const { return m_vm; } void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; } VirtualRegister thisRegister() const { return m_thisRegister; } @@ -407,11 +429,7 @@ return valueProfile(index - numberOfArgumentValueProfiles()); } - RareCaseProfile* addRareCaseProfile(int bytecodeOffset) - { - m_rareCaseProfiles.append(RareCaseProfile(bytecodeOffset)); - return &m_rareCaseProfiles.last(); - } + RareCaseProfile* addRareCaseProfile(int bytecodeOffset); unsigned numberOfRareCaseProfiles() { return m_rareCaseProfiles.size(); } RareCaseProfile* rareCaseProfileForBytecodeOffset(int bytecodeOffset); unsigned rareCaseProfileCountForBytecodeOffset(int bytecodeOffset); @@ -432,46 +450,18 @@ return value >= Options::couldTakeSlowCaseMinimumCount(); } - ResultProfile* ensureResultProfile(int bytecodeOffset) - { - ResultProfile* profile = resultProfileForBytecodeOffset(bytecodeOffset); - if (!profile) { - m_resultProfiles.append(ResultProfile(bytecodeOffset)); - profile = &m_resultProfiles.last(); - ASSERT(&m_resultProfiles.last() == &m_resultProfiles[m_resultProfiles.size() - 1]); - if (!m_bytecodeOffsetToResultProfileIndexMap) - m_bytecodeOffsetToResultProfileIndexMap = std::make_unique(); - m_bytecodeOffsetToResultProfileIndexMap->add(bytecodeOffset, m_resultProfiles.size() - 1); - } - return profile; - } - unsigned numberOfResultProfiles() { return m_resultProfiles.size(); } - ResultProfile* resultProfileForBytecodeOffset(int bytecodeOffset); - - unsigned specialFastCaseProfileCountForBytecodeOffset(int bytecodeOffset) - { - ResultProfile* profile = resultProfileForBytecodeOffset(bytecodeOffset); - if (!profile) - return 0; - return profile->specialFastPathCount(); - } + ArithProfile* arithProfileForBytecodeOffset(int bytecodeOffset); + ArithProfile& arithProfileForPC(Instruction*); - bool couldTakeSpecialFastCase(int bytecodeOffset) - { - if (!hasBaselineJITProfiling()) - return false; - unsigned specialFastCaseCount = specialFastCaseProfileCountForBytecodeOffset(bytecodeOffset); - return specialFastCaseCount >= Options::couldTakeSlowCaseMinimumCount(); - } + bool couldTakeSpecialFastCase(int bytecodeOffset); unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); } const ArrayProfileVector& arrayProfiles() { return m_arrayProfiles; } - ArrayProfile* addArrayProfile(unsigned bytecodeOffset) - { - m_arrayProfiles.append(ArrayProfile(bytecodeOffset)); - return &m_arrayProfiles.last(); - } + ArrayProfile* addArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset); + ArrayProfile* addArrayProfile(unsigned bytecodeOffset); + ArrayProfile* getArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset); ArrayProfile* getArrayProfile(unsigned bytecodeOffset); + ArrayProfile* getOrAddArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset); ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset); // Exception handling support @@ -506,7 +496,7 @@ { ASSERT(JITCode::isBaselineCode(jitType())); ConcurrentJITLocker locker(m_lock); - return m_exitProfile.add(locker, site); + return m_exitProfile.add(locker, this, site); } bool hasExitSite(const ConcurrentJITLocker& locker, const DFG::FrequentExitSite& site) const @@ -557,7 +547,7 @@ } WriteBarrier& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } - ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } + static ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; } ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); } ALWAYS_INLINE SourceCodeRepresentation constantSourceCodeRepresentation(int index) const { return m_constantsSourceCodeRepresentation[index - FirstConstantRegisterIndex]; } @@ -603,14 +593,7 @@ if (!!m_livenessAnalysis) return *m_livenessAnalysis; } - std::unique_ptr analysis = - std::make_unique(this); - { - ConcurrentJITLocker locker(m_lock); - if (!m_livenessAnalysis) - m_livenessAnalysis = WTFMove(analysis); - return *m_livenessAnalysis; - } + return livenessAnalysisSlow(); } void validate(); @@ -631,18 +614,6 @@ StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); } StringJumpTable& stringSwitchJumpTable(int tableIndex) { RELEASE_ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; } - // Live callee registers at yield points. - const FastBitVector& liveCalleeLocalsAtYield(unsigned index) const - { - RELEASE_ASSERT(m_rareData); - return m_rareData->m_liveCalleeLocalsAtYield[index]; - } - FastBitVector& liveCalleeLocalsAtYield(unsigned index) - { - RELEASE_ASSERT(m_rareData); - return m_rareData->m_liveCalleeLocalsAtYield[index]; - } - EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; } enum ShrinkMode { @@ -669,21 +640,18 @@ m_llintExecuteCounter.deferIndefinitely(); } - void jitAfterWarmUp() - { - m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITAfterWarmUp(), this); - } - - void jitSoon() - { - m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon(), this); - } + int32_t thresholdForJIT(int32_t threshold); + void jitAfterWarmUp(); + void jitSoon(); const BaselineExecutionCounter& llintExecuteCounter() const { return m_llintExecuteCounter; } + typedef HashMap> StructureWatchpointMap; + StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; } + // Functions for controlling when tiered compilation kicks in. This // controls both when the optimizing compiler is invoked and when OSR // entry happens. Two triggers exist: the loop trigger and the return @@ -840,6 +808,8 @@ m_steppingMode = SteppingModeDisabled; m_numBreakpoints = 0; } + + bool wasCompiledWithDebuggingOpcodes() const { return m_unlinkedCode->wasCompiledWithDebuggingOpcodes(); } // FIXME: Make these remaining members private. @@ -874,6 +844,7 @@ bool m_allTransitionsHaveBeenMarked : 1; // Initialized and used on every GC. + bool m_didFailJITCompilation : 1; bool m_didFailFTLCompilation : 1; bool m_hasBeenCompiledWithFTL : 1; bool m_isConstructor : 1; @@ -897,8 +868,6 @@ Vector m_switchJumpTables; Vector m_stringSwitchJumpTables; - Vector m_liveCalleeLocalsAtYield; - EvalCodeCache m_evalCodeCache; }; @@ -933,6 +902,8 @@ private: friend class CodeBlockSet; + + BytecodeLivenessAnalysis& livenessAnalysisSlow(); CodeBlock* specialOSREntryBlockOrNull(); @@ -942,15 +913,7 @@ void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles); - void setConstantRegisters(const Vector>& constants, const Vector& constantsSourceCodeRepresentation) - { - ASSERT(constants.size() == constantsSourceCodeRepresentation.size()); - size_t count = constants.size(); - m_constantRegisters.resizeToFit(count); - for (size_t i = 0; i < count; i++) - m_constantRegisters[i].set(*m_vm, this, constants[i].get()); - m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation; - } + void setConstantRegisters(const Vector>& constants, const Vector& constantsSourceCodeRepresentation); void replaceConstant(int index, JSValue value) { @@ -980,7 +943,7 @@ void dumpValueProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling); void dumpArrayProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling); void dumpRareCaseProfile(PrintStream&, const char* name, RareCaseProfile*, bool& hasPrintedProfiling); - void dumpResultProfile(PrintStream&, ResultProfile*, bool& hasPrintedProfiling); + void dumpArithProfile(PrintStream&, ArithProfile*, bool& hasPrintedProfiling); bool shouldVisitStrongly(); bool shouldJettisonDueToWeakReference(); @@ -1031,10 +994,14 @@ RefCountedArray m_llintCallLinkInfos; SentinelLinkedList> m_incomingLLIntCalls; + StructureWatchpointMap m_llintGetByIdWatchpointMap; RefPtr m_jitCode; #if ENABLE(JIT) std::unique_ptr m_calleeSaveRegisters; Bag m_stubInfos; + Bag m_addICs; + Bag m_mulICs; + Bag m_subICs; Bag m_byValInfos; Bag m_callLinkInfos; SentinelLinkedList> m_incomingCalls; @@ -1051,9 +1018,6 @@ RefCountedArray m_argumentValueProfiles; RefCountedArray m_valueProfiles; SegmentedVector m_rareCaseProfiles; - SegmentedVector m_resultProfiles; - typedef HashMap, WTF::UnsignedWithZeroKeyHashTraits> BytecodeOffsetToResultProfileIndexMap; - std::unique_ptr m_bytecodeOffsetToResultProfileIndexMap; RefCountedArray m_arrayAllocationProfiles; ArrayProfileVector m_arrayProfiles; RefCountedArray m_objectAllocationProfiles; @@ -1418,6 +1382,9 @@ } } +#define CODEBLOCK_LOG_EVENT(codeBlock, summary, details) \ + (codeBlock->vm()->logEvent(codeBlock, summary, [&] () { return toCString details; })) + } // namespace JSC #endif // CodeBlock_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h 2016-11-03 07:04:20.000000000 +0000 @@ -40,7 +40,7 @@ } protected: - virtual void fireInternal(const FireDetail&) override; + void fireInternal(const FireDetail&) override; private: CodeBlock* m_codeBlock; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeOrigin.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeOrigin.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/CodeOrigin.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/CodeOrigin.h 2016-11-03 07:04:20.000000000 +0000 @@ -30,7 +30,6 @@ #include "CodeBlockHash.h" #include "CodeSpecializationKind.h" #include "WriteBarrier.h" -#include #include #include #include @@ -109,7 +108,7 @@ // Get the inline stack. This is slow, and is intended for debugging only. Vector inlineStack() const; - void dump(PrintStream&) const; + JS_EXPORT_PRIVATE void dump(PrintStream&) const; void dumpInContext(PrintStream&, DumpContext*) const; private: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -57,13 +57,12 @@ result.m_conditionSet.numberOfConditionsWithKind(PropertyCondition::Presence); RELEASE_ASSERT(numberOfSlotBases <= 1); if (!numberOfSlotBases) { - // Currently we don't support misses. That's a bummer. - // FIXME: https://bugs.webkit.org/show_bug.cgi?id=133052 - return takesSlowPath(); + ASSERT(result.m_offset == invalidOffset); + return result; } ObjectPropertyCondition base = result.m_conditionSet.slotBaseCondition(); ASSERT(base.kind() == PropertyCondition::Presence); - + result.m_offset = base.offset(); } else result.m_offset = headStructure->getConcurrently(uid); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/DFGExitProfile.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,14 +28,27 @@ #if ENABLE(DFG_JIT) +#include "CodeBlock.h" +#include "VMInlines.h" + namespace JSC { namespace DFG { +void FrequentExitSite::dump(PrintStream& out) const +{ + out.print("bc#", m_bytecodeOffset, ": ", m_kind, "/", m_jitType); +} + ExitProfile::ExitProfile() { } ExitProfile::~ExitProfile() { } -bool ExitProfile::add(const ConcurrentJITLocker&, const FrequentExitSite& site) +bool ExitProfile::add(const ConcurrentJITLocker&, CodeBlock* owner, const FrequentExitSite& site) { ASSERT(site.jitType() != ExitFromAnything); + + CODEBLOCK_LOG_EVENT(owner, "frequentExit", (site)); + + if (Options::verboseExitProfile()) + dataLog(pointerDump(owner), ": Adding exit site: ", site, "\n"); // If we've never seen any frequent exits then create the list and put this site // into it. diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/DFGExitProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/DFGExitProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/DFGExitProfile.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/DFGExitProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2011-2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -116,6 +116,8 @@ { return m_kind == ExitKindUnset && m_bytecodeOffset; } + + void dump(PrintStream& out) const; private: unsigned m_bytecodeOffset; @@ -159,7 +161,7 @@ // be called a fixed number of times per recompilation. Recompilation is // rare to begin with, and implies doing O(n) operations on the CodeBlock // anyway. - bool add(const ConcurrentJITLocker&, const FrequentExitSite&); + bool add(const ConcurrentJITLocker&, CodeBlock* owner, const FrequentExitSite&); // Get the frequent exit sites for a bytecode index. This is O(n), and is // meant to only be used from debugging/profiling code. diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/EvalCodeCache.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/EvalCodeCache.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/EvalCodeCache.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/EvalCodeCache.h 2016-11-03 07:04:20.000000000 +0000 @@ -34,6 +34,7 @@ #include "JSScope.h" #include "Options.h" #include "SourceCode.h" +#include "SourceCodeKey.h" #include #include #include @@ -44,11 +45,12 @@ class EvalCodeCache { public: + // Specialized cache key (compared with SourceCodeKey) for eval code cache. class CacheKey { public: - CacheKey(const String& source, bool isArrowFunctionContext) + CacheKey(const String& source, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext) : m_source(source.impl()) - , m_isArrowFunctionContext(isArrowFunctionContext) + , m_flags(SourceCodeType::EvalType, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserCommentMode::Classic, derivedContextType, evalContextType, isArrowFunctionContext) { } @@ -65,7 +67,7 @@ bool operator==(const CacheKey& other) const { - return m_source == other.m_source && m_isArrowFunctionContext == other.m_isArrowFunctionContext; + return m_source == other.m_source && m_flags == other.m_flags; } bool isHashTableDeletedValue() const { return m_source.isHashTableDeletedValue(); } @@ -77,7 +79,7 @@ } static bool equal(const CacheKey& lhs, const CacheKey& rhs) { - return StringHash::equal(lhs.m_source, rhs.m_source) && lhs.m_isArrowFunctionContext == rhs.m_isArrowFunctionContext; + return StringHash::equal(lhs.m_source, rhs.m_source) && lhs.m_flags == rhs.m_flags; } static const bool safeToCompareToEmptyOrDeleted = false; }; @@ -86,31 +88,29 @@ private: RefPtr m_source; - bool m_isArrowFunctionContext { false }; + SourceCodeFlags m_flags; }; - EvalExecutable* tryGet(bool inStrictContext, const String& evalSource, bool isArrowFunctionContext, JSScope* scope) + EvalExecutable* tryGet(bool inStrictContext, const String& evalSource, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext, JSScope* scope) { if (isCacheable(inStrictContext, evalSource, scope)) { ASSERT(!inStrictContext); - return m_cacheMap.fastGet(CacheKey(evalSource, isArrowFunctionContext)).get(); + return m_cacheMap.fastGet(CacheKey(evalSource, derivedContextType, evalContextType, isArrowFunctionContext)).get(); } return nullptr; } - EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, const String& evalSource, JSScope* scope) + EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext, const String& evalSource, JSScope* scope) { VariableEnvironment variablesUnderTDZ; JSScope::collectVariablesUnderTDZ(scope, variablesUnderTDZ); - EvalExecutable* evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext, thisTDZMode, derivedContextType, isArrowFunctionContext, &variablesUnderTDZ); + EvalExecutable* evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, &variablesUnderTDZ); if (!evalExecutable) return nullptr; if (isCacheable(inStrictContext, evalSource, scope) && m_cacheMap.size() < maxCacheEntries) { ASSERT(!inStrictContext); - ASSERT_WITH_MESSAGE(thisTDZMode == ThisTDZMode::CheckIfNeeded, "Always CheckIfNeeded because the caching is enabled only in the sloppy mode."); - ASSERT_WITH_MESSAGE(derivedContextType == DerivedContextType::None, "derivedContextType is always None because class methods and class constructors are always evaluated as the strict code."); - m_cacheMap.set(CacheKey(evalSource, isArrowFunctionContext), WriteBarrier(exec->vm(), owner, evalExecutable)); + m_cacheMap.set(CacheKey(evalSource, derivedContextType, evalContextType, isArrowFunctionContext), WriteBarrier(exec->vm(), owner, evalExecutable)); } return evalExecutable; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExecutableInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExecutableInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExecutableInfo.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExecutableInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,24 +31,28 @@ namespace JSC { enum class DerivedContextType : uint8_t { None, DerivedConstructorContext, DerivedMethodContext }; +enum class EvalContextType : uint8_t { None, FunctionEvalContext }; // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized. // https://bugs.webkit.org/show_bug.cgi?id=151547 struct ExecutableInfo { - ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext) + ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserCommentMode commentMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType) : m_usesEval(usesEval) , m_isStrictMode(isStrictMode) , m_isConstructor(isConstructor) , m_isBuiltinFunction(isBuiltinFunction) , m_constructorKind(static_cast(constructorKind)) , m_superBinding(static_cast(superBinding)) + , m_commentMode(static_cast(commentMode)) , m_parseMode(parseMode) , m_derivedContextType(static_cast(derivedContextType)) , m_isArrowFunctionContext(isArrowFunctionContext) , m_isClassContext(isClassContext) + , m_evalContextType(static_cast(evalContextType)) { ASSERT(m_constructorKind == static_cast(constructorKind)); ASSERT(m_superBinding == static_cast(superBinding)); + ASSERT(m_commentMode == static_cast(commentMode)); } bool usesEval() const { return m_usesEval; } @@ -57,8 +61,10 @@ bool isBuiltinFunction() const { return m_isBuiltinFunction; } ConstructorKind constructorKind() const { return static_cast(m_constructorKind); } SuperBinding superBinding() const { return static_cast(m_superBinding); } + JSParserCommentMode commentMode() const { return static_cast(m_commentMode); } SourceParseMode parseMode() const { return m_parseMode; } DerivedContextType derivedContextType() const { return static_cast(m_derivedContextType); } + EvalContextType evalContextType() const { return static_cast(m_evalContextType); } bool isArrowFunctionContext() const { return m_isArrowFunctionContext; } bool isClassContext() const { return m_isClassContext; } @@ -69,10 +75,12 @@ unsigned m_isBuiltinFunction : 1; unsigned m_constructorKind : 2; unsigned m_superBinding : 1; + unsigned m_commentMode: 1; SourceParseMode m_parseMode; unsigned m_derivedContextType : 2; unsigned m_isArrowFunctionContext : 1; unsigned m_isClassContext : 1; + unsigned m_evalContextType : 2; }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +29,7 @@ #include "CodeBlock.h" #include "ExecutableAllocator.h" #include "JSCInlines.h" +#include "VMInlines.h" #include namespace JSC { @@ -78,7 +79,7 @@ #if ENABLE(JIT) double multiplier = ExecutableAllocator::memoryPressureMultiplier( - codeBlock->predictedMachineCodeSize()); + codeBlock->baselineAlternative()->predictedMachineCodeSize()); #else // This code path will probably not be taken, but if it is, we fake it. double multiplier = 1.0; @@ -123,9 +124,15 @@ double modifiedThreshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock); - return static_cast(m_totalCount) + m_counter >= - modifiedThreshold - static_cast( - std::min(m_activeThreshold, maximumExecutionCountsBetweenCheckpoints())) / 2; + double actualCount = static_cast(m_totalCount) + m_counter; + double desiredCount = modifiedThreshold - static_cast( + std::min(m_activeThreshold, maximumExecutionCountsBetweenCheckpoints())) / 2; + + bool result = actualCount >= desiredCount; + + CODEBLOCK_LOG_EVENT(codeBlock, "thresholdCheck", ("activeThreshold = ", m_activeThreshold, ", modifiedThreshold = ", modifiedThreshold, ", actualCount = ", actualCount, ", desiredCount = ", desiredCount)); + + return result; } template diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExecutionCounter.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExecutionCounter.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExecutionCounter.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExecutionCounter.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,7 +29,6 @@ #include "JSGlobalObject.h" #include "Options.h" #include -#include namespace JSC { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExitKind.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExitKind.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExitKind.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExitKind.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -76,6 +76,8 @@ return "VarargsOverflow"; case TDZFailure: return "TDZFailure"; + case HoistingFailed: + return "HoistingFailed"; case Uncountable: return "Uncountable"; case UncountableInvalidation: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExitKind.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExitKind.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExitKind.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExitKind.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,6 +50,7 @@ NotStringObject, // We exited because we shouldn't have attempted to optimize string object access. VarargsOverflow, // We exited because a varargs call passed more arguments than we expected. TDZFailure, // We exited because we were in the TDZ and accessed the variable. + HoistingFailed, // Something that was hoisted exited. So, assume that hoisting is a bad idea. Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME. UncountableInvalidation, // We exited because the code block was invalidated; this means that we've already counted the reasons why the code block was invalidated. WatchdogTimerFired, // We exited because we need to service the watchdog timer. diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h 2013-08-03 16:10:38.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012-2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -86,13 +86,13 @@ position = ((line & FatColumnModeLineMask) << FatColumnModeLineShift | (column & FatColumnModeColumnMask)); } - void decodeFatLineMode(unsigned& line, unsigned& column) + void decodeFatLineMode(unsigned& line, unsigned& column) const { line = (position >> FatLineModeLineShift) & FatLineModeLineMask; column = position & FatLineModeColumnMask; } - void decodeFatColumnMode(unsigned& line, unsigned& column) + void decodeFatColumnMode(unsigned& line, unsigned& column) const { line = (position >> FatColumnModeLineShift) & FatColumnModeLineMask; column = position & FatColumnModeColumnMask; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -33,6 +33,7 @@ #include "LLIntData.h" #include "LowLevelInterpreter.h" #include "PolymorphicAccess.h" +#include "StructureStubInfo.h" #include namespace JSC { @@ -74,8 +75,14 @@ VM& vm = *profiledBlock->vm(); Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex; - - if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length)) + + Opcode opcode = instruction[0].u.opcode; + + ASSERT(opcode == LLInt::getOpcode(op_get_array_length) || opcode == LLInt::getOpcode(op_try_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_proto_load) || opcode == LLInt::getOpcode(op_get_by_id) || opcode == LLInt::getOpcode(op_get_by_id_unset)); + + // FIXME: We should not just bail if we see a try_get_by_id or a get_by_id_proto_load. + // https://bugs.webkit.org/show_bug.cgi?id=158039 + if (opcode != LLInt::getOpcode(op_get_by_id)) return GetByIdStatus(NoInformation, false); StructureID structureID = instruction[4].u.structureID; @@ -210,7 +217,9 @@ JSFunction* intrinsicFunction = nullptr; switch (access.type()) { - case AccessCase::Load: { + case AccessCase::Load: + case AccessCase::GetGetter: + case AccessCase::Miss: { break; } case AccessCase::IntrinsicGetter: { @@ -218,11 +227,11 @@ break; } case AccessCase::Getter: { - CallLinkInfo* callLinkInfo = access.callLinkInfo(); - ASSERT(callLinkInfo); - callLinkStatus = std::make_unique( - CallLinkStatus::computeFor( - locker, profiledBlock, *callLinkInfo, callExitSiteData)); + callLinkStatus = std::make_unique(); + if (CallLinkInfo* callLinkInfo = access.callLinkInfo()) { + *callLinkStatus = CallLinkStatus::computeFor( + locker, profiledBlock, *callLinkInfo, callExitSiteData); + } break; } default: { @@ -230,7 +239,8 @@ // future. https://bugs.webkit.org/show_bug.cgi?id=133052 return GetByIdStatus(slowPathState, true); } } - + + ASSERT((AccessCase::Miss == access.type()) == (access.offset() == invalidOffset)); GetByIdVariant variant( StructureSet(structure), complexGetStatus.offset(), complexGetStatus.conditionSet(), WTFMove(callLinkStatus), @@ -350,6 +360,22 @@ return false; } +void GetByIdStatus::filter(const StructureSet& set) +{ + if (m_state != Simple) + return; + + // FIXME: We could also filter the variants themselves. + + m_variants.removeAllMatching( + [&] (GetByIdVariant& variant) -> bool { + return !variant.structureSet().overlaps(set); + }); + + if (m_variants.isEmpty()) + m_state = NoInformation; +} + void GetByIdStatus::dump(PrintStream& out) const { out.print("("); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/GetByIdStatus.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/GetByIdStatus.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/GetByIdStatus.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/GetByIdStatus.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,11 +31,13 @@ #include "ConcurrentJITLock.h" #include "ExitingJITType.h" #include "GetByIdVariant.h" -#include "StructureStubInfo.h" namespace JSC { class CodeBlock; +class StructureStubInfo; + +typedef HashMap StubInfoMap; class GetByIdStatus { public: @@ -92,6 +94,9 @@ bool wasSeenInJIT() const { return m_wasSeenInJIT; } + // Attempts to reduce the set of variants to fit the given structure set. This may be approximate. + void filter(const StructureSet&); + void dump(PrintStream&) const; private: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/GetByIdVariant.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/GetByIdVariant.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/GetByIdVariant.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/GetByIdVariant.h 2016-11-03 07:04:20.000000000 +0000 @@ -64,6 +64,8 @@ JSFunction* intrinsicFunction() const { return m_intrinsicFunction; } Intrinsic intrinsic() const { return m_intrinsicFunction ? m_intrinsicFunction->intrinsic() : NoIntrinsic; } + bool isPropertyUnset() const { return offset() == invalidOffset; } + bool attemptToMerge(const GetByIdVariant& other); void dump(PrintStream&) const; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/HandlerInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/HandlerInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/HandlerInfo.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/HandlerInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -27,6 +27,7 @@ #define HandlerInfo_h #include "CodeLocation.h" +#include namespace JSC { @@ -37,6 +38,11 @@ SynthesizedFinally = 3 }; +enum class RequiredHandler { + CatchHandler, + AnyHandler +}; + struct HandlerInfoBase { HandlerType type() const { return static_cast(typeBits); } void setType(HandlerType type) { typeBits = static_cast(type); } @@ -58,6 +64,23 @@ bool isCatchHandler() const { return type() == HandlerType::Catch; } + template + static Handler* handlerForIndex(Vector& exeptionHandlers, unsigned index, RequiredHandler requiredHandler) + { + for (Handler& handler : exeptionHandlers) { + if ((requiredHandler == RequiredHandler::CatchHandler) && !handler.isCatchHandler()) + continue; + + // Handlers are ordered innermost first, so the first handler we encounter + // that contains the source address is the correct handler to use. + // This index used is either the BytecodeOffset or a CallSiteIndex. + if (handler.start <= index && handler.end > index) + return &handler; + } + + return nullptr; + } + uint32_t start; uint32_t end; uint32_t target; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InlineAccess.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InlineAccess.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InlineAccess.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InlineAccess.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "InlineAccess.h" + +#if ENABLE(JIT) + +#include "CCallHelpers.h" +#include "JSArray.h" +#include "JSCellInlines.h" +#include "LinkBuffer.h" +#include "ScratchRegisterAllocator.h" +#include "Structure.h" +#include "StructureStubInfo.h" +#include "VM.h" + +namespace JSC { + +void InlineAccess::dumpCacheSizesAndCrash(VM& vm) +{ + GPRReg base = GPRInfo::regT0; + GPRReg value = GPRInfo::regT1; +#if USE(JSVALUE32_64) + JSValueRegs regs(base, value); +#else + JSValueRegs regs(base); +#endif + + { + CCallHelpers jit(&vm); + + GPRReg scratchGPR = value; + jit.load8(CCallHelpers::Address(base, JSCell::indexingTypeOffset()), value); + jit.and32(CCallHelpers::TrustedImm32(IsArray | IndexingShapeMask), value); + jit.patchableBranch32( + CCallHelpers::NotEqual, value, CCallHelpers::TrustedImm32(IsArray | ContiguousShape)); + jit.loadPtr(CCallHelpers::Address(base, JSObject::butterflyOffset()), value); + jit.load32(CCallHelpers::Address(value, ArrayStorage::lengthOffset()), value); + jit.boxInt32(scratchGPR, regs); + + dataLog("array length size: ", jit.m_assembler.buffer().codeSize(), "\n"); + } + + { + CCallHelpers jit(&vm); + + jit.patchableBranch32( + MacroAssembler::NotEqual, + MacroAssembler::Address(base, JSCell::structureIDOffset()), + MacroAssembler::TrustedImm32(0x000ab21ca)); + jit.loadPtr( + CCallHelpers::Address(base, JSObject::butterflyOffset()), + value); + GPRReg storageGPR = value; + jit.loadValue( + CCallHelpers::Address(storageGPR, 0x000ab21ca), regs); + + dataLog("out of line offset cache size: ", jit.m_assembler.buffer().codeSize(), "\n"); + } + + { + CCallHelpers jit(&vm); + + jit.patchableBranch32( + MacroAssembler::NotEqual, + MacroAssembler::Address(base, JSCell::structureIDOffset()), + MacroAssembler::TrustedImm32(0x000ab21ca)); + jit.loadValue( + MacroAssembler::Address(base, 0x000ab21ca), regs); + + dataLog("inline offset cache size: ", jit.m_assembler.buffer().codeSize(), "\n"); + } + + { + CCallHelpers jit(&vm); + + jit.patchableBranch32( + MacroAssembler::NotEqual, + MacroAssembler::Address(base, JSCell::structureIDOffset()), + MacroAssembler::TrustedImm32(0x000ab21ca)); + + jit.storeValue( + regs, MacroAssembler::Address(base, 0x000ab21ca)); + + dataLog("replace cache size: ", jit.m_assembler.buffer().codeSize(), "\n"); + } + + { + CCallHelpers jit(&vm); + + jit.patchableBranch32( + MacroAssembler::NotEqual, + MacroAssembler::Address(base, JSCell::structureIDOffset()), + MacroAssembler::TrustedImm32(0x000ab21ca)); + + jit.loadPtr(MacroAssembler::Address(base, JSObject::butterflyOffset()), value); + jit.storeValue( + regs, + MacroAssembler::Address(base, 120342)); + + dataLog("replace out of line cache size: ", jit.m_assembler.buffer().codeSize(), "\n"); + } + + CRASH(); +} + + +template +ALWAYS_INLINE static bool linkCodeInline(const char* name, CCallHelpers& jit, StructureStubInfo& stubInfo, const Function& function) +{ + if (jit.m_assembler.buffer().codeSize() <= stubInfo.patch.inlineSize) { + bool needsBranchCompaction = false; + LinkBuffer linkBuffer(jit, stubInfo.patch.start.dataLocation(), stubInfo.patch.inlineSize, JITCompilationMustSucceed, needsBranchCompaction); + ASSERT(linkBuffer.isValid()); + function(linkBuffer); + FINALIZE_CODE(linkBuffer, ("InlineAccessType: '%s'", name)); + return true; + } + + // This is helpful when determining the size for inline ICs on various + // platforms. You want to choose a size that usually succeeds, but sometimes + // there may be variability in the length of the code we generate just because + // of randomness. It's helpful to flip this on when running tests or browsing + // the web just to see how often it fails. You don't want an IC size that always fails. + const bool failIfCantInline = false; + if (failIfCantInline) { + dataLog("Failure for: ", name, "\n"); + dataLog("real size: ", jit.m_assembler.buffer().codeSize(), " inline size:", stubInfo.patch.inlineSize, "\n"); + CRASH(); + } + + return false; +} + +bool InlineAccess::generateSelfPropertyAccess(VM& vm, StructureStubInfo& stubInfo, Structure* structure, PropertyOffset offset) +{ + CCallHelpers jit(&vm); + + GPRReg base = static_cast(stubInfo.patch.baseGPR); + JSValueRegs value = stubInfo.valueRegs(); + + auto branchToSlowPath = jit.patchableBranch32( + MacroAssembler::NotEqual, + MacroAssembler::Address(base, JSCell::structureIDOffset()), + MacroAssembler::TrustedImm32(bitwise_cast(structure->id()))); + GPRReg storage; + if (isInlineOffset(offset)) + storage = base; + else { + jit.loadPtr(CCallHelpers::Address(base, JSObject::butterflyOffset()), value.payloadGPR()); + storage = value.payloadGPR(); + } + + jit.loadValue( + MacroAssembler::Address(storage, offsetRelativeToBase(offset)), value); + + bool linkedCodeInline = linkCodeInline("property access", jit, stubInfo, [&] (LinkBuffer& linkBuffer) { + linkBuffer.link(branchToSlowPath, stubInfo.slowPathStartLocation()); + }); + return linkedCodeInline; +} + +ALWAYS_INLINE static GPRReg getScratchRegister(StructureStubInfo& stubInfo) +{ + ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters); + allocator.lock(static_cast(stubInfo.patch.baseGPR)); + allocator.lock(static_cast(stubInfo.patch.valueGPR)); +#if USE(JSVALUE32_64) + allocator.lock(static_cast(stubInfo.patch.baseTagGPR)); + allocator.lock(static_cast(stubInfo.patch.valueTagGPR)); +#endif + GPRReg scratch = allocator.allocateScratchGPR(); + if (allocator.didReuseRegisters()) + return InvalidGPRReg; + return scratch; +} + +ALWAYS_INLINE static bool hasFreeRegister(StructureStubInfo& stubInfo) +{ + return getScratchRegister(stubInfo) != InvalidGPRReg; +} + +bool InlineAccess::canGenerateSelfPropertyReplace(StructureStubInfo& stubInfo, PropertyOffset offset) +{ + if (isInlineOffset(offset)) + return true; + + return hasFreeRegister(stubInfo); +} + +bool InlineAccess::generateSelfPropertyReplace(VM& vm, StructureStubInfo& stubInfo, Structure* structure, PropertyOffset offset) +{ + ASSERT(canGenerateSelfPropertyReplace(stubInfo, offset)); + + CCallHelpers jit(&vm); + + GPRReg base = static_cast(stubInfo.patch.baseGPR); + JSValueRegs value = stubInfo.valueRegs(); + + auto branchToSlowPath = jit.patchableBranch32( + MacroAssembler::NotEqual, + MacroAssembler::Address(base, JSCell::structureIDOffset()), + MacroAssembler::TrustedImm32(bitwise_cast(structure->id()))); + + GPRReg storage; + if (isInlineOffset(offset)) + storage = base; + else { + storage = getScratchRegister(stubInfo); + ASSERT(storage != InvalidGPRReg); + jit.loadPtr(CCallHelpers::Address(base, JSObject::butterflyOffset()), storage); + } + + jit.storeValue( + value, MacroAssembler::Address(storage, offsetRelativeToBase(offset))); + + bool linkedCodeInline = linkCodeInline("property replace", jit, stubInfo, [&] (LinkBuffer& linkBuffer) { + linkBuffer.link(branchToSlowPath, stubInfo.slowPathStartLocation()); + }); + return linkedCodeInline; +} + +bool InlineAccess::isCacheableArrayLength(StructureStubInfo& stubInfo, JSArray* array) +{ + ASSERT(array->indexingType() & IsArray); + + if (!hasFreeRegister(stubInfo)) + return false; + + return array->indexingType() == ArrayWithInt32 + || array->indexingType() == ArrayWithDouble + || array->indexingType() == ArrayWithContiguous; +} + +bool InlineAccess::generateArrayLength(VM& vm, StructureStubInfo& stubInfo, JSArray* array) +{ + ASSERT(isCacheableArrayLength(stubInfo, array)); + + CCallHelpers jit(&vm); + + GPRReg base = static_cast(stubInfo.patch.baseGPR); + JSValueRegs value = stubInfo.valueRegs(); + GPRReg scratch = getScratchRegister(stubInfo); + + jit.load8(CCallHelpers::Address(base, JSCell::indexingTypeOffset()), scratch); + jit.and32(CCallHelpers::TrustedImm32(IsArray | IndexingShapeMask), scratch); + auto branchToSlowPath = jit.patchableBranch32( + CCallHelpers::NotEqual, scratch, CCallHelpers::TrustedImm32(array->indexingType())); + jit.loadPtr(CCallHelpers::Address(base, JSObject::butterflyOffset()), value.payloadGPR()); + jit.load32(CCallHelpers::Address(value.payloadGPR(), ArrayStorage::lengthOffset()), value.payloadGPR()); + jit.boxInt32(value.payloadGPR(), value); + + bool linkedCodeInline = linkCodeInline("array length", jit, stubInfo, [&] (LinkBuffer& linkBuffer) { + linkBuffer.link(branchToSlowPath, stubInfo.slowPathStartLocation()); + }); + return linkedCodeInline; +} + +void InlineAccess::rewireStubAsJump(VM& vm, StructureStubInfo& stubInfo, CodeLocationLabel target) +{ + CCallHelpers jit(&vm); + + auto jump = jit.jump(); + + // We don't need a nop sled here because nobody should be jumping into the middle of an IC. + bool needsBranchCompaction = false; + LinkBuffer linkBuffer(jit, stubInfo.patch.start.dataLocation(), jit.m_assembler.buffer().codeSize(), JITCompilationMustSucceed, needsBranchCompaction); + RELEASE_ASSERT(linkBuffer.isValid()); + linkBuffer.link(jump, target); + + FINALIZE_CODE(linkBuffer, ("InlineAccess: linking constant jump")); +} + +} // namespace JSC + +#endif // ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InlineAccess.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InlineAccess.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InlineAccess.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InlineAccess.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef InlineAccess_h +#define InlineAccess_h + +#if ENABLE(JIT) + +#include "CodeLocation.h" +#include "PropertyOffset.h" + +namespace JSC { + +class JSArray; +class Structure; +class StructureStubInfo; +class VM; + +class InlineAccess { +public: + + // This is the maximum between inline and out of line self access cases. + static constexpr size_t sizeForPropertyAccess() + { +#if CPU(X86_64) + return 23; +#elif CPU(X86) + return 27; +#elif CPU(ARM64) + return 40; +#elif CPU(ARM) +#if CPU(ARM_THUMB2) + return 48; +#else + return 52; +#endif +#else +#error "unsupported platform" +#endif + } + + // This is the maximum between inline and out of line property replace cases. + static constexpr size_t sizeForPropertyReplace() + { +#if CPU(X86_64) + return 23; +#elif CPU(X86) + return 27; +#elif CPU(ARM64) + return 40; +#elif CPU(ARM) +#if CPU(ARM_THUMB2) + return 48; +#else + return 48; +#endif +#else +#error "unsupported platform" +#endif + } + + // FIXME: Make this constexpr when GCC is able to compile std::max() inside a constexpr function. + // https://bugs.webkit.org/show_bug.cgi?id=159436 + // + // This is the maximum between the size for array length access, and the size for regular self access. + ALWAYS_INLINE static size_t sizeForLengthAccess() + { +#if CPU(X86_64) + size_t size = 26; +#elif CPU(X86) + size_t size = 27; +#elif CPU(ARM64) + size_t size = 32; +#elif CPU(ARM) +#if CPU(ARM_THUMB2) + size_t size = 30; +#else + size_t size = 32; +#endif +#else +#error "unsupported platform" +#endif + return std::max(size, sizeForPropertyAccess()); + } + + static bool generateSelfPropertyAccess(VM&, StructureStubInfo&, Structure*, PropertyOffset); + static bool canGenerateSelfPropertyReplace(StructureStubInfo&, PropertyOffset); + static bool generateSelfPropertyReplace(VM&, StructureStubInfo&, Structure*, PropertyOffset); + static bool isCacheableArrayLength(StructureStubInfo&, JSArray*); + static bool generateArrayLength(VM&, StructureStubInfo&, JSArray*); + static void rewireStubAsJump(VM&, StructureStubInfo&, CodeLocationLabel); + + // This is helpful when determining the size of an IC on + // various platforms. When adding a new type of IC, implement + // its placeholder code here, and log the size. That way we + // can intelligently choose sizes on various platforms. + NO_RETURN_DUE_TO_CRASH static void dumpCacheSizesAndCrash(VM&); +}; + +} // namespace JSC + +#endif // ENABLE(JIT) + +#endif // InlineAccess_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InlineCallFrame.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InlineCallFrame.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InlineCallFrame.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InlineCallFrame.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,7 +31,6 @@ #include "CodeOrigin.h" #include "ValueRecovery.h" #include "WriteBarrier.h" -#include #include #include #include diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Instruction.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Instruction.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Instruction.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Instruction.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,7 +31,6 @@ #include "BasicBlockLocation.h" #include "MacroAssembler.h" -#include "Opcode.h" #include "PutByIdFlags.h" #include "SymbolTable.h" #include "TypeLocation.h" @@ -52,6 +51,12 @@ struct LLIntCallLinkInfo; struct ValueProfile; +#if ENABLE(COMPUTED_GOTO_OPCODES) +typedef void* Opcode; +#else +typedef OpcodeID Opcode; +#endif + struct Instruction { Instruction() { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InternalFunctionAllocationProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InternalFunctionAllocationProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/InternalFunctionAllocationProfile.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/InternalFunctionAllocationProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -47,10 +47,13 @@ inline Structure* InternalFunctionAllocationProfile::createAllocationStructureFromBase(VM& vm, JSCell* owner, JSObject* prototype, Structure* baseStructure) { - ASSERT(prototype != baseStructure->storedPrototype()); ASSERT(!m_structure || m_structure.get()->classInfo() != baseStructure->classInfo()); - Structure* structure = vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseStructure); + Structure* structure; + if (prototype == baseStructure->storedPrototype()) + structure = baseStructure; + else + structure = vm.prototypeMap.emptyStructureForPrototypeFromBaseStructure(prototype, baseStructure); // Ensure that if another thread sees the structure, it will see it properly created. WTF::storeStoreFence(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" + +#include "CodeBlock.h" +#include "Instruction.h" +#include "JSCInlines.h" + +namespace JSC { + +LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, Instruction* getByIdInstruction) + : m_key(key) + , m_getByIdInstruction(getByIdInstruction) +{ + RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint()); + RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint()); +} + +void LLIntPrototypeLoadAdaptiveStructureWatchpoint::install() +{ + RELEASE_ASSERT(m_key.isWatchable()); + + m_key.object()->structure()->addTransitionWatchpoint(this); +} + +void LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal(const FireDetail& detail) +{ + if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) { + install(); + return; + } + + StringPrintStream out; + out.print("ObjectToStringValue Adaptation of ", m_key, " failed: ", detail); + + StringFireDetail stringDetail(out.toCString().data()); + + CodeBlock::clearLLIntGetByIdCache(m_getByIdInstruction); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LLIntPrototypeLoadAdaptiveStructureWatchpoint_h +#define LLIntPrototypeLoadAdaptiveStructureWatchpoint_h + +#include "Instruction.h" +#include "ObjectPropertyCondition.h" +#include "Watchpoint.h" + +namespace JSC { + +class LLIntPrototypeLoadAdaptiveStructureWatchpoint : public Watchpoint { +public: + LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, Instruction*); + + void install(); + +protected: + void fireInternal(const FireDetail&) override; + +private: + ObjectPropertyCondition m_key; + Instruction* m_getByIdInstruction; +}; + +} // namespace JSC + +#endif /* LLIntPrototypeLoadAdaptiveStructureWatchpoint_h */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,8 @@ #if ENABLE(DFG_JIT) +#include "ArithProfile.h" +#include "CCallHelpers.h" #include "CodeBlock.h" #include "JSCInlines.h" @@ -44,14 +46,15 @@ return result; } -EncodedJSValue* MethodOfGettingAValueProfile::getSpecFailBucket(unsigned index) const +void MethodOfGettingAValueProfile::emitReportValue(CCallHelpers& jit, JSValueRegs regs) const { switch (m_kind) { case None: - return 0; + return; case Ready: - return u.profile->specFailBucket(index); + jit.storeValue(regs, u.profile->specFailBucket(0)); + return; case LazyOperand: { LazyOperandValueProfileKey key(u.lazyOperand.bytecodeOffset, VirtualRegister(u.lazyOperand.operand)); @@ -59,13 +62,16 @@ ConcurrentJITLocker locker(u.lazyOperand.codeBlock->m_lock); LazyOperandValueProfile* profile = u.lazyOperand.codeBlock->lazyOperandValueProfiles().add(locker, key); - return profile->specFailBucket(index); + jit.storeValue(regs, profile->specFailBucket(0)); + return; } - default: - RELEASE_ASSERT_NOT_REACHED(); - return 0; - } + case ArithProfileReady: { + u.arithProfile->emitObserveResult(jit, regs, DoNotHaveTagRegisters); + return; + } } + + RELEASE_ASSERT_NOT_REACHED(); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,12 +32,15 @@ // these #if's will disappear... #if ENABLE(DFG_JIT) +#include "GPRInfo.h" #include "JSCJSValue.h" namespace JSC { +class CCallHelpers; class CodeBlock; class LazyOperandValueProfileKey; +struct ArithProfile; struct ValueProfile; class MethodOfGettingAValueProfile { @@ -47,7 +50,7 @@ { } - explicit MethodOfGettingAValueProfile(ValueProfile* profile) + MethodOfGettingAValueProfile(ValueProfile* profile) { if (profile) { m_kind = Ready; @@ -56,31 +59,34 @@ m_kind = None; } + MethodOfGettingAValueProfile(ArithProfile* profile) + { + if (profile) { + m_kind = ArithProfileReady; + u.arithProfile = profile; + } else + m_kind = None; + } + static MethodOfGettingAValueProfile fromLazyOperand( CodeBlock*, const LazyOperandValueProfileKey&); - bool operator!() const { return m_kind == None; } - - // This logically has a pointer to a "There exists X such that - // ValueProfileBase". But since C++ does not have existential - // templates, I cannot return it. So instead, for any methods that - // users of this class would like to call, we'll just have to provide - // a method here that does it through an indirection. Or we could - // possibly just make ValueProfile less template-based. But last I - // tried that, it felt more yucky than this class. + explicit operator bool() const { return m_kind != None; } - EncodedJSValue* getSpecFailBucket(unsigned index) const; + void emitReportValue(CCallHelpers&, JSValueRegs) const; private: enum Kind { None, Ready, + ArithProfileReady, LazyOperand }; Kind m_kind; union { ValueProfile* profile; + ArithProfile* arithProfile; struct { CodeBlock* codeBlock; unsigned bytecodeOffset; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -45,7 +45,7 @@ { } - bool isNull() { return !m_allocator; } + bool isNull() { return !m_structure; } void initialize(VM& vm, JSCell* owner, JSObject* prototype, unsigned inferredInlineCapacity) { @@ -80,14 +80,15 @@ ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity()); size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity); - MarkedAllocator* allocator = &vm.heap.allocatorForObjectWithoutDestructor(allocationSize); - ASSERT(allocator->cellSize()); - + MarkedAllocator* allocator = vm.heap.allocatorForObjectWithoutDestructor(allocationSize); + // Take advantage of extra inline capacity available in the size class. - size_t slop = (allocator->cellSize() - allocationSize) / sizeof(WriteBarrier); - inlineCapacity += slop; - if (inlineCapacity > JSFinalObject::maxInlineCapacity()) - inlineCapacity = JSFinalObject::maxInlineCapacity(); + if (allocator) { + size_t slop = (allocator->cellSize() - allocationSize) / sizeof(WriteBarrier); + inlineCapacity += slop; + if (inlineCapacity > JSFinalObject::maxInlineCapacity()) + inlineCapacity = JSFinalObject::maxInlineCapacity(); + } Structure* structure = vm.prototypeMap.emptyObjectStructureForPrototype(prototype, inlineCapacity); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -73,6 +73,20 @@ return validityRequiresImpurePropertyWatchpoint(m_object->structure()); } +bool ObjectPropertyCondition::isStillValidAssumingImpurePropertyWatchpoint(Structure* structure) const +{ + return m_condition.isStillValidAssumingImpurePropertyWatchpoint(structure, m_object); +} + +bool ObjectPropertyCondition::isStillValidAssumingImpurePropertyWatchpoint() const +{ + if (!*this) + return false; + + return isStillValidAssumingImpurePropertyWatchpoint(m_object->structure()); +} + + bool ObjectPropertyCondition::isStillValid(Structure* structure) const { return m_condition.isStillValid(structure, m_object); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyCondition.h 2016-11-03 07:04:20.000000000 +0000 @@ -186,6 +186,11 @@ bool validityRequiresImpurePropertyWatchpoint(Structure*) const; bool validityRequiresImpurePropertyWatchpoint() const; + // Checks if the condition still holds setting aside the need for an impure property watchpoint. + // Validity might still require watchpoints on the object. + bool isStillValidAssumingImpurePropertyWatchpoint(Structure*) const; + bool isStillValidAssumingImpurePropertyWatchpoint() const; + // Checks if the condition still holds. May conservatively return false, if the object and // structure alone don't guarantee the condition. Note that this may return true if the // condition still requires some watchpoints on the object in addition to checking the diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -62,7 +62,7 @@ bool ObjectPropertyConditionSet::hasOneSlotBaseCondition() const { - return numberOfConditionsWithKind(PropertyCondition::Presence) == 1; + return (numberOfConditionsWithKind(PropertyCondition::Presence) == 1) != (numberOfConditionsWithKind(PropertyCondition::Equivalence) == 1); } ObjectPropertyCondition ObjectPropertyConditionSet::slotBaseCondition() const @@ -70,7 +70,8 @@ ObjectPropertyCondition result; unsigned numFound = 0; for (const ObjectPropertyCondition& condition : *this) { - if (condition.kind() == PropertyCondition::Presence) { + if (condition.kind() == PropertyCondition::Presence + || condition.kind() == PropertyCondition::Equivalence) { result = condition; numFound++; } @@ -167,6 +168,18 @@ dumpInContext(out, nullptr); } +bool ObjectPropertyConditionSet::isValidAndWatchable() const +{ + if (!isValid()) + return false; + + for (ObjectPropertyCondition condition : m_data->vector) { + if (!condition.isWatchable()) + return false; + } + return true; +} + namespace { bool verbose = false; @@ -198,12 +211,21 @@ vm, owner, object, uid, object->structure()->storedPrototypeObject()); break; } + case PropertyCondition::Equivalence: { + unsigned attributes; + PropertyOffset offset = structure->getConcurrently(uid, attributes); + if (offset == invalidOffset) + return ObjectPropertyCondition(); + JSValue value = object->getDirect(offset); + result = ObjectPropertyCondition::equivalence(vm, owner, object, uid, value); + break; + } default: RELEASE_ASSERT_NOT_REACHED(); return ObjectPropertyCondition(); } - if (!result.structureEnsuresValidityAssumingImpurePropertyWatchpoint()) { + if (!result.isStillValidAssumingImpurePropertyWatchpoint()) { if (verbose) dataLog("Failed to create condition: ", result, "\n"); return ObjectPropertyCondition(); @@ -240,7 +262,7 @@ if (value.isNull()) { if (!prototype) { if (verbose) - dataLog("Reached end up prototype chain as expected, done.\n"); + dataLog("Reached end of prototype chain as expected, done.\n"); break; } if (verbose) @@ -251,12 +273,18 @@ JSObject* object = jsCast(value); structure = object->structure(vm); - // Since we're accessing a prototype repeatedly, it's a good bet that it should not be - // treated as a dictionary. if (structure->isDictionary()) { - if (concurrency == MainThread) + if (concurrency == MainThread) { + if (structure->hasBeenFlattenedBefore()) { + if (verbose) + dataLog("Dictionary has been flattened before, so invalid.\n"); + return ObjectPropertyConditionSet::invalid(); + } + + if (verbose) + dataLog("Flattening ", pointerDump(structure)); structure->flattenDictionaryStructure(vm, object); - else { + } else { if (verbose) dataLog("Cannot flatten dictionary when not on main thread, so invalid.\n"); return ObjectPropertyConditionSet::invalid(); @@ -349,6 +377,35 @@ }); } +ObjectPropertyConditionSet generateConditionsForPrototypeEquivalenceConcurrently( + VM& vm, JSGlobalObject* globalObject, Structure* headStructure, JSObject* prototype, UniquedStringImpl* uid) +{ + return generateConditions(vm, globalObject, headStructure, prototype, + [&] (Vector& conditions, JSObject* object) -> bool { + PropertyCondition::Kind kind = + object == prototype ? PropertyCondition::Equivalence : PropertyCondition::Absence; + ObjectPropertyCondition result = generateCondition(vm, nullptr, object, uid, kind); + if (!result) + return false; + conditions.append(result); + return true; + }, Concurrent); +} + +ObjectPropertyConditionSet generateConditionsForPropertyMissConcurrently( + VM& vm, JSGlobalObject* globalObject, Structure* headStructure, UniquedStringImpl* uid) +{ + return generateConditions( + vm, globalObject, headStructure, nullptr, + [&] (Vector& conditions, JSObject* object) -> bool { + ObjectPropertyCondition result = generateCondition(vm, nullptr, object, uid, PropertyCondition::Absence); + if (!result) + return false; + conditions.append(result); + return true; + }, Concurrent); +} + ObjectPropertyConditionSet generateConditionsForPropertySetterMissConcurrently( VM& vm, JSGlobalObject* globalObject, Structure* headStructure, UniquedStringImpl* uid) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h 2016-11-03 07:04:20.000000000 +0000 @@ -67,6 +67,8 @@ { return !m_data || !m_data->vector.isEmpty(); } + + bool isValidAndWatchable() const; bool isEmpty() const { @@ -166,6 +168,11 @@ VM&, JSCell* owner, ExecState*, Structure* headStructure, JSObject* prototype, UniquedStringImpl* uid); +ObjectPropertyConditionSet generateConditionsForPrototypeEquivalenceConcurrently( + VM&, JSGlobalObject*, Structure* headStructure, JSObject* prototype, + UniquedStringImpl* uid); +ObjectPropertyConditionSet generateConditionsForPropertyMissConcurrently( + VM&, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid); ObjectPropertyConditionSet generateConditionsForPropertySetterMissConcurrently( VM&, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Opcode.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Opcode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Opcode.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Opcode.h 2016-11-03 07:04:20.000000000 +0000 @@ -55,7 +55,7 @@ #define OPCODE_ID_ENUM(opcode, length) opcode, - typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID; + enum OpcodeID : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) }; #undef OPCODE_ID_ENUM const int maxOpcodeLength = 9; @@ -75,10 +75,19 @@ const int opcodeLengths[numOpcodeIDs] = { FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTH_MAP) }; #undef OPCODE_ID_LENGTH_MAP +#if COMPILER(GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" +#endif + #define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= numOpcodeIDs, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID); FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID); #undef VERIFY_OPCODE_ID +#if COMPILER(GCC) +#pragma GCC diagnostic pop +#endif + #if ENABLE(COMPUTED_GOTO_OPCODES) typedef void* Opcode; #else @@ -126,6 +135,64 @@ return 0; } +inline bool isBranch(OpcodeID opcodeID) +{ + switch (opcodeID) { + case op_jmp: + case op_jtrue: + case op_jfalse: + case op_jeq_null: + case op_jneq_null: + case op_jneq_ptr: + case op_jless: + case op_jlesseq: + case op_jgreater: + case op_jgreatereq: + case op_jnless: + case op_jnlesseq: + case op_jngreater: + case op_jngreatereq: + case op_switch_imm: + case op_switch_char: + case op_switch_string: + return true; + default: + return false; + } +} + +inline bool isUnconditionalBranch(OpcodeID opcodeID) +{ + switch (opcodeID) { + case op_jmp: + return true; + default: + return false; + } +} + +inline bool isTerminal(OpcodeID opcodeID) +{ + switch (opcodeID) { + case op_ret: + case op_end: + return true; + default: + return false; + } +} + +inline bool isThrow(OpcodeID opcodeID) +{ + switch (opcodeID) { + case op_throw: + case op_throw_static_error: + return true; + default: + return false; + } +} + } // namespace JSC namespace WTF { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Operands.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Operands.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Operands.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Operands.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012, 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012, 2013, 2015, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,32 +37,37 @@ template struct OperandValueTraits; -template -struct OperandValueTraits { - static T defaultValue() { return T(); } - static bool isEmptyForDump(const T& value) { return !value; } -}; - enum OperandKind { ArgumentOperand, LocalOperand }; enum OperandsLikeTag { OperandsLike }; -template> +template class Operands { public: Operands() { } - explicit Operands(size_t numArguments, size_t numLocals, const T& initialValue = Traits::defaultValue()) + explicit Operands(size_t numArguments, size_t numLocals) + { + if (WTF::VectorTraits::needsInitialization) { + m_arguments.resize(numArguments); + m_locals.resize(numLocals); + } else { + m_arguments.fill(T(), numArguments); + m_locals.fill(T(), numLocals); + } + } + + explicit Operands(size_t numArguments, size_t numLocals, const T& initialValue) { m_arguments.fill(initialValue, numArguments); m_locals.fill(initialValue, numLocals); } - template - explicit Operands(OperandsLikeTag, const Operands& other) + template + explicit Operands(OperandsLikeTag, const Operands& other) { - m_arguments.fill(Traits::defaultValue(), other.numberOfArguments()); - m_locals.fill(Traits::defaultValue(), other.numberOfLocals()); + m_arguments.fill(T(), other.numberOfArguments()); + m_locals.fill(T(), other.numberOfLocals()); } size_t numberOfArguments() const { return m_arguments.size(); } @@ -96,7 +101,20 @@ return local(idx); } - void ensureLocals(size_t size, const T& ensuredValue = Traits::defaultValue()) + void ensureLocals(size_t size) + { + if (size <= m_locals.size()) + return; + + size_t oldSize = m_locals.size(); + m_locals.resize(size); + if (!WTF::VectorTraits::needsInitialization) { + for (size_t i = oldSize; i < m_locals.size(); ++i) + m_locals[i] = T(); + } + } + + void ensureLocals(size_t size, const T& ensuredValue) { if (size <= m_locals.size()) return; @@ -117,19 +135,19 @@ T getLocal(size_t idx) { if (idx >= m_locals.size()) - return Traits::defaultValue(); + return T(); return m_locals[idx]; } void setArgumentFirstTime(size_t idx, const T& value) { - ASSERT(m_arguments[idx] == Traits::defaultValue()); + ASSERT(m_arguments[idx] == T()); argument(idx) = value; } void setLocalFirstTime(size_t idx, const T& value) { - ASSERT(idx >= m_locals.size() || m_locals[idx] == Traits::defaultValue()); + ASSERT(idx >= m_locals.size() || m_locals[idx] == T()); setLocal(idx, value); } @@ -245,7 +263,7 @@ void clear() { - fill(Traits::defaultValue()); + fill(T()); } bool operator==(const Operands& other) const diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/OperandsInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/OperandsInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/OperandsInlines.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/OperandsInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,33 +31,33 @@ namespace JSC { -template -void Operands::dumpInContext(PrintStream& out, DumpContext* context) const +template +void Operands::dumpInContext(PrintStream& out, DumpContext* context) const { CommaPrinter comma(" "); for (size_t argumentIndex = numberOfArguments(); argumentIndex--;) { - if (Traits::isEmptyForDump(argument(argumentIndex))) + if (!argument(argumentIndex)) continue; out.print(comma, "arg", argumentIndex, ":", inContext(argument(argumentIndex), context)); } for (size_t localIndex = 0; localIndex < numberOfLocals(); ++localIndex) { - if (Traits::isEmptyForDump(local(localIndex))) + if (!local(localIndex)) continue; out.print(comma, "loc", localIndex, ":", inContext(local(localIndex), context)); } } -template -void Operands::dump(PrintStream& out) const +template +void Operands::dump(PrintStream& out) const { CommaPrinter comma(" "); for (size_t argumentIndex = numberOfArguments(); argumentIndex--;) { - if (Traits::isEmptyForDump(argument(argumentIndex))) + if (!argument(argumentIndex)) continue; out.print(comma, "arg", argumentIndex, ":", argument(argumentIndex)); } for (size_t localIndex = 0; localIndex < numberOfLocals(); ++localIndex) { - if (Traits::isEmptyForDump(local(localIndex))) + if (!local(localIndex)) continue; out.print(comma, "loc", localIndex, ":", local(localIndex)); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,11 +31,13 @@ #include "BinarySwitch.h" #include "CCallHelpers.h" #include "CodeBlock.h" +#include "DirectArguments.h" #include "GetterSetter.h" #include "Heap.h" #include "JITOperations.h" #include "JSCInlines.h" #include "LinkBuffer.h" +#include "ScopedArguments.h" #include "ScratchRegisterAllocator.h" #include "StructureStubClearingWatchpoint.h" #include "StructureStubInfo.h" @@ -46,6 +48,13 @@ static const bool verbose = false; +void AccessGenerationResult::dump(PrintStream& out) const +{ + out.print(m_kind); + if (m_code) + out.print(":", m_code); +} + Watchpoint* AccessGenerationState::addWatchpoint(const ObjectPropertyCondition& condition) { return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint( @@ -63,7 +72,7 @@ success.append(jit->jump()); } -void AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling() +void AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling(const RegisterSet& extra) { if (!m_calculatedRegistersForCallAndExceptionHandling) { m_calculatedRegistersForCallAndExceptionHandling = true; @@ -74,12 +83,16 @@ RELEASE_ASSERT(JITCode::isOptimizingJIT(jit->codeBlock()->jitType())); m_liveRegistersForCall = RegisterSet(m_liveRegistersToPreserveAtExceptionHandlingCallSite, allocator->usedRegisters()); + m_liveRegistersForCall.merge(extra); m_liveRegistersForCall.exclude(RegisterSet::registersToNotSaveForJSCall()); + m_liveRegistersForCall.merge(extra); } } -void AccessGenerationState::preserveLiveRegistersToStackForCall() +void AccessGenerationState::preserveLiveRegistersToStackForCall(const RegisterSet& extra) { + calculateLiveRegistersForCallAndExceptionHandling(extra); + unsigned extraStackPadding = 0; unsigned numberOfStackBytesUsedForRegisterPreservation = ScratchRegisterAllocator::preserveRegistersToStackForCall(*jit, liveRegistersForCall(), extraStackPadding); if (m_numberOfStackBytesUsedForRegisterPreservation != std::numeric_limits::max()) @@ -148,10 +161,62 @@ CallSiteIndex AccessGenerationState::originalCallSiteIndex() const { return stubInfo->callSiteIndex; } +void AccessGenerationState::emitExplicitExceptionHandler() +{ + restoreScratch(); + jit->copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(); + if (needsToRestoreRegistersIfException()) { + // To the JIT that produces the original exception handling + // call site, they will expect the OSR exit to be arrived + // at from genericUnwind. Therefore we must model what genericUnwind + // does here. I.e, set callFrameForCatch and copy callee saves. + + jit->storePtr(GPRInfo::callFrameRegister, jit->vm()->addressOfCallFrameForCatch()); + CCallHelpers::Jump jumpToOSRExitExceptionHandler = jit->jump(); + + // We don't need to insert a new exception handler in the table + // because we're doing a manual exception check here. i.e, we'll + // never arrive here from genericUnwind(). + HandlerInfo originalHandler = originalExceptionHandler(); + jit->addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link(jumpToOSRExitExceptionHandler, originalHandler.nativeCode); + }); + } else { + jit->setupArguments(CCallHelpers::TrustedImmPtr(jit->vm()), GPRInfo::callFrameRegister); + CCallHelpers::Call lookupExceptionHandlerCall = jit->call(); + jit->addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link(lookupExceptionHandlerCall, lookupExceptionHandler); + }); + jit->jumpToExceptionHandler(); + } +} + AccessCase::AccessCase() { } +std::unique_ptr AccessCase::tryGet( + VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure, + const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet) +{ + std::unique_ptr result(new AccessCase()); + + result->m_type = type; + result->m_offset = offset; + result->m_structure.set(vm, owner, structure); + result->m_conditionSet = conditionSet; + + if (viaProxy || additionalSet) { + result->m_rareData = std::make_unique(); + result->m_rareData->viaProxy = viaProxy; + result->m_rareData->additionalSet = additionalSet; + } + + return result; +} + std::unique_ptr AccessCase::get( VM& vm, JSCell* owner, AccessType type, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, bool viaProxy, WatchpointSet* additionalSet, @@ -175,6 +240,21 @@ return result; } +std::unique_ptr AccessCase::megamorphicLoad(VM& vm, JSCell* owner) +{ + UNUSED_PARAM(vm); + UNUSED_PARAM(owner); + + if (GPRInfo::numberOfRegisters < 9) + return nullptr; + + std::unique_ptr result(new AccessCase()); + + result->m_type = MegamorphicLoad; + + return result; +} + std::unique_ptr AccessCase::replace( VM& vm, JSCell* owner, Structure* structure, PropertyOffset offset) { @@ -201,13 +281,6 @@ return nullptr; } - // Skip optimizing the case where we need realloc, and the structure has - // indexing storage. - // FIXME: We shouldn't skip this! Implement it! - // https://bugs.webkit.org/show_bug.cgi?id=130914 - if (oldStructure->couldHaveIndexingHeader()) - return nullptr; - std::unique_ptr result(new AccessCase()); result->m_type = Transition; @@ -316,14 +389,38 @@ return result; } +Vector AccessCase::commit(VM& vm, const Identifier& ident) +{ + // It's fine to commit something that is already committed. That arises when we switch to using + // newly allocated watchpoints. When it happens, it's not efficient - but we think that's OK + // because most AccessCases have no extra watchpoints anyway. + RELEASE_ASSERT(m_state == Primordial || m_state == Committed); + + Vector result; + + if ((structure() && structure()->needImpurePropertyWatchpoint()) + || m_conditionSet.needImpurePropertyWatchpoint()) + result.append(vm.ensureWatchpointSetForImpureProperty(ident)); + + if (additionalSet()) + result.append(additionalSet()); + + m_state = Committed; + + return result; +} + bool AccessCase::guardedByStructureCheck() const { if (viaProxy()) return false; switch (m_type) { + case MegamorphicLoad: case ArrayLength: case StringLength: + case DirectArgumentsLength: + case ScopedArgumentsLength: return false; default: return true; @@ -337,21 +434,65 @@ return conditionSet().slotBaseCondition().object(); } +bool AccessCase::doesCalls(Vector* cellsToMark) const +{ + switch (type()) { + case Getter: + case Setter: + case CustomValueGetter: + case CustomAccessorGetter: + case CustomValueSetter: + case CustomAccessorSetter: + return true; + case Transition: + if (newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity() + && structure()->couldHaveIndexingHeader()) { + if (cellsToMark) + cellsToMark->append(newStructure()); + return true; + } + return false; + default: + return false; + } +} + bool AccessCase::couldStillSucceed() const { return m_conditionSet.structuresEnsureValidityAssumingImpurePropertyWatchpoint(); } -bool AccessCase::canReplace(const AccessCase& other) +bool AccessCase::canBeReplacedByMegamorphicLoad() const { - // We could do a lot better here, but for now we just do something obvious. + if (type() == MegamorphicLoad) + return true; + + return type() == Load + && !viaProxy() + && conditionSet().isEmpty() + && !additionalSet() + && !customSlotBase(); +} - if (!guardedByStructureCheck() || !other.guardedByStructureCheck()) { - // FIXME: Implement this! - return false; - } +bool AccessCase::canReplace(const AccessCase& other) const +{ + // This puts in a good effort to try to figure out if 'other' is made superfluous by '*this'. + // It's fine for this to return false if it's in doubt. - return structure() == other.structure(); + switch (type()) { + case MegamorphicLoad: + return other.canBeReplacedByMegamorphicLoad(); + case ArrayLength: + case StringLength: + case DirectArgumentsLength: + case ScopedArgumentsLength: + return other.type() == type(); + default: + if (!guardedByStructureCheck() || !other.guardedByStructureCheck()) + return false; + + return structure() == other.structure(); + } } void AccessCase::dump(PrintStream& out) const @@ -359,6 +500,8 @@ out.print(m_type, ":("); CommaPrinter comma; + + out.print(comma, m_state); if (m_type == Transition) out.print(comma, "structure = ", pointerDump(structure()), " -> ", pointerDump(newStructure())); @@ -403,21 +546,55 @@ return true; } +bool AccessCase::propagateTransitions(SlotVisitor& visitor) const +{ + bool result = true; + + if (m_structure) + result &= m_structure->markIfCheap(visitor); + + switch (m_type) { + case Transition: + if (Heap::isMarkedConcurrently(m_structure->previousID())) + visitor.appendUnbarrieredReadOnlyPointer(m_structure.get()); + else + result = false; + break; + default: + break; + } + + return result; +} + void AccessCase::generateWithGuard( AccessGenerationState& state, CCallHelpers::JumpList& fallThrough) { + SuperSamplerScope superSamplerScope(false); + + RELEASE_ASSERT(m_state == Committed); + m_state = Generated; + CCallHelpers& jit = *state.jit; + VM& vm = *jit.vm(); + const Identifier& ident = *state.ident; + StructureStubInfo& stubInfo = *state.stubInfo; + JSValueRegs valueRegs = state.valueRegs; + GPRReg baseGPR = state.baseGPR; + GPRReg scratchGPR = state.scratchGPR; + + UNUSED_PARAM(vm); switch (m_type) { case ArrayLength: { ASSERT(!viaProxy()); - jit.load8(CCallHelpers::Address(state.baseGPR, JSCell::indexingTypeOffset()), state.scratchGPR); + jit.load8(CCallHelpers::Address(baseGPR, JSCell::indexingTypeOffset()), scratchGPR); fallThrough.append( jit.branchTest32( - CCallHelpers::Zero, state.scratchGPR, CCallHelpers::TrustedImm32(IsArray))); + CCallHelpers::Zero, scratchGPR, CCallHelpers::TrustedImm32(IsArray))); fallThrough.append( jit.branchTest32( - CCallHelpers::Zero, state.scratchGPR, CCallHelpers::TrustedImm32(IndexingShapeMask))); + CCallHelpers::Zero, scratchGPR, CCallHelpers::TrustedImm32(IndexingShapeMask))); break; } @@ -426,54 +603,210 @@ fallThrough.append( jit.branch8( CCallHelpers::NotEqual, - CCallHelpers::Address(state.baseGPR, JSCell::typeInfoTypeOffset()), + CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), CCallHelpers::TrustedImm32(StringType))); break; } + + case DirectArgumentsLength: { + ASSERT(!viaProxy()); + fallThrough.append( + jit.branch8( + CCallHelpers::NotEqual, + CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), + CCallHelpers::TrustedImm32(DirectArgumentsType))); + + fallThrough.append( + jit.branchTestPtr( + CCallHelpers::NonZero, + CCallHelpers::Address(baseGPR, DirectArguments::offsetOfOverrides()))); + jit.load32( + CCallHelpers::Address(baseGPR, DirectArguments::offsetOfLength()), + valueRegs.payloadGPR()); + jit.boxInt32(valueRegs.payloadGPR(), valueRegs); + state.succeed(); + return; + } + + case ScopedArgumentsLength: { + ASSERT(!viaProxy()); + fallThrough.append( + jit.branch8( + CCallHelpers::NotEqual, + CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), + CCallHelpers::TrustedImm32(ScopedArgumentsType))); + + fallThrough.append( + jit.branchTest8( + CCallHelpers::NonZero, + CCallHelpers::Address(baseGPR, ScopedArguments::offsetOfOverrodeThings()))); + jit.load32( + CCallHelpers::Address(baseGPR, ScopedArguments::offsetOfTotalLength()), + valueRegs.payloadGPR()); + jit.boxInt32(valueRegs.payloadGPR(), valueRegs); + state.succeed(); + return; + } + + case MegamorphicLoad: { + UniquedStringImpl* key = ident.impl(); + unsigned hash = IdentifierRepHash::hash(key); + + ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters); + allocator.lock(baseGPR); +#if USE(JSVALUE32_64) + allocator.lock(static_cast(stubInfo.patch.baseTagGPR)); +#endif + allocator.lock(valueRegs); + allocator.lock(scratchGPR); + + GPRReg intermediateGPR = scratchGPR; + GPRReg maskGPR = allocator.allocateScratchGPR(); + GPRReg maskedHashGPR = allocator.allocateScratchGPR(); + GPRReg indexGPR = allocator.allocateScratchGPR(); + GPRReg offsetGPR = allocator.allocateScratchGPR(); + + if (verbose) { + dataLog("baseGPR = ", baseGPR, "\n"); + dataLog("valueRegs = ", valueRegs, "\n"); + dataLog("scratchGPR = ", scratchGPR, "\n"); + dataLog("intermediateGPR = ", intermediateGPR, "\n"); + dataLog("maskGPR = ", maskGPR, "\n"); + dataLog("maskedHashGPR = ", maskedHashGPR, "\n"); + dataLog("indexGPR = ", indexGPR, "\n"); + dataLog("offsetGPR = ", offsetGPR, "\n"); + } + + ScratchRegisterAllocator::PreservedState preservedState = + allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall); + + CCallHelpers::JumpList myFailAndIgnore; + CCallHelpers::JumpList myFallThrough; + + jit.emitLoadStructure(baseGPR, intermediateGPR, maskGPR); + jit.loadPtr( + CCallHelpers::Address(intermediateGPR, Structure::propertyTableUnsafeOffset()), + intermediateGPR); + + myFailAndIgnore.append(jit.branchTestPtr(CCallHelpers::Zero, intermediateGPR)); + + jit.load32(CCallHelpers::Address(intermediateGPR, PropertyTable::offsetOfIndexMask()), maskGPR); + jit.loadPtr(CCallHelpers::Address(intermediateGPR, PropertyTable::offsetOfIndex()), indexGPR); + jit.load32( + CCallHelpers::Address(intermediateGPR, PropertyTable::offsetOfIndexSize()), + intermediateGPR); + + jit.move(maskGPR, maskedHashGPR); + jit.and32(CCallHelpers::TrustedImm32(hash), maskedHashGPR); + jit.lshift32(CCallHelpers::TrustedImm32(2), intermediateGPR); + jit.addPtr(indexGPR, intermediateGPR); + + CCallHelpers::Label loop = jit.label(); + + jit.load32(CCallHelpers::BaseIndex(indexGPR, maskedHashGPR, CCallHelpers::TimesFour), offsetGPR); + + myFallThrough.append( + jit.branch32( + CCallHelpers::Equal, + offsetGPR, + CCallHelpers::TrustedImm32(PropertyTable::EmptyEntryIndex))); + + jit.sub32(CCallHelpers::TrustedImm32(1), offsetGPR); + jit.mul32(CCallHelpers::TrustedImm32(sizeof(PropertyMapEntry)), offsetGPR, offsetGPR); + jit.addPtr(intermediateGPR, offsetGPR); + + CCallHelpers::Jump collision = jit.branchPtr( + CCallHelpers::NotEqual, + CCallHelpers::Address(offsetGPR, OBJECT_OFFSETOF(PropertyMapEntry, key)), + CCallHelpers::TrustedImmPtr(key)); + + // offsetGPR currently holds a pointer to the PropertyMapEntry, which has the offset and attributes. + // Check them and then attempt the load. + + myFallThrough.append( + jit.branchTest32( + CCallHelpers::NonZero, + CCallHelpers::Address(offsetGPR, OBJECT_OFFSETOF(PropertyMapEntry, attributes)), + CCallHelpers::TrustedImm32(Accessor | CustomAccessor))); + + jit.load32(CCallHelpers::Address(offsetGPR, OBJECT_OFFSETOF(PropertyMapEntry, offset)), offsetGPR); + + jit.loadProperty(baseGPR, offsetGPR, valueRegs); + + allocator.restoreReusedRegistersByPopping(jit, preservedState); + state.succeed(); + + collision.link(&jit); + + jit.add32(CCallHelpers::TrustedImm32(1), maskedHashGPR); + + // FIXME: We could be smarter about this. Currently we're burning a GPR for the mask. But looping + // around isn't super common so we could, for example, recompute the mask from the difference between + // the table and index. But before we do that we should probably make it easier to multiply and + // divide by the size of PropertyMapEntry. That probably involves making PropertyMapEntry be arranged + // to have a power-of-2 size. + jit.and32(maskGPR, maskedHashGPR); + jit.jump().linkTo(loop, &jit); + + if (allocator.didReuseRegisters()) { + myFailAndIgnore.link(&jit); + allocator.restoreReusedRegistersByPopping(jit, preservedState); + state.failAndIgnore.append(jit.jump()); + + myFallThrough.link(&jit); + allocator.restoreReusedRegistersByPopping(jit, preservedState); + fallThrough.append(jit.jump()); + } else { + state.failAndIgnore.append(myFailAndIgnore); + fallThrough.append(myFallThrough); + } + return; + } default: { if (viaProxy()) { fallThrough.append( jit.branch8( CCallHelpers::NotEqual, - CCallHelpers::Address(state.baseGPR, JSCell::typeInfoTypeOffset()), + CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), CCallHelpers::TrustedImm32(PureForwardingProxyType))); - jit.loadPtr( - CCallHelpers::Address(state.baseGPR, JSProxy::targetOffset()), - state.scratchGPR); + jit.loadPtr(CCallHelpers::Address(baseGPR, JSProxy::targetOffset()), scratchGPR); fallThrough.append( jit.branchStructure( CCallHelpers::NotEqual, - CCallHelpers::Address(state.scratchGPR, JSCell::structureIDOffset()), + CCallHelpers::Address(scratchGPR, JSCell::structureIDOffset()), structure())); } else { fallThrough.append( jit.branchStructure( CCallHelpers::NotEqual, - CCallHelpers::Address(state.baseGPR, JSCell::structureIDOffset()), + CCallHelpers::Address(baseGPR, JSCell::structureIDOffset()), structure())); } break; } }; - generate(state); + generateImpl(state); } -// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned on an even-numbered register (r0, r2 or [sp]). -// To prevent the assembler from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary. -#if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS) -#define EABI_32BIT_DUMMY_ARG CCallHelpers::TrustedImm32(0), -#else -#define EABI_32BIT_DUMMY_ARG -#endif - void AccessCase::generate(AccessGenerationState& state) { + RELEASE_ASSERT(m_state == Committed); + m_state = Generated; + + generateImpl(state); +} + +void AccessCase::generateImpl(AccessGenerationState& state) +{ + SuperSamplerScope superSamplerScope(false); if (verbose) dataLog("Generating code for: ", *this, "\n"); + ASSERT(m_state == Generated); // We rely on the callers setting this for us. + CCallHelpers& jit = *state.jit; VM& vm = *jit.vm(); CodeBlock* codeBlock = jit.codeBlock(); @@ -485,13 +818,6 @@ ASSERT(m_conditionSet.structuresEnsureValidityAssumingImpurePropertyWatchpoint()); - if ((structure() && structure()->needImpurePropertyWatchpoint()) - || m_conditionSet.needImpurePropertyWatchpoint()) - vm.registerWatchpointForImpureProperty(ident, state.addWatchpoint()); - - if (additionalSet()) - additionalSet()->add(state.addWatchpoint()); - for (const ObjectPropertyCondition& condition : m_conditionSet) { Structure* structure = condition.object()->structure(); @@ -501,6 +827,10 @@ } if (!condition.structureEnsuresValidityAssumingImpurePropertyWatchpoint(structure)) { + // The reason why this cannot happen is that we require that PolymorphicAccess calls + // AccessCase::generate() only after it has verified that + // AccessCase::couldStillSucceed() returned true. + dataLog("This condition is no longer met: ", condition, "\n"); RELEASE_ASSERT_NOT_REACHED(); } @@ -529,6 +859,7 @@ return; case Load: + case GetGetter: case Getter: case Setter: case CustomValueGetter: @@ -564,7 +895,7 @@ GPRReg loadedValueGPR = InvalidGPRReg; if (m_type != CustomValueGetter && m_type != CustomAccessorGetter && m_type != CustomValueSetter && m_type != CustomAccessorSetter) { - if (m_type == Load) + if (m_type == Load || m_type == GetGetter) loadedValueGPR = valueRegs.payloadGPR(); else loadedValueGPR = scratchGPR; @@ -576,7 +907,6 @@ jit.loadPtr( CCallHelpers::Address(baseForAccessGPR, JSObject::butterflyOffset()), loadedValueGPR); - jit.removeSpaceBits(loadedValueGPR); storageGPR = loadedValueGPR; } @@ -584,7 +914,7 @@ jit.load64( CCallHelpers::Address(storageGPR, offsetRelativeToBase(m_offset)), loadedValueGPR); #else - if (m_type == Load) { + if (m_type == Load || m_type == GetGetter) { jit.load32( CCallHelpers::Address(storageGPR, offsetRelativeToBase(m_offset) + TagOffset), valueRegs.tagGPR()); @@ -595,14 +925,13 @@ #endif } - if (m_type == Load) { + if (m_type == Load || m_type == GetGetter) { state.succeed(); return; } // Stuff for custom getters/setters. CCallHelpers::Call operationCall; - CCallHelpers::Call lookupExceptionHandlerCall; // Stuff for JS getters/setters. CCallHelpers::DataLabelPtr addressOfLinkFunctionCheck; @@ -614,14 +943,11 @@ // This also does the necessary calculations of whether or not we're an // exception handling call site. - state.calculateLiveRegistersForCallAndExceptionHandling(); state.preserveLiveRegistersToStackForCall(); - // Need to make sure that whenever this call is made in the future, we remember the - // place that we made it from. jit.store32( CCallHelpers::TrustedImm32(state.callSiteIndexForExceptionHandlingOrOriginal().bits()), - CCallHelpers::tagFor(static_cast(JSStack::ArgumentCount))); + CCallHelpers::tagFor(static_cast(CallFrameSlot::argumentCount))); if (m_type == Getter || m_type == Setter) { // Create a JS call using a JS call inline cache. Assume that: @@ -676,10 +1002,10 @@ CCallHelpers::Jump returnUndefined = jit.branchTestPtr( CCallHelpers::Zero, loadedValueGPR); - unsigned numberOfRegsForCall = JSStack::CallFrameHeaderSize + numberOfParameters; + unsigned numberOfRegsForCall = CallFrame::headerSizeInRegisters + numberOfParameters; unsigned numberOfBytesForCall = - numberOfRegsForCall * sizeof(Register) + sizeof(CallerFrameAndPC); + numberOfRegsForCall * sizeof(Register) - sizeof(CallerFrameAndPC); unsigned alignedNumberOfBytesForCall = WTF::roundUpToMultipleOf(stackAlignmentBytes(), numberOfBytesForCall); @@ -694,10 +1020,10 @@ jit.store32( CCallHelpers::TrustedImm32(numberOfParameters), - calleeFrame.withOffset(JSStack::ArgumentCount * sizeof(Register) + PayloadOffset)); + calleeFrame.withOffset(CallFrameSlot::argumentCount * sizeof(Register) + PayloadOffset)); jit.storeCell( - loadedValueGPR, calleeFrame.withOffset(JSStack::Callee * sizeof(Register))); + loadedValueGPR, calleeFrame.withOffset(CallFrameSlot::callee * sizeof(Register))); jit.storeCell( baseForGetGPR, @@ -737,11 +1063,11 @@ done.link(&jit); - jit.addPtr(CCallHelpers::TrustedImm32((jit.codeBlock()->stackPointerOffset() * sizeof(Register)) - state.preservedReusedRegisterState.numberOfBytesPreserved - state.numberOfStackBytesUsedForRegisterPreservation()), + jit.addPtr(CCallHelpers::TrustedImm32((codeBlock->stackPointerOffset() * sizeof(Register)) - state.preservedReusedRegisterState.numberOfBytesPreserved - state.numberOfStackBytesUsedForRegisterPreservation()), GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister); state.restoreLiveRegistersFromStackForCall(isGetter()); - state.callbacks.append( + jit.addLinkTask( [=, &vm] (LinkBuffer& linkBuffer) { m_rareData->callLinkInfo->setCallLocations( linkBuffer.locationOfNearCall(slowPathCall), @@ -753,16 +1079,16 @@ CodeLocationLabel(vm.getCTIStub(linkCallThunkGenerator).code())); }); } else { - // Need to make room for the C call so any of our stack spillage isn't overwritten. - // We also need to make room because we may be an inline cache in the FTL and not - // have a JIT call frame. - bool needsToMakeRoomOnStackForCCall = state.numberOfStackBytesUsedForRegisterPreservation() || codeBlock->jitType() == JITCode::FTLJIT; - if (needsToMakeRoomOnStackForCCall) - jit.makeSpaceOnStackForCCall(); + // Need to make room for the C call so any of our stack spillage isn't overwritten. It's + // hard to track if someone did spillage or not, so we just assume that we always need + // to make some space here. + jit.makeSpaceOnStackForCCall(); // getter: EncodedJSValue (*GetValueFunc)(ExecState*, EncodedJSValue thisValue, PropertyName); // setter: void (*PutValueFunc)(ExecState*, EncodedJSValue thisObject, EncodedJSValue value); // Custom values are passed the slotBase (the property holder), custom accessors are passed the thisVaule (reciever). + // FIXME: Remove this differences in custom values and custom accessors. + // https://bugs.webkit.org/show_bug.cgi?id=158014 GPRReg baseForCustomValue = m_type == CustomValueGetter || m_type == CustomValueSetter ? baseForAccessGPR : baseForGetGPR; #if USE(JSVALUE64) if (m_type == CustomValueGetter || m_type == CustomAccessorGetter) { @@ -787,51 +1113,23 @@ jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame); operationCall = jit.call(); + jit.addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link(operationCall, FunctionPtr(m_rareData->customAccessor.opaque)); + }); + if (m_type == CustomValueGetter || m_type == CustomAccessorGetter) jit.setupResults(valueRegs); - if (needsToMakeRoomOnStackForCCall) - jit.reclaimSpaceOnStackForCCall(); + jit.reclaimSpaceOnStackForCCall(); CCallHelpers::Jump noException = jit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck); - bool didSetLookupExceptionHandler = false; state.restoreLiveRegistersFromStackForCallWithThrownException(); - state.restoreScratch(); - jit.copyCalleeSavesToVMCalleeSavesBuffer(); - if (state.needsToRestoreRegistersIfException()) { - // To the JIT that produces the original exception handling - // call site, they will expect the OSR exit to be arrived - // at from genericUnwind. Therefore we must model what genericUnwind - // does here. I.e, set callFrameForCatch and copy callee saves. - - jit.storePtr(GPRInfo::callFrameRegister, vm.addressOfCallFrameForCatch()); - CCallHelpers::Jump jumpToOSRExitExceptionHandler = jit.jump(); - - // We don't need to insert a new exception handler in the table - // because we're doing a manual exception check here. i.e, we'll - // never arrive here from genericUnwind(). - HandlerInfo originalHandler = state.originalExceptionHandler(); - state.callbacks.append( - [=] (LinkBuffer& linkBuffer) { - linkBuffer.link(jumpToOSRExitExceptionHandler, originalHandler.nativeCode); - }); - } else { - jit.setupArguments(CCallHelpers::TrustedImmPtr(&vm), GPRInfo::callFrameRegister); - lookupExceptionHandlerCall = jit.call(); - didSetLookupExceptionHandler = true; - jit.jumpToExceptionHandler(); - } + state.emitExplicitExceptionHandler(); noException.link(&jit); state.restoreLiveRegistersFromStackForCall(isGetter()); - - state.callbacks.append( - [=] (LinkBuffer& linkBuffer) { - linkBuffer.link(operationCall, FunctionPtr(m_rareData->customAccessor.opaque)); - if (didSetLookupExceptionHandler) - linkBuffer.link(lookupExceptionHandlerCall, lookupExceptionHandler); - }); } state.succeed(); return; @@ -842,8 +1140,7 @@ if (verbose) dataLog("Have type: ", type->descriptor(), "\n"); state.failAndRepatch.append( - jit.branchIfNotType( - valueRegs, scratchGPR, type->descriptor(), CCallHelpers::DoNotHaveTagRegisters)); + jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor())); } else if (verbose) dataLog("Don't have type.\n"); @@ -856,7 +1153,6 @@ offsetInInlineStorage(m_offset) * sizeof(JSValue))); } else { jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR); - state.failAndIgnore.append(jit.branchIfNotToSpace(scratchGPR)); jit.storeValue( valueRegs, CCallHelpers::Address( @@ -867,20 +1163,22 @@ } case Transition: { - // AccessCase::transition() should have returned null. + // AccessCase::transition() should have returned null if this wasn't true. RELEASE_ASSERT(GPRInfo::numberOfRegisters >= 6 || !structure()->outOfLineCapacity() || structure()->outOfLineCapacity() == newStructure()->outOfLineCapacity()); - RELEASE_ASSERT(!structure()->couldHaveIndexingHeader()); if (InferredType* type = newStructure()->inferredTypeFor(ident.impl())) { if (verbose) dataLog("Have type: ", type->descriptor(), "\n"); state.failAndRepatch.append( - jit.branchIfNotType( - valueRegs, scratchGPR, type->descriptor(), CCallHelpers::DoNotHaveTagRegisters)); + jit.branchIfNotType(valueRegs, scratchGPR, type->descriptor())); } else if (verbose) dataLog("Don't have type.\n"); - CCallHelpers::JumpList slowPath; + // NOTE: This logic is duplicated in AccessCase::doesCalls(). It's important that doesCalls() knows + // exactly when this would make calls. + bool allocating = newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity(); + bool reallocating = allocating && structure()->outOfLineCapacity(); + bool allocatingInline = allocating && !structure()->couldHaveIndexingHeader(); ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters); allocator.lock(baseGPR); @@ -890,77 +1188,112 @@ allocator.lock(valueRegs); allocator.lock(scratchGPR); - GPRReg scratchGPR2 = allocator.allocateScratchGPR(); - GPRReg scratchGPR3; - if (newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity() - && structure()->outOfLineCapacity()) + GPRReg scratchGPR2 = InvalidGPRReg; + GPRReg scratchGPR3 = InvalidGPRReg; + if (allocatingInline) { + scratchGPR2 = allocator.allocateScratchGPR(); scratchGPR3 = allocator.allocateScratchGPR(); - else - scratchGPR3 = InvalidGPRReg; + } ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall); + + CCallHelpers::JumpList slowPath; ASSERT(structure()->transitionWatchpointSetHasBeenInvalidated()); - bool scratchGPRHasStorage = false; - bool needsToMakeRoomOnStackForCCall = !preservedState.numberOfBytesPreserved && codeBlock->jitType() == JITCode::FTLJIT; - - if (newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity()) { + if (allocating) { size_t newSize = newStructure()->outOfLineCapacity() * sizeof(JSValue); - CopiedAllocator* copiedAllocator = &vm.heap.storageAllocator(); - - if (!structure()->outOfLineCapacity()) { - jit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR); - slowPath.append( - jit.branchSubPtr( - CCallHelpers::Signed, CCallHelpers::TrustedImm32(newSize), scratchGPR)); - jit.storePtr(scratchGPR, &copiedAllocator->m_currentRemaining); - jit.negPtr(scratchGPR); - jit.addPtr( - CCallHelpers::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR); - jit.addPtr(CCallHelpers::TrustedImm32(sizeof(JSValue)), scratchGPR); - } else { - size_t oldSize = structure()->outOfLineCapacity() * sizeof(JSValue); - ASSERT(newSize > oldSize); - jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR3); - slowPath.append(jit.branchIfNotToSpace(scratchGPR3)); - jit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR); - slowPath.append( - jit.branchSubPtr( - CCallHelpers::Signed, CCallHelpers::TrustedImm32(newSize), scratchGPR)); - jit.storePtr(scratchGPR, &copiedAllocator->m_currentRemaining); - jit.negPtr(scratchGPR); - jit.addPtr( - CCallHelpers::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR); - jit.addPtr(CCallHelpers::TrustedImm32(sizeof(JSValue)), scratchGPR); - // We have scratchGPR = new storage, scratchGPR3 = old storage, - // scratchGPR2 = available - for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) { - jit.loadPtr( - CCallHelpers::Address( - scratchGPR3, - -static_cast( - offset + sizeof(JSValue) + sizeof(void*))), - scratchGPR2); - jit.storePtr( - scratchGPR2, - CCallHelpers::Address( - scratchGPR, - -static_cast(offset + sizeof(JSValue) + sizeof(void*)))); + if (allocatingInline) { + MarkedAllocator* allocator = vm.heap.allocatorForAuxiliaryData(newSize); + + if (!allocator) { + // Yuck, this case would suck! + slowPath.append(jit.jump()); + } + + jit.move(CCallHelpers::TrustedImmPtr(allocator), scratchGPR2); + jit.emitAllocate(scratchGPR, allocator, scratchGPR2, scratchGPR3, slowPath); + jit.addPtr(CCallHelpers::TrustedImm32(newSize + sizeof(IndexingHeader)), scratchGPR); + + if (reallocating) { + // Handle the case where we are reallocating (i.e. the old structure/butterfly + // already had out-of-line property storage). + size_t oldSize = structure()->outOfLineCapacity() * sizeof(JSValue); + ASSERT(newSize > oldSize); + + jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR3); + + // We have scratchGPR = new storage, scratchGPR3 = old storage, + // scratchGPR2 = available + for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) { + jit.loadPtr( + CCallHelpers::Address( + scratchGPR3, + -static_cast( + offset + sizeof(JSValue) + sizeof(void*))), + scratchGPR2); + jit.storePtr( + scratchGPR2, + CCallHelpers::Address( + scratchGPR, + -static_cast(offset + sizeof(JSValue) + sizeof(void*)))); + } + } + } else { + // Handle the case where we are allocating out-of-line using an operation. + RegisterSet extraRegistersToPreserve; + extraRegistersToPreserve.set(baseGPR); + extraRegistersToPreserve.set(valueRegs); + state.preserveLiveRegistersToStackForCall(extraRegistersToPreserve); + + jit.store32( + CCallHelpers::TrustedImm32( + state.callSiteIndexForExceptionHandlingOrOriginal().bits()), + CCallHelpers::tagFor(static_cast(CallFrameSlot::argumentCount))); + + jit.makeSpaceOnStackForCCall(); + + if (!reallocating) { + jit.setupArgumentsWithExecState(baseGPR); + + CCallHelpers::Call operationCall = jit.call(); + jit.addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link( + operationCall, + FunctionPtr(operationReallocateButterflyToHavePropertyStorageWithInitialCapacity)); + }); + } else { + // Handle the case where we are reallocating (i.e. the old structure/butterfly + // already had out-of-line property storage). + jit.setupArgumentsWithExecState( + baseGPR, CCallHelpers::TrustedImm32(newSize / sizeof(JSValue))); + + CCallHelpers::Call operationCall = jit.call(); + jit.addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link( + operationCall, + FunctionPtr(operationReallocateButterflyToGrowPropertyStorage)); + }); } + + jit.reclaimSpaceOnStackForCCall(); + jit.move(GPRInfo::returnValueGPR, scratchGPR); + + CCallHelpers::Jump noException = + jit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck); + + state.restoreLiveRegistersFromStackForCallWithThrownException(); + state.emitExplicitExceptionHandler(); + + noException.link(&jit); + state.restoreLiveRegistersFromStackForCall(); } - - jit.storePtr(scratchGPR, CCallHelpers::Address(baseGPR, JSObject::butterflyOffset())); - scratchGPRHasStorage = true; } - uint32_t structureBits = bitwise_cast(newStructure()->id()); - jit.store32( - CCallHelpers::TrustedImm32(structureBits), - CCallHelpers::Address(baseGPR, JSCell::structureIDOffset())); - if (isInlineOffset(m_offset)) { jit.storeValue( valueRegs, @@ -969,120 +1302,81 @@ JSObject::offsetOfInlineStorage() + offsetInInlineStorage(m_offset) * sizeof(JSValue))); } else { - if (!scratchGPRHasStorage) { + if (!allocating) jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR); - state.failAndIgnore.append(jit.branchIfNotToSpace(scratchGPR)); - } jit.storeValue( valueRegs, CCallHelpers::Address(scratchGPR, offsetInButterfly(m_offset) * sizeof(JSValue))); } - - ScratchBuffer* scratchBuffer = nullptr; - if (newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity()) - scratchBuffer = vm.scratchBufferForSize(allocator.desiredScratchBufferSizeForCall()); - - if (newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity()) { - CCallHelpers::Call callFlushWriteBarrierBuffer; + + // If we had allocated using an operation then we would have already executed the store + // barrier and we would have already stored the butterfly into the object. + if (allocatingInline) { CCallHelpers::Jump ownerIsRememberedOrInEden = jit.jumpIfIsRememberedOrInEden(baseGPR); WriteBarrierBuffer& writeBarrierBuffer = jit.vm()->heap.writeBarrierBuffer(); jit.load32(writeBarrierBuffer.currentIndexAddress(), scratchGPR2); - CCallHelpers::Jump needToFlush = + slowPath.append( jit.branch32( CCallHelpers::AboveOrEqual, scratchGPR2, - CCallHelpers::TrustedImm32(writeBarrierBuffer.capacity())); - + CCallHelpers::TrustedImm32(writeBarrierBuffer.capacity()))); + jit.add32(CCallHelpers::TrustedImm32(1), scratchGPR2); jit.store32(scratchGPR2, writeBarrierBuffer.currentIndexAddress()); - - jit.move(CCallHelpers::TrustedImmPtr(writeBarrierBuffer.buffer()), scratchGPR); + + jit.move(CCallHelpers::TrustedImmPtr(writeBarrierBuffer.buffer()), scratchGPR3); // We use an offset of -sizeof(void*) because we already added 1 to scratchGPR2. jit.storePtr( baseGPR, CCallHelpers::BaseIndex( - scratchGPR, scratchGPR2, CCallHelpers::ScalePtr, + scratchGPR3, scratchGPR2, CCallHelpers::ScalePtr, static_cast(-sizeof(void*)))); - - CCallHelpers::Jump doneWithBarrier = jit.jump(); - needToFlush.link(&jit); - - // FIXME: We should restoreReusedRegistersByPopping() before this. Then, we wouldn't need - // padding in preserveReusedRegistersByPushing(). Or, maybe it would be even better if the - // barrier slow path was just the normal slow path, below. - // https://bugs.webkit.org/show_bug.cgi?id=149030 - allocator.preserveUsedRegistersToScratchBufferForCall(jit, scratchBuffer, scratchGPR2); - if (needsToMakeRoomOnStackForCCall) - jit.makeSpaceOnStackForCCall(); - jit.setupArgumentsWithExecState(baseGPR); - callFlushWriteBarrierBuffer = jit.call(); - if (needsToMakeRoomOnStackForCCall) - jit.reclaimSpaceOnStackForCCall(); - allocator.restoreUsedRegistersFromScratchBufferForCall( - jit, scratchBuffer, scratchGPR2); - - doneWithBarrier.link(&jit); ownerIsRememberedOrInEden.link(&jit); - - state.callbacks.append( - [=] (LinkBuffer& linkBuffer) { - linkBuffer.link(callFlushWriteBarrierBuffer, operationFlushWriteBarrierBuffer); - }); + + // We set the new butterfly and the structure last. Doing it this way ensures that + // whatever we had done up to this point is forgotten if we choose to branch to slow + // path. + + jit.storePtr(scratchGPR, CCallHelpers::Address(baseGPR, JSObject::butterflyOffset())); } + uint32_t structureBits = bitwise_cast(newStructure()->id()); + jit.store32( + CCallHelpers::TrustedImm32(structureBits), + CCallHelpers::Address(baseGPR, JSCell::structureIDOffset())); + allocator.restoreReusedRegistersByPopping(jit, preservedState); state.succeed(); - - if (newStructure()->outOfLineCapacity() != structure()->outOfLineCapacity()) { - slowPath.link(&jit); - allocator.restoreReusedRegistersByPopping(jit, preservedState); - allocator.preserveUsedRegistersToScratchBufferForCall(jit, scratchBuffer, scratchGPR); - if (needsToMakeRoomOnStackForCCall) - jit.makeSpaceOnStackForCCall(); -#if USE(JSVALUE64) - jit.setupArgumentsWithExecState( - baseGPR, - CCallHelpers::TrustedImmPtr(newStructure()), - CCallHelpers::TrustedImm32(m_offset), - valueRegs.gpr()); -#else - jit.setupArgumentsWithExecState( - baseGPR, - CCallHelpers::TrustedImmPtr(newStructure()), - CCallHelpers::TrustedImm32(m_offset), - valueRegs.payloadGPR(), valueRegs.tagGPR()); -#endif - CCallHelpers::Call operationCall = jit.call(); - if (needsToMakeRoomOnStackForCCall) - jit.reclaimSpaceOnStackForCCall(); - allocator.restoreUsedRegistersFromScratchBufferForCall(jit, scratchBuffer, scratchGPR); - state.succeed(); - - state.callbacks.append( - [=] (LinkBuffer& linkBuffer) { - linkBuffer.link(operationCall, operationReallocateStorageAndFinishPut); - }); - } + + // We will have a slow path if we were allocating without the help of an operation. + if (allocatingInline) { + if (allocator.didReuseRegisters()) { + slowPath.link(&jit); + allocator.restoreReusedRegistersByPopping(jit, preservedState); + state.failAndIgnore.append(jit.jump()); + } else + state.failAndIgnore.append(slowPath); + } else + RELEASE_ASSERT(slowPath.empty()); return; } case ArrayLength: { jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR); - jit.removeSpaceBits(scratchGPR); jit.load32(CCallHelpers::Address(scratchGPR, ArrayStorage::lengthOffset()), scratchGPR); state.failAndIgnore.append( jit.branch32(CCallHelpers::LessThan, scratchGPR, CCallHelpers::TrustedImm32(0))); - jit.boxInt32(scratchGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters); + jit.boxInt32(scratchGPR, valueRegs); state.succeed(); return; } case StringLength: { jit.load32(CCallHelpers::Address(baseGPR, JSString::offsetOfLength()), valueRegs.payloadGPR()); - jit.boxInt32(valueRegs.payloadGPR(), valueRegs, CCallHelpers::DoNotHaveTagRegisters); + jit.boxInt32(valueRegs.payloadGPR(), valueRegs); state.succeed(); return; } - + case IntrinsicGetter: { RELEASE_ASSERT(isValidOffset(offset())); @@ -1097,7 +1391,16 @@ emitIntrinsicGetter(state); return; - } } + } + + case DirectArgumentsLength: + case ScopedArgumentsLength: + case MegamorphicLoad: + // These need to be handled by generateWithGuard(), since the guard is part of the + // algorithm. We can be sure that nobody will call generate() directly for these since they + // are not guarded by structure checks. + RELEASE_ASSERT_NOT_REACHED(); + } RELEASE_ASSERT_NOT_REACHED(); } @@ -1105,10 +1408,12 @@ PolymorphicAccess::PolymorphicAccess() { } PolymorphicAccess::~PolymorphicAccess() { } -MacroAssemblerCodePtr PolymorphicAccess::regenerateWithCases( +AccessGenerationResult PolymorphicAccess::addCases( VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, const Identifier& ident, - Vector> originalCasesToAdd) + Vector, 2> originalCasesToAdd) { + SuperSamplerScope superSamplerScope(false); + // This method will add the originalCasesToAdd to the list one at a time while preserving the // invariants: // - If a newly added case canReplace() any existing case, then the existing case is removed before @@ -1120,8 +1425,7 @@ // and the previous stub are kept intact and the new cases are destroyed. It's OK to attempt to // add more things after failure. - // First, verify that we can generate code for all of the new cases while eliminating any of the - // new cases that replace each other. + // First ensure that the originalCasesToAdd doesn't contain duplicates. Vector> casesToAdd; for (unsigned i = 0; i < originalCasesToAdd.size(); ++i) { std::unique_ptr myCase = WTFMove(originalCasesToAdd[i]); @@ -1148,57 +1452,28 @@ // new stub that will be identical to the old one. Returning null should tell the caller to just // keep doing what they were doing before. if (casesToAdd.isEmpty()) - return MacroAssemblerCodePtr(); - - // Now construct the list of cases as they should appear if we are successful. This means putting - // all of the previous cases in this list in order but excluding those that can be replaced, and - // then adding the new cases. - ListType newCases; - for (auto& oldCase : m_list) { - // Ignore old cases that cannot possibly succeed anymore. - if (!oldCase->couldStillSucceed()) - continue; + return AccessGenerationResult::MadeNoChanges; - // Figure out if this is replaced by any new cases. - bool found = false; - for (auto& caseToAdd : casesToAdd) { - if (caseToAdd->canReplace(*oldCase)) { - found = true; - break; - } - } - if (found) - continue; - - newCases.append(oldCase->clone()); + // Now add things to the new list. Note that at this point, we will still have old cases that + // may be replaced by the new ones. That's fine. We will sort that out when we regenerate. + for (auto& caseToAdd : casesToAdd) { + commit(vm, m_watchpoints, codeBlock, stubInfo, ident, *caseToAdd); + m_list.append(WTFMove(caseToAdd)); } - for (auto& caseToAdd : casesToAdd) - newCases.append(WTFMove(caseToAdd)); - + if (verbose) - dataLog("newCases: ", listDump(newCases), "\n"); - - if (newCases.size() > Options::maxAccessVariantListSize()) { - if (verbose) - dataLog("Too many cases.\n"); - return MacroAssemblerCodePtr(); - } + dataLog("After addCases: m_list: ", listDump(m_list), "\n"); - MacroAssemblerCodePtr result = regenerate(vm, codeBlock, stubInfo, ident, newCases); - if (!result) - return MacroAssemblerCodePtr(); - - m_list = WTFMove(newCases); - return result; + return AccessGenerationResult::Buffered; } -MacroAssemblerCodePtr PolymorphicAccess::regenerateWithCase( +AccessGenerationResult PolymorphicAccess::addCase( VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, const Identifier& ident, std::unique_ptr newAccess) { - Vector> newAccesses; + Vector, 2> newAccesses; newAccesses.append(WTFMove(newAccess)); - return regenerateWithCases(vm, codeBlock, stubInfo, ident, WTFMove(newAccesses)); + return addCases(vm, codeBlock, stubInfo, ident, WTFMove(newAccesses)); } bool PolymorphicAccess::visitWeak(VM& vm) const @@ -1216,6 +1491,14 @@ return true; } +bool PolymorphicAccess::propagateTransitions(SlotVisitor& visitor) const +{ + bool result = true; + for (unsigned i = 0; i < size(); ++i) + result &= at(i).propagateTransitions(visitor); + return result; +} + void PolymorphicAccess::dump(PrintStream& out) const { out.print(RawPointer(this), ":["); @@ -1225,12 +1508,32 @@ out.print("]"); } -MacroAssemblerCodePtr PolymorphicAccess::regenerate( - VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, const Identifier& ident, - PolymorphicAccess::ListType& cases) +void PolymorphicAccess::commit( + VM& vm, std::unique_ptr& watchpoints, CodeBlock* codeBlock, + StructureStubInfo& stubInfo, const Identifier& ident, AccessCase& accessCase) +{ + // NOTE: We currently assume that this is relatively rare. It mainly arises for accesses to + // properties on DOM nodes. For sure we cache many DOM node accesses, but even in + // Real Pages (TM), we appear to spend most of our time caching accesses to properties on + // vanilla objects or exotic objects from within JSC (like Arguments, those are super popular). + // Those common kinds of JSC object accesses don't hit this case. + + for (WatchpointSet* set : accessCase.commit(vm, ident)) { + Watchpoint* watchpoint = + WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint( + watchpoints, codeBlock, &stubInfo, ObjectPropertyCondition()); + + set->add(watchpoint); + } +} + +AccessGenerationResult PolymorphicAccess::regenerate( + VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, const Identifier& ident) { + SuperSamplerScope superSamplerScope(false); + if (verbose) - dataLog("Generating code for cases: ", listDump(cases), "\n"); + dataLog("Regenerate with m_list: ", listDump(m_list), "\n"); AccessGenerationState state; @@ -1239,11 +1542,7 @@ state.ident = &ident; state.baseGPR = static_cast(stubInfo.patch.baseGPR); - state.valueRegs = JSValueRegs( -#if USE(JSVALUE32_64) - static_cast(stubInfo.patch.valueTagGPR), -#endif - static_cast(stubInfo.patch.valueGPR)); + state.valueRegs = stubInfo.valueRegs(); ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters); state.allocator = &allocator; @@ -1261,11 +1560,81 @@ state.preservedReusedRegisterState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace); + // Regenerating is our opportunity to figure out what our list of cases should look like. We + // do this here. The newly produced 'cases' list may be smaller than m_list. We don't edit + // m_list in-place because we may still fail, in which case we want the PolymorphicAccess object + // to be unmutated. For sure, we want it to hang onto any data structures that may be referenced + // from the code of the current stub (aka previous). + ListType cases; + unsigned srcIndex = 0; + unsigned dstIndex = 0; + while (srcIndex < m_list.size()) { + std::unique_ptr someCase = WTFMove(m_list[srcIndex++]); + + // If the case had been generated, then we have to keep the original in m_list in case we + // fail to regenerate. That case may have data structures that are used by the code that it + // had generated. If the case had not been generated, then we want to remove it from m_list. + bool isGenerated = someCase->state() == AccessCase::Generated; + + [&] () { + if (!someCase->couldStillSucceed()) + return; + + // Figure out if this is replaced by any later case. + for (unsigned j = srcIndex; j < m_list.size(); ++j) { + if (m_list[j]->canReplace(*someCase)) + return; + } + + if (isGenerated) + cases.append(someCase->clone()); + else + cases.append(WTFMove(someCase)); + }(); + + if (isGenerated) + m_list[dstIndex++] = WTFMove(someCase); + } + m_list.resize(dstIndex); + + if (verbose) + dataLog("In regenerate: cases: ", listDump(cases), "\n"); + + // Now that we've removed obviously unnecessary cases, we can check if the megamorphic load + // optimization is applicable. Note that we basically tune megamorphicLoadCost according to code + // size. It would be faster to just allow more repatching with many load cases, and avoid the + // megamorphicLoad optimization, if we had infinite executable memory. + if (cases.size() >= Options::maxAccessVariantListSize()) { + unsigned numSelfLoads = 0; + for (auto& newCase : cases) { + if (newCase->canBeReplacedByMegamorphicLoad()) + numSelfLoads++; + } + + if (numSelfLoads >= Options::megamorphicLoadCost()) { + if (auto mega = AccessCase::megamorphicLoad(vm, codeBlock)) { + cases.removeAllMatching( + [&] (std::unique_ptr& newCase) -> bool { + return newCase->canBeReplacedByMegamorphicLoad(); + }); + + cases.append(WTFMove(mega)); + } + } + } + + if (verbose) + dataLog("Optimized cases: ", listDump(cases), "\n"); + + // At this point we're convinced that 'cases' contains the cases that we want to JIT now and we + // won't change that set anymore. + bool allGuardedByStructureCheck = true; bool hasJSGetterSetterCall = false; - for (auto& entry : cases) { - allGuardedByStructureCheck &= entry->guardedByStructureCheck(); - if (entry->type() == AccessCase::Getter || entry->type() == AccessCase::Setter) + for (auto& newCase : cases) { + commit(vm, state.watchpoints, codeBlock, stubInfo, ident, *newCase); + allGuardedByStructureCheck &= newCase->guardedByStructureCheck(); + if (newCase->type() == AccessCase::Getter || newCase->type() == AccessCase::Setter) hasJSGetterSetterCall = true; } @@ -1281,6 +1650,7 @@ // Cascade through the list, preferring newer entries. for (unsigned i = cases.size(); i--;) { fallThrough.link(&jit); + fallThrough.clear(); cases[i]->generateWithGuard(state, fallThrough); } state.failAndRepatch.append(fallThrough); @@ -1306,9 +1676,14 @@ // of something that isn't patchable. The slow path will decrement "countdown" and will only // patch things if the countdown reaches zero. We increment the slow path count here to ensure // that the slow path does not try to patch. +#if CPU(X86) || CPU(X86_64) + jit.move(CCallHelpers::TrustedImmPtr(&stubInfo.countdown), state.scratchGPR); + jit.add8(CCallHelpers::TrustedImm32(1), CCallHelpers::Address(state.scratchGPR)); +#else jit.load8(&stubInfo.countdown, state.scratchGPR); jit.add32(CCallHelpers::TrustedImm32(1), state.scratchGPR); jit.store8(state.scratchGPR, &stubInfo.countdown); +#endif } CCallHelpers::JumpList failure; @@ -1341,7 +1716,7 @@ HandlerInfo oldHandler = state.originalExceptionHandler(); CallSiteIndex newExceptionHandlingCallSite = state.callSiteIndexForExceptionHandling(); - state.callbacks.append( + jit.addLinkTask( [=] (LinkBuffer& linkBuffer) { linkBuffer.link(jumpToOSRExitExceptionHandler, oldHandler.nativeCode); @@ -1363,21 +1738,15 @@ if (linkBuffer.didFailToAllocate()) { if (verbose) dataLog("Did fail to allocate.\n"); - return MacroAssemblerCodePtr(); + return AccessGenerationResult::GaveUp; } - CodeLocationLabel successLabel = - stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone); + CodeLocationLabel successLabel = stubInfo.doneLocation(); linkBuffer.link(state.success, successLabel); - linkBuffer.link( - failure, - stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase)); + linkBuffer.link(failure, stubInfo.slowPathStartLocation()); - for (auto callback : state.callbacks) - callback(linkBuffer); - if (verbose) dataLog(*codeBlock, " ", stubInfo.codeOrigin, ": Generating polymorphic access stub for ", listDump(cases), "\n"); @@ -1386,21 +1755,32 @@ ("%s", toCString("Access stub for ", *codeBlock, " ", stubInfo.codeOrigin, " with return point ", successLabel, ": ", listDump(cases)).data())); bool doesCalls = false; + Vector cellsToMark; for (auto& entry : cases) - doesCalls |= entry->doesCalls(); + doesCalls |= entry->doesCalls(&cellsToMark); - m_stubRoutine = createJITStubRoutine(code, vm, codeBlock, doesCalls, nullptr, codeBlockThatOwnsExceptionHandlers, callSiteIndexForExceptionHandling); + m_stubRoutine = createJITStubRoutine(code, vm, codeBlock, doesCalls, cellsToMark, codeBlockThatOwnsExceptionHandlers, callSiteIndexForExceptionHandling); m_watchpoints = WTFMove(state.watchpoints); if (!state.weakReferences.isEmpty()) m_weakReferences = std::make_unique>>(WTFMove(state.weakReferences)); if (verbose) dataLog("Returning: ", code.code(), "\n"); - return code.code(); + + m_list = WTFMove(cases); + + AccessGenerationResult::Kind resultKind; + if (m_list.size() >= Options::maxAccessVariantListSize()) + resultKind = AccessGenerationResult::GeneratedFinalCode; + else + resultKind = AccessGenerationResult::GeneratedNewCode; + + return AccessGenerationResult(resultKind, code.code()); } void PolymorphicAccess::aboutToDie() { - m_stubRoutine->aboutToDie(); + if (m_stubRoutine) + m_stubRoutine->aboutToDie(); } } // namespace JSC @@ -1409,12 +1789,38 @@ using namespace JSC; +void printInternal(PrintStream& out, AccessGenerationResult::Kind kind) +{ + switch (kind) { + case AccessGenerationResult::MadeNoChanges: + out.print("MadeNoChanges"); + return; + case AccessGenerationResult::GaveUp: + out.print("GaveUp"); + return; + case AccessGenerationResult::Buffered: + out.print("Buffered"); + return; + case AccessGenerationResult::GeneratedNewCode: + out.print("GeneratedNewCode"); + return; + case AccessGenerationResult::GeneratedFinalCode: + out.print("GeneratedFinalCode"); + return; + } + + RELEASE_ASSERT_NOT_REACHED(); +} + void printInternal(PrintStream& out, AccessCase::AccessType type) { switch (type) { case AccessCase::Load: out.print("Load"); return; + case AccessCase::MegamorphicLoad: + out.print("MegamorphicLoad"); + return; case AccessCase::Transition: out.print("Transition"); return; @@ -1424,6 +1830,9 @@ case AccessCase::Miss: out.print("Miss"); return; + case AccessCase::GetGetter: + out.print("GetGetter"); + return; case AccessCase::Getter: out.print("Getter"); return; @@ -1457,6 +1866,29 @@ case AccessCase::StringLength: out.print("StringLength"); return; + case AccessCase::DirectArgumentsLength: + out.print("DirectArgumentsLength"); + return; + case AccessCase::ScopedArgumentsLength: + out.print("ScopedArgumentsLength"); + return; + } + + RELEASE_ASSERT_NOT_REACHED(); +} + +void printInternal(PrintStream& out, AccessCase::State state) +{ + switch (state) { + case AccessCase::Primordial: + out.print("Primordial"); + return; + case AccessCase::Committed: + out.print("Committed"); + return; + case AccessCase::Generated: + out.print("Generated"); + return; } RELEASE_ASSERT_NOT_REACHED(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PolymorphicAccess.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PolymorphicAccess.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PolymorphicAccess.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PolymorphicAccess.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,10 +29,10 @@ #if ENABLE(JIT) #include "CodeOrigin.h" +#include "JITStubRoutine.h" #include "JSFunctionInlines.h" #include "MacroAssembler.h" #include "ObjectPropertyConditionSet.h" -#include "Opcode.h" #include "ScratchRegisterAllocator.h" #include "Structure.h" #include @@ -47,15 +47,57 @@ struct AccessGenerationState; +// An AccessCase describes one of the cases of a PolymorphicAccess. A PolymorphicAccess represents a +// planned (to generate in future) or generated stub for some inline cache. That stub contains fast +// path code for some finite number of fast cases, each described by an AccessCase object. +// +// An AccessCase object has a lifecycle that proceeds through several states. Note that the states +// of AccessCase have a lot to do with the global effect epoch (we'll say epoch for short). This is +// a simple way of reasoning about the state of the system outside this AccessCase. Any observable +// effect - like storing to a property, changing an object's structure, etc. - increments the epoch. +// The states are: +// +// Primordial: This is an AccessCase that was just allocated. It does not correspond to any actual +// code and it is not owned by any PolymorphicAccess. In this state, the AccessCase +// assumes that it is in the same epoch as when it was created. This is important +// because it may make claims about itself ("I represent a valid case so long as you +// register a watchpoint on this set") that could be contradicted by some outside +// effects (like firing and deleting the watchpoint set in question). This is also the +// state that an AccessCase is in when it is cloned (AccessCase::clone()). +// +// Committed: This happens as soon as some PolymorphicAccess takes ownership of this AccessCase. +// In this state, the AccessCase no longer assumes anything about the epoch. To +// accomplish this, PolymorphicAccess calls AccessCase::commit(). This must be done +// during the same epoch when the AccessCase was created, either by the client or by +// clone(). When created by the client, committing during the same epoch works because +// we can be sure that whatever watchpoint sets they spoke of are still valid. When +// created by clone(), we can be sure that the set is still valid because the original +// of the clone still has watchpoints on it. +// +// Generated: This is the state when the PolymorphicAccess generates code for this case by +// calling AccessCase::generate() or AccessCase::generateWithGuard(). At this point +// the case object will have some extra stuff in it, like possibly the CallLinkInfo +// object associated with the inline cache. +// FIXME: Moving into the Generated state should not mutate the AccessCase object or +// put more stuff into it. If we fix this, then we can get rid of AccessCase::clone(). +// https://bugs.webkit.org/show_bug.cgi?id=156456 +// +// An AccessCase may be destroyed while in any of these states. +// +// We will sometimes buffer committed AccessCases in the PolymorphicAccess object before generating +// code. This allows us to only regenerate once we've accumulated (hopefully) more than one new +// AccessCase. class AccessCase { WTF_MAKE_NONCOPYABLE(AccessCase); WTF_MAKE_FAST_ALLOCATED; public: - enum AccessType { + enum AccessType : uint8_t { Load, + MegamorphicLoad, Transition, Replace, Miss, + GetGetter, Getter, Setter, CustomValueGetter, @@ -66,77 +108,22 @@ InHit, InMiss, ArrayLength, - StringLength + StringLength, + DirectArgumentsLength, + ScopedArgumentsLength + }; + + enum State : uint8_t { + Primordial, + Committed, + Generated }; - static bool isGet(AccessType type) - { - switch (type) { - case Transition: - case Replace: - case Setter: - case CustomValueSetter: - case CustomAccessorSetter: - case InHit: - case InMiss: - return false; - case Load: - case Miss: - case Getter: - case CustomValueGetter: - case CustomAccessorGetter: - case IntrinsicGetter: - case ArrayLength: - case StringLength: - return true; - } - } - - static bool isPut(AccessType type) - { - switch (type) { - case Load: - case Miss: - case Getter: - case CustomValueGetter: - case CustomAccessorGetter: - case IntrinsicGetter: - case InHit: - case InMiss: - case ArrayLength: - case StringLength: - return false; - case Transition: - case Replace: - case Setter: - case CustomValueSetter: - case CustomAccessorSetter: - return true; - } - } - - static bool isIn(AccessType type) - { - switch (type) { - case Load: - case Miss: - case Getter: - case CustomValueGetter: - case CustomAccessorGetter: - case IntrinsicGetter: - case Transition: - case Replace: - case Setter: - case CustomValueSetter: - case CustomAccessorSetter: - case ArrayLength: - case StringLength: - return false; - case InHit: - case InMiss: - return true; - } - } + static std::unique_ptr tryGet( + VM&, JSCell* owner, AccessType, PropertyOffset, Structure*, + const ObjectPropertyConditionSet& = ObjectPropertyConditionSet(), + bool viaProxy = false, + WatchpointSet* additionalSet = nullptr); static std::unique_ptr get( VM&, JSCell* owner, AccessType, PropertyOffset, Structure*, @@ -145,7 +132,9 @@ WatchpointSet* additionalSet = nullptr, PropertySlot::GetValueFunc = nullptr, JSObject* customSlotBase = nullptr); - + + static std::unique_ptr megamorphicLoad(VM&, JSCell* owner); + static std::unique_ptr replace(VM&, JSCell* owner, Structure*, PropertyOffset); static std::unique_ptr transition( @@ -168,9 +157,8 @@ ~AccessCase(); - std::unique_ptr clone() const; - AccessType type() const { return m_type; } + State state() const { return m_state; } PropertyOffset offset() const { return m_offset; } bool viaProxy() const { return m_rareData ? m_rareData->viaProxy : false; } @@ -210,21 +198,10 @@ } JSObject* alternateBase() const; - - bool doesCalls() const - { - switch (type()) { - case Getter: - case Setter: - case CustomValueGetter: - case CustomAccessorGetter: - case CustomValueSetter: - case CustomAccessorSetter: - return true; - default: - return false; - } - } + + // If you supply the optional vector, this will append the set of cells that this will need to keep alive + // past the call. + bool doesCalls(Vector* cellsToMark = nullptr) const; bool isGetter() const { @@ -238,22 +215,29 @@ } } + // This can return null even for a getter/setter, if it hasn't been generated yet. That's + // actually somewhat likely because of how we do buffering of new cases. CallLinkInfo* callLinkInfo() const { if (!m_rareData) return nullptr; return m_rareData->callLinkInfo.get(); } - - // Is it still possible for this case to ever be taken? + + // Is it still possible for this case to ever be taken? Must call this as a prerequisite for + // calling generate() and friends. If this returns true, then you can call generate(). If + // this returns false, then generate() will crash. You must call generate() in the same epoch + // as when you called couldStillSucceed(). bool couldStillSucceed() const; - + static bool canEmitIntrinsicGetter(JSFunction*, Structure*); + bool canBeReplacedByMegamorphicLoad() const; + // If this method returns true, then it's a good idea to remove 'other' from the access once 'this' // is added. This method assumes that in case of contradictions, 'this' represents a newer, and so // more useful, truth. This method can be conservative; it will return false when it doubt. - bool canReplace(const AccessCase& other); + bool canReplace(const AccessCase& other) const; void dump(PrintStream& out) const; @@ -264,6 +248,15 @@ AccessCase(); bool visitWeak(VM&) const; + bool propagateTransitions(SlotVisitor&) const; + + // FIXME: This only exists because of how AccessCase puts post-generation things into itself. + // https://bugs.webkit.org/show_bug.cgi?id=156456 + std::unique_ptr clone() const; + + // Perform any action that must be performed before the end of the epoch in which the case + // was created. Returns a set of watchpoint sets that will need to be watched. + Vector commit(VM&, const Identifier&); // Fall through on success. Two kinds of failures are supported: fall-through, which means that we // should try a different case; and failure, which means that this was the right case but it needs @@ -272,9 +265,12 @@ // Fall through on success, add a jump to the failure list on failure. void generate(AccessGenerationState&); + + void generateImpl(AccessGenerationState&); void emitIntrinsicGetter(AccessGenerationState&); AccessType m_type { Load }; + State m_state { Primordial }; PropertyOffset m_offset { invalidOffset }; // Usually this is the structure that we expect the base object to have. But, this is the *new* @@ -295,6 +291,8 @@ bool viaProxy; RefPtr additionalSet; + // FIXME: This should probably live in the stub routine object. + // https://bugs.webkit.org/show_bug.cgi?id=156456 std::unique_ptr callLinkInfo; union { PropertySlot::GetValueFunc getter; @@ -308,6 +306,73 @@ std::unique_ptr m_rareData; }; +class AccessGenerationResult { +public: + enum Kind { + MadeNoChanges, + GaveUp, + Buffered, + GeneratedNewCode, + GeneratedFinalCode // Generated so much code that we never want to generate code again. + }; + + AccessGenerationResult() + { + } + + AccessGenerationResult(Kind kind) + : m_kind(kind) + { + RELEASE_ASSERT(kind != GeneratedNewCode); + RELEASE_ASSERT(kind != GeneratedFinalCode); + } + + AccessGenerationResult(Kind kind, MacroAssemblerCodePtr code) + : m_kind(kind) + , m_code(code) + { + RELEASE_ASSERT(kind == GeneratedNewCode || kind == GeneratedFinalCode); + RELEASE_ASSERT(code); + } + + bool operator==(const AccessGenerationResult& other) const + { + return m_kind == other.m_kind && m_code == other.m_code; + } + + bool operator!=(const AccessGenerationResult& other) const + { + return !(*this == other); + } + + explicit operator bool() const + { + return *this != AccessGenerationResult(); + } + + Kind kind() const { return m_kind; } + + const MacroAssemblerCodePtr& code() const { return m_code; } + + bool madeNoChanges() const { return m_kind == MadeNoChanges; } + bool gaveUp() const { return m_kind == GaveUp; } + bool buffered() const { return m_kind == Buffered; } + bool generatedNewCode() const { return m_kind == GeneratedNewCode; } + bool generatedFinalCode() const { return m_kind == GeneratedFinalCode; } + + // If we gave up on this attempt to generate code, or if we generated the "final" code, then we + // should give up after this. + bool shouldGiveUpNow() const { return gaveUp() || generatedFinalCode(); } + + bool generatedSomeCode() const { return generatedNewCode() || generatedFinalCode(); } + + void dump(PrintStream&) const; + +private: + Kind m_kind; + MacroAssemblerCodePtr m_code; +}; + class PolymorphicAccess { WTF_MAKE_NONCOPYABLE(PolymorphicAccess); WTF_MAKE_FAST_ALLOCATED; @@ -315,15 +380,16 @@ PolymorphicAccess(); ~PolymorphicAccess(); - // This may return null, in which case the old stub routine is left intact. You are required to - // pass a vector of non-null access cases. This will prune the access cases by rejecting any case - // in the list that is subsumed by a later case in the list. - MacroAssemblerCodePtr regenerateWithCases( - VM&, CodeBlock*, StructureStubInfo&, const Identifier&, Vector>); + // When this fails (returns GaveUp), this will leave the old stub intact but you should not try + // to call this method again for that PolymorphicAccess instance. + AccessGenerationResult addCases( + VM&, CodeBlock*, StructureStubInfo&, const Identifier&, Vector, 2>); - MacroAssemblerCodePtr regenerateWithCase( + AccessGenerationResult addCase( VM&, CodeBlock*, StructureStubInfo&, const Identifier&, std::unique_ptr); + AccessGenerationResult regenerate(VM&, CodeBlock*, StructureStubInfo&, const Identifier&); + bool isEmpty() const { return m_list.isEmpty(); } unsigned size() const { return m_list.size(); } const AccessCase& at(unsigned i) const { return *m_list[i]; } @@ -331,6 +397,10 @@ // If this returns false then we are requesting a reset of the owning StructureStubInfo. bool visitWeak(VM&) const; + + // This returns true if it has marked everything it will ever marked. This can be used as an + // optimization to then avoid calling this method again during the fixpoint. + bool propagateTransitions(SlotVisitor&) const; void aboutToDie(); @@ -350,6 +420,10 @@ friend struct AccessGenerationState; typedef Vector, 2> ListType; + + void commit( + VM&, std::unique_ptr&, CodeBlock*, StructureStubInfo&, + const Identifier&, AccessCase&); MacroAssemblerCodePtr regenerate( VM&, CodeBlock*, StructureStubInfo&, const Identifier&, ListType& cases); @@ -362,9 +436,9 @@ struct AccessGenerationState { AccessGenerationState() - : m_calculatedRegistersForCallAndExceptionHandling(false) - , m_needsToRestoreRegistersIfException(false) - , m_calculatedCallSiteIndex(false) + : m_calculatedRegistersForCallAndExceptionHandling(false) + , m_needsToRestoreRegistersIfException(false) + , m_calculatedCallSiteIndex(false) { } CCallHelpers* jit { nullptr }; @@ -378,7 +452,6 @@ GPRReg baseGPR { InvalidGPRReg }; JSValueRegs valueRegs; GPRReg scratchGPR { InvalidGPRReg }; - Vector> callbacks; const Identifier* ident; std::unique_ptr watchpoints; Vector> weakReferences; @@ -388,11 +461,11 @@ void restoreScratch(); void succeed(); - void calculateLiveRegistersForCallAndExceptionHandling(); + void calculateLiveRegistersForCallAndExceptionHandling(const RegisterSet& extra = RegisterSet()); - void preserveLiveRegistersToStackForCall(); + void preserveLiveRegistersToStackForCall(const RegisterSet& extra = RegisterSet()); - void restoreLiveRegistersFromStackForCall(bool isGetter); + void restoreLiveRegistersFromStackForCall(bool isGetter = false); void restoreLiveRegistersFromStackForCallWithThrownException(); void restoreLiveRegistersFromStackForCall(const RegisterSet& dontRestore); @@ -421,6 +494,8 @@ bool needsToRestoreRegistersIfException() const { return m_needsToRestoreRegistersIfException; } CallSiteIndex originalCallSiteIndex() const; + void emitExplicitExceptionHandler(); + private: const RegisterSet& liveRegistersToPreserveAtExceptionHandlingCallSite() { @@ -441,7 +516,9 @@ namespace WTF { +void printInternal(PrintStream&, JSC::AccessGenerationResult::Kind); void printInternal(PrintStream&, JSC::AccessCase::AccessType); +void printInternal(PrintStream&, JSC::AccessCase::State); } // namespace WTF diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -26,69 +26,37 @@ #include "config.h" #include "PreciseJumpTargets.h" +#include "InterpreterInlines.h" #include "JSCInlines.h" +#include "PreciseJumpTargetsInlines.h" namespace JSC { -template -static void getJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector& out) +template +static void getJumpTargetsForBytecodeOffset(Block* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector& out) { - OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); - Instruction* current = instructionsBegin + bytecodeOffset; - switch (opcodeID) { - case op_jmp: - out.append(bytecodeOffset + current[1].u.operand); - break; - case op_jtrue: - case op_jfalse: - case op_jeq_null: - case op_jneq_null: - out.append(bytecodeOffset + current[2].u.operand); - break; - case op_jneq_ptr: - case op_jless: - case op_jlesseq: - case op_jgreater: - case op_jgreatereq: - case op_jnless: - case op_jnlesseq: - case op_jngreater: - case op_jngreatereq: - case op_save: // The jump of op_save is purely for calculating liveness. - out.append(bytecodeOffset + current[3].u.operand); - break; - case op_switch_imm: - case op_switch_char: { - SimpleJumpTable& table = codeBlock->switchJumpTable(current[1].u.operand); - for (unsigned i = table.branchOffsets.size(); i--;) - out.append(bytecodeOffset + table.branchOffsets[i]); - out.append(bytecodeOffset + current[2].u.operand); - break; - } - case op_switch_string: { - StringJumpTable& table = codeBlock->stringSwitchJumpTable(current[1].u.operand); - StringJumpTable::StringOffsetTable::iterator iter = table.offsetTable.begin(); - StringJumpTable::StringOffsetTable::iterator end = table.offsetTable.end(); - for (; iter != end; ++iter) - out.append(bytecodeOffset + iter->value.branchOffset); - out.append(bytecodeOffset + current[2].u.operand); - break; - } - case op_loop_hint: + OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); + extractStoredJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, [&](int32_t& relativeOffset) { + out.append(bytecodeOffset + relativeOffset); + }); + // op_loop_hint does not have jump target stored in bytecode instructions. + if (opcodeID == op_loop_hint) out.append(bytecodeOffset); - break; - default: - break; - } } -void computePreciseJumpTargets(CodeBlock* codeBlock, Vector& out) +enum class ComputePreciseJumpTargetsMode { + FollowCodeBlockClaim, + ForceCompute, +}; + +template +void computePreciseJumpTargetsInternal(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector& out) { ASSERT(out.isEmpty()); // We will derive a superset of the jump targets that the code block thinks it has. // So, if the code block claims there are none, then we are done. - if (!codeBlock->numberOfJumpTargets()) + if (Mode == ComputePreciseJumpTargetsMode::FollowCodeBlockClaim && !codeBlock->numberOfJumpTargets()) return; for (unsigned i = codeBlock->numberOfExceptionHandlers(); i--;) { @@ -98,10 +66,8 @@ } Interpreter* interpreter = codeBlock->vm()->interpreter; - Instruction* instructionsBegin = codeBlock->instructions().begin(); - unsigned instructionCount = codeBlock->instructions().size(); for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount;) { - OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode); + OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out); bytecodeOffset += opcodeLengths[opcodeID]; } @@ -123,11 +89,34 @@ out.shrinkToFit(); } -void findJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Vector& out) +void computePreciseJumpTargets(CodeBlock* codeBlock, Vector& out) { - Interpreter* interpreter = codeBlock->vm()->interpreter; - Instruction* instructionsBegin = codeBlock->instructions().begin(); - getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out); + computePreciseJumpTargetsInternal(codeBlock, codeBlock->instructions().begin(), codeBlock->instructions().size(), out); +} + +void computePreciseJumpTargets(CodeBlock* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector& out) +{ + computePreciseJumpTargetsInternal(codeBlock, instructionsBegin, instructionCount, out); +} + +void computePreciseJumpTargets(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector& out) +{ + computePreciseJumpTargetsInternal(codeBlock, instructionsBegin, instructionCount, out); +} + +void recomputePreciseJumpTargets(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector& out) +{ + computePreciseJumpTargetsInternal(codeBlock, instructionsBegin, instructionCount, out); +} + +void findJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector& out) +{ + getJumpTargetsForBytecodeOffset(codeBlock, codeBlock->vm()->interpreter, instructionsBegin, bytecodeOffset, out); +} + +void findJumpTargetsForBytecodeOffset(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned bytecodeOffset, Vector& out) +{ + getJumpTargetsForBytecodeOffset(codeBlock, codeBlock->vm()->interpreter, instructionsBegin, bytecodeOffset, out); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,19 +23,23 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PreciseJumpTargets_h -#define PreciseJumpTargets_h +#pragma once #include "CodeBlock.h" namespace JSC { +class UnlinkedCodeBlock; +struct UnlinkedInstruction; + // Return a sorted list of bytecode index that are the destination of a jump. void computePreciseJumpTargets(CodeBlock*, Vector& out); +void computePreciseJumpTargets(CodeBlock*, Instruction* instructionsBegin, unsigned instructionCount, Vector& out); +void computePreciseJumpTargets(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector& out); -void findJumpTargetsForBytecodeOffset(CodeBlock*, unsigned bytecodeOffset, Vector& out); - -} // namespace JSC +void recomputePreciseJumpTargets(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector& out); -#endif // PreciseJumpTargets_h +void findJumpTargetsForBytecodeOffset(CodeBlock*, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector& out); +void findJumpTargetsForBytecodeOffset(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned bytecodeOffset, Vector& out); +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "InterpreterInlines.h" +#include "Opcode.h" +#include "PreciseJumpTargets.h" + +namespace JSC { + +template +inline void extractStoredJumpTargetsForBytecodeOffset(Block* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Function function) +{ + OpcodeID opcodeID = interpreter->getOpcodeID(instructionsBegin[bytecodeOffset]); + Instruction* current = instructionsBegin + bytecodeOffset; + switch (opcodeID) { + case op_jmp: + function(current[1].u.operand); + break; + case op_jtrue: + case op_jfalse: + case op_jeq_null: + case op_jneq_null: + function(current[2].u.operand); + break; + case op_jneq_ptr: + case op_jless: + case op_jlesseq: + case op_jgreater: + case op_jgreatereq: + case op_jnless: + case op_jnlesseq: + case op_jngreater: + case op_jngreatereq: + function(current[3].u.operand); + break; + case op_switch_imm: + case op_switch_char: { + auto& table = codeBlock->switchJumpTable(current[1].u.operand); + for (unsigned i = table.branchOffsets.size(); i--;) + function(table.branchOffsets[i]); + function(current[2].u.operand); + break; + } + case op_switch_string: { + auto& table = codeBlock->stringSwitchJumpTable(current[1].u.operand); + auto iter = table.offsetTable.begin(); + auto end = table.offsetTable.end(); + for (; iter != end; ++iter) + function(iter->value.branchOffset); + function(current[2].u.operand); + break; + } + default: + break; + } +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PropertyCondition.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PropertyCondition.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PropertyCondition.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PropertyCondition.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -254,7 +254,7 @@ // shouldn't have a TOCTOU race either. RELEASE_ASSERT(offset != invalidOffset); - WatchpointSet* set; + WatchpointSet* set = nullptr; switch (effort) { case MakeNoChanges: set = structure->propertyReplacementWatchpointSet(offset); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -34,6 +34,7 @@ #include "PolymorphicAccess.h" #include "Structure.h" #include "StructureChain.h" +#include "StructureStubInfo.h" #include namespace JSC { @@ -224,12 +225,12 @@ return PutByIdStatus(slowPathState); case ComplexGetStatus::Inlineable: { - CallLinkInfo* callLinkInfo = access.callLinkInfo(); - ASSERT(callLinkInfo); std::unique_ptr callLinkStatus = - std::make_unique( - CallLinkStatus::computeFor( - locker, profiledBlock, *callLinkInfo, callExitSiteData)); + std::make_unique(); + if (CallLinkInfo* callLinkInfo = access.callLinkInfo()) { + *callLinkStatus = CallLinkStatus::computeFor( + locker, profiledBlock, *callLinkInfo, callExitSiteData); + } variant = PutByIdVariant::setter( structure, complexGetStatus.offset(), complexGetStatus.conditionSet(), diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PutByIdStatus.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PutByIdStatus.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PutByIdStatus.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PutByIdStatus.h 2016-11-03 07:04:20.000000000 +0000 @@ -29,7 +29,6 @@ #include "CallLinkStatus.h" #include "ExitingJITType.h" #include "PutByIdVariant.h" -#include "StructureStubInfo.h" #include namespace JSC { @@ -39,6 +38,9 @@ class JSGlobalObject; class Structure; class StructureChain; +class StructureStubInfo; + +typedef HashMap StubInfoMap; class PutByIdStatus { public: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PutByIdVariant.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PutByIdVariant.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/PutByIdVariant.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/PutByIdVariant.h 2016-11-03 07:04:20.000000000 +0000 @@ -112,7 +112,10 @@ // We don't support intrinsics for Setters (it would be sweet if we did) but we need this for templated helpers. Intrinsic intrinsic() const { return NoIntrinsic; } - + + // This is needed for templated helpers. + bool isPropertyUnset() const { return false; } + PropertyOffset offset() const { ASSERT(isSet()); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SamplingTool.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SamplingTool.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SamplingTool.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SamplingTool.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,479 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "SamplingTool.h" - -#include "CodeBlock.h" -#include "Interpreter.h" -#include "Opcode.h" -#include "JSCInlines.h" - -#if !OS(WINDOWS) -#include -#endif - -namespace JSC { - -#if ENABLE(SAMPLING_FLAGS) - -void SamplingFlags::sample() -{ - uint32_t mask = static_cast(1 << 31); - unsigned index; - - for (index = 0; index < 32; ++index) { - if (mask & s_flags) - break; - mask >>= 1; - } - - s_flagCounts[32 - index]++; -} - -void SamplingFlags::start() -{ - for (unsigned i = 0; i <= 32; ++i) - s_flagCounts[i] = 0; -} -void SamplingFlags::stop() -{ - uint64_t total = 0; - for (unsigned i = 0; i <= 32; ++i) - total += s_flagCounts[i]; - - if (total) { - dataLogF("\nSamplingFlags: sample counts with flags set: (%lld total)\n", total); - for (unsigned i = 0; i <= 32; ++i) { - if (s_flagCounts[i]) - dataLogF(" [ %02d ] : %lld\t\t(%03.2f%%)\n", i, s_flagCounts[i], (100.0 * s_flagCounts[i]) / total); - } - dataLogF("\n"); - } else - dataLogF("\nSamplingFlags: no samples.\n\n"); -} -uint64_t SamplingFlags::s_flagCounts[33]; - -#else -void SamplingFlags::start() {} -void SamplingFlags::stop() {} -#endif - -#if ENABLE(SAMPLING_REGIONS) -volatile uintptr_t SamplingRegion::s_currentOrReserved; -Spectrum* SamplingRegion::s_spectrum; -unsigned long SamplingRegion::s_noneOfTheAbove; -unsigned SamplingRegion::s_numberOfSamplesSinceDump; - -SamplingRegion::Locker::Locker() -{ - uintptr_t previous; - while (true) { - previous = s_currentOrReserved; - if (previous & 1) { -#if OS(UNIX) - sched_yield(); -#endif - continue; - } - if (WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, previous | 1)) - break; - } -} - -SamplingRegion::Locker::~Locker() -{ - // We don't need the CAS, but we do it out of an - // abundance of caution (and because it gives us a memory fence, which is - // never bad). - uintptr_t previous; - do { - previous = s_currentOrReserved; - } while (!WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, previous & ~1)); -} - -void SamplingRegion::sample() -{ - // Make sure we lock s_current. - Locker locker; - - // Create a spectrum if we don't have one already. - if (!s_spectrum) - s_spectrum = new Spectrum(); - - ASSERT(s_currentOrReserved & 1); - - // Walk the region stack, and record each region we see. - SamplingRegion* region = bitwise_cast(s_currentOrReserved & ~1); - if (region) { - for (; region; region = region->m_previous) - s_spectrum->add(region->m_name); - } else - s_noneOfTheAbove++; - - if (s_numberOfSamplesSinceDump++ == SamplingThread::s_hertz) { - s_numberOfSamplesSinceDump = 0; - dumpInternal(); - } -} - -void SamplingRegion::dump() -{ - Locker locker; - - dumpInternal(); -} - -void SamplingRegion::dumpInternal() -{ - if (!s_spectrum) { - dataLogF("\nSamplingRegion: was never sampled.\n\n"); - return; - } - - Vector::KeyAndCount> list = s_spectrum->buildList(); - - unsigned long total = s_noneOfTheAbove; - for (unsigned i = list.size(); i--;) - total += list[i].count; - - dataLogF("\nSamplingRegion: sample counts for regions: (%lu samples)\n", total); - - for (unsigned i = list.size(); i--;) - dataLogF(" %3.2lf%% %s\n", (100.0 * list[i].count) / total, list[i].key); -} -#else // ENABLE(SAMPLING_REGIONS) -void SamplingRegion::dump() { } -#endif // ENABLE(SAMPLING_REGIONS) - -/* - Start with flag 16 set. - By doing this the monitoring of lower valued flags will be masked out - until flag 16 is explictly cleared. -*/ -uint32_t SamplingFlags::s_flags = 1 << 15; - - -#if OS(WINDOWS) - -static void sleepForMicroseconds(unsigned us) -{ - unsigned ms = us / 1000; - if (us && !ms) - ms = 1; - Sleep(ms); -} - -#else - -static void sleepForMicroseconds(unsigned us) -{ - usleep(us); -} - -#endif - -static inline unsigned hertz2us(unsigned hertz) -{ - return 1000000 / hertz; -} - - -SamplingTool* SamplingTool::s_samplingTool = 0; - - -bool SamplingThread::s_running = false; -unsigned SamplingThread::s_hertz = 10000; -ThreadIdentifier SamplingThread::s_samplingThread; - -void SamplingThread::threadStartFunc(void*) -{ - while (s_running) { - sleepForMicroseconds(hertz2us(s_hertz)); - -#if ENABLE(SAMPLING_FLAGS) - SamplingFlags::sample(); -#endif -#if ENABLE(SAMPLING_REGIONS) - SamplingRegion::sample(); -#endif -#if ENABLE(OPCODE_SAMPLING) - SamplingTool::sample(); -#endif - } -} - - -void SamplingThread::start(unsigned hertz) -{ - ASSERT(!s_running); - s_running = true; - s_hertz = hertz; - - s_samplingThread = createThread(threadStartFunc, 0, "JavaScriptCore::Sampler"); -} - -void SamplingThread::stop() -{ - ASSERT(s_running); - s_running = false; - waitForThreadCompletion(s_samplingThread); -} - - -void ScriptSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC) -{ - if (!m_samples) { - m_size = codeBlock->instructions().size(); - m_samples = static_cast(calloc(m_size, sizeof(int))); - m_codeBlock = codeBlock; - } - - ++m_sampleCount; - - unsigned offest = vPC - codeBlock->instructions().begin(); - // Since we don't read and write codeBlock and vPC atomically, this check - // can fail if we sample mid op_call / op_ret. - if (offest < m_size) { - m_samples[offest]++; - m_opcodeSampleCount++; - } -} - -void SamplingTool::doRun() -{ - Sample sample(m_sample, m_codeBlock); - ++m_sampleCount; - - if (sample.isNull()) - return; - - if (!sample.inHostFunction()) { - unsigned opcodeID = m_interpreter->getOpcodeID(sample.vPC()[0].u.opcode); - - ++m_opcodeSampleCount; - ++m_opcodeSamples[opcodeID]; - - if (sample.inCTIFunction()) - m_opcodeSamplesInCTIFunctions[opcodeID]++; - } - -#if ENABLE(CODEBLOCK_SAMPLING) - if (CodeBlock* codeBlock = sample.codeBlock()) { - LockHolder locker(m_scriptSampleMapMutex); - ScriptSampleRecord* record = m_scopeSampleMap->get(codeBlock->ownerExecutable()); - ASSERT(record); - record->sample(codeBlock, sample.vPC()); - } -#endif -} - -void SamplingTool::sample() -{ - s_samplingTool->doRun(); -} - -void SamplingTool::notifyOfScope(VM& vm, ScriptExecutable* script) -{ -#if ENABLE(CODEBLOCK_SAMPLING) - LockHolder locker(m_scriptSampleMapMutex); - m_scopeSampleMap->set(script, adoptPtr(new ScriptSampleRecord(vm, script))); -#else - UNUSED_PARAM(vm); - UNUSED_PARAM(script); -#endif -} - -void SamplingTool::setup() -{ - s_samplingTool = this; -} - -#if ENABLE(OPCODE_SAMPLING) - -struct OpcodeSampleInfo { - OpcodeID opcode; - long long count; - long long countInCTIFunctions; -}; - -struct LineCountInfo { - unsigned line; - unsigned count; -}; - -static int compareOpcodeIndicesSampling(const void* left, const void* right) -{ - const OpcodeSampleInfo* leftSampleInfo = reinterpret_cast(left); - const OpcodeSampleInfo* rightSampleInfo = reinterpret_cast(right); - - return (leftSampleInfo->count < rightSampleInfo->count) ? 1 : (leftSampleInfo->count > rightSampleInfo->count) ? -1 : 0; -} - -#if ENABLE(CODEBLOCK_SAMPLING) -static int compareLineCountInfoSampling(const void* left, const void* right) -{ - const LineCountInfo* leftLineCount = reinterpret_cast(left); - const LineCountInfo* rightLineCount = reinterpret_cast(right); - - return (leftLineCount->line > rightLineCount->line) ? 1 : (leftLineCount->line < rightLineCount->line) ? -1 : 0; -} - -static int compareScriptSampleRecords(const void* left, const void* right) -{ - const ScriptSampleRecord* const leftValue = *static_cast(left); - const ScriptSampleRecord* const rightValue = *static_cast(right); - - return (leftValue->m_sampleCount < rightValue->m_sampleCount) ? 1 : (leftValue->m_sampleCount > rightValue->m_sampleCount) ? -1 : 0; -} -#endif - -void SamplingTool::dump(ExecState* exec) -{ - // Tidies up SunSpider output by removing short scripts - such a small number of samples would likely not be useful anyhow. - if (m_sampleCount < 10) - return; - - // (1) Build and sort 'opcodeSampleInfo' array. - - OpcodeSampleInfo opcodeSampleInfo[numOpcodeIDs]; - for (int i = 0; i < numOpcodeIDs; ++i) { - opcodeSampleInfo[i].opcode = static_cast(i); - opcodeSampleInfo[i].count = m_opcodeSamples[i]; - opcodeSampleInfo[i].countInCTIFunctions = m_opcodeSamplesInCTIFunctions[i]; - } - - qsort(opcodeSampleInfo, numOpcodeIDs, sizeof(OpcodeSampleInfo), compareOpcodeIndicesSampling); - - // (2) Print Opcode sampling results. - - dataLogF("\nBytecode samples [*]\n"); - dataLogF(" sample %% of %% of | cti cti %%\n"); - dataLogF("opcode count VM total | count of self\n"); - dataLogF("------------------------------------------------------- | ----------------\n"); - - for (int i = 0; i < numOpcodeIDs; ++i) { - long long count = opcodeSampleInfo[i].count; - if (!count) - continue; - - OpcodeID opcodeID = opcodeSampleInfo[i].opcode; - - const char* opcodeName = opcodeNames[opcodeID]; - const char* opcodePadding = padOpcodeName(opcodeID, 28); - double percentOfVM = (static_cast(count) * 100) / m_opcodeSampleCount; - double percentOfTotal = (static_cast(count) * 100) / m_sampleCount; - long long countInCTIFunctions = opcodeSampleInfo[i].countInCTIFunctions; - double percentInCTIFunctions = (static_cast(countInCTIFunctions) * 100) / count; - debugDebugPrintf("%s:%s%-6lld %.3f%%\t%.3f%%\t | %-6lld %.3f%%\n", opcodeName, opcodePadding, count, percentOfVM, percentOfTotal, countInCTIFunctions, percentInCTIFunctions); - } - - dataLogF("\n[*] Samples inside host code are not charged to any Bytecode.\n\n"); - dataLogF("\tSamples inside VM:\t\t%lld / %lld (%.3f%%)\n", m_opcodeSampleCount, m_sampleCount, (static_cast(m_opcodeSampleCount) * 100) / m_sampleCount); - dataLogF("\tSamples inside host code:\t%lld / %lld (%.3f%%)\n\n", m_sampleCount - m_opcodeSampleCount, m_sampleCount, (static_cast(m_sampleCount - m_opcodeSampleCount) * 100) / m_sampleCount); - dataLogF("\tsample count:\tsamples inside this opcode\n"); - dataLogF("\t%% of VM:\tsample count / all opcode samples\n"); - dataLogF("\t%% of total:\tsample count / all samples\n"); - dataLogF("\t--------------\n"); - dataLogF("\tcti count:\tsamples inside a CTI function called by this opcode\n"); - dataLogF("\tcti %% of self:\tcti count / sample count\n"); - -#if ENABLE(CODEBLOCK_SAMPLING) - - // (3) Build and sort 'codeBlockSamples' array. - - int scopeCount = m_scopeSampleMap->size(); - Vector codeBlockSamples(scopeCount); - ScriptSampleRecordMap::iterator iter = m_scopeSampleMap->begin(); - for (int i = 0; i < scopeCount; ++i, ++iter) - codeBlockSamples[i] = iter->value.get(); - - qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScriptSampleRecord*), compareScriptSampleRecords); - - // (4) Print data from 'codeBlockSamples' array. - - dataLogF("\nCodeBlock samples\n\n"); - - for (int i = 0; i < scopeCount; ++i) { - ScriptSampleRecord* record = codeBlockSamples[i]; - CodeBlock* codeBlock = record->m_codeBlock; - - double blockPercent = (record->m_sampleCount * 100.0) / m_sampleCount; - - if (blockPercent >= 1) { - //Instruction* code = codeBlock->instructions().begin(); - dataLogF("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_executable->sourceURL().utf8().data(), codeBlock->lineNumberForBytecodeOffset(0), record->m_sampleCount, m_sampleCount, blockPercent); - if (i < 10) { - HashMap lineCounts; - codeBlock->dump(exec); - - dataLogF(" Opcode and line number samples [*]\n\n"); - for (unsigned op = 0; op < record->m_size; ++op) { - int count = record->m_samples[op]; - if (count) { - dataLogF(" [% 4d] has sample count: % 4d\n", op, count); - unsigned line = codeBlock->lineNumberForBytecodeOffset(op); - lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count); - } - } - dataLogF("\n"); - - int linesCount = lineCounts.size(); - Vector lineCountInfo(linesCount); - int lineno = 0; - for (HashMap::iterator iter = lineCounts.begin(); iter != lineCounts.end(); ++iter, ++lineno) { - lineCountInfo[lineno].line = iter->key; - lineCountInfo[lineno].count = iter->value; - } - - qsort(lineCountInfo.begin(), linesCount, sizeof(LineCountInfo), compareLineCountInfoSampling); - - for (lineno = 0; lineno < linesCount; ++lineno) { - dataLogF(" Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count); - } - dataLogF("\n"); - dataLogF(" [*] Samples inside host code are charged to the calling Bytecode.\n"); - dataLogF(" Samples on a call / return boundary are not charged to a specific opcode or line.\n\n"); - dataLogF(" Samples on a call / return boundary: %d / %d (%.3f%%)\n\n", record->m_sampleCount - record->m_opcodeSampleCount, record->m_sampleCount, (static_cast(record->m_sampleCount - record->m_opcodeSampleCount) * 100) / record->m_sampleCount); - } - } - } -#else - UNUSED_PARAM(exec); -#endif -} - -#else - -void SamplingTool::dump(ExecState*) -{ -} - -#endif - -} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SamplingTool.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SamplingTool.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SamplingTool.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SamplingTool.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,349 +0,0 @@ -/* - * Copyright (C) 2008, 2013, 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SamplingTool_h -#define SamplingTool_h - -#include "Strong.h" -#include "Opcode.h" -#include "SamplingCounter.h" -#include -#include -#include -#include -#include -#include -#include - -namespace JSC { - - class ScriptExecutable; - - class SamplingFlags { - public: - JS_EXPORT_PRIVATE static void start(); - JS_EXPORT_PRIVATE static void stop(); - -#if ENABLE(SAMPLING_FLAGS) - static void setFlag(unsigned flag) - { - ASSERT(flag >= 1); - ASSERT(flag <= 32); - s_flags |= 1u << (flag - 1); - } - - static void clearFlag(unsigned flag) - { - ASSERT(flag >= 1); - ASSERT(flag <= 32); - s_flags &= ~(1u << (flag - 1)); - } - - static void sample(); - - class ScopedFlag { - public: - ScopedFlag(int flag) - : m_flag(flag) - { - setFlag(flag); - } - - ~ScopedFlag() - { - clearFlag(m_flag); - } - - private: - int m_flag; - }; - - static const void* addressOfFlags() - { - return &s_flags; - } - -#endif - private: - JS_EXPORTDATA static uint32_t s_flags; -#if ENABLE(SAMPLING_FLAGS) - static uint64_t s_flagCounts[33]; -#endif - }; - -#if ENABLE(SAMPLING_REGIONS) - class SamplingRegion { - public: - // Create a scoped sampling region using a C string constant name that describes - // what you are doing. This must be a string constant that persists for the - // lifetime of the process and is immutable. - SamplingRegion(const char* name) - { - if (!isMainThread()) { - m_name = 0; - return; - } - - m_name = name; - exchangeCurrent(this, &m_previous); - ASSERT(!m_previous || m_previous > this); - } - - ~SamplingRegion() - { - if (!m_name) - return; - - ASSERT(bitwise_cast(s_currentOrReserved & ~1) == this); - exchangeCurrent(m_previous); - } - - static void sample(); - - JS_EXPORT_PRIVATE static void dump(); - - private: - const char* m_name; - SamplingRegion* m_previous; - - static void exchangeCurrent(SamplingRegion* current, SamplingRegion** previousPtr = 0) - { - uintptr_t previous; - while (true) { - previous = s_currentOrReserved; - - // If it's reserved (i.e. sampling thread is reading it), loop around. - if (previous & 1) { -#if OS(UNIX) - sched_yield(); -#endif - continue; - } - - // If we're going to CAS, then make sure previous is set. - if (previousPtr) - *previousPtr = bitwise_cast(previous); - - if (WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, bitwise_cast(current))) - break; - } - } - - static void dumpInternal(); - - class Locker { - public: - Locker(); - ~Locker(); - }; - - static volatile uintptr_t s_currentOrReserved; - - // rely on identity hashing of string constants - static Spectrum* s_spectrum; - - static unsigned long s_noneOfTheAbove; - - static unsigned s_numberOfSamplesSinceDump; - }; -#else // ENABLE(SAMPLING_REGIONS) - class SamplingRegion { - public: - SamplingRegion(const char*) { } - JS_EXPORT_PRIVATE void dump(); - }; -#endif // ENABLE(SAMPLING_REGIONS) - - class CodeBlock; - class ExecState; - class Interpreter; - class ScopeNode; - struct Instruction; - - struct ScriptSampleRecord { - ScriptSampleRecord(VM& vm, ScriptExecutable* executable) - : m_executable(vm, executable) - , m_codeBlock(0) - , m_sampleCount(0) - , m_opcodeSampleCount(0) - , m_samples(0) - , m_size(0) - { - } - - ~ScriptSampleRecord() - { - if (m_samples) - free(m_samples); - } - - void sample(CodeBlock*, Instruction*); - - Strong m_executable; - CodeBlock* m_codeBlock; - int m_sampleCount; - int m_opcodeSampleCount; - int* m_samples; - unsigned m_size; - }; - - typedef HashMap> ScriptSampleRecordMap; - - class SamplingThread { - public: - // Sampling thread state. - static bool s_running; - static unsigned s_hertz; - static ThreadIdentifier s_samplingThread; - - JS_EXPORT_PRIVATE static void start(unsigned hertz=10000); - JS_EXPORT_PRIVATE static void stop(); - - static void threadStartFunc(void*); - }; - - class SamplingTool { - WTF_MAKE_FAST_ALLOCATED; - public: - friend struct CallRecord; - -#if ENABLE(OPCODE_SAMPLING) - class CallRecord { - WTF_MAKE_NONCOPYABLE(CallRecord); - public: - CallRecord(SamplingTool* samplingTool, bool isHostCall = false) - : m_samplingTool(samplingTool) - , m_savedSample(samplingTool->m_sample) - , m_savedCodeBlock(samplingTool->m_codeBlock) - { - if (isHostcall) - samplingTool->m_sample |= 0x1; - } - - ~CallRecord() - { - m_samplingTool->m_sample = m_savedSample; - m_samplingTool->m_codeBlock = m_savedCodeBlock; - } - - private: - SamplingTool* m_samplingTool; - intptr_t m_savedSample; - CodeBlock* m_savedCodeBlock; - }; -#else - class CallRecord { - WTF_MAKE_NONCOPYABLE(CallRecord); - public: - CallRecord(SamplingTool*, bool = false) - { - } - }; -#endif - - SamplingTool(Interpreter* interpreter) - : m_interpreter(interpreter) - , m_codeBlock(0) - , m_sample(0) - , m_sampleCount(0) - , m_opcodeSampleCount(0) -#if ENABLE(CODEBLOCK_SAMPLING) - , m_scopeSampleMap(std::make_unique) -#endif - { - memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples)); - memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions)); - } - - JS_EXPORT_PRIVATE void setup(); - void dump(ExecState*); - - void notifyOfScope(VM&, ScriptExecutable* scope); - - void sample(CodeBlock* codeBlock, Instruction* vPC) - { - ASSERT(!(reinterpret_cast(vPC) & 0x3)); - m_codeBlock = codeBlock; - m_sample = reinterpret_cast(vPC); - } - - CodeBlock** codeBlockSlot() { return &m_codeBlock; } - intptr_t* sampleSlot() { return &m_sample; } - - void* encodeSample(Instruction* vPC, bool inCTIFunction = false, bool inHostFunction = false) - { - ASSERT(!(reinterpret_cast(vPC) & 0x3)); - return reinterpret_cast(reinterpret_cast(vPC) | (static_cast(inCTIFunction) << 1) | static_cast(inHostFunction)); - } - - static void sample(); - - private: - class Sample { - public: - Sample(volatile intptr_t sample, CodeBlock* volatile codeBlock) - : m_sample(sample) - , m_codeBlock(codeBlock) - { - } - - bool isNull() { return !m_sample; } - CodeBlock* codeBlock() { return m_codeBlock; } - Instruction* vPC() { return reinterpret_cast(m_sample & ~0x3); } - bool inHostFunction() { return m_sample & 0x1; } - bool inCTIFunction() { return m_sample & 0x2; } - - private: - intptr_t m_sample; - CodeBlock* m_codeBlock; - }; - - void doRun(); - static SamplingTool* s_samplingTool; - - Interpreter* m_interpreter; - - // State tracked by the main thread, used by the sampling thread. - CodeBlock* m_codeBlock; - intptr_t m_sample; - - // Gathered sample data. - long long m_sampleCount; - long long m_opcodeSampleCount; - unsigned m_opcodeSamples[numOpcodeIDs]; - unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs]; - -#if ENABLE(CODEBLOCK_SAMPLING) - Lock m_scriptSampleMapMutex; - std::unique_ptr m_scopeSampleMap; -#endif - }; - -} // namespace JSC - -#endif // SamplingTool_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SpeculatedType.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SpeculatedType.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SpeculatedType.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SpeculatedType.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -30,9 +30,11 @@ #include "SpeculatedType.h" #include "DirectArguments.h" +#include "JSCInlines.h" #include "JSArray.h" #include "JSFunction.h" -#include "JSCInlines.h" +#include "JSMap.h" +#include "JSSet.h" #include "ScopedArguments.h" #include "StringObject.h" #include "ValueProfile.h" @@ -168,7 +170,7 @@ isTop = false; } - if (value == SpecInt32) + if (value == SpecInt32Only) myOut.print("Int32"); else { if (value & SpecBoolInt32) @@ -182,14 +184,14 @@ isTop = false; } - if (value & SpecInt52) + if (value & SpecInt52Only) myOut.print("Int52"); if ((value & SpecBytecodeDouble) == SpecBytecodeDouble) myOut.print("Bytecodedouble"); else { - if (value & SpecInt52AsDouble) - myOut.print("Int52asdouble"); + if (value & SpecAnyIntAsDouble) + myOut.print("AnyIntAsDouble"); else isTop = false; @@ -274,12 +276,12 @@ return ""; if (isInt32Speculation(prediction)) return ""; - if (isInt52AsDoubleSpeculation(prediction)) - return ""; + if (isAnyIntAsDoubleSpeculation(prediction)) + return ""; if (isInt52Speculation(prediction)) return ""; - if (isMachineIntSpeculation(prediction)) - return ""; + if (isAnyIntSpeculation(prediction)) + return ""; if (isDoubleSpeculation(prediction)) return ""; if (isFullNumberSpeculation(prediction)) @@ -346,6 +348,12 @@ if (classInfo == RegExpObject::info()) return SpecRegExpObject; + + if (classInfo == JSMap::info()) + return SpecMapObject; + + if (classInfo == JSSet::info()) + return SpecSetObject; if (classInfo->isSubClassOf(JSFunction::info())) return SpecFunction; @@ -393,8 +401,8 @@ double number = value.asNumber(); if (number != number) return SpecDoublePureNaN; - if (value.isMachineInt()) - return SpecInt52AsDouble; + if (value.isAnyInt()) + return SpecAnyIntAsDouble; return SpecNonIntAsDouble; } if (value.isCell()) @@ -439,8 +447,8 @@ SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType type) { - if (type & SpecInteger) - type |= SpecInteger; + if (type & (SpecAnyInt | SpecAnyIntAsDouble)) + type |= (SpecAnyInt | SpecAnyIntAsDouble); if (type & SpecString) type |= SpecString; return type; @@ -522,10 +530,11 @@ SpeculatedType typeOfDoubleNegation(SpeculatedType value) { - // Impure NaN could become pure NaN because bits might get cleared. - if (value & SpecDoubleImpureNaN) - value |= SpecDoublePureNaN; - // We could get negative zero, which mixes SpecInt52AsDouble and SpecNotIntAsDouble. + // Changing bits can make pure NaN impure and vice versa: + // 0xefff000000000000 (pure) - 0xffff000000000000 (impure) + if (value & SpecDoubleNaN) + value |= SpecDoubleNaN; + // We could get negative zero, which mixes SpecAnyIntAsDouble and SpecNotIntAsDouble. // We could also overflow a large negative int into something that is no longer // representable as an int. if (value & SpecDoubleReal) @@ -540,12 +549,13 @@ SpeculatedType typeOfDoubleRounding(SpeculatedType value) { - // We might lose bits, which leads to a NaN being purified. - if (value & SpecDoubleImpureNaN) - value |= SpecDoublePureNaN; + // Double Pure NaN can becomes impure when converted back from Float. + // and vice versa. + if (value & SpecDoubleNaN) + value |= SpecDoubleNaN; // We might lose bits, which leads to a value becoming integer-representable. if (value & SpecNonIntAsDouble) - value |= SpecInt52AsDouble; + value |= SpecAnyIntAsDouble; return value; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SpeculatedType.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SpeculatedType.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SpeculatedType.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SpeculatedType.h 2016-11-03 07:04:20.000000000 +0000 @@ -37,58 +37,59 @@ class Structure; -typedef uint32_t SpeculatedType; +typedef uint64_t SpeculatedType; static const SpeculatedType SpecNone = 0; // We don't know anything yet. -static const SpeculatedType SpecFinalObject = 1u << 0; // It's definitely a JSFinalObject. -static const SpeculatedType SpecArray = 1u << 1; // It's definitely a JSArray. -static const SpeculatedType SpecFunction = 1u << 2; // It's definitely a JSFunction. -static const SpeculatedType SpecInt8Array = 1u << 3; // It's definitely an Int8Array or one of its subclasses. -static const SpeculatedType SpecInt16Array = 1u << 4; // It's definitely an Int16Array or one of its subclasses. -static const SpeculatedType SpecInt32Array = 1u << 5; // It's definitely an Int32Array or one of its subclasses. -static const SpeculatedType SpecUint8Array = 1u << 6; // It's definitely an Uint8Array or one of its subclasses. -static const SpeculatedType SpecUint8ClampedArray = 1u << 7; // It's definitely an Uint8ClampedArray or one of its subclasses. -static const SpeculatedType SpecUint16Array = 1u << 8; // It's definitely an Uint16Array or one of its subclasses. -static const SpeculatedType SpecUint32Array = 1u << 9; // It's definitely an Uint32Array or one of its subclasses. -static const SpeculatedType SpecFloat32Array = 1u << 10; // It's definitely an Uint16Array or one of its subclasses. -static const SpeculatedType SpecFloat64Array = 1u << 11; // It's definitely an Uint16Array or one of its subclasses. +static const SpeculatedType SpecFinalObject = 1ull << 0; // It's definitely a JSFinalObject. +static const SpeculatedType SpecArray = 1ull << 1; // It's definitely a JSArray. +static const SpeculatedType SpecFunction = 1ull << 2; // It's definitely a JSFunction. +static const SpeculatedType SpecInt8Array = 1ull << 3; // It's definitely an Int8Array or one of its subclasses. +static const SpeculatedType SpecInt16Array = 1ull << 4; // It's definitely an Int16Array or one of its subclasses. +static const SpeculatedType SpecInt32Array = 1ull << 5; // It's definitely an Int32Array or one of its subclasses. +static const SpeculatedType SpecUint8Array = 1ull << 6; // It's definitely an Uint8Array or one of its subclasses. +static const SpeculatedType SpecUint8ClampedArray = 1ull << 7; // It's definitely an Uint8ClampedArray or one of its subclasses. +static const SpeculatedType SpecUint16Array = 1ull << 8; // It's definitely an Uint16Array or one of its subclasses. +static const SpeculatedType SpecUint32Array = 1ull << 9; // It's definitely an Uint32Array or one of its subclasses. +static const SpeculatedType SpecFloat32Array = 1ull << 10; // It's definitely an Uint16Array or one of its subclasses. +static const SpeculatedType SpecFloat64Array = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses. static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array; -static const SpeculatedType SpecDirectArguments = 1u << 12; // It's definitely a DirectArguments object. -static const SpeculatedType SpecScopedArguments = 1u << 13; // It's definitely a ScopedArguments object. -static const SpeculatedType SpecStringObject = 1u << 14; // It's definitely a StringObject. -static const SpeculatedType SpecRegExpObject = 1u << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject). -static const SpeculatedType SpecObjectOther = 1u << 16; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. -static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction. -static const SpeculatedType SpecStringIdent = 1u << 17; // It's definitely a JSString, and it's an identifier. -static const SpeculatedType SpecStringVar = 1u << 18; // It's definitely a JSString, and it's not an identifier. +static const SpeculatedType SpecDirectArguments = 1ull << 12; // It's definitely a DirectArguments object. +static const SpeculatedType SpecScopedArguments = 1ull << 13; // It's definitely a ScopedArguments object. +static const SpeculatedType SpecStringObject = 1ull << 14; // It's definitely a StringObject. +static const SpeculatedType SpecRegExpObject = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject). +static const SpeculatedType SpecMapObject = 1ull << 16; // It's definitely Map object (can it be a subclass? FIXME). +static const SpeculatedType SpecSetObject = 1ull << 17; // It's definitely s Set object (can it be a subclass? FIXME). +static const SpeculatedType SpecObjectOther = 1ull << 18; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. +static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction. +static const SpeculatedType SpecStringIdent = 1ull << 19; // It's definitely a JSString, and it's an identifier. +static const SpeculatedType SpecStringVar = 1ull << 20; // It's definitely a JSString, and it's not an identifier. static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString. -static const SpeculatedType SpecSymbol = 1u << 19; // It's definitely a Symbol. -static const SpeculatedType SpecCellOther = 1u << 20; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078 +static const SpeculatedType SpecSymbol = 1ull << 21; // It's definitely a Symbol. +static const SpeculatedType SpecCellOther = 1ull << 22; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078 static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell. -static const SpeculatedType SpecBoolInt32 = 1u << 21; // It's definitely an Int32 with value 0 or 1. -static const SpeculatedType SpecNonBoolInt32 = 1u << 22; // It's definitely an Int32 with value other than 0 or 1. -static const SpeculatedType SpecInt32 = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32. -static const SpeculatedType SpecInt52 = 1u << 23; // It's definitely an Int52 and we intend it to unbox it. -static const SpeculatedType SpecMachineInt = SpecInt32 | SpecInt52; // It's something that we can do machine int arithmetic on. -static const SpeculatedType SpecInt52AsDouble = 1u << 24; // It's definitely an Int52 and it's inside a double. -static const SpeculatedType SpecInteger = SpecMachineInt | SpecInt52AsDouble; // It's definitely some kind of integer. -static const SpeculatedType SpecNonIntAsDouble = 1u << 25; // It's definitely not an Int52 but it's a real number and it's a double. -static const SpeculatedType SpecDoubleReal = SpecNonIntAsDouble | SpecInt52AsDouble; // It's definitely a non-NaN double. -static const SpeculatedType SpecDoublePureNaN = 1u << 26; // It's definitely a NaN that is sae to tag (i.e. pure). -static const SpeculatedType SpecDoubleImpureNaN = 1u << 27; // It's definitely a NaN that is unsafe to tag (i.e. impure). +static const SpeculatedType SpecBoolInt32 = 1ull << 23; // It's definitely an Int32 with value 0 or 1. +static const SpeculatedType SpecNonBoolInt32 = 1ull << 24; // It's definitely an Int32 with value other than 0 or 1. +static const SpeculatedType SpecInt32Only = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32. +static const SpeculatedType SpecInt52Only = 1ull << 25; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32. +static const SpeculatedType SpecAnyInt = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on. +static const SpeculatedType SpecAnyIntAsDouble = 1ull << 26; // It's definitely an Int52 and it's inside a double. +static const SpeculatedType SpecNonIntAsDouble = 1ull << 27; // It's definitely not an Int52 but it's a real number and it's a double. +static const SpeculatedType SpecDoubleReal = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double. +static const SpeculatedType SpecDoublePureNaN = 1ull << 28; // It's definitely a NaN that is sae to tag (i.e. pure). +static const SpeculatedType SpecDoubleImpureNaN = 1ull << 29; // It's definitely a NaN that is unsafe to tag (i.e. impure). static const SpeculatedType SpecDoubleNaN = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN. static const SpeculatedType SpecBytecodeDouble = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN. static const SpeculatedType SpecFullDouble = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double. -static const SpeculatedType SpecBytecodeRealNumber = SpecInt32 | SpecDoubleReal; // It's either an Int32 or a DoubleReal. -static const SpeculatedType SpecFullRealNumber = SpecMachineInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52. -static const SpeculatedType SpecBytecodeNumber = SpecInt32 | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN. -static const SpeculatedType SpecFullNumber = SpecMachineInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN. -static const SpeculatedType SpecBoolean = 1u << 28; // It's definitely a Boolean. -static const SpeculatedType SpecOther = 1u << 29; // It's definitely either Null or Undefined. +static const SpeculatedType SpecBytecodeRealNumber = SpecInt32Only | SpecDoubleReal; // It's either an Int32 or a DoubleReal. +static const SpeculatedType SpecFullRealNumber = SpecAnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52. +static const SpeculatedType SpecBytecodeNumber = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN. +static const SpeculatedType SpecFullNumber = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN. +static const SpeculatedType SpecBoolean = 1ull << 30; // It's definitely a Boolean. +static const SpeculatedType SpecOther = 1ull << 31; // It's definitely either Null or Undefined. static const SpeculatedType SpecMisc = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined. -static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52 and SpecDoubleImpureNaN. +static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. static const SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc; // It's any non-Object JSValue. -static const SpeculatedType SpecEmpty = 1u << 30; // It's definitely an empty value marker. -static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52 and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local. +static const SpeculatedType SpecEmpty = 1ull << 32; // It's definitely an empty value marker. +static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local. static const SpeculatedType SpecFullTop = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers. typedef bool (*SpeculatedTypeChecker)(SpeculatedType); @@ -288,22 +289,22 @@ inline bool isInt32Speculation(SpeculatedType value) { - return value && !(value & ~SpecInt32); + return value && !(value & ~SpecInt32Only); } inline bool isInt32OrBooleanSpeculation(SpeculatedType value) { - return value && !(value & ~(SpecBoolean | SpecInt32)); + return value && !(value & ~(SpecBoolean | SpecInt32Only)); } inline bool isInt32SpeculationForArithmetic(SpeculatedType value) { - return !(value & (SpecFullDouble | SpecInt52)); + return !(value & (SpecFullDouble | SpecInt52Only)); } inline bool isInt32OrBooleanSpeculationForArithmetic(SpeculatedType value) { - return !(value & (SpecFullDouble | SpecInt52)); + return !(value & (SpecFullDouble | SpecInt52Only)); } inline bool isInt32OrBooleanSpeculationExpectingDefined(SpeculatedType value) @@ -313,22 +314,17 @@ inline bool isInt52Speculation(SpeculatedType value) { - return value == SpecInt52; + return value == SpecInt52Only; } -inline bool isMachineIntSpeculation(SpeculatedType value) +inline bool isAnyIntSpeculation(SpeculatedType value) { - return !!value && (value & SpecMachineInt) == value; + return !!value && (value & SpecAnyInt) == value; } -inline bool isInt52AsDoubleSpeculation(SpeculatedType value) +inline bool isAnyIntAsDoubleSpeculation(SpeculatedType value) { - return value == SpecInt52AsDouble; -} - -inline bool isIntegerSpeculation(SpeculatedType value) -{ - return !!value && (value & SpecInteger) == value; + return value == SpecAnyIntAsDouble; } inline bool isDoubleRealSpeculation(SpeculatedType value) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,7 +34,10 @@ namespace JSC { -StructureStubClearingWatchpoint::~StructureStubClearingWatchpoint() { } +StructureStubClearingWatchpoint::~StructureStubClearingWatchpoint() +{ + for (auto current = WTFMove(m_next); current; current = WTFMove(current->m_next)) { } +} StructureStubClearingWatchpoint* StructureStubClearingWatchpoint::push( const ObjectPropertyCondition& key, diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h 2016-11-03 07:04:20.000000000 +0000 @@ -62,7 +62,7 @@ std::unique_ptr& head); protected: - virtual void fireInternal(const FireDetail&) override; + void fireInternal(const FireDetail&) override; private: ObjectPropertyCondition m_key; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,12 +27,16 @@ #include "StructureStubInfo.h" #include "JSObject.h" +#include "JSCInlines.h" #include "PolymorphicAccess.h" #include "Repatch.h" namespace JSC { #if ENABLE(JIT) + +static const bool verbose = false; + StructureStubInfo::StructureStubInfo(AccessType accessType) : callSiteIndex(UINT_MAX) , accessType(accessType) @@ -40,6 +44,7 @@ , countdown(1) // For a totally clear stub, we'll patch it after the first execution. , repatchCount(0) , numberOfCoolDowns(0) + , bufferingCountdown(Options::repatchBufferingCountdown()) , resetByGC(false) , tookSlowPath(false) , everConsidered(false) @@ -59,6 +64,11 @@ u.byIdSelf.offset = offset; } +void StructureStubInfo::initArrayLength() +{ + cacheType = CacheType::ArrayLength; +} + void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset) { cacheType = CacheType::PutByIdReplace; @@ -83,6 +93,7 @@ case CacheType::Unset: case CacheType::GetByIdSelf: case CacheType::PutByIdReplace: + case CacheType::ArrayLength: return; } @@ -98,46 +109,103 @@ case CacheType::Unset: case CacheType::GetByIdSelf: case CacheType::PutByIdReplace: + case CacheType::ArrayLength: return; } RELEASE_ASSERT_NOT_REACHED(); } -MacroAssemblerCodePtr StructureStubInfo::addAccessCase( +AccessGenerationResult StructureStubInfo::addAccessCase( CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr accessCase) { VM& vm = *codeBlock->vm(); + if (verbose) + dataLog("Adding access case: ", accessCase, "\n"); + if (!accessCase) - return MacroAssemblerCodePtr(); + return AccessGenerationResult::GaveUp; - if (cacheType == CacheType::Stub) - return u.stub->regenerateWithCase(vm, codeBlock, *this, ident, WTFMove(accessCase)); - - std::unique_ptr access = std::make_unique(); + AccessGenerationResult result; - Vector> accessCases; + if (cacheType == CacheType::Stub) { + result = u.stub->addCase(vm, codeBlock, *this, ident, WTFMove(accessCase)); + + if (verbose) + dataLog("Had stub, result: ", result, "\n"); + + if (!result.buffered()) { + bufferedStructures.clear(); + return result; + } + } else { + std::unique_ptr access = std::make_unique(); + + Vector, 2> accessCases; + + std::unique_ptr previousCase = + AccessCase::fromStructureStubInfo(vm, codeBlock, *this); + if (previousCase) + accessCases.append(WTFMove(previousCase)); + + accessCases.append(WTFMove(accessCase)); + + result = access->addCases(vm, codeBlock, *this, ident, WTFMove(accessCases)); + + if (verbose) + dataLog("Created stub, result: ", result, "\n"); + + if (!result.buffered()) { + bufferedStructures.clear(); + return result; + } + + initStub(codeBlock, WTFMove(access)); + } - std::unique_ptr previousCase = - AccessCase::fromStructureStubInfo(vm, codeBlock, *this); - if (previousCase) - accessCases.append(WTFMove(previousCase)); - - accessCases.append(WTFMove(accessCase)); - - MacroAssemblerCodePtr result = - access->regenerateWithCases(vm, codeBlock, *this, ident, WTFMove(accessCases)); - - if (!result) - return MacroAssemblerCodePtr(); - - initStub(codeBlock, WTFMove(access)); + RELEASE_ASSERT(!result.generatedSomeCode()); + + // If we didn't buffer any cases then bail. If this made no changes then we'll just try again + // subject to cool-down. + if (!result.buffered()) { + if (verbose) + dataLog("Didn't buffer anything, bailing.\n"); + bufferedStructures.clear(); + return result; + } + + // The buffering countdown tells us if we should be repatching now. + if (bufferingCountdown) { + if (verbose) + dataLog("Countdown is too high: ", bufferingCountdown, ".\n"); + return result; + } + + // Forget the buffered structures so that all future attempts to cache get fully handled by the + // PolymorphicAccess. + bufferedStructures.clear(); + + result = u.stub->regenerate(vm, codeBlock, *this, ident); + + if (verbose) + dataLog("Regeneration result: ", result, "\n"); + + RELEASE_ASSERT(!result.buffered()); + + if (!result.generatedSomeCode()) + return result; + + // If we generated some code then we don't want to attempt to repatch in the future until we + // gather enough cases. + bufferingCountdown = Options::repatchBufferingCountdown(); return result; } void StructureStubInfo::reset(CodeBlock* codeBlock) { + bufferedStructures.clear(); + if (cacheType == CacheType::Unset) return; @@ -148,8 +216,11 @@ } switch (accessType) { + case AccessType::GetPure: + resetGetByID(codeBlock, *this, GetByIDKind::Pure); + break; case AccessType::Get: - resetGetByID(codeBlock, *this); + resetGetByID(codeBlock, *this, GetByIDKind::Normal); break; case AccessType::Put: resetPutByID(codeBlock, *this); @@ -166,6 +237,11 @@ void StructureStubInfo::visitWeakReferences(CodeBlock* codeBlock) { VM& vm = *codeBlock->vm(); + + bufferedStructures.genericFilter( + [&] (Structure* structure) -> bool { + return Heap::isMarked(structure); + }); switch (cacheType) { case CacheType::GetByIdSelf: @@ -185,12 +261,30 @@ resetByGC = true; } +bool StructureStubInfo::propagateTransitions(SlotVisitor& visitor) +{ + switch (cacheType) { + case CacheType::Unset: + case CacheType::ArrayLength: + return true; + case CacheType::GetByIdSelf: + case CacheType::PutByIdReplace: + return u.byIdSelf.baseObjectStructure->markIfCheap(visitor); + case CacheType::Stub: + return u.stub->propagateTransitions(visitor); + } + + RELEASE_ASSERT_NOT_REACHED(); + return true; +} + bool StructureStubInfo::containsPC(void* pc) const { if (cacheType != CacheType::Stub) return false; return u.stub->containsPC(pc); } -#endif + +#endif // ENABLE(JIT) } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/StructureStubInfo.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/StructureStubInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2012-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,21 +31,23 @@ #include "JITStubRoutine.h" #include "MacroAssembler.h" #include "ObjectPropertyConditionSet.h" -#include "Opcode.h" #include "Options.h" -#include "PolymorphicAccess.h" #include "RegisterSet.h" #include "Structure.h" +#include "StructureSet.h" #include "StructureStubClearingWatchpoint.h" namespace JSC { #if ENABLE(JIT) +class AccessCase; +class AccessGenerationResult; class PolymorphicAccess; enum class AccessType : int8_t { Get, + GetPure, Put, In }; @@ -54,7 +56,8 @@ Unset, GetByIdSelf, PutByIdReplace, - Stub + Stub, + ArrayLength }; class StructureStubInfo { @@ -65,11 +68,11 @@ ~StructureStubInfo(); void initGetByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset); + void initArrayLength(); void initPutByIdReplace(CodeBlock*, Structure* baseObjectStructure, PropertyOffset); void initStub(CodeBlock*, std::unique_ptr); - MacroAssemblerCodePtr addAccessCase( - CodeBlock*, const Identifier&, std::unique_ptr); + AccessGenerationResult addAccessCase(CodeBlock*, const Identifier&, std::unique_ptr); void reset(CodeBlock*); @@ -79,14 +82,30 @@ // Check if the stub has weak references that are dead. If it does, then it resets itself, // either entirely or just enough to ensure that those dead pointers don't get used anymore. void visitWeakReferences(CodeBlock*); + + // This returns true if it has marked everything that it will ever mark. + bool propagateTransitions(SlotVisitor&); - ALWAYS_INLINE bool considerCaching() + ALWAYS_INLINE bool considerCaching(Structure* structure) { + // We never cache non-cells. + if (!structure) + return false; + + // This method is called from the Optimize variants of IC slow paths. The first part of this + // method tries to determine if the Optimize variant should really behave like the + // non-Optimize variant and leave the IC untouched. + // + // If we determine that we should do something to the IC then the next order of business is + // to determine if this Structure would impact the IC at all. We know that it won't, if we + // have already buffered something on its behalf. That's what the bufferedStructures set is + // for. + everConsidered = true; if (!countdown) { // Check if we have been doing repatching too frequently. If so, then we should cool off // for a while. - willRepatch(); + WTF::incrementWithSaturation(repatchCount); if (repatchCount > Options::repatchCountForCoolDown()) { // We've been repatching too much, so don't do it now. repatchCount = 0; @@ -98,32 +117,38 @@ static_cast(Options::initialCoolDownCount()), numberOfCoolDowns, static_cast(std::numeric_limits::max() - 1)); - willCoolDown(); - return false; + WTF::incrementWithSaturation(numberOfCoolDowns); + + // We may still have had something buffered. Trigger generation now. + bufferingCountdown = 0; + return true; } - return true; + + // We don't want to return false due to buffering indefinitely. + if (!bufferingCountdown) { + // Note that when this returns true, it's possible that we will not even get an + // AccessCase because this may cause Repatch.cpp to simply do an in-place + // repatching. + return true; + } + + bufferingCountdown--; + + // Now protect the IC buffering. We want to proceed only if this is a structure that + // we don't already have a case buffered for. Note that if this returns true but the + // bufferingCountdown is not zero then we will buffer the access case for later without + // immediately generating code for it. + return bufferedStructures.add(structure); } countdown--; return false; } - ALWAYS_INLINE void willRepatch() - { - WTF::incrementWithSaturation(repatchCount); - } - - ALWAYS_INLINE void willCoolDown() - { - WTF::incrementWithSaturation(numberOfCoolDowns); - } - - CodeLocationCall callReturnLocation; + bool containsPC(void* pc) const; CodeOrigin codeOrigin; CallSiteIndex callSiteIndex; - bool containsPC(void* pc) const; - union { struct { WriteBarrierBase baseObjectStructure; @@ -131,32 +156,53 @@ } byIdSelf; PolymorphicAccess* stub; } u; - + + // Represents those structures that already have buffered AccessCases in the PolymorphicAccess. + // Note that it's always safe to clear this. If we clear it prematurely, then if we see the same + // structure again during this buffering countdown, we will create an AccessCase object for it. + // That's not so bad - we'll get rid of the redundant ones once we regenerate. + StructureSet bufferedStructures; + struct { + CodeLocationLabel start; // This is either the start of the inline IC for *byId caches, or the location of patchable jump for 'in' caches. + RegisterSet usedRegisters; + uint32_t inlineSize; + int32_t deltaFromStartToSlowPathCallLocation; + int32_t deltaFromStartToSlowPathStart; + int8_t baseGPR; + int8_t valueGPR; #if USE(JSVALUE32_64) int8_t valueTagGPR; int8_t baseTagGPR; #endif - int8_t valueGPR; - RegisterSet usedRegisters; - int32_t deltaCallToDone; - int32_t deltaCallToJump; - int32_t deltaCallToSlowCase; - int32_t deltaCheckImmToCall; -#if USE(JSVALUE64) - int32_t deltaCallToLoadOrStore; -#else - int32_t deltaCallToTagLoadOrStore; - int32_t deltaCallToPayloadLoadOrStore; -#endif } patch; + CodeLocationCall slowPathCallLocation() { return patch.start.callAtOffset(patch.deltaFromStartToSlowPathCallLocation); } + CodeLocationLabel doneLocation() { return patch.start.labelAtOffset(patch.inlineSize); } + CodeLocationLabel slowPathStartLocation() { return patch.start.labelAtOffset(patch.deltaFromStartToSlowPathStart); } + CodeLocationJump patchableJumpForIn() + { + ASSERT(accessType == AccessType::In); + return patch.start.jumpAtOffset(0); + } + + JSValueRegs valueRegs() const + { + return JSValueRegs( +#if USE(JSVALUE32_64) + static_cast(patch.valueTagGPR), +#endif + static_cast(patch.valueGPR)); + } + + AccessType accessType; CacheType cacheType; uint8_t countdown; // We repatch only when this is zero. If not zero, we decrement. uint8_t repatchCount; uint8_t numberOfCoolDowns; + uint8_t bufferingCountdown; bool resetByGC : 1; bool tookSlowPath : 1; bool everConsidered : 1; @@ -167,14 +213,14 @@ return structureStubInfo.codeOrigin; } -typedef HashMap StubInfoMap; - #else -typedef HashMap StubInfoMap; +class StructureStubInfo; #endif // ENABLE(JIT) +typedef HashMap StubInfoMap; + } // namespace JSC #endif // StructureStubInfo_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SuperSampler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SuperSampler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SuperSampler.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SuperSampler.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SuperSampler.h" + +#include "MacroAssembler.h" +#include "Options.h" +#include +#include +#include +#include + +namespace JSC { + +volatile uint32_t g_superSamplerCount; + +static StaticLock lock; +static double in; +static double out; + +void initializeSuperSampler() +{ + if (!Options::useSuperSampler()) + return; + + createThread( + "JSC Super Sampler", + [] () { + const int sleepQuantum = 10; + const int printingPeriod = 1000; + for (;;) { + for (int ms = 0; ms < printingPeriod; ms += sleepQuantum) { + { + LockHolder locker(lock); + if (g_superSamplerCount) + in++; + else + out++; + } + sleepMS(sleepQuantum); + } + printSuperSamplerState(); + if (static_cast(g_superSamplerCount) < 0) + dataLog("WARNING: Super sampler undercount detected!\n"); + } + }); +} + +void resetSuperSamplerState() +{ + LockHolder locker(lock); + in = 0; + out = 0; +} + +void printSuperSamplerState() +{ + if (!Options::useSuperSampler()) + return; + + LockHolder locker(lock); + double percentage = 100.0 * in / (in + out); + if (percentage != percentage) + percentage = 0.0; + dataLog("Percent time behind super sampler flag: ", percentage, "\n"); +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SuperSampler.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SuperSampler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/SuperSampler.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/SuperSampler.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SuperSampler_h +#define SuperSampler_h + +namespace JSC { + +class MacroAssembler; + +extern volatile uint32_t g_superSamplerCount; + +void initializeSuperSampler(); + +class SuperSamplerScope { +public: + SuperSamplerScope(bool doSample = true) + : m_doSample(doSample) + { + if (m_doSample) + g_superSamplerCount++; + } + + ~SuperSamplerScope() + { + if (m_doSample) + g_superSamplerCount--; + } + +private: + bool m_doSample; +}; + +JS_EXPORT_PRIVATE void resetSuperSamplerState(); +JS_EXPORT_PRIVATE void printSuperSamplerState(); + +} // namespace JSC + +#endif // SuperSampler_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved. + * Copyright (C) 2012-2013, 2015-2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,7 @@ #include "UnlinkedCodeBlock.h" #include "BytecodeGenerator.h" +#include "BytecodeRewriter.h" #include "ClassInfo.h" #include "CodeCache.h" #include "Executable.h" @@ -36,6 +37,7 @@ #include "JSString.h" #include "JSCInlines.h" #include "Parser.h" +#include "PreciseJumpTargetsInlines.h" #include "SourceProvider.h" #include "Structure.h" #include "SymbolTable.h" @@ -51,7 +53,7 @@ const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) }; const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) }; -UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) +UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode) : Base(*vm, structure) , m_numVars(0) , m_numCalleeLocals(0) @@ -62,14 +64,18 @@ , m_isConstructor(info.isConstructor()) , m_hasCapturedVariables(false) , m_isBuiltinFunction(info.isBuiltinFunction()) - , m_constructorKind(static_cast(info.constructorKind())) , m_superBinding(static_cast(info.superBinding())) - , m_derivedContextType(static_cast(info.derivedContextType())) + , m_commentMode(static_cast(info.commentMode())) , m_isArrowFunctionContext(info.isArrowFunctionContext()) , m_isClassContext(info.isClassContext()) + , m_wasCompiledWithDebuggingOpcodes(debuggerMode == DebuggerMode::DebuggerOn || Options::forceDebuggerBytecodeGeneration()) + , m_constructorKind(static_cast(info.constructorKind())) + , m_derivedContextType(static_cast(info.derivedContextType())) + , m_evalContextType(static_cast(info.evalContextType())) , m_firstLine(0) , m_lineCount(0) , m_endColumn(UINT_MAX) + , m_didOptimize(MixedTriState) , m_parseMode(info.parseMode()) , m_features(0) , m_codeType(codeType) @@ -84,11 +90,6 @@ ASSERT(m_constructorKind == static_cast(info.constructorKind())); } -VM* UnlinkedCodeBlock::vm() const -{ - return MarkedBlock::blockFor(this)->vm(); -} - void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor) { UnlinkedCodeBlock* thisObject = jsCast(cell); @@ -126,8 +127,8 @@ return line; } -inline void UnlinkedCodeBlock::getLineAndColumn(ExpressionRangeInfo& info, - unsigned& line, unsigned& column) +inline void UnlinkedCodeBlock::getLineAndColumn(const ExpressionRangeInfo& info, + unsigned& line, unsigned& column) const { switch (info.mode) { case ExpressionRangeInfo::FatLineMode: @@ -183,7 +184,7 @@ #endif void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, - int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) + int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const { ASSERT(bytecodeOffset < instructions().count()); @@ -196,7 +197,7 @@ return; } - Vector& expressionInfo = m_expressionInfo; + const Vector& expressionInfo = m_expressionInfo; int low = 0; int high = expressionInfo.size(); @@ -211,7 +212,7 @@ if (!low) low = 1; - ExpressionRangeInfo& info = expressionInfo[low - 1]; + const ExpressionRangeInfo& info = expressionInfo[low - 1]; startOffset = info.startOffset; endOffset = info.endOffset; divot = info.divotPoint; @@ -363,5 +364,67 @@ return *m_unlinkedInstructions; } +UnlinkedHandlerInfo* UnlinkedCodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler) +{ + return handlerForIndex(bytecodeOffset, requiredHandler); +} + +UnlinkedHandlerInfo* UnlinkedCodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler) +{ + if (!m_rareData) + return nullptr; + return UnlinkedHandlerInfo::handlerForIndex(m_rareData->m_exceptionHandlers, index, requiredHandler); +} + +void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter) +{ + // Before applying the changes, we adjust the jumps based on the original bytecode offset, the offset to the jump target, and + // the insertion information. + + BytecodeGraph& graph = rewriter.graph(); + UnlinkedInstruction* instructionsBegin = graph.instructions().begin(); + + for (int bytecodeOffset = 0, instructionCount = graph.instructions().size(); bytecodeOffset < instructionCount;) { + UnlinkedInstruction* current = instructionsBegin + bytecodeOffset; + OpcodeID opcodeID = current[0].u.opcode; + extractStoredJumpTargetsForBytecodeOffset(this, vm()->interpreter, instructionsBegin, bytecodeOffset, [&](int32_t& relativeOffset) { + relativeOffset = rewriter.adjustJumpTarget(bytecodeOffset, bytecodeOffset + relativeOffset); + }); + bytecodeOffset += opcodeLength(opcodeID); + } + + // Then, exception handlers should be adjusted. + if (m_rareData) { + for (UnlinkedHandlerInfo& handler : m_rareData->m_exceptionHandlers) { + handler.target = rewriter.adjustAbsoluteOffset(handler.target); + handler.start = rewriter.adjustAbsoluteOffset(handler.start); + handler.end = rewriter.adjustAbsoluteOffset(handler.end); + } + + for (size_t i = 0; i < m_rareData->m_opProfileControlFlowBytecodeOffsets.size(); ++i) + m_rareData->m_opProfileControlFlowBytecodeOffsets[i] = rewriter.adjustAbsoluteOffset(m_rareData->m_opProfileControlFlowBytecodeOffsets[i]); + + if (!m_rareData->m_typeProfilerInfoMap.isEmpty()) { + HashMap adjustedTypeProfilerInfoMap; + for (auto& entry : m_rareData->m_typeProfilerInfoMap) + adjustedTypeProfilerInfoMap.set(rewriter.adjustAbsoluteOffset(entry.key), entry.value); + m_rareData->m_typeProfilerInfoMap.swap(adjustedTypeProfilerInfoMap); + } + } + + for (size_t i = 0; i < m_propertyAccessInstructions.size(); ++i) + m_propertyAccessInstructions[i] = rewriter.adjustAbsoluteOffset(m_propertyAccessInstructions[i]); + + for (size_t i = 0; i < m_expressionInfo.size(); ++i) + m_expressionInfo[i].instructionOffset = rewriter.adjustAbsoluteOffset(m_expressionInfo[i].instructionOffset); + + // Then, modify the unlinked instructions. + rewriter.applyModification(); + + // And recompute the jump target based on the modified unlinked instructions. + m_jumpTargets.clear(); + recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets); +} + } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All Rights Reserved. + * Copyright (C) 2012-2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef UnlinkedCodeBlock_h -#define UnlinkedCodeBlock_h +#pragma once #include "BytecodeConventions.h" #include "CodeSpecializationKind.h" @@ -41,12 +40,12 @@ #include "UnlinkedFunctionExecutable.h" #include "VariableEnvironment.h" #include "VirtualRegister.h" -#include -#include +#include #include namespace JSC { +class BytecodeRewriter; class Debugger; class FunctionMetadataNode; class FunctionExecutable; @@ -68,7 +67,11 @@ typedef unsigned UnlinkedLLIntCallLinkInfo; struct UnlinkedStringJumpTable { - typedef HashMap, int32_t> StringOffsetTable; + struct OffsetLocation { + int32_t branchOffset; + }; + + typedef HashMap, OffsetLocation> StringOffsetTable; StringOffsetTable offsetTable; inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset) @@ -77,7 +80,7 @@ StringOffsetTable::const_iterator loc = offsetTable.find(value); if (loc == end) return defaultOffset; - return loc->value; + return loc->value.branchOffset; } }; @@ -105,6 +108,8 @@ } u; }; +class BytecodeGeneratorification; + class UnlinkedCodeBlock : public JSCell { public: typedef JSCell Base; @@ -114,12 +119,16 @@ enum { CallFunction, ApplyFunction }; + typedef UnlinkedInstruction Instruction; + typedef Vector UnpackedInstructions; + bool isConstructor() const { return m_isConstructor; } bool isStrictMode() const { return m_isStrictMode; } bool usesEval() const { return m_usesEval; } SourceParseMode parseMode() const { return m_parseMode; } bool isArrowFunction() const { return m_parseMode == SourceParseMode::ArrowFunctionMode; } DerivedContextType derivedContextType() const { return static_cast(m_derivedContextType); } + EvalContextType evalContextType() const { return static_cast(m_evalContextType); } bool isArrowFunctionContext() const { return m_isArrowFunctionContext; } bool isClassContext() const { return m_isClassContext; } @@ -202,10 +211,14 @@ unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } unsigned lastJumpTarget() const { return m_jumpTargets.last(); } + UnlinkedHandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler); + UnlinkedHandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler); + bool isBuiltinFunction() const { return m_isBuiltinFunction; } ConstructorKind constructorKind() const { return static_cast(m_constructorKind); } SuperBinding superBinding() const { return static_cast(m_superBinding); } + JSParserCommentMode commentMode() const { return static_cast(m_commentMode); } void shrinkToFit() { @@ -231,6 +244,8 @@ void setInstructions(std::unique_ptr); const UnlinkedInstructionStream& instructions() const; + int numCalleeLocals() const { return m_numCalleeLocals; } + int m_numVars; int m_numCapturedVars; int m_numCalleeLocals; @@ -269,8 +284,6 @@ void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); } UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; } - VM* vm() const; - UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; } unsigned numberOfArrayProfiles() { return m_arrayProfileCount; } UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; } @@ -324,7 +337,7 @@ int lineNumberForBytecodeOffset(unsigned bytecodeOffset); void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, - int& startOffset, int& endOffset, unsigned& line, unsigned& column); + int& startOffset, int& endOffset, unsigned& line, unsigned& column) const; bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot); @@ -338,6 +351,11 @@ m_endColumn = endColumn; } + const String& sourceURLDirective() const { return m_sourceURLDirective; } + const String& sourceMappingURLDirective() const { return m_sourceMappingURLDirective; } + void setSourceURLDirective(const String& sourceURL) { m_sourceURLDirective = sourceURL; } + void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL; } + CodeFeatures codeFeatures() const { return m_features; } bool hasCapturedVariables() const { return m_hasCapturedVariables; } unsigned firstLine() const { return m_firstLine; } @@ -362,8 +380,13 @@ void dumpExpressionRangeInfo(); // For debugging purpose only. + bool wasCompiledWithDebuggingOpcodes() const { return m_wasCompiledWithDebuggingOpcodes; } + + TriState didOptimize() const { return m_didOptimize; } + void setDidOptimize(TriState didOptimize) { m_didOptimize = didOptimize; } + protected: - UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&); + UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode); ~UnlinkedCodeBlock(); void finishCreation(VM& vm) @@ -372,6 +395,8 @@ } private: + friend class BytecodeRewriter; + void applyModification(BytecodeRewriter&); void createRareDataIfNecessary() { @@ -379,7 +404,7 @@ m_rareData = std::make_unique(); } - void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column); + void getLineAndColumn(const ExpressionRangeInfo&, unsigned& line, unsigned& column) const; int m_numParameters; @@ -389,20 +414,27 @@ VirtualRegister m_scopeRegister; VirtualRegister m_globalObjectRegister; + String m_sourceURLDirective; + String m_sourceMappingURLDirective; + unsigned m_usesEval : 1; unsigned m_isStrictMode : 1; unsigned m_isConstructor : 1; unsigned m_hasCapturedVariables : 1; unsigned m_isBuiltinFunction : 1; - unsigned m_constructorKind : 2; unsigned m_superBinding : 1; - unsigned m_derivedContextType : 2; + unsigned m_commentMode: 1; unsigned m_isArrowFunctionContext : 1; unsigned m_isClassContext : 1; + unsigned m_wasCompiledWithDebuggingOpcodes : 1; + unsigned m_constructorKind : 2; + unsigned m_derivedContextType : 2; + unsigned m_evalContextType : 2; unsigned m_firstLine; unsigned m_lineCount; unsigned m_endColumn; + TriState m_didOptimize; SourceParseMode m_parseMode; CodeFeatures m_features; CodeType m_codeType; @@ -469,8 +501,8 @@ typedef UnlinkedCodeBlock Base; protected: - UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) - : Base(vm, structure, codeType, info) + UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode) + : Base(vm, structure, codeType, info, debuggerMode) { } @@ -480,9 +512,9 @@ class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock { private: friend class CodeCache; - static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info) + static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode) { - UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info); + UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info, debuggerMode); instance->finishCreation(*vm); return instance; } @@ -502,8 +534,8 @@ static void visitChildren(JSCell*, SlotVisitor&); private: - UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) - : Base(vm, structure, GlobalCode, info) + UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode) + : Base(vm, structure, GlobalCode, info, debuggerMode) { } @@ -522,9 +554,9 @@ class UnlinkedModuleProgramCodeBlock final : public UnlinkedGlobalCodeBlock { private: friend class CodeCache; - static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo& info) + static UnlinkedModuleProgramCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode) { - UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedModuleProgramCodeBlock(vm, vm->unlinkedModuleProgramCodeBlockStructure.get(), info); + UnlinkedModuleProgramCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedModuleProgramCodeBlock(vm, vm->unlinkedModuleProgramCodeBlockStructure.get(), info, debuggerMode); instance->finishCreation(*vm); return instance; } @@ -568,8 +600,8 @@ } private: - UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) - : Base(vm, structure, ModuleCode, info) + UnlinkedModuleProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode) + : Base(vm, structure, ModuleCode, info, debuggerMode) { } @@ -588,9 +620,9 @@ private: friend class CodeCache; - static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info) + static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info, DebuggerMode debuggerMode) { - UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info); + UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info, debuggerMode); instance->finishCreation(*vm); return instance; } @@ -610,8 +642,8 @@ } private: - UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) - : Base(vm, structure, EvalCode, info) + UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info, DebuggerMode debuggerMode) + : Base(vm, structure, EvalCode, info, debuggerMode) { } @@ -631,9 +663,9 @@ typedef UnlinkedCodeBlock Base; static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info) + static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode) { - UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info); + UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info, debuggerMode); instance->finishCreation(*vm); return instance; } @@ -641,8 +673,8 @@ static void destroy(JSCell*); private: - UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) - : Base(vm, structure, codeType, info) + UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info, DebuggerMode debuggerMode) + : Base(vm, structure, codeType, info, debuggerMode) { } @@ -656,5 +688,3 @@ }; } - -#endif // UnlinkedCodeBlock_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013, 2015 Apple Inc. All Rights Reserved. + * Copyright (C) 2012-2013, 2015-2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,17 +29,14 @@ #include "BytecodeGenerator.h" #include "ClassInfo.h" #include "CodeCache.h" +#include "Debugger.h" #include "Executable.h" #include "ExecutableInfo.h" #include "FunctionOverrides.h" #include "JSCInlines.h" -#include "JSString.h" #include "Parser.h" #include "SourceProvider.h" #include "Structure.h" -#include "SymbolTable.h" -#include "UnlinkedInstructionStream.h" -#include namespace JSC { @@ -49,14 +46,15 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock( VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, - CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, + CodeSpecializationKind kind, DebuggerMode debuggerMode, UnlinkedFunctionKind functionKind, ParserError& error, SourceParseMode parseMode) { JSParserBuiltinMode builtinMode = executable->isBuiltinFunction() ? JSParserBuiltinMode::Builtin : JSParserBuiltinMode::NotBuiltin; JSParserStrictMode strictMode = executable->isInStrictContext() ? JSParserStrictMode::Strict : JSParserStrictMode::NotStrict; + JSParserCommentMode commentMode = executable->commentMode(); ASSERT(isFunctionParseMode(executable->parseMode())); std::unique_ptr function = parse( - &vm, source, executable->name(), builtinMode, strictMode, executable->parseMode(), executable->superBinding(), error, nullptr); + &vm, source, executable->name(), builtinMode, strictMode, commentMode, executable->parseMode(), executable->superBinding(), error, nullptr); if (!function) { ASSERT(error.isValid()); @@ -68,17 +66,16 @@ bool isClassContext = executable->superBinding() == SuperBinding::Needed; - UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, - ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext)); + UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), commentMode, executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext), debuggerMode); + + error = BytecodeGenerator::generate(vm, function.get(), result, debuggerMode, executable->parentScopeTDZVariables()); - auto generator(std::make_unique(vm, function.get(), result, debuggerMode, profilerMode, executable->parentScopeTDZVariables())); - error = generator->generate(); if (error.isValid()) return nullptr; return result; } -UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr&& sourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType) +UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr&& sourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserCommentMode commentMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType) : Base(*vm, structure) , m_firstLineOffset(node->firstLine() - source.firstLine()) , m_lineCount(node->lastLine() - node->firstLine()) @@ -97,15 +94,26 @@ , m_isBuiltinFunction(kind == UnlinkedBuiltinFunction) , m_constructAbility(static_cast(constructAbility)) , m_constructorKind(static_cast(node->constructorKind())) - , m_functionMode(node->functionMode()) + , m_functionMode(static_cast(node->functionMode())) + , m_commentMode(static_cast(commentMode)) , m_superBinding(static_cast(node->superBinding())) , m_derivedContextType(static_cast(derivedContextType)) , m_sourceParseMode(static_cast(node->parseMode())) , m_name(node->ident()) + , m_ecmaName(node->ecmaName()) , m_inferredName(node->inferredName()) , m_sourceOverride(WTFMove(sourceOverride)) + , m_classSource(node->classSource()) { + // Make sure these bitfields are adequately wide. + ASSERT(m_constructAbility == static_cast(constructAbility)); ASSERT(m_constructorKind == static_cast(node->constructorKind())); + ASSERT(m_functionMode == static_cast(node->functionMode())); + ASSERT(m_commentMode == static_cast(commentMode)); + ASSERT(m_superBinding == static_cast(node->superBinding())); + ASSERT(m_derivedContextType == static_cast(derivedContextType)); + ASSERT(m_sourceParseMode == static_cast(node->parseMode())); + m_parentScopeTDZVariables.swap(parentScopeTDZVariables); } @@ -116,10 +124,9 @@ Base::visitChildren(thisObject, visitor); visitor.append(&thisObject->m_unlinkedCodeBlockForCall); visitor.append(&thisObject->m_unlinkedCodeBlockForConstruct); - visitor.append(&thisObject->m_nameValue); } -FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, int overrideLineNumber) +FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& ownerSource, Optional overrideLineNumber, Intrinsic intrinsic) { SourceCode source = m_sourceOverride ? SourceCode(m_sourceOverride) : ownerSource; unsigned firstLine = source.firstLine() + m_firstLineOffset; @@ -138,7 +145,7 @@ if (UNLIKELY(Options::functionOverrides())) { hasFunctionOverride = FunctionOverrides::initializeOverrideFor(code, overrideInfo); - if (hasFunctionOverride) { + if (UNLIKELY(hasFunctionOverride)) { firstLine = overrideInfo.firstLine; lineCount = overrideInfo.lineCount; startColumn = overrideInfo.startColumn; @@ -147,9 +154,9 @@ } } - FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + lineCount, startColumn, endColumn); - if (overrideLineNumber != -1) - result->setOverrideLineNumber(overrideLineNumber); + FunctionExecutable* result = FunctionExecutable::create(vm, code, this, firstLine, firstLine + lineCount, startColumn, endColumn, intrinsic); + if (overrideLineNumber) + result->setOverrideLineNumber(*overrideLineNumber); if (UNLIKELY(hasFunctionOverride)) { result->overrideParameterAndTypeProfilingStartEndOffsets( @@ -184,7 +191,7 @@ UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::unlinkedCodeBlockFor( VM& vm, const SourceCode& source, CodeSpecializationKind specializationKind, - DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error, SourceParseMode parseMode) + DebuggerMode debuggerMode, ParserError& error, SourceParseMode parseMode) { switch (specializationKind) { case CodeForCall: @@ -198,7 +205,7 @@ } UnlinkedFunctionCodeBlock* result = generateUnlinkedFunctionCodeBlock( - vm, this, source, specializationKind, debuggerMode, profilerMode, + vm, this, source, specializationKind, debuggerMode, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, error, parseMode); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All Rights Reserved. + * Copyright (C) 2012-2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef UnlinkedFunctionExecutable_h -#define UnlinkedFunctionExecutable_h +#pragma once #include "BytecodeConventions.h" #include "CodeSpecializationKind.h" @@ -34,6 +33,7 @@ #include "ExpressionRangeInfo.h" #include "HandlerInfo.h" #include "Identifier.h" +#include "Intrinsic.h" #include "JSCell.h" #include "JSString.h" #include "ParserModes.h" @@ -41,8 +41,6 @@ #include "SpecialPointer.h" #include "VariableEnvironment.h" #include "VirtualRegister.h" -#include -#include namespace JSC { @@ -66,20 +64,24 @@ typedef JSCell Base; static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; - static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, RefPtr&& sourceOverride = nullptr) + static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserCommentMode commentMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, RefPtr&& sourceOverride = nullptr) { UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell(vm->heap)) - UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTFMove(sourceOverride), node, unlinkedFunctionKind, constructAbility, parentScopeTDZVariables, derivedContextType); + UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTFMove(sourceOverride), node, unlinkedFunctionKind, constructAbility, commentMode, parentScopeTDZVariables, derivedContextType); instance->finishCreation(*vm); return instance; } const Identifier& name() const { return m_name; } + const Identifier& ecmaName() const { return m_ecmaName; } + void setEcmaName(const Identifier& name) { m_ecmaName = name; } const Identifier& inferredName() const { return m_inferredName; } - JSString* nameValue() const { return m_nameValue.get(); } - void setNameValue(VM& vm, JSString* nameValue) { m_nameValue.set(vm, this, nameValue); } unsigned parameterCount() const { return m_parameterCount; }; SourceParseMode parseMode() const { return static_cast(m_sourceParseMode); }; + + const SourceCode& classSource() const { return m_classSource; }; + void setClassSource(const SourceCode& source) { m_classSource = source; }; + bool isInStrictContext() const { return m_isInStrictContext; } FunctionMode functionMode() const { return static_cast(m_functionMode); } ConstructorKind constructorKind() const { return static_cast(m_constructorKind); } @@ -96,14 +98,14 @@ void setInvalidTypeProfilingOffsets(); UnlinkedFunctionCodeBlock* unlinkedCodeBlockFor( - VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, + VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ParserError&, SourceParseMode); static UnlinkedFunctionExecutable* fromGlobalCode( const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, int overrideLineNumber); - JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode&, int overrideLineNumber = -1); + JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode&, Optional overrideLineNumber = Nullopt, Intrinsic = NoIntrinsic); void clearCode() { @@ -125,15 +127,21 @@ bool isBuiltinFunction() const { return m_isBuiltinFunction; } ConstructAbility constructAbility() const { return static_cast(m_constructAbility); } + JSParserCommentMode commentMode() const { return static_cast(m_commentMode); } bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; } const VariableEnvironment* parentScopeTDZVariables() const { return &m_parentScopeTDZVariables; } bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; } JSC::DerivedContextType derivedContextType() const {return static_cast(m_derivedContextType); } - + + const String& sourceURLDirective() const { return m_sourceURLDirective; } + const String& sourceMappingURLDirective() const { return m_sourceMappingURLDirective; } + void setSourceURLDirective(const String& sourceURL) { m_sourceURLDirective = sourceURL; } + void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL; } + private: - UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, VariableEnvironment&, JSC::DerivedContextType); + UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserCommentMode, VariableEnvironment&, JSC::DerivedContextType); unsigned m_firstLineOffset; unsigned m_lineCount; @@ -152,7 +160,8 @@ unsigned m_isBuiltinFunction : 1; unsigned m_constructAbility: 1; unsigned m_constructorKind : 2; - unsigned m_functionMode : 1; // FunctionMode + unsigned m_functionMode : 2; // FunctionMode + unsigned m_commentMode: 1; // JSParserCommentMode unsigned m_superBinding : 1; unsigned m_derivedContextType: 2; unsigned m_sourceParseMode : 4; // SourceParseMode @@ -161,19 +170,17 @@ WriteBarrier m_unlinkedCodeBlockForConstruct; Identifier m_name; + Identifier m_ecmaName; Identifier m_inferredName; - WriteBarrier m_nameValue; RefPtr m_sourceOverride; + SourceCode m_classSource; + + String m_sourceURLDirective; + String m_sourceMappingURLDirective; VariableEnvironment m_parentScopeTDZVariables; protected: - void finishCreation(VM& vm) - { - Base::finishCreation(vm); - m_nameValue.set(vm, this, jsString(&vm, name().string())); - } - static void visitChildren(JSCell*, SlotVisitor&); public: @@ -186,5 +193,3 @@ }; } // namespace JSC - -#endif // UnlinkedFunctionExecutable_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -26,6 +26,8 @@ #include "config.h" #include "UnlinkedInstructionStream.h" +#include "Opcode.h" + namespace JSC { static void append8(unsigned char*& ptr, unsigned char value) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/UnlinkedInstructionStream.h 2016-11-03 07:04:20.000000000 +0000 @@ -27,6 +27,7 @@ #ifndef UnlinkedInstructionStream_h #define UnlinkedInstructionStream_h +#include "Opcode.h" #include "UnlinkedCodeBlock.h" #include diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ValueProfile.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ValueProfile.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ValueProfile.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ValueProfile.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ValueProfile.h" - -namespace WTF { - -using namespace JSC; - -void printInternal(PrintStream& out, const ResultProfile& profile) -{ - const char* separator = ""; - - if (!profile.didObserveNonInt32()) { - out.print("Int32"); - separator = "|"; - } else { - if (profile.didObserveNegZeroDouble()) { - out.print(separator, "NegZeroDouble"); - separator = "|"; - } - if (profile.didObserveNonNegZeroDouble()) { - out.print("NonNegZeroDouble"); - separator = "|"; - } - if (profile.didObserveNonNumber()) { - out.print("NonNumber"); - separator = "|"; - } - if (profile.didObserveInt32Overflow()) { - out.print("Int32Overflow"); - separator = "|"; - } - if (profile.didObserveInt52Overflow()) { - out.print("Int52Overflow"); - separator = "|"; - } - } - if (profile.specialFastPathCount()) { - out.print(" special fast path: "); - out.print(profile.specialFastPathCount()); - } -} - -} // namespace WTF diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ValueProfile.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ValueProfile.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ValueProfile.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ValueProfile.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2011-2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,12 +34,15 @@ #include "JSArray.h" #include "SpeculatedType.h" #include "Structure.h" +#include "TagRegistersMode.h" #include "WriteBarrier.h" #include #include namespace JSC { +class CCallHelpers; + template struct ValueProfileBase { static const unsigned numberOfBuckets = numberOfBucketsArgument; @@ -206,65 +209,6 @@ return rareCaseProfile->m_bytecodeOffset; } -struct ResultProfile { -private: - static const int numberOfFlagBits = 5; - -public: - ResultProfile(int bytecodeOffset) - : m_bytecodeOffsetAndFlags(bytecodeOffset << numberOfFlagBits) - { - ASSERT(((bytecodeOffset << numberOfFlagBits) >> numberOfFlagBits) == bytecodeOffset); - } - - enum ObservedResults { - NonNegZeroDouble = 1 << 0, - NegZeroDouble = 1 << 1, - NonNumber = 1 << 2, - Int32Overflow = 1 << 3, - Int52Overflow = 1 << 4, - }; - - int bytecodeOffset() const { return m_bytecodeOffsetAndFlags >> numberOfFlagBits; } - unsigned specialFastPathCount() const { return m_specialFastPathCount; } - - bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumber); } - bool didObserveDouble() const { return hasBits(NonNegZeroDouble | NegZeroDouble); } - bool didObserveNonNegZeroDouble() const { return hasBits(NonNegZeroDouble); } - bool didObserveNegZeroDouble() const { return hasBits(NegZeroDouble); } - bool didObserveNonNumber() const { return hasBits(NonNumber); } - bool didObserveInt32Overflow() const { return hasBits(Int32Overflow); } - bool didObserveInt52Overflow() const { return hasBits(Int52Overflow); } - - void setObservedNonNegZeroDouble() { setBit(NonNegZeroDouble); } - void setObservedNegZeroDouble() { setBit(NegZeroDouble); } - void setObservedNonNumber() { setBit(NonNumber); } - void setObservedInt32Overflow() { setBit(Int32Overflow); } - void setObservedInt52Overflow() { setBit(Int52Overflow); } - - void* addressOfFlags() { return &m_bytecodeOffsetAndFlags; } - void* addressOfSpecialFastPathCount() { return &m_specialFastPathCount; } - -private: - bool hasBits(int mask) const { return m_bytecodeOffsetAndFlags & mask; } - void setBit(int mask) { m_bytecodeOffsetAndFlags |= mask; } - - int m_bytecodeOffsetAndFlags; - unsigned m_specialFastPathCount { 0 }; -}; - -inline int getResultProfileBytecodeOffset(ResultProfile* profile) -{ - return profile->bytecodeOffset(); -} - } // namespace JSC -namespace WTF { - -void printInternal(PrintStream&, const JSC::ResultProfile&); - -} // namespace WTF - #endif // ValueProfile_h - diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ValueRecovery.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ValueRecovery.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/ValueRecovery.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/ValueRecovery.h 2016-11-03 07:04:20.000000000 +0000 @@ -197,7 +197,7 @@ return result; } - static ValueRecovery outOfBandArgumentsThatWereNotCreated(DFG::MinifiedID id) + static ValueRecovery clonedArgumentsThatWereNotCreated(DFG::MinifiedID id) { ValueRecovery result; result.m_technique = ClonedArgumentsThatWereNotCreated; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -35,9 +35,9 @@ out.print("Write to ", m_name, " in ", JSValue(m_object)); } -void VariableWriteFireDetail::touch(WatchpointSet* set, JSObject* object, const PropertyName& name) +void VariableWriteFireDetail::touch(VM& vm, WatchpointSet* set, JSObject* object, const PropertyName& name) { - set->touch(VariableWriteFireDetail(object, name)); + set->touch(vm, VariableWriteFireDetail(object, name)); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/VariableWriteFireDetail.h 2016-11-03 07:04:20.000000000 +0000 @@ -41,9 +41,9 @@ { } - virtual void dump(PrintStream&) const override; + JS_EXPORT_PRIVATE void dump(PrintStream&) const override; - JS_EXPORT_PRIVATE static void touch(WatchpointSet*, JSObject*, const PropertyName&); + JS_EXPORT_PRIVATE static void touch(VM&, WatchpointSet*, JSObject*, const PropertyName&); private: JSObject* m_object; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/VirtualRegister.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/VirtualRegister.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/VirtualRegister.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/VirtualRegister.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,8 +26,8 @@ #ifndef VirtualRegister_h #define VirtualRegister_h +#include "BytecodeConventions.h" #include "CallFrame.h" - #include namespace JSC { @@ -59,7 +59,7 @@ bool isValid() const { return (m_virtualRegister != s_invalidVirtualRegister); } bool isLocal() const { return operandIsLocal(m_virtualRegister); } bool isArgument() const { return operandIsArgument(m_virtualRegister); } - bool isHeader() const { return m_virtualRegister >= 0 && m_virtualRegister < JSStack::ThisArgument; } + bool isHeader() const { return m_virtualRegister >= 0 && m_virtualRegister < CallFrameSlot::thisArgument; } bool isConstant() const { return m_virtualRegister >= s_firstConstantRegisterIndex; } int toLocal() const { ASSERT(isLocal()); return operandToLocal(m_virtualRegister); } int toArgument() const { ASSERT(isArgument()); return operandToArgument(m_virtualRegister); } @@ -103,7 +103,7 @@ private: static const int s_invalidVirtualRegister = 0x3fffffff; - static const int s_firstConstantRegisterIndex = 0x40000000; + static const int s_firstConstantRegisterIndex = FirstConstantRegisterIndex; static int localToOperand(int local) { return -1 - local; } static int operandToLocal(int operand) { return -1 - operand; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Watchpoint.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Watchpoint.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Watchpoint.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Watchpoint.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -26,8 +26,9 @@ #include "config.h" #include "Watchpoint.h" +#include "HeapInlines.h" +#include "VM.h" #include -#include namespace JSC { @@ -81,26 +82,33 @@ m_state = IsWatched; } -void WatchpointSet::fireAllSlow(const FireDetail& detail) +void WatchpointSet::fireAllSlow(VM& vm, const FireDetail& detail) { ASSERT(state() == IsWatched); WTF::storeStoreFence(); m_state = IsInvalidated; // Do this first. Needed for adaptive watchpoints. - fireAllWatchpoints(detail); + fireAllWatchpoints(vm, detail); WTF::storeStoreFence(); } -void WatchpointSet::fireAllSlow(const char* reason) +void WatchpointSet::fireAllSlow(VM& vm, const char* reason) { - fireAllSlow(StringFireDetail(reason)); + fireAllSlow(vm, StringFireDetail(reason)); } -void WatchpointSet::fireAllWatchpoints(const FireDetail& detail) +void WatchpointSet::fireAllWatchpoints(VM& vm, const FireDetail& detail) { // In case there are any adaptive watchpoints, we need to make sure that they see that this // watchpoint has been already invalidated. RELEASE_ASSERT(hasBeenInvalidated()); + + // Firing a watchpoint may cause a GC to happen. This GC could destroy various + // Watchpoints themselves while they're in the process of firing. It's not safe + // for most Watchpoints to be destructed while they're in the middle of firing. + // This GC could also destroy us, and we're not in a safe state to be destroyed. + // The safest thing to do is to DeferGCForAWhile to prevent this GC from happening. + DeferGCForAWhile deferGC(vm.heap); while (!m_set.isEmpty()) { Watchpoint* watchpoint = m_set.begin(); @@ -130,9 +138,9 @@ inflate()->add(watchpoint); } -void InlineWatchpointSet::fireAll(const char* reason) +void InlineWatchpointSet::fireAll(VM& vm, const char* reason) { - fireAll(StringFireDetail(reason)); + fireAll(vm, StringFireDetail(reason)); } WatchpointSet* InlineWatchpointSet::inflateSlow() diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Watchpoint.h webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Watchpoint.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecode/Watchpoint.h 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecode/Watchpoint.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,7 +57,7 @@ { } - virtual void dump(PrintStream& out) const override; + void dump(PrintStream& out) const override; private: const char* m_string; @@ -90,11 +90,15 @@ }; class InlineWatchpointSet; +class VM; class WatchpointSet : public ThreadSafeRefCounted { friend class LLIntOffsetsExtractor; public: JS_EXPORT_PRIVATE WatchpointSet(WatchpointState); + + // FIXME: In many cases, it would be amazing if this *did* fire the watchpoints. I suspect that + // this might be hard to get right, but still, it might be awesome. JS_EXPORT_PRIVATE ~WatchpointSet(); // Note that this will not fire any of the watchpoints; if you need to know when a WatchpointSet dies then you need a separate mechanism for this. // Fast way of getting the state, which only works from the main thread. @@ -149,43 +153,43 @@ WTF::storeStoreFence(); } - void fireAll(const FireDetail& detail) + void fireAll(VM& vm, const FireDetail& detail) { if (LIKELY(m_state != IsWatched)) return; - fireAllSlow(detail); + fireAllSlow(vm, detail); } - void fireAll(const char* reason) + void fireAll(VM& vm, const char* reason) { if (LIKELY(m_state != IsWatched)) return; - fireAllSlow(reason); + fireAllSlow(vm, reason); } - void touch(const FireDetail& detail) + void touch(VM& vm, const FireDetail& detail) { if (state() == ClearWatchpoint) startWatching(); else - fireAll(detail); + fireAll(vm, detail); } - void touch(const char* reason) + void touch(VM& vm, const char* reason) { - touch(StringFireDetail(reason)); + touch(vm, StringFireDetail(reason)); } - void invalidate(const FireDetail& detail) + void invalidate(VM& vm, const FireDetail& detail) { if (state() == IsWatched) - fireAll(detail); + fireAll(vm, detail); m_state = IsInvalidated; } - void invalidate(const char* reason) + void invalidate(VM& vm, const char* reason) { - invalidate(StringFireDetail(reason)); + invalidate(vm, StringFireDetail(reason)); } bool isBeingWatched() const @@ -197,11 +201,11 @@ static ptrdiff_t offsetOfState() { return OBJECT_OFFSETOF(WatchpointSet, m_state); } int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; } - JS_EXPORT_PRIVATE void fireAllSlow(const FireDetail&); // Call only if you've checked isWatched. - JS_EXPORT_PRIVATE void fireAllSlow(const char* reason); // Ditto. + JS_EXPORT_PRIVATE void fireAllSlow(VM&, const FireDetail&); // Call only if you've checked isWatched. + JS_EXPORT_PRIVATE void fireAllSlow(VM&, const char* reason); // Ditto. private: - void fireAllWatchpoints(const FireDetail&); + void fireAllWatchpoints(VM&, const FireDetail&); friend class InlineWatchpointSet; @@ -293,10 +297,10 @@ m_data = encodeState(IsWatched); } - void fireAll(const FireDetail& detail) + void fireAll(VM& vm, const FireDetail& detail) { if (isFat()) { - fat()->fireAll(detail); + fat()->fireAll(vm, detail); return; } if (decodeState(m_data) == ClearWatchpoint) @@ -305,20 +309,20 @@ WTF::storeStoreFence(); } - void invalidate(const FireDetail& detail) + void invalidate(VM& vm, const FireDetail& detail) { if (isFat()) - fat()->invalidate(detail); + fat()->invalidate(vm, detail); else m_data = encodeState(IsInvalidated); } - JS_EXPORT_PRIVATE void fireAll(const char* reason); + JS_EXPORT_PRIVATE void fireAll(VM&, const char* reason); - void touch(const FireDetail& detail) + void touch(VM& vm, const FireDetail& detail) { if (isFat()) { - fat()->touch(detail); + fat()->touch(vm, detail); return; } uintptr_t data = m_data; @@ -332,9 +336,9 @@ WTF::storeStoreFence(); } - void touch(const char* reason) + void touch(VM& vm, const char* reason) { - touch(StringFireDetail(reason)); + touch(vm, StringFireDetail(reason)); } // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp 2016-05-23 10:03:35.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008-2009, 2012-2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * Copyright (C) 2012 Igalia, S.L. * @@ -31,7 +31,9 @@ #include "config.h" #include "BytecodeGenerator.h" +#include "ArithProfile.h" #include "BuiltinExecutables.h" +#include "BytecodeGeneratorification.h" #include "BytecodeLivenessAnalysis.h" #include "Interpreter.h" #include "JSFunction.h" @@ -45,6 +47,8 @@ #include "StrongInlines.h" #include "UnlinkedCodeBlock.h" #include "UnlinkedInstructionStream.h" +#include +#include #include #include @@ -61,11 +65,23 @@ m_generator.instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; } -ParserError BytecodeGenerator::generate() +void Variable::dump(PrintStream& out) const { - SamplingRegion samplingRegion("Bytecode Generation"); + out.print( + "{ident = ", m_ident, + ", offset = ", m_offset, + ", local = ", RawPointer(m_local), + ", attributes = ", m_attributes, + ", kind = ", m_kind, + ", symbolTableConstantIndex = ", m_symbolTableConstantIndex, + ", isLexicallyScoped = ", m_isLexicallyScoped, "}"); +} +ParserError BytecodeGenerator::generate() +{ m_codeBlock->setThisRegister(m_thisRegister.virtualRegister()); + + emitLogShadowChickenPrologueIfNecessary(); // If we have declared a variable named "arguments" and we are using arguments then we should // perform that assignment now. @@ -92,7 +108,7 @@ globalScope = newBlockScopeVariable(); emitMove(globalScope.get(), globalObjectScope.get()); } - emitPutToScope(globalScope.get(), Variable(metadata->ident()), temp.get(), ThrowIfNotFound, NotInitialization); + emitPutToScope(globalScope.get(), Variable(metadata->ident()), temp.get(), ThrowIfNotFound, InitializationMode::NotInitialization); } else RELEASE_ASSERT_NOT_REACHED(); } @@ -140,6 +156,10 @@ m_codeBlock->addExceptionHandler(info); } + + if (m_codeBlock->parseMode() == SourceParseMode::GeneratorBodyMode) + performGeneratorification(m_codeBlock.get(), m_instructions, m_generatorFrameSymbolTable.get(), m_generatorFrameSymbolTableIndex); + m_codeBlock->setInstructions(std::make_unique(m_instructions)); m_codeBlock->shrinkToFit(); @@ -149,9 +169,8 @@ return ParserError(ParserError::ErrorNone); } -BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables) +BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, const VariableEnvironment* parentScopeTDZVariables) : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn) - , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn) , m_scopeNode(programNode) , m_codeBlock(vm, codeBlock) , m_thisRegister(CallFrame::thisArgumentOffset()) @@ -195,9 +214,8 @@ } } -BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables) +BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, const VariableEnvironment* parentScopeTDZVariables) : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn) - , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn) , m_scopeNode(functionNode) , m_codeBlock(vm, codeBlock) , m_codeType(FunctionCode) @@ -209,7 +227,7 @@ // op_will_call / op_did_call pairs before and after a call, which are not // compatible with tail calls (we have no way of emitting op_did_call). // https://bugs.webkit.org/show_bug.cgi?id=148819 - , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode() && !m_shouldEmitProfileHooks) + , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode()) , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval()) , m_derivedContextType(codeBlock->derivedContextType()) { @@ -223,32 +241,40 @@ SymbolTable* functionSymbolTable = SymbolTable::create(*m_vm); functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval); - int symbolTableConstantIndex = addConstantValue(functionSymbolTable)->index(); + int symbolTableConstantIndex = 0; - Vector boundParameterProperties; FunctionParameters& parameters = *functionNode->parameters(); - if (!parameters.hasDefaultParameterValues()) { - // If we do have default parameters, they will be allocated in a separate scope. - for (size_t i = 0; i < parameters.size(); i++) { - auto pattern = parameters.at(i).first; - if (pattern->isBindingNode()) - continue; - pattern->collectBoundIdentifiers(boundParameterProperties); - } + // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation + // This implements IsSimpleParameterList in the Ecma 2015 spec. + // If IsSimpleParameterList is false, we will create a strict-mode like arguments object. + // IsSimpleParameterList is false if the argument list contains any default parameter values, + // a rest parameter, or any destructuring patterns. + bool isSimpleParameterList = true; + // If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope. + for (size_t i = 0; i < parameters.size(); i++) { + std::pair parameter = parameters.at(i); + bool hasDefaultParameterValue = !!parameter.second; + auto pattern = parameter.first; + bool isSimpleParameter = !hasDefaultParameterValue && pattern->isBindingNode(); + isSimpleParameterList &= isSimpleParameter; } SourceParseMode parseMode = codeBlock->parseMode(); - bool containsArrowOrEvalButNotInArrowBlock = needsToUpdateArrowFunctionContext() && !m_codeBlock->isArrowFunction(); + bool containsArrowOrEvalButNotInArrowBlock = ((functionNode->usesArrowFunction() && functionNode->doAnyInnerArrowFunctionsUseAnyFeature()) || functionNode->usesEval()) && !m_codeBlock->isArrowFunction(); bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || functionNode->needsActivation() || containsArrowOrEvalButNotInArrowBlock; bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval(); - bool needsArguments = (functionNode->usesArguments() || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction())); + bool needsArguments = (functionNode->usesArguments() || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction())); - // Generator never provides "arguments". "arguments" reference will be resolved in an upper generator function scope. - if (parseMode == SourceParseMode::GeneratorBodyMode) + if (parseMode == SourceParseMode::GeneratorBodyMode) { + // Generator never provides "arguments". "arguments" reference will be resolved in an upper generator function scope. needsArguments = false; + // Generator uses the var scope to save and resume its variables. So the lexical scope is always instantiated. + shouldCaptureSomeOfTheThings = true; + } + if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode && needsArguments) { // Generator does not provide "arguments". Instead, wrapping GeneratorFunction provides "arguments". // This is because arguments of a generator should be evaluated before starting it. @@ -257,7 +283,7 @@ // function *gen(a, b = hello()) // { // return { - // @generatorNext: function (@generator, @generatorState, @generatorValue, @generatorResumeMode) + // @generatorNext: function (@generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrame) // { // arguments; // This `arguments` should reference to the gen's arguments. // ... @@ -286,27 +312,17 @@ return captures(uid) ? VarKind::Scope : VarKind::Stack; }; - emitEnter(); - - allocateAndEmitScope(); - - m_calleeRegister.setIndex(JSStack::Callee); + m_calleeRegister.setIndex(CallFrameSlot::callee); initializeParameters(parameters); + ASSERT(!(isSimpleParameterList && m_restParameter)); - // Before emitting a scope creation, emit a generator prologue that contains jump based on a generator's state. - if (parseMode == SourceParseMode::GeneratorBodyMode) { - m_generatorRegister = &m_parameters[1]; - - // Jump with switch_imm based on @generatorState. We don't take the coroutine styled generator implementation. - // When calling `next()`, we would like to enter the same prologue instead of jumping based on the saved instruction pointer. - // It's suitale for inlining, because it just inlines one `next` function implementation. + emitEnter(); - beginGenerator(generatorStateRegister()); + if (parseMode == SourceParseMode::GeneratorBodyMode) + m_generatorRegister = &m_parameters[1]; - // Initial state. - emitGeneratorStateLabel(); - } + allocateAndEmitScope(); if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())) { ASSERT(parseMode != SourceParseMode::GeneratorBodyMode); @@ -316,14 +332,17 @@ emitPushFunctionNameScope(functionNode->ident(), &m_calleeRegister, markAsCaptured); } - if (shouldCaptureSomeOfTheThings) { + if (shouldCaptureSomeOfTheThings) m_lexicalEnvironmentRegister = addVar(); - // We can allocate the "var" environment if we don't have default parameter expressions. If we have - // default parameter expressions, we have to hold off on allocating the "var" environment because - // the parent scope of the "var" environment is the parameter environment. - if (!parameters.hasDefaultParameterValues()) - initializeVarLexicalEnvironment(symbolTableConstantIndex); - } + + if (shouldCaptureSomeOfTheThings || vm.typeProfiler()) + symbolTableConstantIndex = addConstantValue(functionSymbolTable)->index(); + + // We can allocate the "var" environment if we don't have default parameter expressions. If we have + // default parameter expressions, we have to hold off on allocating the "var" environment because + // the parent scope of the "var" environment is the parameter environment. + if (isSimpleParameterList) + initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, shouldCaptureSomeOfTheThings); // Figure out some interesting facts about our arguments. bool capturesAnyArgumentByName = false; @@ -357,13 +376,6 @@ m_argumentsRegister->ref(); } - // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation - // This implements IsSimpleParameterList in the Ecma 2015 spec. - // If IsSimpleParameterList is false, we will create a strict-mode like arguments object. - // IsSimpleParameterList is false if the argument list contains any default parameter values, - // a rest parameter, or any destructuring patterns. - // FIXME: Take into account destructuring to make isSimpleParameterList false. https://bugs.webkit.org/show_bug.cgi?id=151450 - bool isSimpleParameterList = !parameters.hasDefaultParameterValues() && !m_restParameter; if (needsArguments && !codeBlock->isStrictMode() && isSimpleParameterList) { // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we // use DirectArguments. With ScopedArguments, we lift all of our arguments into the @@ -377,7 +389,7 @@ // in the symbol table - or it just gets space reserved in the symbol table. Either // way we lift the value into the scope. for (unsigned i = 0; i < parameters.size(); ++i) { - ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(); + ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary); functionSymbolTable->setArgumentOffset(vm, i, offset); if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) { VarOffset varOffset(offset); @@ -386,14 +398,14 @@ // notifyWrite(), since that would be cumbersome. Also, watching formal // parameters when "arguments" is in play is unlikely to be super profitable. // So, we just disable it. - entry.disableWatching(); - functionSymbolTable->set(name, entry); + entry.disableWatching(*m_vm); + functionSymbolTable->set(NoLockingNecessary, name, entry); } emitOpcode(op_put_to_scope); instructions().append(m_lexicalEnvironmentRegister->index()); instructions().append(UINT_MAX); instructions().append(virtualRegisterForArgument(1 + i).offset()); - instructions().append(GetPutInfo(ThrowIfNotFound, LocalClosureVar, NotInitialization).operand()); + instructions().append(GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand()); instructions().append(symbolTableConstantIndex); instructions().append(offset.offset()); } @@ -408,15 +420,15 @@ // that the symbol table knows that this is happening. for (unsigned i = 0; i < parameters.size(); ++i) { if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) - functionSymbolTable->set(name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i)))); + functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i)))); } emitOpcode(op_create_direct_arguments); instructions().append(m_argumentsRegister->index()); } - } else if (!parameters.hasDefaultParameterValues()) { + } else if (isSimpleParameterList) { // Create the formal parameters the normal way. Any of them could be captured, or not. If - // captured, lift them into the scope. We can not do this if we have default parameter expressions + // captured, lift them into the scope. We cannot do this if we have default parameter expressions // because when default parameter expressions exist, they belong in their own lexical environment // separate from the "var" lexical environment. for (unsigned i = 0; i < parameters.size(); ++i) { @@ -427,49 +439,31 @@ if (!captures(name)) { // This is the easy case - just tell the symbol table about the argument. It will // be accessed directly. - functionSymbolTable->set(name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i)))); + functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i)))); continue; } - ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(); + ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary); const Identifier& ident = static_cast(parameters.at(i).first)->boundProperty(); - functionSymbolTable->set(name, SymbolTableEntry(VarOffset(offset))); + functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(offset))); emitOpcode(op_put_to_scope); instructions().append(m_lexicalEnvironmentRegister->index()); instructions().append(addConstant(ident)); instructions().append(virtualRegisterForArgument(1 + i).offset()); - instructions().append(GetPutInfo(ThrowIfNotFound, LocalClosureVar, NotInitialization).operand()); + instructions().append(GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand()); instructions().append(symbolTableConstantIndex); instructions().append(offset.offset()); } } if (needsArguments && (codeBlock->isStrictMode() || !isSimpleParameterList)) { - // Allocate an out-of-bands arguments object. - emitOpcode(op_create_out_of_band_arguments); + // Allocate a cloned arguments object. + emitOpcode(op_create_cloned_arguments); instructions().append(m_argumentsRegister->index()); } - // Now declare all variables. - for (const Identifier& ident : boundParameterProperties) { - ASSERT(!parameters.hasDefaultParameterValues()); - createVariable(ident, varKind(ident.impl()), functionSymbolTable); - } - for (FunctionMetadataNode* function : functionNode->functionStack()) { - const Identifier& ident = function->ident(); - createVariable(ident, varKind(ident.impl()), functionSymbolTable); - m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable)); - } - for (auto& entry : functionNode->varDeclarations()) { - ASSERT(!entry.value.isLet() && !entry.value.isConst()); - if (!entry.value.isVar()) // This is either a parameter or callee. - continue; - // Variables named "arguments" are never const. - createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting); - } - // There are some variables that need to be preinitialized to something other than Undefined: // // - "arguments": unless it's used as a function or parameter, this should refer to the @@ -491,6 +485,7 @@ // This is our final act of weirdness. "arguments" is overridden by everything except the // callee. We add it to the symbol table if it's not already there and it's not an argument. + bool shouldCreateArgumentsVariableInParameterScope = false; if (needsArguments) { // If "arguments" is overridden by a function or destructuring parameter name, then it's // OK for us to call createVariable() because it won't change anything. It's also OK for @@ -509,8 +504,10 @@ } } + bool shouldCreateArgumensVariable = !haveParameterNamedArguments && !m_codeBlock->isArrowFunction(); + shouldCreateArgumentsVariableInParameterScope = shouldCreateArgumensVariable && !isSimpleParameterList; // Do not create arguments variable in case of Arrow function. Value will be loaded from parent scope - if (!haveParameterNamedArguments && !m_codeBlock->isArrowFunction()) { + if (shouldCreateArgumensVariable && !shouldCreateArgumentsVariableInParameterScope) { createVariable( propertyNames().arguments, varKind(propertyNames().arguments.impl()), functionSymbolTable); @@ -518,6 +515,21 @@ } } + for (FunctionMetadataNode* function : functionNode->functionStack()) { + const Identifier& ident = function->ident(); + createVariable(ident, varKind(ident.impl()), functionSymbolTable); + m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable)); + } + for (auto& entry : functionNode->varDeclarations()) { + ASSERT(!entry.value.isLet() && !entry.value.isConst()); + if (!entry.value.isVar()) // This is either a parameter or callee. + continue; + if (shouldCreateArgumentsVariableInParameterScope && entry.key.get() == propertyNames().arguments.impl()) + continue; + createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting); + } + + m_newTargetRegister = addVar(); switch (parseMode) { case SourceParseMode::GeneratorWrapperFunctionMode: { @@ -546,48 +558,103 @@ if (SourceParseMode::ArrowFunctionMode != parseMode) { if (isConstructor()) { emitMove(m_newTargetRegister, &m_thisRegister); - if (constructorKind() == ConstructorKind::Derived) + if (constructorKind() == ConstructorKind::Extends) { + RefPtr @@ -122,8 +214,7 @@ oso rexw 05 - rAX Iz - sext + rAX sIz aso rexr rexx rexb @@ -132,43 +223,39 @@ aso rexr rexx rexb - 82 /reg=0 + 82 /reg=0 /m=!64 Eb Ib inv64 aso oso rexw rexr rexx rexb 81 /reg=0 - Ev Iz - sext + Ev sIz aso oso rexw rexr rexx rexb 83 /reg=0 - Ev Ib - sext + Ev sIb - - addpd - aso rexr rexx rexb - sse66 0f 58 - V W + aso rexr rexx rexb vexl + /sse=66 0f 58 + V H W + sse2 avx addps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 58 - V W + V H W + sse avx @@ -176,8 +263,9 @@ addsd aso rexr rexx rexb - ssef2 0f 58 - V W + /sse=f2 0f 58 + V H W + sse2 avx @@ -185,12 +273,94 @@ addss aso rexr rexx rexb - ssef3 0f 58 + /sse=f3 0f 58 + V H W + sse avx + + + + + addsubpd + + aso rexr rexx rexb + /sse=66 0f d0 + V H W + sse3 avx + + + + + addsubps + + aso rexr rexx rexb + /sse=f2 0f d0 + V H W + sse3 avx + + + + + aesdec + + aso rexr rexx rexb + /sse=66 0f 38 de + V H W + aesni avx + + + + + aesdeclast + + aso rexr rexx rexb + /sse=66 0f 38 df V W + aesni avx - + + aesenc + aesni + + aso rexr rexx rexb + /sse=66 0f 38 dc + V W + aesni avx + + + + + aesenclast + aesni avx + + aso rexr rexx rexb + /sse=66 0f 38 dd + V H W + + + + + aesimc + + aso rexr rexx rexb + /sse=66 0f 38 db + V W + aesni avx + + + + + aeskeygenassist + + aso rexr rexx rexb + /sse=66 0f 3a df + V W Ib + aesni avx + + + + and aso rexr rexx rexb @@ -219,8 +389,7 @@ oso rexw 25 - rAX Iz - sext + rAX sIz aso rexw rexr rexx rexb @@ -229,30 +398,29 @@ aso rexr rexx rexb - 82 /reg=4 + 82 /reg=4 /m=!64 Eb Ib inv64 aso oso rexw rexr rexx rexb 81 /reg=4 - Ev Iz - sext + Ev sIz aso oso rexw rexr rexx rexb 83 /reg=4 - Ev Ib - sext + Ev sIb andpd - aso rexr rexx rexb - sse66 0f 54 - V W + aso rexr rexx rexb vexl + /sse=66 0f 54 + V H W + sse2 avx @@ -261,7 +429,8 @@ aso rexr rexx rexb 0f 54 - V W + V H W + sse avx @@ -269,8 +438,9 @@ andnpd aso rexr rexx rexb - sse66 0f 55 - V W + /sse=66 0f 55 + V H W + sse2 avx @@ -279,7 +449,8 @@ aso rexr rexx rexb 0f 55 - V W + V H W + sse2 avx @@ -287,15 +458,8 @@ arpl aso - 63 /m=16 - Ew Gw - inv64 - - - aso - 63 /m=32 + 63 /m=!64 Ew Gw - inv64 @@ -304,150 +468,27 @@ aso oso rexw rexx rexr rexb 63 /m=64 - Gv Ed - - - - - bound - - aso oso - 62 - Gv M - inv64 - - - - - bsf - - aso oso rexw rexr rexx rexb - 0f bc - Gv Ev - - - - - bsr - - aso oso rexw rexr rexx rexb - 0f bd - Gv Ev - - - - - bswap - - oso rexw rexb - 0f c8 - rAXr8 - - - oso rexw rexb - 0f c9 - rCXr9 - - - oso rexw rexb - 0f ca - rDXr10 - - - oso rexw rexb - 0f cb - rBXr11 - - - oso rexw rexb - 0f cc - rSPr12 - - - oso rexw rexb - 0f cd - rBPr13 - - - oso rexw rexb - 0f ce - rSIr14 - - - oso rexw rexb - 0f cf - rDIr15 - - - - - bt - - aso oso rexw rexr rexx rexb - 0f ba /reg=4 - Ev Ib - - - aso oso rexw rexr rexx rexb - 0f a3 - Ev Gv - - - - - btc - - aso oso rexw rexr rexx rexb - 0f bb - Ev Gv - - - aso oso rexw rexr rexx rexb - 0f ba /reg=7 - Ev Ib + Gq Ed - btr - - aso oso rexw rexr rexx rexb - 0f b3 - Ev Gv - - - aso oso rexw rexr rexx rexb - 0f ba /reg=6 - Ev Ib - - - - - bts - - aso oso rexw rexr rexx rexb - 0f ab - Ev Gv - + call aso oso rexw rexr rexx rexb - 0f ba /reg=5 - Ev Ib + ff /reg=2 /m=!64 + Ev - - - - call aso oso rexw rexr rexx rexb - ff /reg=2 - Ev + ff /reg=2 /m=64 + Eq def64 aso oso rexw rexr rexx rexb ff /reg=3 - Ep + Fv oso @@ -457,9 +498,8 @@ oso - 9a - Ap - inv64 + 9a /m=!64 + Av @@ -712,7 +752,7 @@ oso rexw 3d - rAX Iz + rAX sIz aso rexr rexx rexb @@ -721,43 +761,46 @@ aso rexr rexx rexb - 82 /reg=7 + 82 /reg=7 /m=!64 Eb Ib inv64 aso oso rexw rexr rexx rexb 81 /reg=7 - Ev Iz + Ev sIz aso oso rexw rexr rexx rexb 83 /reg=7 - Ev Ib + Ev sIb cmppd - aso rexr rexx rexb - sse66 0f c2 - V W Ib + aso rexr rexx rexb vexl + /sse=66 0f c2 + V H W Ib + sse2 avx cmpps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f c2 - V W Ib + V H W Ib + sse2 avx cmpsb + repz seg a6 @@ -765,7 +808,7 @@ cmpsw - oso rexw + repz oso rexw seg a7 /o=16 @@ -773,20 +816,21 @@ cmpsd - oso rexw + repz oso rexw seg a7 /o=32 aso rexr rexx rexb - ssef2 0f c2 - V W Ib + /sse=f2 0f c2 + V H W Ib + sse2 avx cmpsq - oso rexw + repz oso rexw seg a7 /o=64 @@ -795,8 +839,9 @@ cmpss aso rexr rexx rexb - ssef3 0f c2 - V W Ib + /sse=f3 0f c2 + V H W Ib + sse2 avx @@ -818,7 +863,21 @@ cmpxchg8b aso rexr rexx rexb - 0f c7 /reg=1 + 0f c7 /mod=!11 /reg=1 /o=16 + M + + + aso rexr rexx rexb + 0f c7 /mod=!11 /reg=1 /o=32 + M + + + + + cmpxchg16b + + aso rexr rexx rexb + 0f c7 /mod=!11 /reg=1 /o=64 M @@ -827,8 +886,9 @@ comisd aso rexr rexx rexb - sse66 0f 2f - V W + /sse=66 0f 2f + Vsd Wsd + sse2 avx @@ -838,6 +898,7 @@ aso rexr rexx rexb 0f 2f V W + sse2 avx @@ -851,9 +912,10 @@ cvtdq2pd - aso rexr rexx rexb - ssef3 0f e6 - V W + aso rexr rexx rexb vexl + /sse=f3 0f e6 + V Wdq + sse2 avx @@ -863,15 +925,17 @@ aso rexr rexx rexb 0f 5b V W + sse2 avx cvtpd2dq - aso rexr rexx rexb - ssef2 0f e6 - V W + aso rexr rexx rexb vexl + /sse=f2 0f e6 + Vdq W + sse2 avx @@ -879,7 +943,7 @@ cvtpd2pi aso rexr rexx rexb - sse66 0f 2d + /sse=66 0f 2d P W @@ -887,9 +951,10 @@ cvtpd2ps - aso rexr rexx rexb - sse66 0f 5a - V W + aso rexr rexx rexb vexl + /sse=66 0f 5a + Vdq W + sse2 avx @@ -906,7 +971,7 @@ cvtpi2pd aso rexr rexx rexb - sse66 0f 2a + /sse=66 0f 2a V Q @@ -914,27 +979,29 @@ cvtps2dq - aso rexr rexx rexb - sse66 0f 5b + aso rexr rexx rexb vexl + /sse=66 0f 5b V W + sse2 avx - cvtps2pi + cvtps2pd - aso rexr rexx rexb - 0f 2d - P W + aso rexr rexx rexb vexl + 0f 5a + V Wdq + sse2 avx - cvtps2pd + cvtps2pi aso rexr rexx rexb - 0f 5a - V W + 0f 2d + P MqU @@ -942,8 +1009,9 @@ cvtsd2si aso rexw rexr rexx rexb - ssef2 0f 2d - Gy W + /sse=f2 0f 2d + Gy MqU + sse2 avx @@ -951,26 +1019,29 @@ cvtsd2ss aso rexr rexx rexb - ssef2 0f 5a - V W + /sse=f2 0f 5a + V H W + sse2 avx - cvtsi2ss + cvtsi2sd aso rexw rexr rexx rexb - ssef3 0f 2a - V Ex + /sse=f2 0f 2a + V H Ey + sse2 avx - cvtss2si + cvtsi2ss aso rexw rexr rexx rexb - ssef3 0f 2d - Gy W + /sse=f3 0f 2a + V H Ey + sse avx @@ -978,35 +1049,48 @@ cvtss2sd aso rexr rexx rexb - ssef3 0f 5a - V W + /sse=f3 0f 5a + V H W + sse2 avx - cvttpd2pi + cvtss2si - aso rexr rexx rexb - sse66 0f 2c - P W + aso rexw rexr rexx rexb + /sse=f3 0f 2d + Gy MdU + sse avx cvttpd2dq + aso rexr rexx rexb vexl + /sse=66 0f e6 + Vdq W + sse2 avx + + + + + cvttpd2pi + aso rexr rexx rexb - sse66 0f e6 - V W + /sse=66 0f 2c + P W cvttps2dq - aso rexr rexx rexb - ssef3 0f 5b + aso rexr rexx rexb vexl + /sse=f3 0f 5b V W + sse2 avx @@ -1023,17 +1107,9 @@ cvttsd2si aso rexw rexr rexx rexb - ssef2 0f 2c - Gy Wsd - - - - - cvtsi2sd - - aso rexw rexr rexx rexb - ssef2 0f 2a - V Ex + /sse=f2 0f 2c + Gy MqU + sse2 avx @@ -1041,8 +1117,9 @@ cvttss2si aso rexw rexr rexx rexb - ssef3 0f 2c - Gy Wsd + /sse=f3 0f 2c + Gy MdU + sse2 avx @@ -1073,7 +1150,7 @@ daa - 27 + 27 /m=!64 inv64 @@ -1081,7 +1158,7 @@ das - 2f + 2f /m=!64 inv64 @@ -1091,42 +1168,42 @@ oso 48 - eAX + R0z oso 49 - eCX + R1z oso 4a - eDX + R2z oso 4b - eBX + R3z oso 4c - eSP + R4z oso 4d - eBP + R5z oso 4e - eSI + R6z oso 4f - eDI + R7z aso rexw rexr rexx rexb @@ -1157,9 +1234,10 @@ divpd - aso rexr rexx rexb - sse66 0f 5e - V W + aso rexr rexx rexb vexl + /sse=66 0f 5e + V H W + sse2 avx @@ -1168,7 +1246,8 @@ aso rexr rexx rexb 0f 5e - V W + V H W + sse avx @@ -1176,8 +1255,9 @@ divsd aso rexr rexx rexb - ssef2 0f 5e - V W + /sse=f2 0f 5e + V H MqU + sse2 avx @@ -1185,8 +1265,29 @@ divss aso rexr rexx rexb - ssef3 0f 5e - V W + /sse=f3 0f 5e + V H MdU + sse avx + + + + + dppd + + aso rexr rexx rexb + /sse=66 0f 3a 41 + V H W Ib + sse4.1 avx + + + + + dpps + + aso rexr rexx rexb vexl + /sse=66 0f 3a 40 + V H W Ib + sse4.1 avx @@ -1202,13 +1303,23 @@ c8 Iw Ib - def64 depM + def64 + + + + + extractps + + aso rexr rexw rexx rexb + /sse=66 0f 3a 17 + MdRy V Ib + sse4.1 avx f2xm1 - X87 + X87 d9 /mod=11 /x87=30 @@ -1216,7 +1327,7 @@ fabs - X87 + X87 d9 /mod=11 /x87=21 @@ -1224,7 +1335,7 @@ fadd - X87 + X87 aso rexr rexx rexb dc /mod=!11 /reg=0 @@ -1303,7 +1414,7 @@ faddp - X87 + X87 de /mod=11 /x87=00 ST0 ST0 @@ -1340,7 +1451,7 @@ fbld - X87 + X87 aso rexr rexx rexb df /mod=!11 /reg=4 @@ -1350,7 +1461,7 @@ fbstp - X87 + X87 aso rexr rexx rexb df /mod=!11 /reg=6 @@ -1360,7 +1471,7 @@ fchs - X87 + X87 d9 /mod=11 /x87=20 @@ -1368,7 +1479,7 @@ fclex - X87 + X87 db /mod=11 /x87=22 @@ -1376,7 +1487,7 @@ fcmovb - X87 + X87 da /mod=11 /x87=00 ST0 ST0 @@ -1413,7 +1524,7 @@ fcmove - X87 + X87 da /mod=11 /x87=08 ST0 ST0 @@ -1450,7 +1561,7 @@ fcmovbe - X87 + X87 da /mod=11 /x87=10 ST0 ST0 @@ -1487,7 +1598,7 @@ fcmovu - X87 + X87 da /mod=11 /x87=18 ST0 ST0 @@ -1524,7 +1635,7 @@ fcmovnb - X87 + X87 db /mod=11 /x87=00 ST0 ST0 @@ -1561,7 +1672,7 @@ fcmovne - X87 + X87 db /mod=11 /x87=08 ST0 ST0 @@ -1598,7 +1709,7 @@ fcmovnbe - X87 + X87 db /mod=11 /x87=10 ST0 ST0 @@ -1635,7 +1746,7 @@ fcmovnu - X87 + X87 db /mod=11 /x87=18 ST0 ST0 @@ -1672,7 +1783,7 @@ fucomi - X87 + X87 db /mod=11 /x87=28 ST0 ST0 @@ -1709,7 +1820,7 @@ fcom - X87 + X87 aso rexr rexx rexb d8 /mod=!11 /reg=2 @@ -1756,7 +1867,7 @@ fcom2 - X87 UNDOC + X87 UNDOC dc /mod=11 /x87=10 ST0 @@ -1793,7 +1904,7 @@ fcomp3 - X87 UNDOC + X87 UNDOC dc /mod=11 /x87=18 ST0 @@ -1830,7 +1941,7 @@ fcomi - X87 + X87 db /mod=11 /x87=30 ST0 ST0 @@ -1867,7 +1978,7 @@ fucomip - X87 + X87 df /mod=11 /x87=28 ST0 ST0 @@ -1904,7 +2015,7 @@ fcomip - X87 + X87 df /mod=11 /x87=30 ST0 ST0 @@ -1941,7 +2052,7 @@ fcomp - X87 + X87 aso rexr rexx rexb d8 /mod=!11 /reg=3 @@ -1988,7 +2099,7 @@ fcomp5 - X87 UNDOC + X87 UNDOC de /mod=11 /x87=10 ST0 @@ -2025,7 +2136,7 @@ fcompp - X87 + X87 de /mod=11 /x87=19 @@ -2033,7 +2144,7 @@ fcos - X87 + X87 d9 /mod=11 /x87=3f @@ -2041,7 +2152,7 @@ fdecstp - X87 + X87 d9 /mod=11 /x87=36 @@ -2049,7 +2160,7 @@ fdiv - X87 + X87 aso rexr rexx rexb dc /mod=!11 /reg=6 @@ -2128,7 +2239,7 @@ fdivp - X87 + X87 de /mod=11 /x87=38 ST0 ST0 @@ -2165,7 +2276,7 @@ fdivr - X87 + X87 aso rexr rexx rexb dc /mod=!11 /reg=7 @@ -2244,7 +2355,7 @@ fdivrp - X87 + X87 de /mod=11 /x87=30 ST0 ST0 @@ -2288,7 +2399,7 @@ ffree - X87 + X87 dd /mod=11 /x87=00 ST0 @@ -2325,7 +2436,7 @@ ffreep - X87 + X87 df /mod=11 /x87=00 ST0 @@ -2362,7 +2473,7 @@ ficom - X87 + X87 aso rexr rexx rexb de /mod=!11 /reg=2 @@ -2377,7 +2488,7 @@ ficomp - X87 + X87 aso rexr rexx rexb de /mod=!11 /reg=3 @@ -2392,7 +2503,7 @@ fild - X87 + X87 aso rexr rexx rexb df /mod=!11 /reg=0 @@ -2411,8 +2522,8 @@ - fncstp - X87 + fincstp + X87 d9 /mod=11 /x87=37 @@ -2420,7 +2531,7 @@ fninit - X87 + X87 db /mod=11 /x87=23 @@ -2428,7 +2539,7 @@ fiadd - X87 + X87 aso rexr rexx rexb da /mod=!11 /reg=0 @@ -2443,7 +2554,7 @@ fidivr - X87 + X87 aso rexr rexx rexb da /mod=!11 /reg=7 @@ -2458,7 +2569,7 @@ fidiv - X87 + X87 aso rexr rexx rexb da /mod=!11 /reg=6 @@ -2473,7 +2584,7 @@ fisub - X87 + X87 aso rexr rexx rexb da /mod=!11 /reg=4 @@ -2488,7 +2599,7 @@ fisubr - X87 + X87 aso rexr rexx rexb da /mod=!11 /reg=5 @@ -2503,7 +2614,7 @@ fist - X87 + X87 aso rexr rexx rexb df /mod=!11 /reg=2 @@ -2518,7 +2629,7 @@ fistp - X87 + X87 aso rexr rexx rexb df /mod=!11 /reg=3 @@ -2538,7 +2649,7 @@ fisttp - X87 + X87 aso rexr rexx rexb db /mod=!11 /reg=1 @@ -2558,7 +2669,7 @@ fld - X87 + X87 aso rexr rexx rexb db /mod=!11 /reg=5 @@ -2610,7 +2721,7 @@ fld1 - X87 + X87 d9 /mod=11 /x87=28 @@ -2618,7 +2729,7 @@ fldl2t - X87 + X87 d9 /mod=11 /x87=29 @@ -2626,15 +2737,15 @@ fldl2e - X87 + X87 d9 /mod=11 /x87=2a - fldlpi - X87 + fldpi + X87 d9 /mod=11 /x87=2b @@ -2642,7 +2753,7 @@ fldlg2 - X87 + X87 d9 /mod=11 /x87=2c @@ -2650,7 +2761,7 @@ fldln2 - X87 + X87 d9 /mod=11 /x87=2d @@ -2658,7 +2769,7 @@ fldz - X87 + X87 d9 /mod=11 /x87=2e @@ -2666,7 +2777,7 @@ fldcw - X87 + X87 aso rexr rexx rexb d9 /mod=!11 /reg=5 @@ -2676,7 +2787,7 @@ fldenv - X87 + X87 aso rexr rexx rexb d9 /mod=!11 /reg=4 @@ -2686,7 +2797,7 @@ fmul - X87 + X87 aso rexr rexx rexb dc /mod=!11 /reg=1 @@ -2765,7 +2876,7 @@ fmulp - X87 + X87 de /mod=11 /x87=08 ST0 ST0 @@ -2802,7 +2913,7 @@ fimul - X87 + X87 aso rexr rexx rexb da /mod=!11 /reg=1 @@ -2817,15 +2928,39 @@ fnop - X87 + X87 d9 /mod=11 /x87=10 + + + fndisi + X87 + + db /mod=11 /x87=21 + + + + + fneni + X87 + + db /mod=11 /x87=20 + + + + + fnsetpm + X87 + + db /mod=11 /x87=24 + + fpatan - X87 + X87 d9 /mod=11 /x87=33 @@ -2833,7 +2968,7 @@ fprem - X87 + X87 d9 /mod=11 /x87=38 @@ -2841,7 +2976,7 @@ fprem1 - X87 + X87 d9 /mod=11 /x87=35 @@ -2849,7 +2984,7 @@ fptan - X87 + X87 d9 /mod=11 /x87=32 @@ -2857,7 +2992,7 @@ frndint - X87 + X87 d9 /mod=11 /x87=3c @@ -2865,17 +3000,25 @@ frstor - X87 + X87 aso rexr rexx rexb dd /mod=!11 /reg=4 M + + + frstpm + X87 + + db /mod=11 /x87=25 + + fnsave - X87 + X87 aso rexr rexx rexb dd /mod=!11 /reg=6 @@ -2885,7 +3028,7 @@ fscale - X87 + X87 d9 /mod=11 /x87=3d @@ -2893,7 +3036,7 @@ fsin - X87 + X87 d9 /mod=11 /x87=3e @@ -2901,7 +3044,7 @@ fsincos - X87 + X87 d9 /mod=11 /x87=3b @@ -2909,7 +3052,7 @@ fsqrt - X87 + X87 d9 /mod=11 /x87=3a @@ -2917,7 +3060,7 @@ fstp - X87 + X87 aso rexr rexx rexb db /mod=!11 /reg=7 @@ -3077,7 +3220,7 @@ fst - X87 + X87 aso rexr rexx rexb d9 /mod=!11 /reg=2 @@ -3124,7 +3267,7 @@ fnstcw - X87 + X87 aso rexr rexx rexb d9 /mod=!11 /reg=7 @@ -3134,7 +3277,7 @@ fnstenv - X87 + X87 aso rexr rexx rexb d9 /mod=!11 /reg=6 @@ -3144,7 +3287,7 @@ fnstsw - X87 + X87 aso rexr rexx rexb dd /mod=!11 /reg=7 @@ -3158,7 +3301,7 @@ fsub - X87 + X87 aso rexr rexx rexb d8 /mod=!11 /reg=4 @@ -3237,7 +3380,7 @@ fsubp - X87 + X87 de /mod=11 /x87=28 ST0 ST0 @@ -3274,7 +3417,7 @@ fsubr - X87 + X87 aso rexr rexx rexb dc /mod=!11 /reg=5 @@ -3353,7 +3496,7 @@ fsubrp - X87 + X87 de /mod=11 /x87=20 ST0 ST0 @@ -3390,7 +3533,7 @@ ftst - X87 + X87 d9 /mod=11 /x87=24 @@ -3398,7 +3541,7 @@ fucom - X87 + X87 dd /mod=11 /x87=20 ST0 @@ -3435,7 +3578,7 @@ fucomp - X87 + X87 dd /mod=11 /x87=28 ST0 @@ -3472,7 +3615,7 @@ fucompp - X87 + X87 da /mod=11 /x87=29 @@ -3480,7 +3623,7 @@ fxam - X87 + X87 d9 /mod=11 /x87=25 @@ -3488,7 +3631,7 @@ fxch - X87 + X87 d9 /mod=11 /x87=08 ST0 ST0 @@ -3525,7 +3668,7 @@ fxch4 - X87 + X87 dd /mod=11 /x87=08 ST0 @@ -3562,7 +3705,7 @@ fxch7 - X87 + X87 df /mod=11 /x87=08 ST0 @@ -3601,7 +3744,7 @@ fxrstor aso rexw rexr rexx rexb - 0f ae /mod=11 /reg=1 + 0f ae /mod=!11 /reg=1 M @@ -3610,14 +3753,14 @@ fxsave aso rexw rexr rexx rexb - 0f ae /mod=11 /reg=0 + 0f ae /mod=!11 /reg=0 M - fpxtract - X87 + fxtract + X87 d9 /mod=11 /x87=34 @@ -3625,7 +3768,7 @@ fyl2x - X87 + X87 d9 /mod=11 /x87=31 @@ -3633,7 +3776,7 @@ fyl2xp1 - X87 + X87 d9 /mod=11 /x87=39 @@ -3703,13 +3846,11 @@ aso oso rexw rexr rexx rexb 69 Gv Ev Iz - sext aso oso rexw rexr rexx rexb 6b - Gv Ev Ib - sext + Gv Ev sIb @@ -3718,42 +3859,42 @@ oso 40 - eAX + R0z oso 41 - eCX + R1z oso 42 - eDX + R2z oso 43 - eBX + R3z oso 44 - eSP + R4z oso 45 - eBP + R5z oso 46 - eSI + R6z oso 47 - eDI + R7z aso oso rexw rexr rexx rexb @@ -3770,6 +3911,7 @@ insb + rep seg 6c @@ -3777,7 +3919,7 @@ insw - oso + rep oso seg 6d /o=16 @@ -3785,7 +3927,7 @@ insd - oso + rep oso seg 6d /o=32 @@ -3815,7 +3957,7 @@ into - ce + ce /m=!64 inv64 @@ -3831,11 +3973,11 @@ invept intel - sse66 0f 38 80 /m=32 + /sse=66 0f 38 80 /m=32 Gd Mo - sse66 0f 38 80 /m=64 + /sse=66 0f 38 80 /m=64 Gq Mo @@ -3861,11 +4003,11 @@ invvpid intel - sse66 0f 38 81 /m=32 + /sse=66 0f 38 81 /m=32 Gd Mo - sse66 0f 38 81 /m=64 + /sse=66 0f 38 81 /m=64 Gq Mo @@ -3904,7 +4046,7 @@ oso 0f 80 Jz - def64 depM + def64 @@ -3918,7 +4060,7 @@ oso 0f 81 Jz - def64 depM + def64 @@ -3932,7 +4074,7 @@ oso 0f 82 Jz - def64 depM + def64 @@ -3946,7 +4088,7 @@ oso 0f 83 Jz - def64 depM + def64 @@ -3960,7 +4102,7 @@ oso 0f 84 Jz - def64 depM + def64 @@ -3974,7 +4116,7 @@ oso 0f 85 Jz - def64 depM + def64 @@ -3988,7 +4130,7 @@ oso 0f 86 Jz - def64 depM + def64 @@ -4002,7 +4144,7 @@ oso 0f 87 Jz - def64 depM + def64 @@ -4016,7 +4158,7 @@ oso 0f 88 Jz - def64 depM + def64 @@ -4030,7 +4172,7 @@ oso 0f 89 Jz - def64 depM + def64 @@ -4044,7 +4186,7 @@ oso 0f 8a Jz - def64 depM + def64 @@ -4058,7 +4200,7 @@ oso 0f 8b Jz - def64 depM + def64 @@ -4072,7 +4214,7 @@ oso 0f 8c Jz - def64 depM + def64 @@ -4086,7 +4228,7 @@ oso 0f 8d Jz - def64 depM + def64 @@ -4100,7 +4242,7 @@ oso 0f 8e Jz - def64 depM + def64 @@ -4114,7 +4256,7 @@ oso 0f 8f Jz - def64 depM + def64 @@ -4151,28 +4293,28 @@ aso oso rexw rexr rexx rexb ff /reg=4 Ev - def64 depM + def64 aso oso rexw rexr rexx rexb ff /reg=5 - Ep + Fv oso e9 Jz - def64 depM - cast + def64 - ea - Ap - inv64 + oso + ea /m=!64 + Av eb Jb + def64 @@ -4193,19 +4335,10 @@ - lddqu - - aso rexr rexx rexb - ssef2 0f f0 - V M - - - - ldmxcsr aso rexw rexr rexx rexb - 0f ae /reg=2 /mod=11 + 0f ae /reg=2 /mod=!11 Md @@ -4214,9 +4347,8 @@ lds aso oso - c5 + c5 /vex=none /m=!64 Gv M - inv64 @@ -4233,9 +4365,8 @@ les aso oso - c4 + c4 /m=!64 Gv M - inv64 @@ -4271,7 +4402,7 @@ aso oso rexw rexr rexx rexb 0f b2 - Gz M + Gv M @@ -4335,6 +4466,11 @@ 0f 01 /reg=6 /mod=!11 Ew + + aso rexr rexx rexb + 0f 01 /reg=6 /mod=11 + Ew + @@ -4347,7 +4483,7 @@ lodsb - seg + rep seg ac @@ -4355,7 +4491,7 @@ lodsw - seg oso rexw + rep seg oso rexw ad /o=16 @@ -4363,7 +4499,7 @@ lodsd - seg oso rexw + rep seg oso rexw ad /o=32 @@ -4371,13 +4507,13 @@ lodsq - seg oso rexw + rep seg oso rexw ad /o=64 - loopnz + loopne e0 Jb @@ -4422,26 +4558,28 @@ maskmovq aso rexr rexx rexb - 0f f7 - P PR + 0f f7 /mod=11 + P N maxpd - aso rexr rexx rexb - sse66 0f 5f - V W + aso rexr rexx rexb vexl + /sse=66 0f 5f + V H W + sse2 avx maxps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 5f - V W + V H W + sse avx @@ -4449,8 +4587,9 @@ maxsd aso rexr rexx rexb - ssef2 0f 5f - V W + /sse=f2 0f 5f + V H W + sse2 avx @@ -4458,8 +4597,9 @@ maxss aso rexr rexx rexb - ssef3 0f 5f - V W + /sse=f3 0f 5f + V H W + sse avx @@ -4494,9 +4634,10 @@ minpd - aso rexr rexx rexb - sse66 0f 5d - V W + aso rexr rexx rexb vexl + /sse=66 0f 5d + V H W + sse2 avx @@ -4505,7 +4646,8 @@ aso rexr rexx rexb 0f 5d - V W + V H W + sse2 avx @@ -4513,8 +4655,9 @@ minsd aso rexr rexx rexb - ssef2 0f 5d - V W + /sse=f2 0f 5d + V H MqU + sse2 avx @@ -4522,8 +4665,9 @@ minss aso rexr rexx rexb - ssef3 0f 5d - V W + /sse=f3 0f 5d + V H MdU + sse avx @@ -4551,7 +4695,7 @@ aso oso rexw rexr rexx rexb c7 /reg=0 - Ev Iz + Ev sIz aso rexr rexx rexb @@ -4574,14 +4718,14 @@ Gv Ev - aso oso rexr rexx rexb + aso oso rexw rexr rexx rexb 8c - Ev S + MwRv S - aso oso rexr rexx rexb + aso oso rexw rexr rexx rexb 8e - S Ev + S MwRv a0 @@ -4604,100 +4748,100 @@ rexb b0 - ALr8b Ib + R0b Ib rexb b1 - CLr9b Ib + R1b Ib rexb b2 - DLr10b Ib + R2b Ib rexb b3 - BLr11b Ib + R3b Ib rexb b4 - AHr12b Ib + R4b Ib rexb b5 - CHr13b Ib + R5b Ib rexb b6 - DHr14b Ib + R6b Ib rexb b7 - BHr15b Ib + R7b Ib oso rexw rexb b8 - rAXr8 Iv + R0v Iv oso rexw rexb b9 - rCXr9 Iv + R1v Iv oso rexw rexb ba - rDXr10 Iv + R2v Iv oso rexw rexb bb - rBXr11 Iv + R3v Iv oso rexw rexb bc - rSPr12 Iv + R4v Iv oso rexw rexb bd - rBPr13 Iv + R5v Iv oso rexw rexb be - rSIr14 Iv + R6v Iv oso rexw rexb bf - rDIr15 Iv + R7v Iv - rexr + rexr rexw rexb 0f 20 R C - rexr + rexr rexw rexb 0f 21 R D - rexr + rexr rexw rexb 0f 22 C R - rexr + rexr rexw rexb 0f 23 D R @@ -4706,28 +4850,32 @@ movapd - aso rexr rexx rexb - sse66 0f 28 + aso rexr rexx rexb vexl + /sse=66 0f 28 V W + sse2 avx - aso rexr rexx rexb - sse66 0f 29 + aso rexr rexx rexb vexl + /sse=66 0f 29 W V + sse2 avx movaps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 28 V W + sse avx - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 29 W V + sse avx @@ -4735,23 +4883,52 @@ movd aso rexw rexr rexx rexb - sse66 0f 6e - V Ex + 0f 6e /o=16 + P Ey + mmx - aso rexr rexx rexb - 0f 6e - P Ex + aso rexw rexr rexx rexb + 0f 6e /o=32 + P Ey + mmx + aso rexw rexr rexx rexb - sse66 0f 7e - Ex V + /sse=66 0f 6e /o=16 + V Ey + sse2 avx - aso rexr rexx rexb - 0f 7e - Ex P + aso rexw rexr rexx rexb + /sse=66 0f 6e /o=32 + V Ey + sse2 avx + + + aso rexw rexr rexx rexb + 0f 7e /o=16 + Ey P + mmx + + + aso rexw rexr rexx rexb + 0f 7e /o=32 + Ey P + mmx + + + aso rexw rexr rexx rexb + /sse=66 0f 7e /o=16 + Ey V + sse2 avx + + + aso rexw rexr rexx rexb + /sse=66 0f 7e /o=32 + Ey V + sse2 avx @@ -4759,13 +4936,15 @@ movhpd aso rexr rexx rexb - sse66 0f 16 /mod=!11 - V M + /sse=66 0f 16 /mod=!11 + V H M + sse2 avx aso rexr rexx rexb - sse66 0f 17 + /sse=66 0f 17 M V + sse2 avx @@ -4774,12 +4953,14 @@ aso rexr rexx rexb 0f 16 /mod=!11 - V M + V H M + sse avx aso rexr rexx rexb 0f 17 M V + sse avx @@ -4788,7 +4969,8 @@ aso rexr rexx rexb 0f 16 /mod=11 - V VR + V H U + sse avx @@ -4796,14 +4978,15 @@ movlpd aso rexr rexx rexb - sse66 0f 12 /mod=!11 + /sse=66 0f 12 /mod=!11 V M aso rexr rexx rexb - sse66 0f 13 + /sse=66 0f 13 M V + sse2 avx @@ -4818,6 +5001,7 @@ 0f 13 M V + sse avx @@ -4825,16 +5009,18 @@ aso rexr rexx rexb 0f 12 /mod=11 - V VR + V U + sse avx movmskpd - oso rexr rexb - sse66 0f 50 - Gd VR + oso rexr rexb vexl + /sse=66 0f 50 + Gd U + sse2 avx @@ -4843,16 +5029,18 @@ oso rexr rexb 0f 50 - Gd VR + Gd U + sse2 avx movntdq - aso rexr rexx rexb - sse66 0f e7 + aso rexr rexx rexb vexl + /sse=66 0f e7 M V + sse2 avx @@ -4868,24 +5056,27 @@ movntpd - aso rexr rexx rexb - sse66 0f 2b + aso rexr rexx rexb vexl + /sse=66 0f 2b M V + sse2 avx movntps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 2b M V + sse2 avx movntq + aso rexr rexx rexb 0f e7 M P @@ -4894,31 +5085,59 @@ movq - aso rexr rexx rexb - 0f 6f - P Q + aso rexw rexr rexx rexb + 0f 6e /o=64 + P Eq + mmx - aso rexr rexx rexb - sse66 0f d6 - W V + aso rexw rexr rexx rexb + /sse=66 0f 6e /o=64 + V Eq + sse2 avx - aso rexr rexx rexb - ssef3 0f 7e + aso rexw rexr rexx rexb + 0f 7e /o=64 + Eq P + mmx + + + aso rexw rexr rexx rexb + /sse=66 0f 7e /o=64 + Eq V + sse2 avx + + + aso rexw rexr rexx rexb + /sse=f3 0f 7e V W + sse2 avx - aso rexr rexx rexb + aso rexw rexr rexx rexb + /sse=66 0f d6 + W V + sse2 avx + + + aso rexw rexr rexx rexb + 0f 6f + P Q + mmx + + + aso rexw rexr rexx rexb 0f 7f Q P + mmx movsb - seg + rep seg a4 @@ -4926,7 +5145,7 @@ movsw - seg oso rexw + rep seg oso rexw a5 /o=16 @@ -4934,25 +5153,27 @@ movsd - seg oso rexw + rep seg oso rexw a5 /o=32 aso rexr rexx rexb - ssef2 0f 10 - V W + /sse=f2 0f 10 + V MqU + sse2 aso rexr rexx rexb - ssef2 0f 11 + /sse=f2 0f 11 W V + sse2 movsq - seg oso rexw + rep seg oso rexw a5 /o=64 @@ -4961,13 +5182,15 @@ movss aso rexr rexx rexb - ssef3 0f 10 - V W + /sse=f3 0f 10 + V MdU + sse aso rexr rexx rexb - ssef3 0f 11 + /sse=f3 0f 11 W V + sse @@ -4981,35 +5204,39 @@ aso oso rexw rexr rexx rexb 0f bf - Gv Ew + Gy Ew movupd - aso rexr rexx rexb - sse66 0f 10 + aso rexr rexx rexb vexl + /sse=66 0f 10 V W + sse2 avx - aso rexr rexx rexb - sse66 0f 11 + aso rexr rexx rexb vexl + /sse=66 0f 11 W V + sse2 avx movups - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 10 V W + sse2 avx - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 11 W V + sse2 avx @@ -5023,7 +5250,7 @@ aso oso rexw rexr rexx rexb 0f b7 - Gv Ew + Gy Ew @@ -5044,18 +5271,20 @@ mulpd - aso rexr rexx rexb - sse66 0f 59 - V W + aso rexr rexx rexb vexl + /sse=66 0f 59 + V H W + sse2 avx mulps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 59 - V W + V H W + sse2 avx @@ -5063,8 +5292,9 @@ mulsd aso rexr rexx rexb - ssef2 0f 59 - V W + /sse=f2 0f 59 + V H W + sse2 avx @@ -5072,8 +5302,9 @@ mulss aso rexr rexx rexb - ssef3 0f 59 - V W + /sse=f3 0f 59 + V H W + sse avx @@ -5101,9 +5332,6 @@ nop - 90 - - aso rexr rexx rexb 0f 19 M @@ -5183,8 +5411,7 @@ oso rexw 0d - rAX Iz - sext + rAX sIz aso rexr rexx rexb @@ -5194,38 +5421,37 @@ aso oso rexw rexr rexx rexb 81 /reg=1 - Ev Iz - sext + Ev sIz aso rexr rexx rexb - 82 /reg=1 + 82 /reg=1 /m=!64 Eb Ib - inv64 aso oso rexw rexr rexx rexb 83 /reg=1 - Ev Ib - sext + Ev sIb orpd - aso rexr rexx rexb - sse66 0f 56 - V W + aso rexr rexx rexb vexl + /sse=66 0f 56 + V H W + sse2 avx orps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 56 - V W + V H W + sse avx @@ -5254,6 +5480,7 @@ outsb + rep seg 6e @@ -5261,7 +5488,7 @@ outsw - oso + rep oso seg 6f /o=16 @@ -5269,72 +5496,72 @@ outsd - oso + rep oso seg 6f /o=32 - outsq - - oso - 6f /o=64 - - - - packsswb - aso rexr rexx rexb - sse66 0f 63 - V W + aso rexr rexx rexb vexl + /sse=66 0f 63 + V H W + sse2 avx aso rexr rexx rexb 0f 63 P Q + mmx packssdw - aso rexr rexx rexb - sse66 0f 6b - V W + aso rexr rexx rexb vexl + /sse=66 0f 6b + V H W + sse2 avx aso rexr rexx rexb 0f 6b P Q + mmx packuswb - aso rexr rexx rexb - sse66 0f 67 - V W + aso rexr rexx rexb vexl + /sse=66 0f 67 + V H W + sse2 avx aso rexr rexx rexb 0f 67 P Q + mmx paddb - aso rexr rexx rexb - sse66 0f fc - V W + aso rexr rexx rexb vexl + /sse=66 0f fc + V H W + sse2 avx aso rexr rexx rexb 0f fc P Q + mmx @@ -5344,11 +5571,13 @@ aso rexr rexx rexb 0f fd P Q + mmx - aso rexr rexx rexb - sse66 0f fd - V W + aso rexr rexx rexb vexl + /sse=66 0f fd + V H W + sse2 avx @@ -5358,11 +5587,13 @@ aso rexr rexx rexb 0f fe P Q + mmx - aso rexr rexx rexb - sse66 0f fe - V W + aso rexr rexx rexb vexl + /sse=66 0f fe + V H W + sse2 avx @@ -5376,8 +5607,9 @@ aso rexr rexx rexb - sse66 0f ec - V W + /sse=66 0f ec + V H W + sse2 avx @@ -5390,8 +5622,9 @@ aso rexr rexx rexb - sse66 0f ed - V W + /sse=66 0f ed + V H W + sse2 avx @@ -5404,8 +5637,9 @@ aso rexr rexx rexb - sse66 0f dc - V W + /sse=66 0f dc + V H W + sse2 avx @@ -5418,8 +5652,9 @@ aso rexr rexx rexb - sse66 0f dd - V W + /sse=66 0f dd + V H W + sse2 avx @@ -5427,8 +5662,9 @@ pand aso rexr rexx rexb - sse66 0f db - V W + /sse=66 0f db + V H W + sse2 avx aso rexr rexx rexb @@ -5441,8 +5677,9 @@ pandn aso rexr rexx rexb - sse66 0f df - V W + /sse=66 0f df + V H W + sse2 avx aso rexr rexx rexb @@ -5455,8 +5692,9 @@ pavgb aso rexr rexx rexb - sse66 0f e0 - V W + /sse=66 0f e0 + V H W + sse2 avx aso rexr rexx rexb @@ -5469,8 +5707,9 @@ pavgw aso rexr rexx rexb - sse66 0f e3 - V W + /sse=66 0f e3 + V H W + sse2 avx aso rexr rexx rexb @@ -5488,8 +5727,9 @@ aso rexr rexx rexb - sse66 0f 74 - V W + /sse=66 0f 74 + V H W + sse2 avx @@ -5502,8 +5742,9 @@ aso rexr rexx rexb - sse66 0f 75 - V W + /sse=66 0f 75 + V H W + sse2 avx @@ -5516,8 +5757,9 @@ aso rexr rexx rexb - sse66 0f 76 - V W + /sse=66 0f 76 + V H W + sse2 avx @@ -5525,8 +5767,9 @@ pcmpgtb aso rexr rexx rexb - sse66 0f 64 - V W + /sse=66 0f 64 + V H W + sse2 avx aso rexr rexx rexb @@ -5539,8 +5782,9 @@ pcmpgtw aso rexr rexx rexb - sse66 0f 65 - V W + /sse=66 0f 65 + V H W + sse2 avx aso rexr rexx rexb @@ -5553,8 +5797,9 @@ pcmpgtd aso rexr rexx rexb - sse66 0f 66 - V W + /sse=66 0f 66 + V H W + sse2 avx aso rexr rexx rexb @@ -5566,24 +5811,27 @@ pextrb - aso rexr rexb - sse66 0f 3a 14 + aso rexx rexr rexb + /sse=66 0f 3a 14 /vexw=0 MbRv V Ib def64 + sse4.1 avx pextrd - aso rexr rexw rexb - sse66 0f 3a 16 /o=16 - Ev V Ib + aso rexr rexx rexw rexb + /sse=66 0f 3a 16 /o=16 /vexw=0 + Ed V Ib + sse4.1 avx - aso rexr rexw rexb - sse66 0f 3a 16 /o=32 - Ev V Ib + aso rexr rexx rexw rexb + /sse=66 0f 3a 16 /o=32 /vexw=0 + Ed V Ib + sse4.1 avx @@ -5591,62 +5839,150 @@ pextrq aso rexr rexw rexb - sse66 0f 3a 16 /o=64 - Ev V Ib + /sse=66 0f 3a 16 /o=64 /vexw=1 + Eq V Ib def64 + sse4.1 avx pextrw - aso rexr rexb - sse66 0f c5 - Gd VR Ib + aso rexw rexr rexb + /sse=66 0f c5 + Gd U Ib + sse avx - aso oso rexw rexr rexx rexb + aso rexw rexr rexx rexb 0f c5 - Gd PR Ib + Gd N Ib + + + aso rexw rexx rexr rexb + /sse=66 0f 3a 15 + MwRd V Ib + sse4.1 avx + + + + + pinsrb + + aso rexw rexr rexx rexb + /sse=66 0f 3a 20 + V MbRd Ib + sse4.1 pinsrw - aso oso rexw rexr rexx rexb + aso rexw rexr rexx rexb 0f c4 - P Ew Ib + P MwRy Ib + def64 aso rexw rexr rexx rexb - sse66 0f c4 - V Ew Ib + /sse=66 0f c4 + V MwRy Ib + def64 + sse2 avx - pmaddwd + pinsrd - aso rexr rexx rexb - 0f f5 - P Q + aso rexw rexr rexx rexb + /sse=66 0f 3a 22 /o=16 + V Ed Ib + sse4.1 + - aso rexr rexx rexb - sse66 0f f5 - V W + aso rexw rexr rexx rexb + /sse=66 0f 3a 22 /o=32 + V Ed Ib + sse4.1 - pmaxsw + pinsrq - aso rexr rexx rexb - sse66 0f ee - V W + aso oso rexw rexr rexx rexb + /sse=66 0f 3a 22 /o=64 + V Eq Ib + sse4.1 - + + + + vpinsrb + + aso rexw rexr rexx rexb + /vex=66_0f3a 20 /vexw=0 /vexl=0 + V H MbRd Ib + avx + + + + + vpinsrd + + aso oso rexw rexr rexx rexb + /vex=66_0f3a 22 /m=!64 /vexw=0 /vexl=0 + V H Ed Ib + avx + + + aso oso rexw rexr rexx rexb + /vex=66_0f3a 22 /m=64 /vexw=0 /vexl=0 + V H Ed Ib + avx + + + + + + vpinsrq + + aso oso rexw rexr rexx rexb + /vex=66_0f3a 22 /m=64 /vexw=1 /vexl=0 + V H Eq Ib + avx + + + + + + pmaddwd + + aso rexr rexx rexb + 0f f5 + P Q + + + aso rexr rexx rexb + /sse=66 0f f5 + V H W + sse4.1 avx + + + + + pmaxsw + + aso rexr rexx rexb + /sse=66 0f ee + V H W + sse4.1 avx + + aso rexr rexx rexb 0f ee P Q @@ -5662,8 +5998,9 @@ aso rexr rexx rexb - sse66 0f de - V W + /sse=66 0f de + V H W + sse2 avx @@ -5671,8 +6008,9 @@ pminsw aso rexr rexx rexb - sse66 0f ea - V W + /sse=66 0f ea + V H W + sse2 avx aso rexr rexx rexb @@ -5685,8 +6023,9 @@ pminub aso rexr rexx rexb - sse66 0f da - V W + /sse=66 0f da + V H W + sse2 avx aso rexr rexx rexb @@ -5698,14 +6037,15 @@ pmovmskb - rexr rexb - sse66 0f d7 - Gd VR + oso rexr rexw rexb + /sse=66 0f d7 /vexl=0 + Gd U + sse2 avx - oso rexr rexb + oso rexr rexw rexb 0f d7 - Gd PR + Gd N @@ -5718,8 +6058,9 @@ aso rexr rexx rexb - sse66 0f e4 - V W + /sse=66 0f e4 + V H W + sse2 avx @@ -5727,8 +6068,9 @@ pmulhw aso rexr rexx rexb - sse66 0f e5 - V W + /sse=66 0f e5 + V H W + sse2 avx aso rexr rexx rexb @@ -5746,25 +6088,26 @@ aso rexr rexx rexb - sse66 0f d5 - V W + /sse=66 0f d5 + V H W + sse2 avx pop - 07 + 07 /m=!64 ES inv64 - 17 + 17 /m=!64 SS inv64 - 1f + 1f /m=!64 DS inv64 @@ -5779,56 +6122,56 @@ oso rexb 58 - rAXr8 - def64 depM + R0v + def64 oso rexb 59 - rCXr9 - def64 depM + R1v + def64 oso rexb 5a - rDXr10 - def64 depM + R2v + def64 oso rexb 5b - rBXr11 - def64 depM + R3v + def64 oso rexb 5c - rSPr12 - def64 depM + R4v + def64 oso rexb 5d - rBPr13 - def64 depM + R5v + def64 oso rexb 5e - rSIr14 - def64 depM + R6v + def64 oso rexb 5f - rDIr15 - def64 depM + R7v + def64 aso oso rexw rexr rexx rexb 8f /reg=0 Ev - def64 depM + def64 @@ -5836,7 +6179,7 @@ popa oso - 61 /o=16 + 61 /o=16 /m=!64 inv64 @@ -5845,7 +6188,7 @@ popad oso - 61 /o=32 + 61 /o=32 /m=!64 inv64 @@ -5854,13 +6197,7 @@ popfw oso - 9d /m=32 /o=16 - def64 depM - - - oso - 9d /m=16 /o=16 - def64 depM + 9d /m=!64 /o=16 @@ -5868,13 +6205,7 @@ popfd oso - 9d /m=16 /o=32 - def64 depM - - - oso - 9d /m=32 /o=32 - def64 depM + 9d /m=!64 /o=32 @@ -5882,8 +6213,13 @@ popfq oso + 9d /m=64 /o=32 + def64 + + + oso 9d /m=64 /o=64 - def64 depM + def64 @@ -5891,8 +6227,9 @@ por aso rexr rexx rexb - sse66 0f eb - V W + /sse=66 0f eb + V H W + sse2 avx aso rexr rexx rexb @@ -5985,8 +6322,9 @@ psadbw aso rexr rexx rexb - sse66 0f f6 - V W + /sse=66 0f f6 + V H W + sse2 avx aso rexr rexx rexb @@ -6004,12 +6342,13 @@ - + psllw aso rexr rexx rexb - sse66 0f f1 + /sse=66 0f f1 V W + sse2 aso rexr rexx rexb @@ -6018,12 +6357,13 @@ rexb - sse66 0f 71 /reg=6 - VR Ib + /sse=66 0f 71 /reg=6 + U Ib + sse2 0f 71 /reg=6 - PR Ib + N Ib @@ -6031,8 +6371,9 @@ pslld aso rexr rexx rexb - sse66 0f f2 + /sse=66 0f f2 V W + sse2 aso rexr rexx rexb @@ -6041,12 +6382,13 @@ rexb - sse66 0f 72 /reg=6 - VR Ib + /sse=66 0f 72 /reg=6 + U Ib + sse2 0f 72 /reg=6 - PR Ib + N Ib @@ -6054,8 +6396,9 @@ psllq aso rexr rexx rexb - sse66 0f f3 + /sse=66 0f f3 V W + sse2 aso rexr rexx rexb @@ -6064,12 +6407,13 @@ rexb - sse66 0f 73 /reg=6 - VR Ib + /sse=66 0f 73 /reg=6 + U Ib + sse2 0f 73 /reg=6 - PR Ib + N Ib @@ -6082,17 +6426,19 @@ aso rexr rexx rexb - sse66 0f e1 - V W + /sse=66 0f e1 + V H W + sse2 avx rexb - sse66 0f 71 /reg=4 - VR Ib + /sse=66 0f 71 /reg=4 + H U Ib + sse2 avx 0f 71 /reg=4 - PR Ib + N Ib @@ -6100,12 +6446,13 @@ psrad 0f 72 /reg=4 - PR Ib + N Ib aso rexr rexx rexb - sse66 0f e2 - V W + /sse=66 0f e2 + V H W + sse2 avx aso rexr rexx rexb @@ -6114,8 +6461,9 @@ rexb - sse66 0f 72 /reg=4 - VR Ib + /sse=66 0f 72 /reg=4 + H U Ib + sse2 avx @@ -6123,7 +6471,7 @@ psrlw 0f 71 /reg=2 - PR Ib + N Ib aso rexr rexx rexb @@ -6132,13 +6480,15 @@ aso rexr rexx rexb - sse66 0f d1 - V W + /sse=66 0f d1 + V H W + sse2 avx rexb - sse66 0f 71 /reg=2 - VR Ib + /sse=66 0f 71 /reg=2 + H U Ib + sse2 avx @@ -6146,7 +6496,7 @@ psrld 0f 72 /reg=2 - PR Ib + N Ib aso rexr rexx rexb @@ -6155,13 +6505,15 @@ aso rexr rexx rexb - sse66 0f d2 - V W + /sse=66 0f d2 + V H W + sse2 avx rexb - sse66 0f 72 /reg=2 - VR Ib + /sse=66 0f 72 /reg=2 + H U Ib + sse2 avx @@ -6169,7 +6521,7 @@ psrlq 0f 73 /reg=2 - PR Ib + N Ib aso rexr rexx rexb @@ -6178,13 +6530,15 @@ aso rexr rexx rexb - sse66 0f d3 - V W + /sse=66 0f d3 + V H W + sse2 avx rexb - sse66 0f 73 /reg=2 - VR Ib + /sse=66 0f 73 /reg=2 + H U Ib + sse2 avx @@ -6192,8 +6546,9 @@ psubb aso rexr rexx rexb - sse66 0f f8 - V W + /sse=66 0f f8 + V H W + sse2 avx aso rexr rexx rexb @@ -6206,8 +6561,9 @@ psubw aso rexr rexx rexb - sse66 0f f9 - V W + /sse=66 0f f9 + V H W + sse2 avx aso rexr rexx rexb @@ -6225,8 +6581,9 @@ aso rexr rexx rexb - sse66 0f fa - V W + /sse=66 0f fa + V H W + sse2 avx @@ -6239,8 +6596,9 @@ aso rexr rexx rexb - sse66 0f e8 - V W + /sse=66 0f e8 + V H W + sse2 avx @@ -6253,8 +6611,9 @@ aso rexr rexx rexb - sse66 0f e9 - V W + /sse=66 0f e9 + V H W + sse2 avx @@ -6267,8 +6626,9 @@ aso rexr rexx rexb - sse66 0f d8 - V W + /sse=66 0f d8 + V H W + sse2 avx @@ -6281,8 +6641,9 @@ aso rexr rexx rexb - sse66 0f d9 - V W + /sse=66 0f d9 + V H W + sse2 avx @@ -6290,8 +6651,9 @@ punpckhbw aso rexr rexx rexb - sse66 0f 68 - V W + /sse=66 0f 68 + V H W + sse2 avx aso rexr rexx rexb @@ -6304,8 +6666,9 @@ punpckhwd aso rexr rexx rexb - sse66 0f 69 - V W + /sse=66 0f 69 + V H W + sse2 avx aso rexr rexx rexb @@ -6318,8 +6681,9 @@ punpckhdq aso rexr rexx rexb - sse66 0f 6a - V W + /sse=66 0f 6a + V H W + sse2 avx aso rexr rexx rexb @@ -6332,8 +6696,9 @@ punpcklbw aso rexr rexx rexb - sse66 0f 60 - V W + /sse=66 0f 60 + V H W + sse2 avx aso rexr rexx rexb @@ -6346,8 +6711,9 @@ punpcklwd aso rexr rexx rexb - sse66 0f 61 - V W + /sse=66 0f 61 + V H W + sse2 avx aso rexr rexx rexb @@ -6360,8 +6726,9 @@ punpckldq aso rexr rexx rexb - sse66 0f 62 - V W + /sse=66 0f 62 + V H W + sse2 avx aso rexr rexx rexb @@ -6373,6 +6740,7 @@ pi2fw + aso rexr rexx rexb 0f 0f /3dnow=0c P Q @@ -6381,6 +6749,7 @@ pi2fd + aso rexr rexx rexb 0f 0f /3dnow=0d P Q @@ -6389,6 +6758,7 @@ pf2iw + aso rexr rexx rexb 0f 0f /3dnow=1c P Q @@ -6397,6 +6767,7 @@ pf2id + aso rexr rexx rexb 0f 0f /3dnow=1d P Q @@ -6405,6 +6776,7 @@ pfnacc + aso rexr rexx rexb 0f 0f /3dnow=8a P Q @@ -6413,6 +6785,7 @@ pfpnacc + aso rexr rexx rexb 0f 0f /3dnow=8e P Q @@ -6421,6 +6794,7 @@ pfcmpge + aso rexr rexx rexb 0f 0f /3dnow=90 P Q @@ -6429,6 +6803,7 @@ pfmin + aso rexr rexx rexb 0f 0f /3dnow=94 P Q @@ -6437,6 +6812,7 @@ pfrcp + aso rexr rexx rexb 0f 0f /3dnow=96 P Q @@ -6445,6 +6821,7 @@ pfrsqrt + aso rexr rexx rexb 0f 0f /3dnow=97 P Q @@ -6453,6 +6830,7 @@ pfsub + aso rexr rexx rexb 0f 0f /3dnow=9a P Q @@ -6461,6 +6839,7 @@ pfadd + aso rexr rexx rexb 0f 0f /3dnow=9e P Q @@ -6469,6 +6848,7 @@ pfcmpgt + aso rexr rexx rexb 0f 0f /3dnow=a0 P Q @@ -6477,6 +6857,7 @@ pfmax + aso rexr rexx rexb 0f 0f /3dnow=a4 P Q @@ -6485,6 +6866,7 @@ pfrcpit1 + aso rexr rexx rexb 0f 0f /3dnow=a6 P Q @@ -6493,6 +6875,7 @@ pfrsqit1 + aso rexr rexx rexb 0f 0f /3dnow=a7 P Q @@ -6501,6 +6884,7 @@ pfsubr + aso rexr rexx rexb 0f 0f /3dnow=aa P Q @@ -6509,6 +6893,7 @@ pfacc + aso rexr rexx rexb 0f 0f /3dnow=ae P Q @@ -6517,6 +6902,7 @@ pfcmpeq + aso rexr rexx rexb 0f 0f /3dnow=b0 P Q @@ -6525,6 +6911,7 @@ pfmul + aso rexr rexx rexb 0f 0f /3dnow=b4 P Q @@ -6533,6 +6920,7 @@ pfrcpit2 + aso rexr rexx rexb 0f 0f /3dnow=b6 P Q @@ -6541,6 +6929,7 @@ pmulhrw + aso rexr rexx rexb 0f 0f /3dnow=b7 P Q @@ -6549,6 +6938,7 @@ pswapd + aso rexr rexx rexb 0f 0f /3dnow=bb P Q @@ -6557,6 +6947,7 @@ pavgusb + aso rexr rexx rexb 0f 0f /3dnow=bf P Q @@ -6565,22 +6956,22 @@ push - 06 + 06 /m=!64 ES inv64 - 0e + 0e /m=!64 CS inv64 - 16 + 16 /m=!64 SS inv64 - 1e + 1e /m=!64 DS inv64 @@ -6595,56 +6986,56 @@ oso rexb 50 - rAXr8 - def64 depM + R0v + def64 oso rexb 51 - rCXr9 - def64 depM + R1v + def64 oso rexb 52 - rDXr10 - def64 depM + R2v + def64 oso rexb 53 - rBXr11 - def64 depM + R3v + def64 oso rexb 54 - rSPr12 - def64 depM + R4v + def64 oso rexb 55 - rBPr13 - def64 depM + R5v + def64 oso rexb 56 - rSIr14 - def64 depM + R6v + def64 oso rexb 57 - rDIr15 - def64 depM + R7v + def64 oso 68 - Iz - cast + sIz + def64 aso oso rexw rexr rexx rexb @@ -6653,9 +7044,10 @@ def64 + oso 6a - Ib - sext + sIb + def64 @@ -6663,7 +7055,7 @@ pusha oso - 60 /o=16 + 60 /o=16 /m=!64 inv64 @@ -6672,7 +7064,7 @@ pushad oso - 60 /o=32 + 60 /o=32 /m=!64 inv64 @@ -6681,13 +7073,7 @@ pushfw oso - 9c /m=32 /o=16 - def64 - - - oso - 9c /m=16 /o=16 - def64 + 9c /m=!64 /o=16 oso rexw @@ -6700,13 +7086,7 @@ pushfd oso - 9c /m=16 /o=32 - def64 - - - oso - 9c /m=32 /o=32 - def64 + 9c /m=!64 /o=32 @@ -6728,8 +7108,9 @@ pxor aso rexr rexx rexb - sse66 0f ef - V W + /sse=66 0f ef + V H W + sse2 avx aso rexr rexx rexb @@ -6759,13 +7140,11 @@ aso rexw rexr rexx rexb d2 /reg=2 Eb CL - cast aso oso rexw rexr rexx rexb d3 /reg=2 Ev CL - cast aso oso rexw rexr rexx rexb @@ -6800,13 +7179,11 @@ aso rexw rexr rexx rexb d2 /reg=3 Eb CL - cast aso oso rexw rexr rexx rexb d3 /reg=3 Ev CL - cast @@ -6831,13 +7208,11 @@ aso rexw rexr rexx rexb d2 /reg=0 Eb CL - cast aso oso rexw rexr rexx rexb d3 /reg=0 Ev CL - cast aso oso rexw rexr rexx rexb @@ -6872,22 +7247,21 @@ aso rexw rexr rexx rexb d2 /reg=1 Eb CL - cast aso oso rexw rexr rexx rexb d3 /reg=1 Ev CL - cast rcpps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 53 V W + sse avx @@ -6895,8 +7269,9 @@ rcpss aso rexr rexx rexb - ssef3 0f 53 + /sse=f3 0f 53 V W + sse avx @@ -6975,9 +7350,10 @@ rsqrtps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 52 V W + sse avx @@ -6985,8 +7361,9 @@ rsqrtss aso rexr rexx rexb - ssef3 0f 52 + /sse=f3 0f 52 V W + sse avx @@ -7004,7 +7381,7 @@ salc - d6 + d6 /m=!64 inv64 @@ -7035,13 +7412,11 @@ aso rexw rexr rexx rexb d2 /reg=7 Eb CL - cast aso oso rexw rexr rexx rexb d3 /reg=7 Ev CL - cast @@ -7066,13 +7441,11 @@ aso rexw rexr rexx rexb d2 /reg=6 Eb CL - cast aso oso rexw rexr rexx rexb d3 /reg=6 Ev CL - cast aso oso rexw rexr rexx rexb @@ -7083,7 +7456,6 @@ aso rexr rexx rexb d2 /reg=4 Eb CL - cast aso oso rexw rexr rexx rexb @@ -7123,7 +7495,6 @@ aso rexw rexr rexx rexb d2 /reg=5 Eb CL - cast aso oso rexw rexr rexx rexb @@ -7144,7 +7515,6 @@ aso oso rexw rexr rexx rexb d3 /reg=5 Ev CL - cast @@ -7177,8 +7547,7 @@ oso rexw 1d - rAX Iz - sext + rAX sIz aso rexr rexx rexb @@ -7188,26 +7557,25 @@ aso oso rexw rexr rexx rexb 81 /reg=3 - Ev Iz - sext + Ev sIz aso rexr rexx rexb - 82 /reg=3 + 82 /reg=3 /m=!64 Eb Ib inv64 aso oso rexw rexr rexx rexb 83 /reg=3 - Ev Ib - sext + Ev sIb scasb + repz ae @@ -7215,7 +7583,7 @@ scasw - oso rexw + repz oso rexw af /o=16 @@ -7223,7 +7591,7 @@ scasd - oso rexw + repz oso rexw af /o=32 @@ -7231,7 +7599,7 @@ scasq - oso rexw + repz oso rexw af /o=64 @@ -7264,7 +7632,7 @@ - setnb + setae aso rexr rexx rexb 0f 93 @@ -7448,9 +7816,10 @@ shufpd - aso rexr rexx rexb - sse66 0f c6 - V W Ib + aso rexr rexx rexb vexl + /sse=66 0f c6 + V H W Ib + sse2 avx @@ -7459,7 +7828,8 @@ aso rexr rexx rexb 0f c6 - V W Ib + V H W Ib + sse2 avx @@ -7475,7 +7845,7 @@ sldt - aso oso rexr rexx rexb + aso oso rexr rexw rexx rexb 0f 00 /reg=0 MwRv @@ -7484,18 +7854,24 @@ smsw - aso rexr rexx rexb + aso oso rexr rexw rexx rexb 0f 01 /reg=4 /mod=!11 - M + MwRv + + + aso oso rexr rexw rexx rexb + 0f 01 /reg=4 /mod=11 + MwRv sqrtps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 51 V W + sse avx @@ -7503,8 +7879,9 @@ sqrtpd aso rexr rexx rexb - sse66 0f 51 + /sse=66 0f 51 V W + sse2 avx @@ -7512,8 +7889,9 @@ sqrtsd aso rexr rexx rexb - ssef2 0f 51 - V W + /sse=f2 0f 51 + V H W + sse2 avx @@ -7521,8 +7899,9 @@ sqrtss aso rexr rexx rexb - ssef3 0f 51 - V W + /sse=f3 0f 51 + V H W + sse avx @@ -7567,15 +7946,16 @@ stmxcsr aso rexw rexr rexx rexb - 0f ae /mod=11 /reg=3 + 0f ae /mod=!11 /reg=3 Md + sse avx stosb - seg + rep seg aa @@ -7583,7 +7963,7 @@ stosw - seg oso rexw + rep seg oso rexw ab /o=16 @@ -7591,7 +7971,7 @@ stosd - seg oso rexw + rep seg oso rexw ab /o=32 @@ -7599,7 +7979,7 @@ stosq - seg oso rexw + rep seg oso rexw ab /o=64 @@ -7607,9 +7987,9 @@ str - aso oso rexr rexx rexb + aso oso rexr rexw rexx rexb 0f 00 /reg=1 - Ev + MwRv @@ -7642,8 +8022,7 @@ oso rexw 2d - rAX Iz - sext + rAX sIz aso rexr rexx rexb @@ -7653,38 +8032,38 @@ aso oso rexw rexr rexx rexb 81 /reg=5 - Ev Iz - sext + Ev sIz aso rexr rexx rexb - 82 /reg=5 + 82 /reg=5 /m=!64 Eb Ib inv64 aso oso rexw rexr rexx rexb 83 /reg=5 - Ev Ib - sext + Ev sIb subpd - aso rexr rexx rexb - sse66 0f 5c - V W + aso rexr rexx rexb vexl + /sse=66 0f 5c + V H W + sse2 avx subps - aso rexr rexx rexb + aso rexr rexx rexb vexl 0f 5c - V W + V H W + sse avx @@ -7692,8 +8071,9 @@ subsd aso rexr rexx rexb - ssef2 0f 5c - V W + /sse=f2 0f 5c + V H W + sse2 avx @@ -7701,8 +8081,9 @@ subss aso rexr rexx rexb - ssef3 0f 5c - V W + /sse=f3 0f 5c + V H W + sse avx @@ -7723,15 +8104,22 @@ sysenter - 0f 34 - inv64 + 0f 34 /m=!64 + + + 0f 34 /m=64 + intel sysexit - 0f 35 + 0f 35 /m=!64 + + + 0f 35 /m=64 + intel @@ -7766,8 +8154,7 @@ oso rexw a9 - rAX Iz - sext + rAX sIz aso rexw rexr rexx rexb @@ -7777,14 +8164,12 @@ aso oso rexw rexr rexx rexb f7 /reg=0 - Ev Iz - sext + Ev sIz aso oso rexw rexr rexx rexb f7 /reg=1 Ev Iz - sext @@ -7792,8 +8177,9 @@ ucomisd aso rexr rexx rexb - sse66 0f 2e + /sse=66 0f 2e V W + sse2 avx @@ -7803,6 +8189,7 @@ aso rexr rexx rexb 0f 2e V W + sse avx @@ -7816,9 +8203,10 @@ unpckhpd - aso rexr rexx rexb - sse66 0f 15 - V W + aso rexr rexx rexb vexl + /sse=66 0f 15 + V H W + sse2 avx @@ -7827,7 +8215,8 @@ aso rexr rexx rexb 0f 15 - V W + V H W + sse avx @@ -7836,16 +8225,18 @@ aso rexr rexx rexb 0f 14 - V W + V H W + sse avx unpcklpd - aso rexr rexx rexb - sse66 0f 14 - V W + aso rexr rexx rexb vexl + /sse=66 0f 14 + V H W + sse2 avx @@ -7876,11 +8267,21 @@ + rdrand + + oso rexr rexw rexx rexb + 0f c7 /mod=11 /reg=6 + R + + rdrand + + + vmclear intel aso rexr rexx rexb - sse66 0f c7 /reg=6 + /sse=66 0f c7 /mod=!11 /reg=6 Mq @@ -7890,7 +8291,7 @@ intel aso rexr rexx rexb - ssef3 0f c7 /reg=6 + /sse=f3 0f c7 /mod=!11 /reg=6 Mq @@ -7900,7 +8301,7 @@ intel aso rexr rexx rexb - 0f c7 /reg=6 + 0f c7 /mod=!11 /reg=6 Mq @@ -7910,7 +8311,7 @@ intel aso rexr rexx rexb - 0f c7 /reg=7 + 0f c7 /mod=!11 /reg=7 Mq @@ -7944,20 +8345,8 @@ intel aso rexr rexx rexb - 0f 78 /m=16 - Ed Gd - def64 - - - aso rexr rexx rexb - 0f 78 /m=32 - Ed Gd - def64 - - - aso rexr rexx rexb - 0f 78 /m=64 - Eq Gq + 0f 78 + Ey Gy def64 @@ -7967,20 +8356,8 @@ intel aso rexr rexx rexb - 0f 79 /m=16 - Gd Ed - def64 - - - aso rexr rexx rexb - 0f 79 /m=32 - Gd Ed - def64 - - - aso rexr rexx rexb - 0f 79 /m=64 - Gq Eq + 0f 79 + Gy Ey def64 @@ -8067,49 +8444,56 @@ oso rexw rexb 90 - rAXr8 rAX + R0v rAX oso rexw rexb 91 - rCXr9 rAX + R1v rAX oso rexw rexb 92 - rDXr10 rAX + R2v rAX oso rexw rexb 93 - rBXr11 rAX + R3v rAX oso rexw rexb 94 - rSPr12 rAX + R4v rAX oso rexw rexb 95 - rBPr13 rAX + R5v rAX oso rexw rexb 96 - rSIr14 rAX + R6v rAX oso rexw rexb 97 - rDIr15 rAX + R7v rAX + xgetbv + + 0f 01 /mod=11 /reg=2 /rm=0 + + + + xlatb - rexw + rexw seg d7 @@ -8143,8 +8527,7 @@ oso rexw 35 - rAX Iz - sext + rAX sIz aso rexr rexx rexb @@ -8154,29 +8537,28 @@ aso oso rexw rexr rexx rexb 81 /reg=6 - Ev Iz - sext + Ev sIz aso rexr rexx rexb - 82 /reg=6 + 82 /reg=6 /m=!64 Eb Ib inv64 aso oso rexw rexr rexx rexb 83 /reg=6 - Ev Ib - sext + Ev sIb xorpd - aso rexr rexx rexb - sse66 0f 57 - V W + aso rexr rexx rexb vexl + /sse=66 0f 57 + V H W + sse2 avx @@ -8185,7 +8567,8 @@ aso rexr rexx rexb 0f 57 - V W + V H W + sse2 avx @@ -8225,6 +8608,31 @@ + xrstor + + aso rexw rexr rexx rexb + 0f ae /reg=5 /mod=!11 + M + + + + + xsave + + aso rexw rexr rexx rexb + 0f ae /reg=4 /mod=!11 + M + + + + + xsetbv + + 0f 01 /mod=11 /reg=2 /rm=1 + + + + xsha1 0f a6 /mod=11 /rm=0 /reg=1 @@ -8246,7 +8654,25 @@ - db + pclmulqdq + + aso rexr rexx rexb + /sse=66 0f 3a 44 + V H W Ib + aesni avx + + + + + + + getsec + smx + + 0f 37 + - - addsubpd + haddpd - aso rexr rexx rexb - sse66 0f d0 - V W + aso rexr rexx rexb vexl + /sse=66 0f 7c + V H W + sse3 avx - addsubps + haddps - aso rexr rexx rexb - ssef2 0f d0 - V W + aso rexr rexx rexb vexl + /sse=f2 0f 7c + V H W + sse3 avx - haddpd + hsubpd - aso rexr rexx rexb - sse66 0f 7c - V W + aso rexr rexx rexb vexl + /sse=66 0f 7d + V H W + sse3 avx - haddps + hsubps - aso rexr rexx rexb - ssef2 0f 7c - V W + aso rexr rexx rexb vexl + /sse=f2 0f 7d + V H W + sse3 avx - hsubpd + insertps - aso rexr rexx rexb - sse66 0f 7d - V W + aso rexr rexw rexx rexb + /sse=66 0f 3a 21 + V H Md Ib + sse4.1 avx - hsubps + lddqu - aso rexr rexx rexb - ssef2 0f 7d - V W + aso rexr rexx rexb vexl + /sse=f2 0f f0 + V M + sse3 avx @@ -8466,41 +8915,46 @@ movddup aso rexr rexx rexb - ssef2 0f 12 /mod=11 + /sse=f2 0f 12 /mod=11 V W aso rexr rexx rexb - ssef2 0f 12 /mod=!11 + /sse=f2 0f 12 /mod=!11 V W + sse3 avx movshdup - aso rexr rexx rexb - ssef3 0f 16 /mod=11 + aso rexr rexx rexb vexl + /sse=f3 0f 16 /mod=11 V W + sse3 avx - aso rexr rexx rexb - ssef3 0f 16 /mod=!11 + aso rexr rexx rexb vexl + /sse=f3 0f 16 /mod=!11 V W + sse3 avx movsldup - aso rexr rexx rexb - ssef3 0f 12 /mod=11 + aso rexr rexx rexb vexl + /sse=f3 0f 12 /mod=11 V W + sse3 avx - aso rexr rexx rexb - ssef3 0f 12 /mod=!11 + aso rexr rexx rexb vexl + /sse=f3 0f 12 /mod=!11 V W + sse3 avx @@ -8514,11 +8968,13 @@ aso rexr rexx rexb 0f 38 1c P Q + ssse3 - aso rexr rexx rexb - sse66 0f 38 1c + aso rexr rexx rexb vexl + /sse=66 0f 38 1c V W + ssse3 avx @@ -8528,11 +8984,13 @@ aso rexr rexx rexb 0f 38 1d P Q + ssse3 - aso rexr rexx rexb - sse66 0f 38 1d + aso rexr rexx rexb vexl + /sse=66 0f 38 1d V W + ssse3 avx @@ -8542,16 +9000,18 @@ aso rexr rexx rexb 0f 38 1e P Q + ssse3 - aso rexr rexx rexb - sse66 0f 38 1e + aso rexr rexx rexb vexl + /sse=66 0f 38 1e V W + ssse3 avx - psignb + pshufb aso rexr rexx rexb 0f 38 00 @@ -8559,8 +9019,9 @@ aso rexr rexx rexb - sse66 0f 38 00 - V W + /sse=66 0f 38 00 + V H W + ssse3 avx @@ -8573,8 +9034,9 @@ aso rexr rexx rexb - sse66 0f 38 01 - V W + /sse=66 0f 38 01 + V H W + ssse3 avx @@ -8587,8 +9049,9 @@ aso rexr rexx rexb - sse66 0f 38 02 - V W + /sse=66 0f 38 02 + V H W + ssse3 avx @@ -8601,8 +9064,9 @@ aso rexr rexx rexb - sse66 0f 38 03 - V W + /sse=66 0f 38 03 + V H W + ssse3 avx @@ -8615,8 +9079,9 @@ aso rexr rexx rexb - sse66 0f 38 04 - V W + /sse=66 0f 38 04 + V H W + ssse3 avx @@ -8629,8 +9094,9 @@ aso rexr rexx rexb - sse66 0f 38 05 - V W + /sse=66 0f 38 05 + V H W + ssse3 avx @@ -8643,8 +9109,9 @@ aso rexr rexx rexb - sse66 0f 38 06 - V W + /sse=66 0f 38 06 + V H W + ssse3 avx @@ -8657,8 +9124,9 @@ aso rexr rexx rexb - sse66 0f 38 07 - V W + /sse=66 0f 38 07 + V H W + ssse3 avx @@ -8671,8 +9139,9 @@ aso rexr rexx rexb - sse66 0f 38 08 - V W + /sse=66 0f 38 08 + V H W + ssse3 avx @@ -8685,8 +9154,9 @@ aso rexr rexx rexb - sse66 0f 38 0a - V W + /sse=66 0f 38 0a + V H W + ssse3 avx @@ -8699,8 +9169,9 @@ aso rexr rexx rexb - sse66 0f 38 09 - V W + /sse=66 0f 38 09 + V H W + ssse3 avx @@ -8713,8 +9184,9 @@ aso rexr rexx rexb - sse66 0f 38 0b - V W + /sse=66 0f 38 0b + V H W + ssse3 avx @@ -8727,8 +9199,9 @@ aso rexr rexx rexb - sse66 0f 3a 0f - V W Ib + /sse=66 0f 3a 0f + V H W Ib + ssse3 avx @@ -8740,8 +9213,9 @@ pblendvb aso rexr rexx rexb - sse66 0f 38 10 + /sse=66 0f 38 10 V W + sse4.1 @@ -8749,8 +9223,9 @@ pmuldq aso rexr rexx rexb - sse66 0f 38 28 - V W + /sse=66 0f 38 28 + V H W + sse4.1 avx @@ -8758,8 +9233,9 @@ pminsb aso rexr rexx rexb - sse66 0f 38 38 - V W + /sse=66 0f 38 38 + V H W + sse4.1 avx @@ -8767,8 +9243,9 @@ pminsd aso rexr rexx rexb - sse66 0f 38 39 - V W + /sse=66 0f 38 39 + V H W + sse4.1 avx @@ -8776,8 +9253,9 @@ pminuw aso rexr rexx rexb - sse66 0f 38 3a - V W + /sse=66 0f 38 3a + V H W + sse4.1 avx @@ -8785,8 +9263,9 @@ pminud aso rexr rexx rexb - sse66 0f 38 3b - V W + /sse=66 0f 38 3b + V H W + sse4.1 avx @@ -8794,8 +9273,9 @@ pmaxsb aso rexr rexx rexb - sse66 0f 38 3c - V W + /sse=66 0f 38 3c + V H W + sse4.1 avx @@ -8803,8 +9283,9 @@ pmaxsd aso rexr rexx rexb - sse66 0f 38 3d - V W + /sse=66 0f 38 3d + V H W + sse4.1 avx @@ -8812,8 +9293,19 @@ pmaxud aso rexr rexx rexb - sse66 0f 38 3f - V W + /sse=66 0f 38 3f + V H W + sse4.1 avx + + + + + pmaxuw + + aso rexr rexx rexb + /sse=66 0f 38 3e + V H W + sse4.1 avx @@ -8821,8 +9313,9 @@ pmulld aso rexr rexx rexb - sse66 0f 38 40 - V W + /sse=66 0f 38 40 + V H W + sse4.1 avx @@ -8830,26 +9323,29 @@ phminposuw aso rexr rexx rexb - sse66 0f 38 41 + /sse=66 0f 38 41 V W + sse4.1 avx roundps - aso rexr rexx rexb - sse66 0f 3a 08 + aso rexr rexx rexb vexl + /sse=66 0f 3a 08 V W Ib + sse avx roundpd - aso rexr rexx rexb - sse66 0f 3a 09 + aso rexr rexx rexb vexl + /sse=66 0f 3a 09 V W Ib + sse4.1 avx @@ -8857,8 +9353,9 @@ roundss aso rexr rexx rexb - sse66 0f 3a 0a - V W Ib + /sse=66 0f 3a 0a + V H W Ib + sse4.1 avx @@ -8866,89 +9363,448 @@ roundsd aso rexr rexx rexb - sse66 0f 3a 0b - V W Ib + /sse=66 0f 3a 0b + V H W Ib + sse4.1 avx blendpd - aso rexr rexx rexb - sse66 0f 3a 0d - V W Ib + aso rexr rexx rexb vexl + /sse=66 0f 3a 0d + V H W Ib + sse4.1 avx - pblendw + blendps aso rexr rexx rexb - sse66 0f 3a 0e - V W Ib + /sse=66 0f 3a 0c + V H W Ib + sse4.1 avx - blendps + blendvpd aso rexr rexx rexb - sse66 0f 3a 0c - V W Ib + /sse=66 0f 38 15 + V W + sse4.1 - blendvpd + blendvps aso rexr rexx rexb - sse66 0f 38 15 + /sse=66 0f 38 14 V W + sse4.1 - blendvps + bound + + aso oso + 62 /m=!64 + Gv M + + + + + bsf + + aso oso rexw rexr rexx rexb + 0f bc + Gv Ev + + + + + bsr + + aso oso rexw rexr rexx rexb + 0f bd + Gv Ev + + + + + bswap + + oso rexw rexb + 0f c8 + R0y + + + oso rexw rexb + 0f c9 + R1y + + + oso rexw rexb + 0f ca + R2y + + + oso rexw rexb + 0f cb + R3y + + + oso rexw rexb + 0f cc + R4y + + + oso rexw rexb + 0f cd + R5y + + + oso rexw rexb + 0f ce + R6y + + + oso rexw rexb + 0f cf + R7y + + + + + bt + + aso oso rexw rexr rexx rexb + 0f ba /reg=4 + Ev Ib + + + aso oso rexw rexr rexx rexb + 0f a3 + Ev Gv + + + + + btc + + aso oso rexw rexr rexx rexb + 0f bb + Ev Gv + + + aso oso rexw rexr rexx rexb + 0f ba /reg=7 + Ev Ib + + + + + btr + + aso oso rexw rexr rexx rexb + 0f b3 + Ev Gv + + + aso oso rexw rexr rexx rexb + 0f ba /reg=6 + Ev Ib + + + + + bts + + aso oso rexw rexr rexx rexb + 0f ab + Ev Gv + + + aso oso rexw rexr rexx rexb + 0f ba /reg=5 + Ev Ib + + + + + pblendw aso rexr rexx rexb - sse66 0f 38 14 + /sse=66 0f 3a 0e + V H W Ib + sse4.1 avx + + + + + mpsadbw + + aso rexr rexx rexb vexl + /sse=66 0f 3a 42 + V H W Ib + sse4.1 avx + + + + + movntdqa + + aso rexr rexw rexx rexb vexl + /sse=66 0f 38 2a + V M + sse4.1 avx + + + + + packusdw + + aso rexr rexw rexx rexb vexl + /sse=66 0f 38 2b + V H W + sse2 avx + + + + + pmovsxbw + + aso rexr rexw rexx rexb + /sse=66 0f 38 20 + V MqU + sse4.1 avx + + + + + pmovsxbd + + aso rexr rexw rexx rexb + /sse=66 0f 38 21 + V MdU + sse4.1 avx + + + + + pmovsxbq + + aso rexr rexw rexx rexb + /sse=66 0f 38 22 + V MwU + sse4.1 avx + + + + + pmovsxwd + + aso rexr rexw rexx rexb + /sse=66 0f 38 23 + V MqU + sse4.1 avx + + + + + pmovsxwq + + aso rexr rexw rexx rexb + /sse=66 0f 38 24 + V MdU + sse4.1 avx + + + + + pmovsxdq + + aso rexr rexw rexx rexb + /sse=66 0f 38 25 + V MqU + sse4.1 + + + + + pmovzxbw + + aso rexr rexw rexx rexb + /sse=66 0f 38 30 + V MqU + sse4.1 avx + + + + + pmovzxbd + + aso rexr rexw rexx rexb + /sse=66 0f 38 31 + V MdU + sse4.1 avx + + + + + pmovzxbq + + aso rexr rexw rexx rexb + /sse=66 0f 38 32 + V MwU + sse4.1 avx + + + + + pmovzxwd + + aso rexr rexw rexx rexb + /sse=66 0f 38 33 + V MqU + sse4.1 avx + + + + + pmovzxwq + + aso rexr rexw rexx rexb + /sse=66 0f 38 34 + V MdU + sse4.1 avx + + + + + pmovzxdq + + aso rexr rexw rexx rexb + /sse=66 0f 38 35 + V MqU + sse4.1 avx + + + + + pcmpeqq + + aso rexr rexw rexx rexb + /sse=66 0f 38 29 + V H W + sse4.1 avx + + + + + popcnt + + aso oso rexr rexw rexx rexb + /sse=f3 0f b8 + Gv Ev + + sse4.2 + + + + ptest + + aso rexr rexw rexx rexb vexl + /sse=66 0f 38 17 V W + sse4.1 avx - dpps + pcmpestri - aso rexr rexx rexb - sse66 0f 3a 40 + aso rexr rexw rexx rexb + /sse=66 0f 3a 61 V W Ib + sse4.2 avx - dppd + pcmpestrm - aso rexr rexx rexb - sse66 0f 3a 41 + aso rexr rexw rexx rexb + /sse=66 0f 3a 60 V W Ib + sse4.2 avx - mpsadbw + pcmpgtq - aso rexr rexx rexb - sse66 0f 3a 42 + aso rexr rexw rexx rexb + /sse=66 0f 38 37 + V H W + sse4.2 avx + + + + + pcmpistri + + aso rexr rexw rexx rexb + /sse=66 0f 3a 63 V W Ib + sse4.2 avx - extractps + pcmpistrm - aso rexr rexw rexb - sse66 0f 3a 17 - MdRy V Ib + aso rexr rexw rexx rexb + /sse=66 0f 3a 62 + V W Ib + sse4.2 avx + + + + + movbe + + aso oso rexr rexw rexx rexb + 0f 38 f0 + Gv Mv + sse3 atom + + + aso oso rexr rexw rexx rexb + 0f 38 f1 + Mv Gv + sse3 atom + + + + + crc32 + + aso oso rexr rexw rexx rexb + /sse=f2 0f 38 f0 + Gy Eb + sse4.2 + + + aso oso rexr rexw rexx rexb + /sse=f2 0f 38 f1 + Gy Ev + sse4.2 @@ -8956,4 +9812,288 @@ invalid + + vbroadcastss + + aso rexr rexx rexb vexl + /vex=66_0f38 18 /vexw=0 + V Md + avx + + + + + vbroadcastsd + + aso rexr rexx rexb vexl + /vex=66_0f38 19 /vexw=0 /vexl=1 + Vqq Mq + avx + + + + + vextractf128 + + aso rexr rexx rexb vexl + /vex=66_0f3a 19 /vexw=0 /vexl=1 + Wdq Vqq Ib + avx + + + + + vinsertf128 + + aso rexr rexx rexb vexl + /vex=66_0f3a 18 /vexw=0 /vexl=1 + Vqq Hqq Wdq Ib + avx + + + + + vmaskmovps + + aso rexr rexx rexb vexl + /vex=66_0f38 2c /vexw=0 + V H M + avx + + + aso rexr rexx rexb vexl + /vex=66_0f38 2e /vexw=0 + M H V + avx + + + + + vmaskmovpd + + aso rexr rexx rexb vexl + /vex=66_0f38 2d /vexw=0 + V H M + avx + + + aso rexr rexx rexb vexl + /vex=66_0f38 2f /vexw=0 + M H V + avx + + + + + vpermilpd + + aso rexr rexx rexb vexl + /vex=66_0f38 0d /vexw=0 + Vx Hx Wx + avx + + + aso rexr rexx rexb vexl + /vex=66_0f3a 05 /vexw=0 + V W Ib + avx + + + + + vpermilps + + aso rexr rexx rexb vexl + /vex=66_0f38 0c /vexw=0 + Vx Hx Wx + avx + + + aso rexr rexx rexb vexl + /vex=66_0f3a 04 /vexw=0 + Vx Wx Ib + avx + + + + + vperm2f128 + + aso rexr rexx rexb vexl + /vex=66_0f3a 06 /vexw=0 /vexl=1 + Vqq Hqq Wqq Ib + avx + + + + + vtestps + + aso rexr rexx rexb vexl + /vex=66_0f38 0e /vexw=0 + Vx Wx + avx + + + + + vtestpd + + aso rexr rexx rexb vexl + /vex=66_0f38 0f /vexw=0 + Vx Wx + avx + + + + + vzeroupper + + /vex=0f 77 /vexl=0 + avx + + + + + vzeroall + + /vex=0f 77 /vexl=1 + avx + + + + + vblendvpd + + aso rexr rexx rexb vexl + /vex=66_0f3a 4b /vexw=0 + Vx Hx Wx Lx + avx + + + + + vblendvps + + aso rexr rexx rexb vexl + /vex=66_0f3a 4a /vexw=0 + Vx Hx Wx Lx + avx + + + + + vmovsd + + aso rexr rexx rexb + /vex=f2_0f 10 /mod=11 + V H U + avx + + + aso rexr rexx rexb + /vex=f2_0f 10 /mod=!11 + V Mq + avx + + + aso rexr rexx rexb + /vex=f2_0f 11 /mod=11 + U H V + avx + + + aso rexr rexx rexb + /vex=f2_0f 11 /mod=!11 + Mq V + avx + + + + + vmovss + + aso rexr rexx rexb + /vex=f3_0f 10 /mod=11 + V H U + avx + + + aso rexr rexx rexb + /vex=f3_0f 10 /mod=!11 + V Md + avx + + + aso rexr rexx rexb + /vex=f3_0f 11 /mod=11 + U H V + avx + + + aso rexr rexx rexb + /vex=f3_0f 11 /mod=!11 + Md V + avx + + + + + vpblendvb + + aso rexr rexx rexb + /vex=66_0f3a 4c /vexw=0 + V H W L + avx + + + + + vpsllw + + aso rexr rexx rexb + /vex=66_0f f1 /vexl=0 + V H W + avx + + + aso rexr rexx rexb + /vex=66_0f 71 /reg=6 /vexl=0 + H V W + avx + + + + + vpslld + + aso rexr rexx rexb + /vex=66_0f f2 /vexl=0 + V H W + avx + + + aso rexr rexx rexb + /vex=66_0f 72 /reg=6 /vexl=0 + H V W + avx + + + + + vpsllq + + aso rexr rexx rexb + /vex=66_0f f3 /vexl=0 + V H W + avx + + + aso rexr rexx rexb + /vex=66_0f 73 /reg=6 /vexl=0 + H V W + avx + + + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86.c webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86.c 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86.c 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ /* udis86 - libudis86/udis86.c * - * Copyright (c) 2002-2009 Vivek Thampi + * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,16 +28,19 @@ #if USE(UDIS86) -#include "udis86_input.h" +#include "udis86_udint.h" #include "udis86_extern.h" +#include "udis86_decode.h" -#ifndef __UD_STANDALONE__ -# include -# include -#endif /* __UD_STANDALONE__ */ +#if !defined(__UD_STANDALONE__) +#include +#endif /* !__UD_STANDALONE__ */ + +static void ud_inp_init(struct ud *u); /* ============================================================================= - * ud_init() - Initializes ud_t object. + * ud_init + * Initializes ud_t object. * ============================================================================= */ extern void @@ -50,30 +53,34 @@ #ifndef __UD_STANDALONE__ ud_set_input_file(u, stdin); #endif /* __UD_STANDALONE__ */ + + ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); } + /* ============================================================================= - * ud_disassemble() - disassembles one instruction and returns the number of - * bytes disassembled. A zero means end of disassembly. + * ud_disassemble + * Disassembles one instruction and returns the number of + * bytes disassembled. A zero means end of disassembly. * ============================================================================= */ extern unsigned int ud_disassemble(struct ud* u) { - if (ud_input_end(u)) - return 0; - - - u->insn_buffer[0] = u->insn_hexcode[0] = 0; - - - if (ud_decode(u) == 0) - return 0; - if (u->translator) - u->translator(u); - return ud_insn_len(u); + int len; + if (u->inp_end) { + return 0; + } + if ((len = ud_decode(u)) > 0) { + if (u->translator != NULL) { + u->asm_buf[0] = '\0'; + u->translator(u); + } + } + return len; } + /* ============================================================================= * ud_set_mode() - Set Disassemly Mode. * ============================================================================= @@ -82,10 +89,10 @@ ud_set_mode(struct ud* u, uint8_t m) { switch(m) { - case 16: - case 32: - case 64: u->dis_mode = m ; return; - default: u->dis_mode = 16; return; + case 16: + case 32: + case 64: u->dis_mode = m ; return; + default: u->dis_mode = 16; return; } } @@ -97,14 +104,14 @@ ud_set_vendor(struct ud* u, unsigned v) { switch(v) { - case UD_VENDOR_INTEL: - u->vendor = v; - break; - case UD_VENDOR_ANY: - u->vendor = v; - break; - default: - u->vendor = UD_VENDOR_AMD; + case UD_VENDOR_INTEL: + u->vendor = v; + break; + case UD_VENDOR_ANY: + u->vendor = v; + break; + default: + u->vendor = UD_VENDOR_AMD; } } @@ -132,18 +139,18 @@ * ud_insn() - returns the disassembled instruction * ============================================================================= */ -extern char* -ud_insn_asm(struct ud* u) +const char* +ud_insn_asm(const struct ud* u) { - return u->insn_buffer; + return u->asm_buf; } /* ============================================================================= * ud_insn_offset() - Returns the offset. * ============================================================================= */ -extern uint64_t -ud_insn_off(struct ud* u) +uint64_t +ud_insn_off(const struct ud* u) { return u->insn_offset; } @@ -153,30 +160,303 @@ * ud_insn_hex() - Returns hex form of disassembled instruction. * ============================================================================= */ -extern char* +const char* ud_insn_hex(struct ud* u) { + u->insn_hexcode[0] = 0; + if (!u->error) { + unsigned int i; + const unsigned char *src_ptr = ud_insn_ptr(u); + char* src_hex; + src_hex = (char*) u->insn_hexcode; + /* for each byte used to decode instruction */ + for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; + ++i, ++src_ptr) { + sprintf(src_hex, "%02x", *src_ptr & 0xFF); + src_hex += 2; + } + } return u->insn_hexcode; } + /* ============================================================================= - * ud_insn_ptr() - Returns code disassembled. + * ud_insn_ptr + * Returns a pointer to buffer containing the bytes that were + * disassembled. * ============================================================================= */ -extern uint8_t* -ud_insn_ptr(struct ud* u) +extern const uint8_t* +ud_insn_ptr(const struct ud* u) { - return u->inp_sess; + return (u->inp_buf == NULL) ? + u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); } + /* ============================================================================= - * ud_insn_len() - Returns the count of bytes disassembled. + * ud_insn_len + * Returns the count of bytes disassembled. * ============================================================================= */ extern unsigned int -ud_insn_len(struct ud* u) +ud_insn_len(const struct ud* u) { return u->inp_ctr; } + +/* ============================================================================= + * ud_insn_get_opr + * Return the operand struct representing the nth operand of + * the currently disassembled instruction. Returns NULL if + * there's no such operand. + * ============================================================================= + */ +const struct ud_operand* +ud_insn_opr(const struct ud *u, unsigned int n) +{ + if (n > 3 || u->operand[n].type == UD_NONE) { + return NULL; + } else { + return &u->operand[n]; + } +} + + +/* ============================================================================= + * ud_opr_is_sreg + * Returns non-zero if the given operand is of a segment register type. + * ============================================================================= + */ +int +ud_opr_is_sreg(const struct ud_operand *opr) +{ + return opr->type == UD_OP_REG && + opr->base >= UD_R_ES && + opr->base <= UD_R_GS; +} + + +/* ============================================================================= + * ud_opr_is_sreg + * Returns non-zero if the given operand is of a general purpose + * register type. + * ============================================================================= + */ +int +ud_opr_is_gpr(const struct ud_operand *opr) +{ + return opr->type == UD_OP_REG && + opr->base >= UD_R_AL && + opr->base <= UD_R_R15; +} + + +/* ============================================================================= + * ud_set_user_opaque_data + * ud_get_user_opaque_data + * Get/set user opaqute data pointer + * ============================================================================= + */ +void +ud_set_user_opaque_data(struct ud * u, void* opaque) +{ + u->user_opaque_data = opaque; +} + +void* +ud_get_user_opaque_data(const struct ud *u) +{ + return u->user_opaque_data; +} + + +/* ============================================================================= + * ud_set_asm_buffer + * Allow the user to set an assembler output buffer. If `buf` is NULL, + * we switch back to the internal buffer. + * ============================================================================= + */ +void +ud_set_asm_buffer(struct ud *u, char *buf, size_t size) +{ + if (buf == NULL) { + ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); + } else { + u->asm_buf = buf; + u->asm_buf_size = size; + } +} + + +/* ============================================================================= + * ud_set_sym_resolver + * Set symbol resolver for relative targets used in the translation + * phase. + * + * The resolver is a function that takes a uint64_t address and returns a + * symbolic name for the that address. The function also takes a second + * argument pointing to an integer that the client can optionally set to a + * non-zero value for offsetted targets. (symbol+offset) The function may + * also return NULL, in which case the translator only prints the target + * address. + * + * The function pointer maybe NULL which resets symbol resolution. + * ============================================================================= + */ +void +ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, + uint64_t addr, + int64_t *offset)) +{ + u->sym_resolver = resolver; +} + + +/* ============================================================================= + * ud_insn_mnemonic + * Return the current instruction mnemonic. + * ============================================================================= + */ +enum ud_mnemonic_code +ud_insn_mnemonic(const struct ud *u) +{ + return u->mnemonic; +} + + +/* ============================================================================= + * ud_lookup_mnemonic + * Looks up mnemonic code in the mnemonic string table. + * Returns NULL if the mnemonic code is invalid. + * ============================================================================= + */ +const char* +ud_lookup_mnemonic(enum ud_mnemonic_code c) +{ + if (c < UD_MAX_MNEMONIC_CODE) { + return ud_mnemonics_str[c]; + } else { + return NULL; + } +} + + +/* + * ud_inp_init + * Initializes the input system. + */ +static void +ud_inp_init(struct ud *u) +{ + u->inp_hook = NULL; + u->inp_buf = NULL; + u->inp_buf_size = 0; + u->inp_buf_index = 0; + u->inp_curr = 0; + u->inp_ctr = 0; + u->inp_end = 0; + u->inp_peek = UD_EOI; + UD_NON_STANDALONE(u->inp_file = NULL); +} + + +/* ============================================================================= + * ud_inp_set_hook + * Sets input hook. + * ============================================================================= + */ +void +ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) +{ + ud_inp_init(u); + u->inp_hook = hook; +} + +/* ============================================================================= + * ud_inp_set_buffer + * Set buffer as input. + * ============================================================================= + */ +void +ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) +{ + ud_inp_init(u); + u->inp_buf = buf; + u->inp_buf_size = len; + u->inp_buf_index = 0; +} + + +#ifndef __UD_STANDALONE__ +/* ============================================================================= + * ud_input_set_file + * Set FILE as input. + * ============================================================================= + */ +static int +inp_file_hook(struct ud* u) +{ + return fgetc(u->inp_file); +} + +void +ud_set_input_file(register struct ud* u, FILE* f) +{ + ud_inp_init(u); + u->inp_hook = inp_file_hook; + u->inp_file = f; +} +#endif /* __UD_STANDALONE__ */ + + +/* ============================================================================= + * ud_input_skip + * Skip n input bytes. + * ============================================================================ + */ +void +ud_input_skip(struct ud* u, size_t n) +{ + if (u->inp_end) { + return; + } + if (u->inp_buf == NULL) { + while (n--) { + int c = u->inp_hook(u); + if (c == UD_EOI) { + goto eoi; + } + } + return; + } else { + if (n > u->inp_buf_size || + u->inp_buf_index > u->inp_buf_size - n) { + u->inp_buf_index = u->inp_buf_size; + goto eoi; + } + u->inp_buf_index += n; + return; + } +eoi: + u->inp_end = 1; + UDERR(u, "cannot skip, eoi received\b"); + return; +} + + +/* ============================================================================= + * ud_input_end + * Returns non-zero on end-of-input. + * ============================================================================= + */ +int +ud_input_end(const struct ud *u) +{ + return u->inp_end; +} + #endif // USE(UDIS86) + +/* vim:set ts=2 sw=2 expandtab */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c 2016-09-16 09:56:47.000000000 +0000 @@ -28,14 +28,10 @@ #if USE(UDIS86) -#include "udis86_extern.h" +#include "udis86_udint.h" #include "udis86_types.h" -#include "udis86_input.h" +#include "udis86_extern.h" #include "udis86_decode.h" -#include - -#define dbg(x, n...) -/* #define dbg printf */ #ifndef __UD_STANDALONE__ # include @@ -44,15 +40,164 @@ /* The max number of prefixes to an instruction */ #define MAX_PREFIXES 15 -/* instruction aliases and special cases */ -static struct ud_itab_entry s_ie__invalid = - { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }; +/* rex prefix bits */ +#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) +#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) +#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) +#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) +#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ + ( P_REXR(n) << 2 ) | \ + ( P_REXX(n) << 1 ) | \ + ( P_REXB(n) << 0 ) ) + +/* scable-index-base bits */ +#define SIB_S(b) ( ( b ) >> 6 ) +#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) +#define SIB_B(b) ( ( b ) & 7 ) + +/* modrm bits */ +#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) +#define MODRM_RM(b) ( ( b ) & 7 ) + +static int decode_ext(struct ud *u, uint16_t ptr); +static int decode_opcode(struct ud *u); + +enum reg_class { /* register classes */ + REGCLASS_GPR, + REGCLASS_MMX, + REGCLASS_CR, + REGCLASS_DB, + REGCLASS_SEG, + REGCLASS_XMM +}; + + /* + * inp_start + * Should be called before each de-code operation. + */ +static void +inp_start(struct ud *u) +{ + u->inp_ctr = 0; +} -static int -decode_ext(struct ud *u, uint16_t ptr); +static uint8_t +inp_peek(struct ud *u) +{ + if (u->inp_end == 0) { + if (u->inp_buf != NULL) { + if (u->inp_buf_index < u->inp_buf_size) { + return u->inp_buf[u->inp_buf_index]; + } + } else if (u->inp_peek != UD_EOI) { + return u->inp_peek; + } else { + int c; + if ((c = u->inp_hook(u)) != UD_EOI) { + u->inp_peek = c; + return u->inp_peek; + } + } + } + u->inp_end = 1; + UDERR(u, "byte expected, eoi received\n"); + return 0; +} + +static uint8_t +inp_next(struct ud *u) +{ + if (u->inp_end == 0) { + if (u->inp_buf != NULL) { + if (u->inp_buf_index < u->inp_buf_size) { + u->inp_ctr++; + return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); + } + } else { + int c = u->inp_peek; + if (c != UD_EOI || (c = u->inp_hook(u)) != UD_EOI) { + u->inp_peek = UD_EOI; + u->inp_curr = c; + u->inp_sess[u->inp_ctr++] = u->inp_curr; + return u->inp_curr; + } + } + } + u->inp_end = 1; + UDERR(u, "byte expected, eoi received\n"); + return 0; +} + +static uint8_t +inp_curr(struct ud *u) +{ + return u->inp_curr; +} + + +/* + * inp_uint8 + * int_uint16 + * int_uint32 + * int_uint64 + * Load little-endian values from input + */ +static uint8_t +inp_uint8(struct ud* u) +{ + return inp_next(u); +} + +static uint16_t +inp_uint16(struct ud* u) +{ + uint16_t r, ret; + ret = inp_next(u); + r = inp_next(u); + return ret | (r << 8); +} -static inline int +static uint32_t +inp_uint32(struct ud* u) +{ + uint32_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + return ret | (r << 24); +} + +static uint64_t +inp_uint64(struct ud* u) +{ + uint64_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + ret = ret | (r << 24); + r = inp_next(u); + ret = ret | (r << 32); + r = inp_next(u); + ret = ret | (r << 40); + r = inp_next(u); + ret = ret | (r << 48); + r = inp_next(u); + return ret | (r << 56); +} + + +static UD_INLINE int eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) { if (dis_mode == 64) { @@ -60,13 +205,13 @@ } else if (dis_mode == 32) { return pfx_opr ? 16 : 32; } else { - ASSERT(dis_mode == 16); + UD_ASSERT(dis_mode == 16); return pfx_opr ? 32 : 16; } } -static inline int +static UD_INLINE int eff_adr_mode(int dis_mode, int pfx_adr) { if (dis_mode == 64) { @@ -74,21 +219,12 @@ } else if (dis_mode == 32) { return pfx_adr ? 16 : 32; } else { - ASSERT(dis_mode == 16); + UD_ASSERT(dis_mode == 16); return pfx_adr ? 32 : 16; } } -/* Looks up mnemonic code in the mnemonic string table - * Returns NULL if the mnemonic code is invalid - */ -const char * ud_lookup_mnemonic( enum ud_mnemonic_code c ) -{ - return ud_mnemonics_str[ c ]; -} - - /* * decode_prefixes * @@ -97,164 +233,128 @@ static int decode_prefixes(struct ud *u) { - unsigned int have_pfx = 1; - unsigned int i; - uint8_t curr; - - /* if in error state, bail out */ - if ( u->error ) - return -1; - - /* keep going as long as there are prefixes available */ - for ( i = 0; have_pfx ; ++i ) { - - /* Get next byte. */ - ud_inp_next(u); - if ( u->error ) - return -1; - curr = ud_inp_curr( u ); - - /* rex prefixes in 64bit mode */ - if ( u->dis_mode == 64 && ( curr & 0xF0 ) == 0x40 ) { - u->pfx_rex = curr; - } else { - switch ( curr ) - { - case 0x2E : - u->pfx_seg = UD_R_CS; - u->pfx_rex = 0; - break; - case 0x36 : - u->pfx_seg = UD_R_SS; - u->pfx_rex = 0; - break; - case 0x3E : - u->pfx_seg = UD_R_DS; - u->pfx_rex = 0; - break; - case 0x26 : - u->pfx_seg = UD_R_ES; - u->pfx_rex = 0; - break; - case 0x64 : - u->pfx_seg = UD_R_FS; - u->pfx_rex = 0; - break; - case 0x65 : - u->pfx_seg = UD_R_GS; - u->pfx_rex = 0; - break; - case 0x67 : /* adress-size override prefix */ - u->pfx_adr = 0x67; - u->pfx_rex = 0; - break; - case 0xF0 : - u->pfx_lock = 0xF0; - u->pfx_rex = 0; - break; - case 0x66: - /* the 0x66 sse prefix is only effective if no other sse prefix - * has already been specified. - */ - if ( !u->pfx_insn ) u->pfx_insn = 0x66; - u->pfx_opr = 0x66; - u->pfx_rex = 0; - break; - case 0xF2: - u->pfx_insn = 0xF2; - u->pfx_repne = 0xF2; - u->pfx_rex = 0; - break; - case 0xF3: - u->pfx_insn = 0xF3; - u->pfx_rep = 0xF3; - u->pfx_repe = 0xF3; - u->pfx_rex = 0; - break; - default : - /* No more prefixes */ - have_pfx = 0; - break; - } - } - - /* check if we reached max instruction length */ - if ( i + 1 == MAX_INSN_LENGTH ) { - u->error = 1; - break; - } + int done = 0; + uint8_t curr = 0, last = 0; + UD_RETURN_ON_ERROR(u); + + do { + last = curr; + curr = inp_next(u); + UD_RETURN_ON_ERROR(u); + if (u->inp_ctr == MAX_INSN_LENGTH) { + UD_RETURN_WITH_ERROR(u, "max instruction length"); } + + switch (curr) + { + case 0x2E: + u->pfx_seg = UD_R_CS; + break; + case 0x36: + u->pfx_seg = UD_R_SS; + break; + case 0x3E: + u->pfx_seg = UD_R_DS; + break; + case 0x26: + u->pfx_seg = UD_R_ES; + break; + case 0x64: + u->pfx_seg = UD_R_FS; + break; + case 0x65: + u->pfx_seg = UD_R_GS; + break; + case 0x67: /* adress-size override prefix */ + u->pfx_adr = 0x67; + break; + case 0xF0: + u->pfx_lock = 0xF0; + break; + case 0x66: + u->pfx_opr = 0x66; + break; + case 0xF2: + u->pfx_str = 0xf2; + break; + case 0xF3: + u->pfx_str = 0xf3; + break; + default: + /* consume if rex */ + done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; + break; + } + } while (!done); + /* rex prefixes in 64bit mode, must be the last prefix */ + if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { + u->pfx_rex = last; + } + return 0; +} - /* return status */ - if ( u->error ) - return -1; - /* rewind back one byte in stream, since the above loop - * stops with a non-prefix byte. - */ - ud_inp_back(u); - return 0; +/* + * vex_l, vex_w + * Return the vex.L and vex.W bits + */ +static UD_INLINE uint8_t +vex_l(const struct ud *u) +{ + UD_ASSERT(u->vex_op != 0); + return ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 2) & 1; } +static UD_INLINE uint8_t +vex_w(const struct ud *u) +{ + UD_ASSERT(u->vex_op != 0); + return u->vex_op == 0xc4 ? ((u->vex_b2 >> 7) & 1) : 0; +} -static inline unsigned int modrm( struct ud * u ) + +static UD_INLINE uint8_t +modrm(struct ud * u) { if ( !u->have_modrm ) { - u->modrm = ud_inp_next( u ); + u->modrm = inp_next( u ); + u->modrm_offset = (uint8_t) (u->inp_ctr - 1); u->have_modrm = 1; } return u->modrm; } -static unsigned int resolve_operand_size( const struct ud * u, unsigned int s ) +static unsigned int +resolve_operand_size(const struct ud* u, ud_operand_size_t osize) { - switch ( s ) - { - case SZ_V: - return ( u->opr_mode ); - case SZ_Z: - return ( u->opr_mode == 16 ) ? 16 : 32; - case SZ_P: - return ( u->opr_mode == 16 ) ? SZ_WP : SZ_DP; - case SZ_MDQ: - return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; - case SZ_RDQ: - return ( u->dis_mode == 64 ) ? 64 : 32; - default: - return s; - } + switch (osize) { + case SZ_V: + return u->opr_mode; + case SZ_Z: + return u->opr_mode == 16 ? 16 : 32; + case SZ_Y: + return u->opr_mode == 16 ? 32 : u->opr_mode; + case SZ_RDQ: + return u->dis_mode == 64 ? 64 : 32; + case SZ_X: + UD_ASSERT(u->vex_op != 0); + return (P_VEXL(u->itab_entry->prefix) && vex_l(u)) ? SZ_QQ : SZ_DQ; + default: + return osize; + } } static int resolve_mnemonic( struct ud* u ) { - /* far/near flags */ - u->br_far = 0; - u->br_near = 0; - /* readjust operand sizes for call/jmp instrcutions */ - if ( u->mnemonic == UD_Icall || u->mnemonic == UD_Ijmp ) { - /* WP: 16:16 pointer */ - if ( u->operand[ 0 ].size == SZ_WP ) { - u->operand[ 0 ].size = 16; - u->br_far = 1; - u->br_near= 0; - /* DP: 32:32 pointer */ - } else if ( u->operand[ 0 ].size == SZ_DP ) { - u->operand[ 0 ].size = 32; - u->br_far = 1; - u->br_near= 0; - } else { - u->br_far = 0; - u->br_near= 1; - } /* resolve 3dnow weirdness. */ - } else if ( u->mnemonic == UD_I3dnow ) { - u->mnemonic = ud_itab[ u->le->table[ ud_inp_curr( u ) ] ].mnemonic; + if ( u->mnemonic == UD_I3dnow ) { + u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; } /* SWAPGS is only valid in 64bits mode */ if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { - u->error = 1; + UDERR(u, "swapgs invalid in 64bits mode\n"); return -1; } @@ -269,8 +369,8 @@ } } - if (u->mnemonic == UD_Inop && u->pfx_rep) { - u->pfx_rep = 0; + if (u->mnemonic == UD_Inop && u->pfx_repe) { + u->pfx_repe = 0; u->mnemonic = UD_Ipause; } return 0; @@ -288,14 +388,14 @@ /* seg16:off16 */ op->type = UD_OP_PTR; op->size = 32; - op->lval.ptr.off = ud_inp_uint16(u); - op->lval.ptr.seg = ud_inp_uint16(u); + op->lval.ptr.off = inp_uint16(u); + op->lval.ptr.seg = inp_uint16(u); } else { /* seg16:off32 */ op->type = UD_OP_PTR; op->size = 48; - op->lval.ptr.off = ud_inp_uint32(u); - op->lval.ptr.seg = ud_inp_uint16(u); + op->lval.ptr.off = inp_uint32(u); + op->lval.ptr.seg = inp_uint16(u); } } @@ -306,15 +406,11 @@ static enum ud_type decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) { - s = resolve_operand_size(u, s); - switch (s) { case 64: return UD_R_RAX + rm; - case SZ_DP: case 32: return UD_R_EAX + rm; - case SZ_WP: case 16: return UD_R_AX + rm; case 8: @@ -323,94 +419,103 @@ return UD_R_SPL + (rm-4); return UD_R_AL + rm; } else return UD_R_AL + rm; + case 0: + /* invalid size in case of a decode error */ + UD_ASSERT(u->error); + return UD_NONE; default: - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * resolve_gpr64() - 64bit General Purpose Register-Selection. - * ----------------------------------------------------------------------------- - */ -static enum ud_type -resolve_gpr64(struct ud* u, enum ud_operand_code gpr_op, enum ud_operand_size * size) -{ - if (gpr_op >= OP_rAXr8 && gpr_op <= OP_rDIr15) - gpr_op = (gpr_op - OP_rAXr8) | (REX_B(u->pfx_rex) << 3); - else gpr_op = (gpr_op - OP_rAX); - - if (u->opr_mode == 16) { - *size = 16; - return gpr_op + UD_R_AX; + UD_ASSERT(!"invalid operand size"); + return UD_NONE; } - if (u->dis_mode == 32 || - (u->opr_mode == 32 && ! (REX_W(u->pfx_rex) || u->default64))) { - *size = 32; - return gpr_op + UD_R_EAX; - } - - *size = 64; - return gpr_op + UD_R_RAX; } -/* ----------------------------------------------------------------------------- - * resolve_gpr32 () - 32bit General Purpose Register-Selection. - * ----------------------------------------------------------------------------- - */ -static enum ud_type -resolve_gpr32(struct ud* u, enum ud_operand_code gpr_op) -{ - gpr_op = gpr_op - OP_eAX; - - if (u->opr_mode == 16) - return gpr_op + UD_R_AX; - - return gpr_op + UD_R_EAX; -} - -/* ----------------------------------------------------------------------------- - * resolve_reg() - Resolves the register type - * ----------------------------------------------------------------------------- - */ -static enum ud_type -resolve_reg(struct ud* u, unsigned int type, unsigned char i) +static void +decode_reg(struct ud *u, + struct ud_operand *opr, + int type, + int num, + int size) { + int reg; + size = resolve_operand_size(u, size); switch (type) { - case T_MMX : return UD_R_MM0 + (i & 7); - case T_XMM : return UD_R_XMM0 + i; - case T_CRG : return UD_R_CR0 + i; - case T_DBG : return UD_R_DR0 + i; - case T_SEG : { + case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; + case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; + case REGCLASS_XMM : + reg = num + (size == SZ_QQ ? UD_R_YMM0 : UD_R_XMM0); + break; + case REGCLASS_CR : reg = UD_R_CR0 + num; break; + case REGCLASS_DB : reg = UD_R_DR0 + num; break; + case REGCLASS_SEG : { /* * Only 6 segment registers, anything else is an error. */ - if ((i & 7) > 5) { - u->error = 1; + if ((num & 7) > 5) { + UDERR(u, "invalid segment register value\n"); + return; } else { - return UD_R_ES + (i & 7); + reg = UD_R_ES + (num & 7); } + break; } - case T_NONE: - default: return UD_NONE; + default: + UD_ASSERT(!"invalid register type"); + return; } + opr->type = UD_OP_REG; + opr->base = reg; + opr->size = size; } -/* ----------------------------------------------------------------------------- - * decode_imm() - Decodes Immediate values. - * ----------------------------------------------------------------------------- + +/* + * decode_imm + * + * Decode Immediate values. */ static void -decode_imm(struct ud* u, unsigned int s, struct ud_operand *op) +decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) { - op->size = resolve_operand_size(u, s); + op->size = resolve_operand_size(u, size); op->type = UD_OP_IMM; switch (op->size) { - case 8: op->lval.sbyte = ud_inp_uint8(u); break; - case 16: op->lval.uword = ud_inp_uint16(u); break; - case 32: op->lval.udword = ud_inp_uint32(u); break; - case 64: op->lval.uqword = ud_inp_uint64(u); break; - default: return; + case 8: op->lval.sbyte = inp_uint8(u); break; + case 16: op->lval.uword = inp_uint16(u); break; + case 32: op->lval.udword = inp_uint32(u); break; + case 64: op->lval.uqword = inp_uint64(u); break; + default: return; + } +} + + +/* + * decode_mem_disp + * + * Decode mem address displacement. + */ +static void +decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) +{ + switch (size) { + case 8: + op->offset = 8; + op->lval.ubyte = inp_uint8(u); + break; + case 16: + op->offset = 16; + op->lval.uword = inp_uint16(u); + break; + case 32: + op->offset = 32; + op->lval.udword = inp_uint32(u); + break; + case 64: + op->offset = 64; + op->lval.uqword = inp_uint64(u); + break; + default: + return; } } @@ -421,21 +526,14 @@ * Decodes reg field of mod/rm byte * */ -static void +static UD_INLINE void decode_modrm_reg(struct ud *u, struct ud_operand *operand, unsigned int type, unsigned int size) { - uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); - operand->type = UD_OP_REG; - operand->size = resolve_operand_size(u, size); - - if (type == T_GPR) { - operand->base = decode_gpr(u, operand->size, reg); - } else { - operand->base = resolve_reg(u, type, reg); - } + uint8_t reg = (REX_R(u->_rex) << 3) | MODRM_REG(modrm(u)); + decode_reg(u, operand, type, reg, size); } @@ -448,67 +546,58 @@ static void decode_modrm_rm(struct ud *u, struct ud_operand *op, - unsigned char type, - unsigned int size) + unsigned char type, /* register type */ + unsigned int size) /* operand size */ { - unsigned char mod, rm, reg; + size_t offset = 0; + unsigned char mod, rm; /* get mod, r/m and reg fields */ mod = MODRM_MOD(modrm(u)); - rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); - reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); - - UNUSED_PARAM(reg); - - op->size = resolve_operand_size(u, size); + rm = (REX_B(u->_rex) << 3) | MODRM_RM(modrm(u)); /* * If mod is 11b, then the modrm.rm specifies a register. * */ if (mod == 3) { - op->type = UD_OP_REG; - if (type == T_GPR) { - op->base = decode_gpr(u, op->size, rm); - } else { - op->base = resolve_reg(u, type, (REX_B(u->pfx_rex) << 3) | (rm & 7)); - } + decode_reg(u, op, type, rm, size); return; - } - + } /* - * !11 => Memory Address + * !11b => Memory Address */ op->type = UD_OP_MEM; + op->size = resolve_operand_size(u, size); if (u->adr_mode == 64) { op->base = UD_R_RAX + rm; if (mod == 1) { - op->offset = 8; + offset = 8; } else if (mod == 2) { - op->offset = 32; + offset = 32; } else if (mod == 0 && (rm & 7) == 5) { op->base = UD_R_RIP; - op->offset = 32; + offset = 32; } else { - op->offset = 0; + offset = 0; } /* * Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { - ud_inp_next(u); + inp_next(u); - op->scale = (1 << SIB_S(ud_inp_curr(u))) & ~1; - op->index = UD_R_RAX + (SIB_I(ud_inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); - op->base = UD_R_RAX + (SIB_B(ud_inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); - + op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->_rex) << 3)); + op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->_rex) << 3)); /* special conditions for base reference */ if (op->index == UD_R_RSP) { op->index = UD_NONE; op->scale = UD_NONE; + } else { + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; } if (op->base == UD_R_RBP || op->base == UD_R_R13) { @@ -516,32 +605,35 @@ op->base = UD_NONE; } if (mod == 1) { - op->offset = 8; + offset = 8; } else { - op->offset = 32; + offset = 32; } } + } else { + op->scale = UD_NONE; + op->index = UD_NONE; } } else if (u->adr_mode == 32) { op->base = UD_R_EAX + rm; if (mod == 1) { - op->offset = 8; + offset = 8; } else if (mod == 2) { - op->offset = 32; + offset = 32; } else if (mod == 0 && rm == 5) { op->base = UD_NONE; - op->offset = 32; + offset = 32; } else { - op->offset = 0; + offset = 0; } /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { - ud_inp_next(u); + inp_next(u); - op->scale = (1 << SIB_S(ud_inp_curr(u))) & ~1; - op->index = UD_R_EAX + (SIB_I(ud_inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); - op->base = UD_R_EAX + (SIB_B(ud_inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); + op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); if (op->index == UD_R_ESP) { op->index = UD_NONE; @@ -554,11 +646,14 @@ op->base = UD_NONE; } if (mod == 1) { - op->offset = 8; + offset = 8; } else { - op->offset = 32; + offset = 32; } } + } else { + op->scale = UD_NONE; + op->index = UD_NONE; } } else { const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, @@ -567,58 +662,72 @@ UD_NONE, UD_NONE, UD_NONE, UD_NONE }; op->base = bases[rm & 7]; op->index = indices[rm & 7]; + op->scale = UD_NONE; if (mod == 0 && rm == 6) { - op->offset= 16; + offset = 16; op->base = UD_NONE; } else if (mod == 1) { - op->offset = 8; + offset = 8; } else if (mod == 2) { - op->offset = 16; + offset = 16; } } - /* - * extract offset, if any - */ - switch (op->offset) { - case 8 : op->lval.ubyte = ud_inp_uint8(u); break; - case 16: op->lval.uword = ud_inp_uint16(u); break; - case 32: op->lval.udword = ud_inp_uint32(u); break; - case 64: op->lval.uqword = ud_inp_uint64(u); break; - default: break; + if (offset) { + decode_mem_disp(u, offset, op); + } else { + op->offset = 0; } } -/* ----------------------------------------------------------------------------- - * decode_o() - Decodes offset - * ----------------------------------------------------------------------------- + +/* + * decode_moffset + * Decode offset-only memory operand */ -static void -decode_o(struct ud* u, unsigned int s, struct ud_operand *op) +static void +decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) { - switch (u->adr_mode) { - case 64: - op->offset = 64; - op->lval.uqword = ud_inp_uint64(u); - break; - case 32: - op->offset = 32; - op->lval.udword = ud_inp_uint32(u); - break; - case 16: - op->offset = 16; - op->lval.uword = ud_inp_uint16(u); - break; - default: - return; - } - op->type = UD_OP_MEM; - op->size = resolve_operand_size(u, s); + opr->type = UD_OP_MEM; + opr->base = UD_NONE; + opr->index = UD_NONE; + opr->scale = UD_NONE; + opr->size = resolve_operand_size(u, size); + decode_mem_disp(u, u->adr_mode, opr); } -/* ----------------------------------------------------------------------------- - * decode_operands() - Disassembles Operands. - * ----------------------------------------------------------------------------- + +static void +decode_vex_vvvv(struct ud *u, struct ud_operand *opr, unsigned size) +{ + uint8_t vvvv; + UD_ASSERT(u->vex_op != 0); + vvvv = ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 3) & 0xf; + decode_reg(u, opr, REGCLASS_XMM, (0xf & ~vvvv), size); +} + + +/* + * decode_vex_immreg + * Decode source operand encoded in immediate byte [7:4] + */ +static int +decode_vex_immreg(struct ud *u, struct ud_operand *opr, unsigned size) +{ + uint8_t imm = inp_next(u); + uint8_t mask = u->dis_mode == 64 ? 0xf : 0x7; + UD_RETURN_ON_ERROR(u); + UD_ASSERT(u->vex_op != 0); + decode_reg(u, opr, REGCLASS_XMM, mask & (imm >> 4), size); + return 0; +} + + +/* + * decode_operand + * + * Decodes a single operand. + * Returns the type of the operand (UD_NONE if none) */ static int decode_operand(struct ud *u, @@ -626,35 +735,33 @@ enum ud_operand_code type, unsigned int size) { + operand->type = UD_NONE; + operand->_oprcode = type; + switch (type) { case OP_A : decode_a(u, operand); break; case OP_MR: - if (MODRM_MOD(modrm(u)) == 3) { - decode_modrm_rm(u, operand, T_GPR, - size == SZ_DY ? SZ_MDQ : SZ_V); - } else if (size == SZ_WV) { - decode_modrm_rm( u, operand, T_GPR, SZ_W); - } else if (size == SZ_BV) { - decode_modrm_rm( u, operand, T_GPR, SZ_B); - } else if (size == SZ_DY) { - decode_modrm_rm( u, operand, T_GPR, SZ_D); - } else { - ASSERT(!"unexpected size"); - } + decode_modrm_rm(u, operand, REGCLASS_GPR, + MODRM_MOD(modrm(u)) == 3 ? + Mx_reg_size(size) : Mx_mem_size(size)); break; + case OP_F: + u->br_far = 1; + /* intended fall through */ case OP_M: if (MODRM_MOD(modrm(u)) == 3) { - u->error = 1; + UDERR(u, "expected modrm.mod != 3\n"); } /* intended fall through */ case OP_E: - decode_modrm_rm(u, operand, T_GPR, size); + decode_modrm_rm(u, operand, REGCLASS_GPR, size); break; case OP_G: - decode_modrm_reg(u, operand, T_GPR, size); + decode_modrm_reg(u, operand, REGCLASS_GPR, size); break; + case OP_sI: case OP_I: decode_imm(u, size, operand); break; @@ -662,96 +769,68 @@ operand->type = UD_OP_CONST; operand->lval.udword = 1; break; - case OP_PR: + case OP_N: if (MODRM_MOD(modrm(u)) != 3) { - u->error = 1; + UDERR(u, "expected modrm.mod == 3\n"); } - decode_modrm_rm(u, operand, T_MMX, size); + /* intended fall through */ + case OP_Q: + decode_modrm_rm(u, operand, REGCLASS_MMX, size); break; case OP_P: - decode_modrm_reg(u, operand, T_MMX, size); + decode_modrm_reg(u, operand, REGCLASS_MMX, size); break; - case OP_VR: + case OP_U: if (MODRM_MOD(modrm(u)) != 3) { - u->error = 1; + UDERR(u, "expected modrm.mod == 3\n"); } /* intended fall through */ case OP_W: - decode_modrm_rm(u, operand, T_XMM, size); + decode_modrm_rm(u, operand, REGCLASS_XMM, size); break; case OP_V: - decode_modrm_reg(u, operand, T_XMM, size); + decode_modrm_reg(u, operand, REGCLASS_XMM, size); break; - case OP_S: - decode_modrm_reg(u, operand, T_SEG, size); + case OP_H: + decode_vex_vvvv(u, operand, size); break; - case OP_AL: - case OP_CL: - case OP_DL: - case OP_BL: - case OP_AH: - case OP_CH: - case OP_DH: - case OP_BH: - operand->type = UD_OP_REG; - operand->base = UD_R_AL + (type - OP_AL); - operand->size = 8; + case OP_MU: + decode_modrm_rm(u, operand, REGCLASS_XMM, + MODRM_MOD(modrm(u)) == 3 ? + Mx_reg_size(size) : Mx_mem_size(size)); break; - case OP_DX: - operand->type = UD_OP_REG; - operand->base = UD_R_DX; - operand->size = 16; + case OP_S: + decode_modrm_reg(u, operand, REGCLASS_SEG, size); break; case OP_O: - decode_o(u, size, operand); + decode_moffset(u, size, operand); break; - case OP_rAXr8: - case OP_rCXr9: - case OP_rDXr10: - case OP_rBXr11: - case OP_rSPr12: - case OP_rBPr13: - case OP_rSIr14: - case OP_rDIr15: - case OP_rAX: - case OP_rCX: - case OP_rDX: - case OP_rBX: - case OP_rSP: - case OP_rBP: - case OP_rSI: - case OP_rDI: - operand->type = UD_OP_REG; - operand->base = resolve_gpr64(u, type, &operand->size); + case OP_R0: + case OP_R1: + case OP_R2: + case OP_R3: + case OP_R4: + case OP_R5: + case OP_R6: + case OP_R7: + decode_reg(u, operand, REGCLASS_GPR, + (REX_B(u->_rex) << 3) | (type - OP_R0), size); break; - case OP_ALr8b: - case OP_CLr9b: - case OP_DLr10b: - case OP_BLr11b: - case OP_AHr12b: - case OP_CHr13b: - case OP_DHr14b: - case OP_BHr15b: { - ud_type_t gpr = (type - OP_ALr8b) + UD_R_AL - + (REX_B(u->pfx_rex) << 3); - if (UD_R_AH <= gpr && u->pfx_rex) { - gpr = gpr + 4; - } - operand->type = UD_OP_REG; - operand->base = gpr; + case OP_AL: + case OP_AX: + case OP_eAX: + case OP_rAX: + decode_reg(u, operand, REGCLASS_GPR, 0, size); break; - } - case OP_eAX: - case OP_eCX: - case OP_eDX: - case OP_eBX: - case OP_eSP: - case OP_eBP: - case OP_eSI: - case OP_eDI: - operand->type = UD_OP_REG; - operand->base = resolve_gpr32(u, type); - operand->size = u->opr_mode == 16 ? 16 : 32; + case OP_CL: + case OP_CX: + case OP_eCX: + decode_reg(u, operand, REGCLASS_GPR, 1, size); + break; + case OP_DL: + case OP_DX: + case OP_eDX: + decode_reg(u, operand, REGCLASS_GPR, 2, size); break; case OP_ES: case OP_CS: @@ -762,7 +841,7 @@ /* in 64bits mode, only fs and gs are allowed */ if (u->dis_mode == 64) { if (type != OP_FS && type != OP_GS) { - u->error= 1; + UDERR(u, "invalid segment register in 64bits\n"); } } operand->type = UD_OP_REG; @@ -773,17 +852,17 @@ decode_imm(u, size, operand); operand->type = UD_OP_JIMM; break ; - case OP_Q: - decode_modrm_rm(u, operand, T_MMX, size); - break; case OP_R : - decode_modrm_rm(u, operand, T_GPR, size); + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + decode_modrm_rm(u, operand, REGCLASS_GPR, size); break; case OP_C: - decode_modrm_reg(u, operand, T_CRG, size); + decode_modrm_reg(u, operand, REGCLASS_CR, size); break; case OP_D: - decode_modrm_reg(u, operand, T_DBG, size); + decode_modrm_reg(u, operand, REGCLASS_DB, size); break; case OP_I3 : operand->type = UD_OP_CONST; @@ -799,18 +878,16 @@ case OP_ST7: operand->type = UD_OP_REG; operand->base = (type - OP_ST0) + UD_R_ST0; - operand->size = 0; + operand->size = 80; break; - case OP_AX: - operand->type = UD_OP_REG; - operand->base = UD_R_AX; - operand->size = 16; + case OP_L: + decode_vex_immreg(u, operand, size); break; default : operand->type = UD_NONE; break; } - return 0; + return operand->type; } @@ -827,12 +904,21 @@ decode_operand(u, &u->operand[0], u->itab_entry->operand1.type, u->itab_entry->operand1.size); - decode_operand(u, &u->operand[1], - u->itab_entry->operand2.type, - u->itab_entry->operand2.size); - decode_operand(u, &u->operand[2], - u->itab_entry->operand3.type, - u->itab_entry->operand3.size); + if (u->operand[0].type != UD_NONE) { + decode_operand(u, &u->operand[1], + u->itab_entry->operand2.type, + u->itab_entry->operand2.size); + } + if (u->operand[1].type != UD_NONE) { + decode_operand(u, &u->operand[2], + u->itab_entry->operand3.type, + u->itab_entry->operand3.size); + } + if (u->operand[2].type != UD_NONE) { + decode_operand(u, &u->operand[3], + u->itab_entry->operand4.type, + u->itab_entry->operand4.size); + } return 0; } @@ -852,19 +938,40 @@ u->pfx_rep = 0; u->pfx_repe = 0; u->pfx_rex = 0; - u->pfx_insn = 0; + u->pfx_str = 0; u->mnemonic = UD_Inone; u->itab_entry = NULL; u->have_modrm = 0; + u->br_far = 0; + u->vex_op = 0; + u->_rex = 0; + u->operand[0].type = UD_NONE; + u->operand[1].type = UD_NONE; + u->operand[2].type = UD_NONE; + u->operand[3].type = UD_NONE; +} - memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); - memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); - memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); + +static UD_INLINE int +resolve_pfx_str(struct ud* u) +{ + if (u->pfx_str == 0xf3) { + if (P_STR(u->itab_entry->prefix)) { + u->pfx_rep = 0xf3; + } else { + u->pfx_repe = 0xf3; + } + } else if (u->pfx_str == 0xf2) { + u->pfx_repne = 0xf3; + } + return 0; } + static int resolve_mode( struct ud* u ) { + int default64; /* if in error state, bail out */ if ( u->error ) return -1; @@ -873,22 +980,34 @@ /* Check validity of instruction m64 */ if ( P_INV64( u->itab_entry->prefix ) ) { - u->error = 1; - return -1; + UDERR(u, "instruction invalid in 64bits\n"); + return -1; } - /* effective rex prefix is the effective mask for the - * instruction hard-coded in the opcode map. + /* compute effective rex based on, + * - vex prefix (if any) + * - rex prefix (if any, and not vex) + * - allowed prefixes specified by the opcode map */ - u->pfx_rex = ( u->pfx_rex & 0x40 ) | - ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); + if (u->vex_op == 0xc4) { + /* vex has rex.rxb in 1's complement */ + u->_rex = ((~(u->vex_b1 >> 5) & 0x7) /* rex.0rxb */ | + ((u->vex_b2 >> 4) & 0x8) /* rex.w000 */); + } else if (u->vex_op == 0xc5) { + /* vex has rex.r in 1's complement */ + u->_rex = (~(u->vex_b1 >> 5)) & 4; + } else { + UD_ASSERT(u->vex_op == 0); + u->_rex = u->pfx_rex; + } + u->_rex &= REX_PFX_MASK(u->itab_entry->prefix); /* whether this instruction has a default operand size of * 64bit, also hardcoded into the opcode map. */ - u->default64 = P_DEF64( u->itab_entry->prefix ); + default64 = P_DEF64( u->itab_entry->prefix ); /* calculate effective operand size */ - if ( REX_W( u->pfx_rex ) ) { + if (REX_W(u->_rex)) { u->opr_mode = 64; } else if ( u->pfx_opr ) { u->opr_mode = 16; @@ -897,7 +1016,7 @@ * the effective operand size in the absence of rex.w * prefix is 32. */ - u->opr_mode = ( u->default64 ) ? 64 : 32; + u->opr_mode = default64 ? 64 : 32; } /* calculate effective address size */ @@ -910,45 +1029,18 @@ u->adr_mode = ( u->pfx_adr ) ? 32 : 16; } - /* These flags determine which operand to apply the operand size - * cast to. - */ - u->c1 = ( P_C1( u->itab_entry->prefix ) ) ? 1 : 0; - u->c2 = ( P_C2( u->itab_entry->prefix ) ) ? 1 : 0; - u->c3 = ( P_C3( u->itab_entry->prefix ) ) ? 1 : 0; - - /* set flags for implicit addressing */ - u->implicit_addr = P_IMPADDR( u->itab_entry->prefix ); - return 0; } -static int gen_hex( struct ud *u ) -{ - unsigned int i; - unsigned char *src_ptr = ud_inp_sess( u ); - char* src_hex; - /* bail out if in error stat. */ - if ( u->error ) return -1; - /* output buffer pointe */ - src_hex = ( char* ) u->insn_hexcode; - /* for each byte used to decode instruction */ - for ( i = 0; i < u->inp_ctr; ++i, ++src_ptr) { - sprintf( src_hex, "%02x", *src_ptr & 0xFF ); - src_hex += 2; - } - return 0; -} - - -static inline int +static UD_INLINE int decode_insn(struct ud *u, uint16_t ptr) { - ASSERT((ptr & 0x8000) == 0); + UD_ASSERT((ptr & 0x8000) == 0); u->itab_entry = &ud_itab[ ptr ]; u->mnemonic = u->itab_entry->mnemonic; - return (resolve_mode(u) == 0 && + return (resolve_pfx_str(u) == 0 && + resolve_mode(u) == 0 && decode_operands(u) == 0 && resolve_mnemonic(u) == 0) ? 0 : -1; } @@ -965,19 +1057,19 @@ * valid entry in the table, decode the operands, and read the final * byte to resolve the menmonic. */ -static inline int +static UD_INLINE int decode_3dnow(struct ud* u) { uint16_t ptr; - ASSERT(u->le->type == UD_TAB__OPC_3DNOW); - ASSERT(u->le->table[0xc] != 0); + UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); + UD_ASSERT(u->le->table[0xc] != 0); decode_insn(u, u->le->table[0xc]); - ud_inp_next(u); + inp_next(u); if (u->error) { return -1; } - ptr = u->le->table[ud_inp_curr(u)]; - ASSERT((ptr & 0x8000) == 0); + ptr = u->le->table[inp_curr(u)]; + UD_ASSERT((ptr & 0x8000) == 0); u->mnemonic = ud_itab[ptr].mnemonic; return 0; } @@ -986,7 +1078,18 @@ static int decode_ssepfx(struct ud *u) { - uint8_t idx = ((u->pfx_insn & 0xf) + 1) / 2; + uint8_t idx; + uint8_t pfx; + + /* + * String prefixes (f2, f3) take precedence over operand + * size prefix (66). + */ + pfx = u->pfx_str; + if (pfx == 0) { + pfx = u->pfx_opr; + } + idx = ((pfx & 0xf) + 1) / 2; if (u->le->table[idx] == 0) { idx = 0; } @@ -995,23 +1098,50 @@ * "Consume" the prefix as a part of the opcode, so it is no * longer exported as an instruction prefix. */ - switch (u->pfx_insn) { - case 0xf2: - u->pfx_repne = 0; - break; - case 0xf3: - u->pfx_rep = 0; - u->pfx_repe = 0; - break; - case 0x66: + u->pfx_str = 0; + if (pfx == 0x66) { + /* + * consume "66" only if it was used for decoding, leaving + * it to be used as an operands size override for some + * simd instructions. + */ u->pfx_opr = 0; - break; } } return decode_ext(u, u->le->table[idx]); } +static int +decode_vex(struct ud *u) +{ + uint8_t index; + if (u->dis_mode != 64 && MODRM_MOD(inp_peek(u)) != 0x3) { + index = 0; + } else { + u->vex_op = inp_curr(u); + u->vex_b1 = inp_next(u); + if (u->vex_op == 0xc4) { + uint8_t pp, m; + /* 3-byte vex */ + u->vex_b2 = inp_next(u); + UD_RETURN_ON_ERROR(u); + m = u->vex_b1 & 0x1f; + if (m == 0 || m > 3) { + UD_RETURN_WITH_ERROR(u, "reserved vex.m-mmmm value"); + } + pp = u->vex_b2 & 0x3; + index = (pp << 2) | m; + } else { + /* 2-byte vex */ + UD_ASSERT(u->vex_op == 0xc5); + index = 0x1 | ((u->vex_b1 & 0x3) << 2); + } + } + return decode_ext(u, u->le->table[index]); +} + + /* * decode_ext() * @@ -1038,7 +1168,7 @@ * 16 = 0,, 32 = 1, 64 = 2 */ case UD_TAB__OPC_MODE: - idx = u->dis_mode / 32; + idx = u->dis_mode != 64 ? 0 : 1; break; case UD_TAB__OPC_OSIZE: idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; @@ -1067,8 +1197,19 @@ break; case UD_TAB__OPC_SSE: return decode_ssepfx(u); + case UD_TAB__OPC_VEX: + return decode_vex(u); + case UD_TAB__OPC_VEX_W: + idx = vex_w(u); + break; + case UD_TAB__OPC_VEX_L: + idx = vex_l(u); + break; + case UD_TAB__OPC_TABLE: + inp_next(u); + return decode_opcode(u); default: - ASSERT(!"not reached"); + UD_ASSERT(!"not reached"); break; } @@ -1076,22 +1217,13 @@ } -static inline int +static int decode_opcode(struct ud *u) { uint16_t ptr; - ASSERT(u->le->type == UD_TAB__OPC_TABLE); - ud_inp_next(u); - if (u->error) { - return -1; - } - ptr = u->le->table[ud_inp_curr(u)]; - if (ptr & 0x8000) { - u->le = &ud_lookup_table_list[ptr & ~0x8000]; - if (u->le->type == UD_TAB__OPC_TABLE) { - return decode_opcode(u); - } - } + UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); + UD_RETURN_ON_ERROR(u); + ptr = u->le->table[inp_curr(u)]; return decode_ext(u, ptr); } @@ -1103,7 +1235,7 @@ unsigned int ud_decode(struct ud *u) { - ud_inp_start(u); + inp_start(u); clear_insn(u); u->le = &ud_lookup_table_list[0]; u->error = decode_prefixes(u) == -1 || @@ -1114,7 +1246,7 @@ /* clear out the decode data. */ clear_insn(u); /* mark the sequence of bytes as invalid. */ - u->itab_entry = & s_ie__invalid; + u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ u->mnemonic = u->itab_entry->mnemonic; } @@ -1127,16 +1259,15 @@ u->pfx_seg = 0; u->insn_offset = u->pc; /* set offset of instruction */ - u->insn_fill = 0; /* set translation buffer index to 0 */ + u->asm_buf_fill = 0; /* set translation buffer index to 0 */ u->pc += u->inp_ctr; /* move program counter by bytes decoded */ - gen_hex( u ); /* generate hex code */ /* return number of bytes disassembled. */ return u->inp_ctr; } +#endif // USE(UDIS86) + /* vim: set ts=2 sw=2 expandtab */ - -#endif // USE(UDIS86) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h 2016-09-16 09:56:47.000000000 +0000 @@ -27,74 +27,45 @@ #define UD_DECODE_H #include "udis86_types.h" +#include "udis86_udint.h" #include "udis86_itab.h" #define MAX_INSN_LENGTH 15 -/* register classes */ -#define T_NONE 0 -#define T_GPR 1 -#define T_MMX 2 -#define T_CRG 3 -#define T_DBG 4 -#define T_SEG 5 -#define T_XMM 6 - /* itab prefix bits */ #define P_none ( 0 ) -#define P_cast ( 1 << 0 ) -#define P_CAST(n) ( ( n >> 0 ) & 1 ) -#define P_c1 ( 1 << 0 ) -#define P_C1(n) ( ( n >> 0 ) & 1 ) -#define P_rexb ( 1 << 1 ) -#define P_REXB(n) ( ( n >> 1 ) & 1 ) -#define P_depM ( 1 << 2 ) -#define P_DEPM(n) ( ( n >> 2 ) & 1 ) -#define P_c3 ( 1 << 3 ) -#define P_C3(n) ( ( n >> 3 ) & 1 ) -#define P_inv64 ( 1 << 4 ) -#define P_INV64(n) ( ( n >> 4 ) & 1 ) + +#define P_inv64 ( 1 << 0 ) +#define P_INV64(n) ( ( n >> 0 ) & 1 ) +#define P_def64 ( 1 << 1 ) +#define P_DEF64(n) ( ( n >> 1 ) & 1 ) + +#define P_oso ( 1 << 2 ) +#define P_OSO(n) ( ( n >> 2 ) & 1 ) +#define P_aso ( 1 << 3 ) +#define P_ASO(n) ( ( n >> 3 ) & 1 ) + +#define P_rexb ( 1 << 4 ) +#define P_REXB(n) ( ( n >> 4 ) & 1 ) #define P_rexw ( 1 << 5 ) #define P_REXW(n) ( ( n >> 5 ) & 1 ) -#define P_c2 ( 1 << 6 ) -#define P_C2(n) ( ( n >> 6 ) & 1 ) -#define P_def64 ( 1 << 7 ) -#define P_DEF64(n) ( ( n >> 7 ) & 1 ) -#define P_rexr ( 1 << 8 ) -#define P_REXR(n) ( ( n >> 8 ) & 1 ) -#define P_oso ( 1 << 9 ) -#define P_OSO(n) ( ( n >> 9 ) & 1 ) -#define P_aso ( 1 << 10 ) -#define P_ASO(n) ( ( n >> 10 ) & 1 ) -#define P_rexx ( 1 << 11 ) -#define P_REXX(n) ( ( n >> 11 ) & 1 ) -#define P_ImpAddr ( 1 << 12 ) -#define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) -#define P_seg ( 1 << 13 ) -#define P_SEG(n) ( ( n >> 13 ) & 1 ) -#define P_sext ( 1 << 14 ) -#define P_SEXT(n) ( ( n >> 14 ) & 1 ) - -/* rex prefix bits */ -#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) -#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) -#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) -#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) -#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ - ( P_REXR(n) << 2 ) | \ - ( P_REXX(n) << 1 ) | \ - ( P_REXB(n) << 0 ) ) - -/* scable-index-base bits */ -#define SIB_S(b) ( ( b ) >> 6 ) -#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) -#define SIB_B(b) ( ( b ) & 7 ) - -/* modrm bits */ -#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) -#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) -#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) -#define MODRM_RM(b) ( ( b ) & 7 ) +#define P_rexr ( 1 << 6 ) +#define P_REXR(n) ( ( n >> 6 ) & 1 ) +#define P_rexx ( 1 << 7 ) +#define P_REXX(n) ( ( n >> 7 ) & 1 ) + +#define P_seg ( 1 << 8 ) +#define P_SEG(n) ( ( n >> 8 ) & 1 ) + +#define P_vexl ( 1 << 9 ) +#define P_VEXL(n) ( ( n >> 9 ) & 1 ) +#define P_vexw ( 1 << 10 ) +#define P_VEXW(n) ( ( n >> 10 ) & 1 ) + +#define P_str ( 1 << 11 ) +#define P_STR(n) ( ( n >> 11 ) & 1 ) +#define P_strz ( 1 << 12 ) +#define P_STR_ZF(n) ( ( n >> 12 ) & 1 ) /* operand type constants -- order is important! */ @@ -102,25 +73,15 @@ OP_NONE, OP_A, OP_E, OP_M, OP_G, - OP_I, - - OP_AL, OP_CL, OP_DL, OP_BL, - OP_AH, OP_CH, OP_DH, OP_BH, - - OP_ALr8b, OP_CLr9b, OP_DLr10b, OP_BLr11b, - OP_AHr12b, OP_CHr13b, OP_DHr14b, OP_BHr15b, + OP_I, OP_F, - OP_AX, OP_CX, OP_DX, OP_BX, - OP_SI, OP_DI, OP_SP, OP_BP, + OP_R0, OP_R1, OP_R2, OP_R3, + OP_R4, OP_R5, OP_R6, OP_R7, - OP_rAX, OP_rCX, OP_rDX, OP_rBX, - OP_rSP, OP_rBP, OP_rSI, OP_rDI, - - OP_rAXr8, OP_rCXr9, OP_rDXr10, OP_rBXr11, - OP_rSPr12, OP_rBPr13, OP_rSIr14, OP_rDIr15, - - OP_eAX, OP_eCX, OP_eDX, OP_eBX, - OP_eSP, OP_eBP, OP_eSI, OP_eDI, + OP_AL, OP_CL, OP_DL, + OP_AX, OP_CX, OP_DX, + OP_eAX, OP_eCX, OP_eDX, + OP_rAX, OP_rCX, OP_rDX, OP_ES, OP_CS, OP_SS, OP_DS, OP_FS, OP_GS, @@ -129,45 +90,71 @@ OP_ST4, OP_ST5, OP_ST6, OP_ST7, OP_J, OP_S, OP_O, - OP_I1, OP_I3, + OP_I1, OP_I3, OP_sI, OP_V, OP_W, OP_Q, OP_P, + OP_U, OP_N, OP_MU, OP_H, + OP_L, - OP_R, OP_C, OP_D, OP_VR, OP_PR, + OP_R, OP_C, OP_D, OP_MR } UD_ATTR_PACKED; -/* operand size constants */ +/* + * Operand size constants + * + * Symbolic constants for various operand sizes. Some of these constants + * are given a value equal to the width of the data (SZ_B == 8), such + * that they maybe used interchangeably in the internals. Modifying them + * will most certainly break things! + */ +typedef uint16_t ud_operand_size_t; + +#define SZ_NA 0 +#define SZ_Z 1 +#define SZ_V 2 +#define SZ_Y 3 +#define SZ_X 4 +#define SZ_RDQ 7 +#define SZ_B 8 +#define SZ_W 16 +#define SZ_D 32 +#define SZ_Q 64 +#define SZ_T 80 +#define SZ_O 12 +#define SZ_DQ 128 /* double quad */ +#define SZ_QQ 256 /* quad quad */ + +/* + * Complex size types; that encode sizes for operands of type MR (memory or + * register); for internal use only. Id space above 256. + */ +#define SZ_BD ((SZ_B << 8) | SZ_D) +#define SZ_BV ((SZ_B << 8) | SZ_V) +#define SZ_WD ((SZ_W << 8) | SZ_D) +#define SZ_WV ((SZ_W << 8) | SZ_V) +#define SZ_WY ((SZ_W << 8) | SZ_Y) +#define SZ_DY ((SZ_D << 8) | SZ_Y) +#define SZ_WO ((SZ_W << 8) | SZ_O) +#define SZ_DO ((SZ_D << 8) | SZ_O) +#define SZ_QO ((SZ_Q << 8) | SZ_O) -enum ud_operand_size { - SZ_NA = 0, - SZ_Z = 1, - SZ_V = 2, - SZ_P = 3, - SZ_WP = 4, - SZ_DP = 5, - SZ_MDQ = 6, - SZ_RDQ = 7, - - /* the following values are used as is, - * and thus hard-coded. changing them - * will break internals - */ - SZ_B = 8, - SZ_W = 16, - SZ_D = 32, - SZ_Q = 64, - SZ_T = 80, - SZ_O = 128, - - SZ_WV = 17, - SZ_BV = 18, - SZ_DY = 19 -} UD_ATTR_PACKED; +/* resolve complex size type. + */ +static UD_INLINE ud_operand_size_t +Mx_mem_size(ud_operand_size_t size) +{ + return (size >> 8) & 0xff; +} +static UD_INLINE ud_operand_size_t +Mx_reg_size(ud_operand_size_t size) +{ + return size & 0xff; +} /* A single operand of an entry in the instruction table. * (internal use only) @@ -175,7 +162,7 @@ struct ud_itab_entry_operand { enum ud_operand_code type; - enum ud_operand_size size; + ud_operand_size_t size; }; @@ -188,6 +175,7 @@ struct ud_itab_entry_operand operand1; struct ud_itab_entry_operand operand2; struct ud_itab_entry_operand operand3; + struct ud_itab_entry_operand operand4; uint32_t prefix; }; @@ -197,55 +185,6 @@ const char *meta; }; - -static inline unsigned int sse_pfx_idx( const unsigned int pfx ) -{ - /* 00 = 0 - * f2 = 1 - * f3 = 2 - * 66 = 3 - */ - return ( ( pfx & 0xf ) + 1 ) / 2; -} - -static inline unsigned int mode_idx( const unsigned int mode ) -{ - /* 16 = 0 - * 32 = 1 - * 64 = 2 - */ - return ( mode / 32 ); -} - -static inline unsigned int modrm_mod_idx( const unsigned int mod ) -{ - /* !11 = 0 - * 11 = 1 - */ - return ( mod + 1 ) / 4; -} - -static inline unsigned int vendor_idx( const unsigned int vendor ) -{ - switch ( vendor ) { - case UD_VENDOR_AMD: return 0; - case UD_VENDOR_INTEL: return 1; - case UD_VENDOR_ANY: return 2; - default: return 2; - } -} - -static inline unsigned int is_group_ptr( uint16_t ptr ) -{ - return ( 0x8000 & ptr ); -} - -static inline unsigned int group_idx( uint16_t ptr ) -{ - return ( ~0x8000 & ptr ); -} - - extern struct ud_itab_entry ud_itab[]; extern struct ud_lookup_table_list_entry ud_lookup_table_list[]; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ /* udis86 - libudis86/extern.h * - * Copyright (c) 2002-2009 Vivek Thampi + * Copyright (c) 2002-2009, 2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,57 +32,82 @@ #include "udis86_types.h" +#if defined(_MSC_VER) && defined(_USRDLL) +# ifdef LIBUDIS86_EXPORTS +# define LIBUDIS86_DLLEXTERN __declspec(dllexport) +# else +# define LIBUDIS86_DLLEXTERN __declspec(dllimport) +# endif +#else +# define LIBUDIS86_DLLEXTERN +#endif + /* ============================= PUBLIC API ================================= */ -extern void ud_init(struct ud*); +extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*); -extern void ud_set_mode(struct ud*, uint8_t); +extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t); -extern void ud_set_pc(struct ud*, uint64_t); +extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t); -extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); +extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*)); -extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t); +extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); #ifndef __UD_STANDALONE__ -extern void ud_set_input_file(struct ud*, FILE*); +extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*); #endif /* __UD_STANDALONE__ */ -extern void ud_set_vendor(struct ud*, unsigned); +extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned); + +extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*)); + +extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t); + +extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*); -extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); +extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*); -extern void ud_input_skip(struct ud*, size_t); +extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*); -extern int ud_input_end(struct ud*); +extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*); -extern unsigned int ud_decode(struct ud*); +extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*); -extern unsigned int ud_disassemble(struct ud*); +extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u); -extern void ud_translate_intel(struct ud*); +extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u); -extern void ud_translate_att(struct ud*); +extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*); -extern char* ud_insn_asm(struct ud* u); +extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*); -extern uint8_t* ud_insn_ptr(struct ud* u); +extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u); -extern uint64_t ud_insn_off(struct ud*); +extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); -extern char* ud_insn_hex(struct ud*); +extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr); -extern unsigned int ud_insn_len(struct ud* u); +extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr); -extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); +extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); -extern void ud_set_user_opaque_data(struct ud*, void*); +extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); -extern void *ud_get_user_opaque_data(struct ud*); +extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*); + +extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*); + +extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); + +extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u, + const char* (*resolver)(struct ud*, + uint64_t addr, + int64_t *offset)); /* ========================================================================== */ #ifdef __cplusplus } #endif -#endif +#endif /* UD_EXTERN_H */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_input.c webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_input.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_input.c 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_input.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,262 +0,0 @@ -/* udis86 - libudis86/input.c - * - * Copyright (c) 2002-2009 Vivek Thampi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "config.h" - -#if USE(UDIS86) - -#include "udis86_extern.h" -#include "udis86_types.h" -#include "udis86_input.h" - -/* ----------------------------------------------------------------------------- - * inp_buff_hook() - Hook for buffered inputs. - * ----------------------------------------------------------------------------- - */ -static int -inp_buff_hook(struct ud* u) -{ - if (u->inp_buff < u->inp_buff_end) - return *u->inp_buff++; - else return -1; -} - -#ifndef __UD_STANDALONE__ -/* ----------------------------------------------------------------------------- - * inp_file_hook() - Hook for FILE inputs. - * ----------------------------------------------------------------------------- - */ -static int -inp_file_hook(struct ud* u) -{ - return fgetc(u->inp_file); -} -#endif /* __UD_STANDALONE__*/ - -/* ============================================================================= - * ud_inp_set_hook() - Sets input hook. - * ============================================================================= - */ -extern void -ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) -{ - u->inp_hook = hook; - ud_inp_init(u); -} - -extern void -ud_set_user_opaque_data( struct ud * u, void * opaque ) -{ - u->user_opaque_data = opaque; -} - -extern void * -ud_get_user_opaque_data( struct ud * u ) -{ - return u->user_opaque_data; -} - -/* ============================================================================= - * ud_inp_set_buffer() - Set buffer as input. - * ============================================================================= - */ -extern void -ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len) -{ - u->inp_hook = inp_buff_hook; - u->inp_buff = buf; - u->inp_buff_end = buf + len; - ud_inp_init(u); -} - -#ifndef __UD_STANDALONE__ -/* ============================================================================= - * ud_input_set_file() - Set buffer as input. - * ============================================================================= - */ -extern void -ud_set_input_file(register struct ud* u, FILE* f) -{ - u->inp_hook = inp_file_hook; - u->inp_file = f; - ud_inp_init(u); -} -#endif /* __UD_STANDALONE__ */ - -/* ============================================================================= - * ud_input_skip() - Skip n input bytes. - * ============================================================================= - */ -extern void -ud_input_skip(struct ud* u, size_t n) -{ - while (n--) { - u->inp_hook(u); - } -} - -/* ============================================================================= - * ud_input_end() - Test for end of input. - * ============================================================================= - */ -extern int -ud_input_end(struct ud* u) -{ - return (u->inp_curr == u->inp_fill) && u->inp_end; -} - -/* ----------------------------------------------------------------------------- - * ud_inp_next() - Loads and returns the next byte from input. - * - * inp_curr and inp_fill are pointers to the cache. The program is written based - * on the property that they are 8-bits in size, and will eventually wrap around - * forming a circular buffer. So, the size of the cache is 256 in size, kind of - * unnecessary yet optimized. - * - * A buffer inp_sess stores the bytes disassembled for a single session. - * ----------------------------------------------------------------------------- - */ -extern uint8_t ud_inp_next(struct ud* u) -{ - int c = -1; - /* if current pointer is not upto the fill point in the - * input cache. - */ - if ( u->inp_curr != u->inp_fill ) { - c = u->inp_cache[ ++u->inp_curr ]; - /* if !end-of-input, call the input hook and get a byte */ - } else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) { - /* end-of-input, mark it as an error, since the decoder, - * expected a byte more. - */ - u->error = 1; - /* flag end of input */ - u->inp_end = 1; - return 0; - } else { - /* increment pointers, we have a new byte. */ - u->inp_curr = ++u->inp_fill; - /* add the byte to the cache */ - u->inp_cache[ u->inp_fill ] = c; - } - /* record bytes input per decode-session. */ - u->inp_sess[ u->inp_ctr++ ] = c; - /* return byte */ - return ( uint8_t ) c; -} - -/* ----------------------------------------------------------------------------- - * ud_inp_back() - Move back a single byte in the stream. - * ----------------------------------------------------------------------------- - */ -extern void -ud_inp_back(struct ud* u) -{ - if ( u->inp_ctr > 0 ) { - --u->inp_curr; - --u->inp_ctr; - } -} - -/* ----------------------------------------------------------------------------- - * ud_inp_peek() - Peek into the next byte in source. - * ----------------------------------------------------------------------------- - */ -extern uint8_t -ud_inp_peek(struct ud* u) -{ - uint8_t r = ud_inp_next(u); - if ( !u->error ) ud_inp_back(u); /* Don't backup if there was an error */ - return r; -} - -/* ----------------------------------------------------------------------------- - * ud_inp_move() - Move ahead n input bytes. - * ----------------------------------------------------------------------------- - */ -extern void -ud_inp_move(struct ud* u, size_t n) -{ - while (n--) - ud_inp_next(u); -} - -/*------------------------------------------------------------------------------ - * ud_inp_uintN() - return uintN from source. - *------------------------------------------------------------------------------ - */ -extern uint8_t -ud_inp_uint8(struct ud* u) -{ - return ud_inp_next(u); -} - -extern uint16_t -ud_inp_uint16(struct ud* u) -{ - uint16_t r, ret; - - ret = ud_inp_next(u); - r = ud_inp_next(u); - return ret | (r << 8); -} - -extern uint32_t -ud_inp_uint32(struct ud* u) -{ - uint32_t r, ret; - - ret = ud_inp_next(u); - r = ud_inp_next(u); - ret = ret | (r << 8); - r = ud_inp_next(u); - ret = ret | (r << 16); - r = ud_inp_next(u); - return ret | (r << 24); -} - -extern uint64_t -ud_inp_uint64(struct ud* u) -{ - uint64_t r, ret; - - ret = ud_inp_next(u); - r = ud_inp_next(u); - ret = ret | (r << 8); - r = ud_inp_next(u); - ret = ret | (r << 16); - r = ud_inp_next(u); - ret = ret | (r << 24); - r = ud_inp_next(u); - ret = ret | (r << 32); - r = ud_inp_next(u); - ret = ret | (r << 40); - r = ud_inp_next(u); - ret = ret | (r << 48); - r = ud_inp_next(u); - return ret | (r << 56); -} - -#endif // USE(UDIS86) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_input.h webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_input.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_input.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_input.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -/* udis86 - libudis86/input.h - * - * Copyright (c) 2002-2009 Vivek Thampi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef UD_INPUT_H -#define UD_INPUT_H - -#include "udis86_types.h" - -uint8_t ud_inp_next(struct ud*); -uint8_t ud_inp_peek(struct ud*); -uint8_t ud_inp_uint8(struct ud*); -uint16_t ud_inp_uint16(struct ud*); -uint32_t ud_inp_uint32(struct ud*); -uint64_t ud_inp_uint64(struct ud*); -void ud_inp_move(struct ud*, size_t); -void ud_inp_back(struct ud*); - -/* ud_inp_init() - Initializes the input system. */ -#define ud_inp_init(u) \ -do { \ - u->inp_curr = 0; \ - u->inp_fill = 0; \ - u->inp_ctr = 0; \ - u->inp_end = 0; \ -} while (0) - -/* ud_inp_start() - Should be called before each de-code operation. */ -#define ud_inp_start(u) u->inp_ctr = 0 - -/* ud_inp_back() - Resets the current pointer to its position before the current - * instruction disassembly was started. - */ -#define ud_inp_reset(u) \ -do { \ - u->inp_curr -= u->inp_ctr; \ - u->inp_ctr = 0; \ -} while (0) - -/* ud_inp_sess() - Returns the pointer to current session. */ -#define ud_inp_sess(u) (u->inp_sess) - -/* inp_cur() - Returns the current input byte. */ -#define ud_inp_curr(u) ((u)->inp_cache[(u)->inp_curr]) - -#endif diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c 2016-09-16 09:56:47.000000000 +0000 @@ -23,6 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "config.h" #if USE(UDIS86) @@ -32,6 +33,7 @@ #include "udis86_decode.h" #include "udis86_itab.h" #include "udis86_syn.h" +#include "udis86_udint.h" /* ----------------------------------------------------------------------------- * opr_cast() - Prints an operand cast. @@ -41,9 +43,9 @@ opr_cast(struct ud* u, struct ud_operand* op) { switch(op->size) { - case 16 : case 32 : - mkasm(u, "*"); break; - default: break; + case 16 : case 32 : + ud_asmprintf(u, "*"); break; + default: break; } } @@ -55,107 +57,66 @@ gen_operand(struct ud* u, struct ud_operand* op) { switch(op->type) { - case UD_OP_REG: - mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); - break; - - case UD_OP_MEM: - if (u->br_far) opr_cast(u, op); - if (u->pfx_seg) - mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); - if (op->offset == 8) { - if (op->lval.sbyte < 0) - mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff); - else - mkasm(u, "0x%x", op->lval.sbyte); - } - else if (op->offset == 16) { - if (op->lval.sword < 0) - mkasm(u, "-0x%x", (-op->lval.sword) & 0xffff); - else - mkasm(u, "0x%x", op->lval.sword); - } else if (op->offset == 32) { - if (op->lval.sdword < 0) - mkasm(u, "-0x%x", (-op->lval.sdword) & 0xffffffff); - else - mkasm(u, "0x%x", op->lval.sdword); - } else if (op->offset == 64) { - if (op->lval.sdword < 0) - mkasm(u, "-0x" FMT64 "x", (uint64_t)-op->lval.sqword); - else - mkasm(u, "0x" FMT64 "x", (uint64_t)op->lval.sqword); - } - - if (op->base) - mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); - if (op->index) { - if (op->base) - mkasm(u, ","); - else mkasm(u, "("); - mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); - } - if (op->scale) - mkasm(u, ",%d", op->scale); - if (op->base || op->index) - mkasm(u, ")"); - break; - - case UD_OP_IMM: { - int64_t imm = 0; - uint64_t sext_mask = 0xffffffffffffffffull; - unsigned sext_size = op->size; - - switch (op->size) { - case 8: imm = op->lval.sbyte; break; - case 16: imm = op->lval.sword; break; - case 32: imm = op->lval.sdword; break; - case 64: imm = op->lval.sqword; break; - } - if ( P_SEXT( u->itab_entry->prefix ) ) { - sext_size = u->operand[ 0 ].size; - if ( u->mnemonic == UD_Ipush ) - /* push sign-extends to operand size */ - sext_size = u->opr_mode; - } - if ( sext_size < 64 ) - sext_mask = ( 1ull << sext_size ) - 1; - mkasm( u, "$0x" FMT64 "x", (uint64_t)(imm & sext_mask) ); - - break; - } - - case UD_OP_JIMM: - switch (op->size) { - case 8: - mkasm(u, "0x" FMT64 "x", (uint64_t)(u->pc + op->lval.sbyte)); - break; - case 16: - mkasm(u, "0x" FMT64 "x", (uint64_t)((u->pc + op->lval.sword) & 0xffff) ); - break; - case 32: - if (u->dis_mode == 32) - mkasm(u, "0x" FMT64 "x", (uint64_t)((u->pc + op->lval.sdword) & 0xffffffff)); - else - mkasm(u, "0x" FMT64 "x", (uint64_t)(u->pc + op->lval.sdword)); - break; - default:break; - } - break; - - case UD_OP_PTR: - switch (op->size) { - case 32: - mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg, - op->lval.ptr.off & 0xFFFF); - break; - case 48: - mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg, - (unsigned long)op->lval.ptr.off); - break; - } - break; - - default: return; + case UD_OP_CONST: + ud_asmprintf(u, "$0x%x", op->lval.udword); + break; + + case UD_OP_REG: + ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); + break; + + case UD_OP_MEM: + if (u->br_far) { + opr_cast(u, op); + } + if (u->pfx_seg) { + ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); + } + if (op->offset != 0) { + ud_syn_print_mem_disp(u, op, 0); + } + if (op->base) { + ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); + } + if (op->index) { + if (op->base) { + ud_asmprintf(u, ","); + } else { + ud_asmprintf(u, "("); + } + ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); + } + if (op->scale) { + ud_asmprintf(u, ",%d", op->scale); + } + if (op->base || op->index) { + ud_asmprintf(u, ")"); + } + break; + + case UD_OP_IMM: + ud_asmprintf(u, "$"); + ud_syn_print_imm(u, op); + break; + + case UD_OP_JIMM: + ud_syn_print_addr(u, ud_syn_rel_target(u, op)); + break; + + case UD_OP_PTR: + switch (op->size) { + case 32: + ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, + op->lval.ptr.off & 0xFFFF); + break; + case 48: + ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, + op->lval.ptr.off); + break; + } + break; + + default: return; } } @@ -167,99 +128,108 @@ ud_translate_att(struct ud *u) { int size = 0; - unsigned i; + int star = 0; /* check if P_OSO prefix is used */ if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { - switch (u->dis_mode) { - case 16: - mkasm(u, "o32 "); - break; - case 32: - case 64: - mkasm(u, "o16 "); - break; - } + switch (u->dis_mode) { + case 16: + ud_asmprintf(u, "o32 "); + break; + case 32: + case 64: + ud_asmprintf(u, "o16 "); + break; + } } /* check if P_ASO prefix was used */ if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { - switch (u->dis_mode) { - case 16: - mkasm(u, "a32 "); - break; - case 32: - mkasm(u, "a16 "); - break; - case 64: - mkasm(u, "a32 "); - break; - } + switch (u->dis_mode) { + case 16: + ud_asmprintf(u, "a32 "); + break; + case 32: + ud_asmprintf(u, "a16 "); + break; + case 64: + ud_asmprintf(u, "a32 "); + break; + } } if (u->pfx_lock) - mkasm(u, "lock "); - if (u->pfx_rep) - mkasm(u, "rep "); - if (u->pfx_repne) - mkasm(u, "repne "); + ud_asmprintf(u, "lock "); + if (u->pfx_rep) { + ud_asmprintf(u, "rep "); + } else if (u->pfx_repe) { + ud_asmprintf(u, "repe "); + } else if (u->pfx_repne) { + ud_asmprintf(u, "repne "); + } /* special instructions */ switch (u->mnemonic) { - case UD_Iretf: - mkasm(u, "lret "); - break; - case UD_Idb: - mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte); - return; - case UD_Ijmp: - case UD_Icall: - if (u->br_far) mkasm(u, "l"); - mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); - break; - case UD_Ibound: - case UD_Ienter: - if (u->operand[0].type != UD_NONE) - gen_operand(u, &u->operand[0]); - if (u->operand[1].type != UD_NONE) { - mkasm(u, ","); - gen_operand(u, &u->operand[1]); - } - return; - default: - mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); - } - - for (i = 3; i--;) { - if (u->operand[i].size > size - && u->operand[i].type != UD_OP_JIMM) - size = u->operand[i].size; - } - - if (size == 8) - mkasm(u, "b"); - else if (size == 16) - mkasm(u, "w"); - else if (size == 32) - mkasm(u, "l"); - else if (size == 64) - mkasm(u, "q"); + case UD_Iretf: + ud_asmprintf(u, "lret "); + break; + case UD_Idb: + ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); + return; + case UD_Ijmp: + case UD_Icall: + if (u->br_far) ud_asmprintf(u, "l"); + if (u->operand[0].type == UD_OP_REG) { + star = 1; + } + ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + break; + case UD_Ibound: + case UD_Ienter: + if (u->operand[0].type != UD_NONE) + gen_operand(u, &u->operand[0]); + if (u->operand[1].type != UD_NONE) { + ud_asmprintf(u, ","); + gen_operand(u, &u->operand[1]); + } + return; + default: + ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + } + + if (size == 8) { + ud_asmprintf(u, "b"); + } else if (size == 16) { + ud_asmprintf(u, "w"); + } else if (size == 64) { + ud_asmprintf(u, "q"); + } - mkasm(u, " "); + if (star) { + ud_asmprintf(u, " *"); + } else { + ud_asmprintf(u, " "); + } + if (u->operand[3].type != UD_NONE) { + gen_operand(u, &u->operand[3]); + ud_asmprintf(u, ", "); + } if (u->operand[2].type != UD_NONE) { - gen_operand(u, &u->operand[2]); - mkasm(u, ", "); + gen_operand(u, &u->operand[2]); + ud_asmprintf(u, ", "); } - if (u->operand[1].type != UD_NONE) { - gen_operand(u, &u->operand[1]); - mkasm(u, ", "); + gen_operand(u, &u->operand[1]); + ud_asmprintf(u, ", "); + } + if (u->operand[0].type != UD_NONE) { + gen_operand(u, &u->operand[0]); } - - if (u->operand[0].type != UD_NONE) - gen_operand(u, &u->operand[0]); } #endif // USE(UDIS86) +/* +vim: set ts=2 sw=2 expandtab +*/ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ /* udis86 - libudis86/syn.c * - * Copyright (c) 2002-2009 Vivek Thampi + * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,59 +28,192 @@ #if USE(UDIS86) -/* ----------------------------------------------------------------------------- - * Intel Register Table - Order Matters (types.h)! - * ----------------------------------------------------------------------------- +#include "udis86_types.h" +#include "udis86_decode.h" +#include "udis86_syn.h" +#include "udis86_udint.h" + +/* + * Register Table - Order Matters (types.h)! + * */ const char* ud_reg_tab[] = { - "al", "cl", "dl", "bl", - "ah", "ch", "dh", "bh", - "spl", "bpl", "sil", "dil", - "r8b", "r9b", "r10b", "r11b", - "r12b", "r13b", "r14b", "r15b", - - "ax", "cx", "dx", "bx", - "sp", "bp", "si", "di", - "r8w", "r9w", "r10w", "r11w", - "r12w", "r13W" , "r14w", "r15w", - - "eax", "ecx", "edx", "ebx", - "esp", "ebp", "esi", "edi", - "r8d", "r9d", "r10d", "r11d", - "r12d", "r13d", "r14d", "r15d", - - "rax", "rcx", "rdx", "rbx", - "rsp", "rbp", "rsi", "rdi", - "r8", "r9", "r10", "r11", - "r12", "r13", "r14", "r15", - - "es", "cs", "ss", "ds", - "fs", "gs", - - "cr0", "cr1", "cr2", "cr3", - "cr4", "cr5", "cr6", "cr7", - "cr8", "cr9", "cr10", "cr11", - "cr12", "cr13", "cr14", "cr15", - - "dr0", "dr1", "dr2", "dr3", - "dr4", "dr5", "dr6", "dr7", - "dr8", "dr9", "dr10", "dr11", - "dr12", "dr13", "dr14", "dr15", - - "mm0", "mm1", "mm2", "mm3", - "mm4", "mm5", "mm6", "mm7", - - "st0", "st1", "st2", "st3", - "st4", "st5", "st6", "st7", - - "xmm0", "xmm1", "xmm2", "xmm3", - "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9", "xmm10", "xmm11", - "xmm12", "xmm13", "xmm14", "xmm15", + "al", "cl", "dl", "bl", + "ah", "ch", "dh", "bh", + "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", + "r12b", "r13b", "r14b", "r15b", + + "ax", "cx", "dx", "bx", + "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", + "r12w", "r13w", "r14w", "r15w", + + "eax", "ecx", "edx", "ebx", + "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", + "r12d", "r13d", "r14d", "r15d", + + "rax", "rcx", "rdx", "rbx", + "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + + "es", "cs", "ss", "ds", + "fs", "gs", + + "cr0", "cr1", "cr2", "cr3", + "cr4", "cr5", "cr6", "cr7", + "cr8", "cr9", "cr10", "cr11", + "cr12", "cr13", "cr14", "cr15", + + "dr0", "dr1", "dr2", "dr3", + "dr4", "dr5", "dr6", "dr7", + "dr8", "dr9", "dr10", "dr11", + "dr12", "dr13", "dr14", "dr15", + + "mm0", "mm1", "mm2", "mm3", + "mm4", "mm5", "mm6", "mm7", + + "st0", "st1", "st2", "st3", + "st4", "st5", "st6", "st7", + + "xmm0", "xmm1", "xmm2", "xmm3", + "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", + "xmm12", "xmm13", "xmm14", "xmm15", + + "ymm0", "ymm1", "ymm2", "ymm3", + "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", + "ymm12", "ymm13", "ymm14", "ymm15", "rip" }; + +uint64_t +ud_syn_rel_target(struct ud *u, struct ud_operand *opr) +{ + const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode); + switch (opr->size) { + case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask; + case 16: return (u->pc + opr->lval.sword) & trunc_mask; + case 32: return (u->pc + opr->lval.sdword) & trunc_mask; + default: UD_ASSERT(!"invalid relative offset size."); + return 0ull; + } +} + + +/* + * asmprintf + * Printf style function for printing translated assembly + * output. Returns the number of characters written and + * moves the buffer pointer forward. On an overflow, + * returns a negative number and truncates the output. + */ +int +ud_asmprintf(struct ud *u, const char *fmt, ...) +{ + int ret; + int avail; + va_list ap; + va_start(ap, fmt); + avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */; + ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap); + if (ret < 0 || ret > avail) { + u->asm_buf_fill = u->asm_buf_size - 1; + } else { + u->asm_buf_fill += ret; + } + va_end(ap); + return ret; +} + + +void +ud_syn_print_addr(struct ud *u, uint64_t addr) +{ + const char *name = NULL; + if (u->sym_resolver) { + int64_t offset = 0; + name = u->sym_resolver(u, addr, &offset); + if (name) { + if (offset) { + ud_asmprintf(u, "%s%+" FMT64 "d", name, offset); + } else { + ud_asmprintf(u, "%s", name); + } + return; + } + } + ud_asmprintf(u, "0x%" FMT64 "x", addr); +} + + +void +ud_syn_print_imm(struct ud* u, const struct ud_operand *op) +{ + uint64_t v; + if (op->_oprcode == OP_sI && op->size != u->opr_mode) { + if (op->size == 8) { + v = (int64_t)op->lval.sbyte; + } else { + UD_ASSERT(op->size == 32); + v = (int64_t)op->lval.sdword; + } + if (u->opr_mode < 64) { + v = v & ((1ull << u->opr_mode) - 1ull); + } + } else { + switch (op->size) { + case 8 : v = op->lval.ubyte; break; + case 16: v = op->lval.uword; break; + case 32: v = op->lval.udword; break; + case 64: v = op->lval.uqword; break; + default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ + } + } + ud_asmprintf(u, "0x%" FMT64 "x", v); +} + + +void +ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign) +{ + UD_ASSERT(op->offset != 0); + if (op->base == UD_NONE && op->index == UD_NONE) { + uint64_t v; + UD_ASSERT(op->scale == UD_NONE && op->offset != 8); + /* unsigned mem-offset */ + switch (op->offset) { + case 16: v = op->lval.uword; break; + case 32: v = op->lval.udword; break; + case 64: v = op->lval.uqword; break; + default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ + } + ud_asmprintf(u, "0x%" FMT64 "x", v); + } else { + int64_t v; + UD_ASSERT(op->offset != 64); + switch (op->offset) { + case 8 : v = op->lval.sbyte; break; + case 16: v = op->lval.sword; break; + case 32: v = op->lval.sdword; break; + default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ + } + if (v < 0) { + ud_asmprintf(u, "-0x%" FMT64 "x", -v); + } else if (v > 0) { + ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v); + } + } +} + #endif // USE(UDIS86) +/* +vim: set ts=2 sw=2 expandtab +*/ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h 2016-09-16 09:56:47.000000000 +0000 @@ -27,21 +27,27 @@ #define UD_SYN_H #include "udis86_types.h" -#include - #ifndef __UD_STANDALONE__ # include #endif /* __UD_STANDALONE__ */ extern const char* ud_reg_tab[]; -static void mkasm(struct ud* u, const char* fmt, ...) WTF_ATTRIBUTE_PRINTF(2, 3); -static void mkasm(struct ud* u, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - u->insn_fill += vsnprintf((char*) u->insn_buffer + u->insn_fill, UD_STRING_BUFFER_SIZE - u->insn_fill, fmt, ap); - va_end(ap); -} +uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*); +#ifdef __GNUC__ +int ud_asmprintf(struct ud *u, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +#else +int ud_asmprintf(struct ud *u, const char *fmt, ...); #endif + +void ud_syn_print_addr(struct ud *u, uint64_t addr); +void ud_syn_print_imm(struct ud* u, const struct ud_operand *op); +void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign); + +#endif /* UD_SYN_H */ + +/* +vim: set ts=2 sw=2 expandtab +*/ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ /* udis86 - libudis86/syn-intel.c * - * Copyright (c) 2002-2009 Vivek Thampi + * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -23,6 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "config.h" #if USE(UDIS86) @@ -32,6 +33,7 @@ #include "udis86_decode.h" #include "udis86_itab.h" #include "udis86_syn.h" +#include "udis86_udint.h" /* ----------------------------------------------------------------------------- * opr_cast() - Prints an operand cast. @@ -40,16 +42,19 @@ static void opr_cast(struct ud* u, struct ud_operand* op) { + if (u->br_far) { + ud_asmprintf(u, "far "); + } switch(op->size) { - case 8: mkasm(u, "byte " ); break; - case 16: mkasm(u, "word " ); break; - case 32: mkasm(u, "dword "); break; - case 64: mkasm(u, "qword "); break; - case 80: mkasm(u, "tword "); break; - default: break; + case 8: ud_asmprintf(u, "byte " ); break; + case 16: ud_asmprintf(u, "word " ); break; + case 32: ud_asmprintf(u, "dword "); break; + case 64: ud_asmprintf(u, "qword "); break; + case 80: ud_asmprintf(u, "tword "); break; + case 128: ud_asmprintf(u, "oword "); break; + case 256: ud_asmprintf(u, "yword "); break; + default: break; } - if (u->br_far) - mkasm(u, "far "); } /* ----------------------------------------------------------------------------- @@ -59,121 +64,63 @@ static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) { switch(op->type) { - case UD_OP_REG: - mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); - break; - - case UD_OP_MEM: { - - int op_f = 0; - - if (syn_cast) - opr_cast(u, op); - - mkasm(u, "["); - - if (u->pfx_seg) - mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); - - if (op->base) { - mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); - op_f = 1; - } - - if (op->index) { - if (op_f) - mkasm(u, "+"); - mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]); - op_f = 1; - } - - if (op->scale) - mkasm(u, "*%d", op->scale); - - if (op->offset == 8) { - if (op->lval.sbyte < 0) - mkasm(u, "-0x%x", -op->lval.sbyte); - else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte); - } - else if (op->offset == 16) - mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword); - else if (op->offset == 32) { - if (u->adr_mode == 64) { - if (op->lval.sdword < 0) - mkasm(u, "-0x%x", -op->lval.sdword); - else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword); - } - else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", (unsigned long)op->lval.udword); - } - else if (op->offset == 64) - mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", (uint64_t)op->lval.uqword); - - mkasm(u, "]"); - break; - } - - case UD_OP_IMM: { - int64_t imm = 0; - uint64_t sext_mask = 0xffffffffffffffffull; - unsigned sext_size = op->size; - - if (syn_cast) - opr_cast(u, op); - switch (op->size) { - case 8: imm = op->lval.sbyte; break; - case 16: imm = op->lval.sword; break; - case 32: imm = op->lval.sdword; break; - case 64: imm = op->lval.sqword; break; - } - if ( P_SEXT( u->itab_entry->prefix ) ) { - sext_size = u->operand[ 0 ].size; - if ( u->mnemonic == UD_Ipush ) - /* push sign-extends to operand size */ - sext_size = u->opr_mode; - } - if ( sext_size < 64 ) - sext_mask = ( 1ull << sext_size ) - 1; - mkasm( u, "0x" FMT64 "x", (uint64_t)(imm & sext_mask) ); - - break; - } - - - case UD_OP_JIMM: - if (syn_cast) opr_cast(u, op); - switch (op->size) { - case 8: - mkasm(u, "0x" FMT64 "x", (uint64_t)(u->pc + op->lval.sbyte)); - break; - case 16: - mkasm(u, "0x" FMT64 "x", (uint64_t)(( u->pc + op->lval.sword ) & 0xffff) ); - break; - case 32: - mkasm(u, "0x" FMT64 "x", (uint64_t)(( u->pc + op->lval.sdword ) & 0xfffffffful) ); - break; - default:break; - } - break; - - case UD_OP_PTR: - switch (op->size) { - case 32: - mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg, - op->lval.ptr.off & 0xFFFF); - break; - case 48: - mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg, - (unsigned long)op->lval.ptr.off); - break; - } - break; - - case UD_OP_CONST: - if (syn_cast) opr_cast(u, op); - mkasm(u, "%d", op->lval.udword); - break; + case UD_OP_REG: + ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); + break; + + case UD_OP_MEM: + if (syn_cast) { + opr_cast(u, op); + } + ud_asmprintf(u, "["); + if (u->pfx_seg) { + ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); + } + if (op->base) { + ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); + } + if (op->index) { + ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "", + ud_reg_tab[op->index - UD_R_AL]); + if (op->scale) { + ud_asmprintf(u, "*%d", op->scale); + } + } + if (op->offset != 0) { + ud_syn_print_mem_disp(u, op, (op->base != UD_NONE || + op->index != UD_NONE) ? 1 : 0); + } + ud_asmprintf(u, "]"); + break; + + case UD_OP_IMM: + ud_syn_print_imm(u, op); + break; + + + case UD_OP_JIMM: + ud_syn_print_addr(u, ud_syn_rel_target(u, op)); + break; + + case UD_OP_PTR: + switch (op->size) { + case 32: + ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg, + op->lval.ptr.off & 0xFFFF); + break; + case 48: + ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg, + op->lval.ptr.off); + break; + } + break; + + case UD_OP_CONST: + if (syn_cast) opr_cast(u, op); + ud_asmprintf(u, "%d", op->lval.udword); + break; - default: return; + default: return; } } @@ -181,98 +128,104 @@ * translates to intel syntax * ============================================================================= */ -extern void ud_translate_intel(struct ud* u) +extern void +ud_translate_intel(struct ud* u) { - /* -- prefixes -- */ - /* check if P_OSO prefix is used */ - if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { - switch (u->dis_mode) { - case 16: - mkasm(u, "o32 "); - break; - case 32: - case 64: - mkasm(u, "o16 "); - break; - } + if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) { + switch (u->dis_mode) { + case 16: ud_asmprintf(u, "o32 "); break; + case 32: + case 64: ud_asmprintf(u, "o16 "); break; + } } /* check if P_ASO prefix was used */ - if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { - switch (u->dis_mode) { - case 16: - mkasm(u, "a32 "); - break; - case 32: - mkasm(u, "a16 "); - break; - case 64: - mkasm(u, "a32 "); - break; - } - } - - if ( u->pfx_seg && - u->operand[0].type != UD_OP_MEM && - u->operand[1].type != UD_OP_MEM ) { - mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); - } - if (u->pfx_lock) - mkasm(u, "lock "); - if (u->pfx_rep) - mkasm(u, "rep "); - if (u->pfx_repne) - mkasm(u, "repne "); + if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) { + switch (u->dis_mode) { + case 16: ud_asmprintf(u, "a32 "); break; + case 32: ud_asmprintf(u, "a16 "); break; + case 64: ud_asmprintf(u, "a32 "); break; + } + } + + if (u->pfx_seg && + u->operand[0].type != UD_OP_MEM && + u->operand[1].type != UD_OP_MEM ) { + ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); + } + + if (u->pfx_lock) { + ud_asmprintf(u, "lock "); + } + if (u->pfx_rep) { + ud_asmprintf(u, "rep "); + } else if (u->pfx_repe) { + ud_asmprintf(u, "repe "); + } else if (u->pfx_repne) { + ud_asmprintf(u, "repne "); + } /* print the instruction mnemonic */ - mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic)); + ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); - /* operand 1 */ if (u->operand[0].type != UD_NONE) { int cast = 0; - if ( u->operand[0].type == UD_OP_IMM && - u->operand[1].type == UD_NONE ) - cast = u->c1; - if ( u->operand[0].type == UD_OP_MEM ) { - cast = u->c1; - if ( u->operand[1].type == UD_OP_IMM || - u->operand[1].type == UD_OP_CONST ) - cast = 1; - if ( u->operand[1].type == UD_NONE ) - cast = 1; - if ( ( u->operand[0].size != u->operand[1].size ) && u->operand[1].size ) - cast = 1; - } else if ( u->operand[ 0 ].type == UD_OP_JIMM ) { - if ( u->operand[ 0 ].size > 8 ) cast = 1; + ud_asmprintf(u, " "); + if (u->operand[0].type == UD_OP_MEM) { + if (u->operand[1].type == UD_OP_IMM || + u->operand[1].type == UD_OP_CONST || + u->operand[1].type == UD_NONE || + (u->operand[0].size != u->operand[1].size)) { + cast = 1; + } else if (u->operand[1].type == UD_OP_REG && + u->operand[1].base == UD_R_CL) { + switch (u->mnemonic) { + case UD_Ircl: + case UD_Irol: + case UD_Iror: + case UD_Ircr: + case UD_Ishl: + case UD_Ishr: + case UD_Isar: + cast = 1; + break; + default: break; + } + } } - gen_operand(u, &u->operand[0], cast); + gen_operand(u, &u->operand[0], cast); } - /* operand 2 */ + if (u->operand[1].type != UD_NONE) { int cast = 0; - mkasm(u, ", "); - if ( u->operand[1].type == UD_OP_MEM ) { - cast = u->c1; - - if ( u->operand[0].type != UD_OP_REG ) - cast = 1; - if ( u->operand[0].size != u->operand[1].size && u->operand[1].size ) - cast = 1; - if ( u->operand[0].type == UD_OP_REG && - u->operand[0].base >= UD_R_ES && - u->operand[0].base <= UD_R_GS ) - cast = 0; + ud_asmprintf(u, ", "); + if (u->operand[1].type == UD_OP_MEM && + u->operand[0].size != u->operand[1].size && + !ud_opr_is_sreg(&u->operand[0])) { + cast = 1; } - gen_operand(u, &u->operand[1], cast ); + gen_operand(u, &u->operand[1], cast); } - /* operand 3 */ if (u->operand[2].type != UD_NONE) { - mkasm(u, ", "); - gen_operand(u, &u->operand[2], u->c3); + int cast = 0; + ud_asmprintf(u, ", "); + if (u->operand[2].type == UD_OP_MEM && + u->operand[2].size != u->operand[1].size) { + cast = 1; + } + gen_operand(u, &u->operand[2], cast); + } + + if (u->operand[3].type != UD_NONE) { + ud_asmprintf(u, ", "); + gen_operand(u, &u->operand[3], 0); } } #endif // USE(UDIS86) +/* +vim: set ts=2 sw=2 expandtab +*/ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_types.h webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_types.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_types.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_types.h 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ /* udis86 - libudis86/types.h * - * Copyright (c) 2002-2009 Vivek Thampi + * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -26,9 +26,23 @@ #ifndef UD_TYPES_H #define UD_TYPES_H -#ifndef __UD_STANDALONE__ +#ifdef __KERNEL__ + /* + * -D__KERNEL__ is automatically passed on the command line when + * building something as part of the Linux kernel. Assume standalone + * mode. + */ +# include +# include +# ifndef __UD_STANDALONE__ +# define __UD_STANDALONE__ 1 +# endif +#endif /* __KERNEL__ */ + +#if !defined(__UD_STANDALONE__) +# include # include -#endif /* __UD_STANDALONE__ */ +#endif /* gcc specific extensions */ #ifdef __GNUC__ @@ -37,26 +51,6 @@ # define UD_ATTR_PACKED #endif /* UD_ATTR_PACKED */ -#ifdef _MSC_VER -# define FMT64 "%I64" - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; -#else -# if defined(__GNU_LIBRARY__) && defined(__WORDSIZE) && (__WORDSIZE == 64) -# define FMT64 "%l" -# else -# define FMT64 "%ll" -# endif -# ifndef __UD_STANDALONE__ -# include -# endif /* __UD_STANDALONE__ */ -#endif /* ----------------------------------------------------------------------------- * All possible "types" of objects in udis86. Order is Important! @@ -67,152 +61,176 @@ UD_NONE, /* 8 bit GPRs */ - UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, - UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, - UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, - UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, - UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, + UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, + UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, + UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, + UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, + UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, /* 16 bit GPRs */ - UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, - UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, - UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, - UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, - + UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, + UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, + UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, + UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, + /* 32 bit GPRs */ - UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, - UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, - UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, - UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, - + UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, + UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, + UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, + UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, + /* 64 bit GPRs */ - UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, - UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, - UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, - UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, + UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, + UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, + UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, + UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, /* segment registers */ - UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, - UD_R_FS, UD_R_GS, + UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, + UD_R_FS, UD_R_GS, /* control registers*/ - UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, - UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, - UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, - UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, - + UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, + UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, + UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, + UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, + /* debug registers */ - UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, - UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, - UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, - UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, + UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, + UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, + UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, + UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, /* mmx registers */ - UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, - UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, + UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, + UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, /* x87 registers */ - UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, - UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, + UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, + UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, /* extended multimedia registers */ - UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, - UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, - UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, - UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, + UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, + UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, + UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, + UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, + + /* 256B multimedia registers */ + UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3, + UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7, + UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11, + UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15, UD_R_RIP, /* Operand Types */ - UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, - UD_OP_JIMM, UD_OP_CONST + UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, + UD_OP_JIMM, UD_OP_CONST }; #include "udis86_itab.h" +union ud_lval { + int8_t sbyte; + uint8_t ubyte; + int16_t sword; + uint16_t uword; + int32_t sdword; + uint32_t udword; + int64_t sqword; + uint64_t uqword; + struct { + uint16_t seg; + uint32_t off; + } ptr; +}; + /* ----------------------------------------------------------------------------- * struct ud_operand - Disassembled instruction Operand. * ----------------------------------------------------------------------------- */ -struct ud_operand -{ - enum ud_type type; - uint8_t size; - union { - int8_t sbyte; - uint8_t ubyte; - int16_t sword; - uint16_t uword; - int32_t sdword; - uint32_t udword; - int64_t sqword; - uint64_t uqword; - - struct { - uint16_t seg; - uint32_t off; - } ptr; - } lval; - - enum ud_type base; - enum ud_type index; - uint8_t offset; - uint8_t scale; +struct ud_operand { + enum ud_type type; + uint16_t size; + enum ud_type base; + enum ud_type index; + uint8_t scale; + uint8_t offset; + union ud_lval lval; + /* + * internal use only + */ + uint64_t _legacy; /* this will be removed in 1.8 */ + uint8_t _oprcode; }; -#define UD_STRING_BUFFER_SIZE 64 - /* ----------------------------------------------------------------------------- * struct ud - The udis86 object. * ----------------------------------------------------------------------------- */ struct ud { - int (*inp_hook) (struct ud*); - uint8_t inp_curr; - uint8_t inp_fill; + /* + * input buffering + */ + int (*inp_hook) (struct ud*); #ifndef __UD_STANDALONE__ - FILE* inp_file; + FILE* inp_file; #endif - uint8_t inp_ctr; - uint8_t* inp_buff; - uint8_t* inp_buff_end; - uint8_t inp_end; - void (*translator)(struct ud*); - uint64_t insn_offset; - char insn_hexcode[32]; - char insn_buffer[UD_STRING_BUFFER_SIZE]; - unsigned int insn_fill; - uint8_t dis_mode; - uint64_t pc; - uint8_t vendor; - struct map_entry* mapen; - enum ud_mnemonic_code mnemonic; - struct ud_operand operand[3]; - uint8_t error; - uint8_t pfx_rex; - uint8_t pfx_seg; - uint8_t pfx_opr; - uint8_t pfx_adr; - uint8_t pfx_lock; - uint8_t pfx_rep; - uint8_t pfx_repe; - uint8_t pfx_repne; - uint8_t pfx_insn; - uint8_t default64; - uint8_t opr_mode; - uint8_t adr_mode; - uint8_t br_far; - uint8_t br_near; - uint8_t implicit_addr; - uint8_t c1; - uint8_t c2; - uint8_t c3; - uint8_t inp_cache[256]; - uint8_t inp_sess[64]; - uint8_t have_modrm; - uint8_t modrm; - void * user_opaque_data; + const uint8_t* inp_buf; + size_t inp_buf_size; + size_t inp_buf_index; + uint8_t inp_curr; + size_t inp_ctr; + uint8_t inp_sess[64]; + int inp_end; + int inp_peek; + + void (*translator)(struct ud*); + uint64_t insn_offset; + char insn_hexcode[64]; + + /* + * Assembly output buffer + */ + char *asm_buf; + size_t asm_buf_size; + size_t asm_buf_fill; + char asm_buf_int[128]; + + /* + * Symbol resolver for use in the translation phase. + */ + const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); + + uint8_t dis_mode; + uint64_t pc; + uint8_t vendor; + enum ud_mnemonic_code mnemonic; + struct ud_operand operand[4]; + uint8_t error; + uint8_t _rex; + uint8_t pfx_rex; + uint8_t pfx_seg; + uint8_t pfx_opr; + uint8_t pfx_adr; + uint8_t pfx_lock; + uint8_t pfx_str; + uint8_t pfx_rep; + uint8_t pfx_repe; + uint8_t pfx_repne; + uint8_t opr_mode; + uint8_t adr_mode; + uint8_t br_far; + uint8_t br_near; + uint8_t have_modrm; + uint8_t modrm; + uint8_t modrm_offset; + uint8_t vex_op; + uint8_t vex_b1; + uint8_t vex_b2; + uint8_t primary_opcode; + void * user_opaque_data; struct ud_itab_entry * itab_entry; struct ud_lookup_table_list_entry *le; }; @@ -221,22 +239,22 @@ * Type-definitions * ----------------------------------------------------------------------------- */ -typedef enum ud_type ud_type_t; -typedef enum ud_mnemonic_code ud_mnemonic_code_t; +typedef enum ud_type ud_type_t; +typedef enum ud_mnemonic_code ud_mnemonic_code_t; -typedef struct ud ud_t; -typedef struct ud_operand ud_operand_t; +typedef struct ud ud_t; +typedef struct ud_operand ud_operand_t; -#define UD_SYN_INTEL ud_translate_intel -#define UD_SYN_ATT ud_translate_att -#define UD_EOI -1 -#define UD_INP_CACHE_SZ 32 -#define UD_VENDOR_AMD 0 -#define UD_VENDOR_INTEL 1 -#define UD_VENDOR_ANY 2 - -#define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code ) -#define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 ) -#define catch_error() else +#define UD_SYN_INTEL ud_translate_intel +#define UD_SYN_ATT ud_translate_att +#define UD_EOI (-1) +#define UD_INP_CACHE_SZ 32 +#define UD_VENDOR_AMD 0 +#define UD_VENDOR_INTEL 1 +#define UD_VENDOR_ANY 2 #endif + +/* +vim: set ts=2 sw=2 expandtab +*/ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,98 @@ +/* udis86 - libudis86/udint.h -- definitions for internal use only + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _UDINT_H_ +#define _UDINT_H_ + +#include "udis86_types.h" + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#if defined(UD_DEBUG) && HAVE_ASSERT_H +# define UD_ASSERT(_x) ASSERT(_x) +#else +# define UD_ASSERT(_x) +#endif /* !HAVE_ASSERT_H */ + +#if defined(UD_DEBUG) + #define UDERR(u, msg) \ + do { \ + (u)->error = 1; \ + fprintf(stderr, "decode-error: %s:%d: %s", \ + __FILE__, __LINE__, (msg)); \ + } while (0) +#else + #define UDERR(u, m) \ + do { \ + (u)->error = 1; \ + } while (0) +#endif /* !LOGERR */ + +#define UD_RETURN_ON_ERROR(u) \ + do { \ + if ((u)->error != 0) { \ + return (u)->error; \ + } \ + } while (0) + +#define UD_RETURN_WITH_ERROR(u, m) \ + do { \ + UDERR(u, m); \ + return (u)->error; \ + } while (0) + +#ifndef __UD_STANDALONE__ +# define UD_NON_STANDALONE(x) x +#else +# define UD_NON_STANDALONE(x) +#endif + +/* printf formatting int64 specifier */ +#ifdef FMT64 +# undef FMT64 +#endif +#if defined(_MSC_VER) || defined(__BORLANDC__) +# define FMT64 "I64" +#else +# if defined(__APPLE__) +# define FMT64 "ll" +# elif defined(__amd64__) || defined(__x86_64__) +# define FMT64 "l" +# else +# define FMT64 "ll" +# endif /* !x64 */ +#endif + +/* define an inline macro */ +#if defined(_MSC_VER) || defined(__BORLANDC__) +# define UD_INLINE __inline /* MS Visual Studio requires __inline + instead of inline for C code */ +#else +# define UD_INLINE inline +#endif + +#endif /* _UDINT_H_ */ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/ud_itab.py webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/ud_itab.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/ud_itab.py 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/ud_itab.py 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,379 @@ +# udis86 - scripts/ud_itab.py +# +# Copyright (c) 2009, 2013 Vivek Thampi +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import sys +from ud_opcode import UdOpcodeTable, UdOpcodeTables, UdInsnDef + +class UdItabGenerator: + + OperandDict = { + "Av" : [ "OP_A" , "SZ_V" ], + "E" : [ "OP_E" , "SZ_NA" ], + "Eb" : [ "OP_E" , "SZ_B" ], + "Ew" : [ "OP_E" , "SZ_W" ], + "Ev" : [ "OP_E" , "SZ_V" ], + "Ed" : [ "OP_E" , "SZ_D" ], + "Ey" : [ "OP_E" , "SZ_Y" ], + "Eq" : [ "OP_E" , "SZ_Q" ], + "Ez" : [ "OP_E" , "SZ_Z" ], + "Fv" : [ "OP_F" , "SZ_V" ], + "G" : [ "OP_G" , "SZ_NA" ], + "Gb" : [ "OP_G" , "SZ_B" ], + "Gw" : [ "OP_G" , "SZ_W" ], + "Gv" : [ "OP_G" , "SZ_V" ], + "Gy" : [ "OP_G" , "SZ_Y" ], + "Gd" : [ "OP_G" , "SZ_D" ], + "Gq" : [ "OP_G" , "SZ_Q" ], + "Gz" : [ "OP_G" , "SZ_Z" ], + "M" : [ "OP_M" , "SZ_NA" ], + "Mb" : [ "OP_M" , "SZ_B" ], + "Mw" : [ "OP_M" , "SZ_W" ], + "Ms" : [ "OP_M" , "SZ_W" ], + "Md" : [ "OP_M" , "SZ_D" ], + "Mq" : [ "OP_M" , "SZ_Q" ], + "Mdq" : [ "OP_M" , "SZ_DQ" ], + "Mv" : [ "OP_M" , "SZ_V" ], + "Mt" : [ "OP_M" , "SZ_T" ], + "Mo" : [ "OP_M" , "SZ_O" ], + "MbRd" : [ "OP_MR" , "SZ_BD" ], + "MbRv" : [ "OP_MR" , "SZ_BV" ], + "MwRv" : [ "OP_MR" , "SZ_WV" ], + "MwRd" : [ "OP_MR" , "SZ_WD" ], + "MwRy" : [ "OP_MR" , "SZ_WY" ], + "MdRy" : [ "OP_MR" , "SZ_DY" ], + "I1" : [ "OP_I1" , "SZ_NA" ], + "I3" : [ "OP_I3" , "SZ_NA" ], + "Ib" : [ "OP_I" , "SZ_B" ], + "Iw" : [ "OP_I" , "SZ_W" ], + "Iv" : [ "OP_I" , "SZ_V" ], + "Iz" : [ "OP_I" , "SZ_Z" ], + "sIb" : [ "OP_sI" , "SZ_B" ], + "sIz" : [ "OP_sI" , "SZ_Z" ], + "sIv" : [ "OP_sI" , "SZ_V" ], + "Jv" : [ "OP_J" , "SZ_V" ], + "Jz" : [ "OP_J" , "SZ_Z" ], + "Jb" : [ "OP_J" , "SZ_B" ], + "R" : [ "OP_R" , "SZ_RDQ" ], + "C" : [ "OP_C" , "SZ_NA" ], + "D" : [ "OP_D" , "SZ_NA" ], + "S" : [ "OP_S" , "SZ_W" ], + "Ob" : [ "OP_O" , "SZ_B" ], + "Ow" : [ "OP_O" , "SZ_W" ], + "Ov" : [ "OP_O" , "SZ_V" ], + "U" : [ "OP_U" , "SZ_O" ], + "Ux" : [ "OP_U" , "SZ_X" ], + "V" : [ "OP_V" , "SZ_DQ" ], + "Vdq" : [ "OP_V" , "SZ_DQ" ], + "Vqq" : [ "OP_V" , "SZ_QQ" ], + "Vsd" : [ "OP_V" , "SZ_Q" ], + "Vx" : [ "OP_V" , "SZ_X" ], + "H" : [ "OP_H" , "SZ_X" ], + "Hx" : [ "OP_H" , "SZ_X" ], + "Hqq" : [ "OP_H" , "SZ_QQ" ], + "W" : [ "OP_W" , "SZ_DQ" ], + "Wdq" : [ "OP_W" , "SZ_DQ" ], + "Wqq" : [ "OP_W" , "SZ_QQ" ], + "Wsd" : [ "OP_W" , "SZ_Q" ], + "Wx" : [ "OP_W" , "SZ_X" ], + "L" : [ "OP_L" , "SZ_O" ], + "Lx" : [ "OP_L" , "SZ_X" ], + "MwU" : [ "OP_MU" , "SZ_WO" ], + "MdU" : [ "OP_MU" , "SZ_DO" ], + "MqU" : [ "OP_MU" , "SZ_QO" ], + "N" : [ "OP_N" , "SZ_Q" ], + "P" : [ "OP_P" , "SZ_Q" ], + "Q" : [ "OP_Q" , "SZ_Q" ], + "AL" : [ "OP_AL" , "SZ_B" ], + "AX" : [ "OP_AX" , "SZ_W" ], + "eAX" : [ "OP_eAX" , "SZ_Z" ], + "rAX" : [ "OP_rAX" , "SZ_V" ], + "CL" : [ "OP_CL" , "SZ_B" ], + "CX" : [ "OP_CX" , "SZ_W" ], + "eCX" : [ "OP_eCX" , "SZ_Z" ], + "rCX" : [ "OP_rCX" , "SZ_V" ], + "DL" : [ "OP_DL" , "SZ_B" ], + "DX" : [ "OP_DX" , "SZ_W" ], + "eDX" : [ "OP_eDX" , "SZ_Z" ], + "rDX" : [ "OP_rDX" , "SZ_V" ], + "R0b" : [ "OP_R0" , "SZ_B" ], + "R1b" : [ "OP_R1" , "SZ_B" ], + "R2b" : [ "OP_R2" , "SZ_B" ], + "R3b" : [ "OP_R3" , "SZ_B" ], + "R4b" : [ "OP_R4" , "SZ_B" ], + "R5b" : [ "OP_R5" , "SZ_B" ], + "R6b" : [ "OP_R6" , "SZ_B" ], + "R7b" : [ "OP_R7" , "SZ_B" ], + "R0w" : [ "OP_R0" , "SZ_W" ], + "R1w" : [ "OP_R1" , "SZ_W" ], + "R2w" : [ "OP_R2" , "SZ_W" ], + "R3w" : [ "OP_R3" , "SZ_W" ], + "R4w" : [ "OP_R4" , "SZ_W" ], + "R5w" : [ "OP_R5" , "SZ_W" ], + "R6w" : [ "OP_R6" , "SZ_W" ], + "R7w" : [ "OP_R7" , "SZ_W" ], + "R0v" : [ "OP_R0" , "SZ_V" ], + "R1v" : [ "OP_R1" , "SZ_V" ], + "R2v" : [ "OP_R2" , "SZ_V" ], + "R3v" : [ "OP_R3" , "SZ_V" ], + "R4v" : [ "OP_R4" , "SZ_V" ], + "R5v" : [ "OP_R5" , "SZ_V" ], + "R6v" : [ "OP_R6" , "SZ_V" ], + "R7v" : [ "OP_R7" , "SZ_V" ], + "R0z" : [ "OP_R0" , "SZ_Z" ], + "R1z" : [ "OP_R1" , "SZ_Z" ], + "R2z" : [ "OP_R2" , "SZ_Z" ], + "R3z" : [ "OP_R3" , "SZ_Z" ], + "R4z" : [ "OP_R4" , "SZ_Z" ], + "R5z" : [ "OP_R5" , "SZ_Z" ], + "R6z" : [ "OP_R6" , "SZ_Z" ], + "R7z" : [ "OP_R7" , "SZ_Z" ], + "R0y" : [ "OP_R0" , "SZ_Y" ], + "R1y" : [ "OP_R1" , "SZ_Y" ], + "R2y" : [ "OP_R2" , "SZ_Y" ], + "R3y" : [ "OP_R3" , "SZ_Y" ], + "R4y" : [ "OP_R4" , "SZ_Y" ], + "R5y" : [ "OP_R5" , "SZ_Y" ], + "R6y" : [ "OP_R6" , "SZ_Y" ], + "R7y" : [ "OP_R7" , "SZ_Y" ], + "ES" : [ "OP_ES" , "SZ_NA" ], + "CS" : [ "OP_CS" , "SZ_NA" ], + "DS" : [ "OP_DS" , "SZ_NA" ], + "SS" : [ "OP_SS" , "SZ_NA" ], + "GS" : [ "OP_GS" , "SZ_NA" ], + "FS" : [ "OP_FS" , "SZ_NA" ], + "ST0" : [ "OP_ST0" , "SZ_NA" ], + "ST1" : [ "OP_ST1" , "SZ_NA" ], + "ST2" : [ "OP_ST2" , "SZ_NA" ], + "ST3" : [ "OP_ST3" , "SZ_NA" ], + "ST4" : [ "OP_ST4" , "SZ_NA" ], + "ST5" : [ "OP_ST5" , "SZ_NA" ], + "ST6" : [ "OP_ST6" , "SZ_NA" ], + "ST7" : [ "OP_ST7" , "SZ_NA" ], + "NONE" : [ "OP_NONE" , "SZ_NA" ], + } + + # + # opcode prefix dictionary + # + PrefixDict = { + "rep" : "P_str", + "repz" : "P_strz", + "aso" : "P_aso", + "oso" : "P_oso", + "rexw" : "P_rexw", + "rexb" : "P_rexb", + "rexx" : "P_rexx", + "rexr" : "P_rexr", + "vexl" : "P_vexl", + "vexw" : "P_vexw", + "seg" : "P_seg", + "inv64" : "P_inv64", + "def64" : "P_def64", + "cast" : "P_cast", + } + + MnemonicAliases = ( "invalid", "3dnow", "none", "db", "pause" ) + + def __init__(self, tables): + self.tables = tables + self._insnIndexMap, i = {}, 0 + for insn in tables.getInsnList(): + self._insnIndexMap[insn], i = i, i + 1 + + self._tableIndexMap, i = {}, 0 + for table in tables.getTableList(): + self._tableIndexMap[table], i = i, i + 1 + + def getInsnIndex(self, insn): + assert isinstance(insn, UdInsnDef) + return self._insnIndexMap[insn] + + def getTableIndex(self, table): + assert isinstance(table, UdOpcodeTable) + return self._tableIndexMap[table] + + def getTableName(self, table): + return "ud_itab__%d" % self.getTableIndex(table) + + def genOpcodeTable(self, table, isGlobal=False): + """Emit Opcode Table in C. + """ + self.ItabC.write( "\n" ); + if not isGlobal: + self.ItabC.write('static ') + self.ItabC.write( "const uint16_t %s[] = {\n" % self.getTableName(table)) + for i in range(table.size()): + if i > 0 and i % 4 == 0: + self.ItabC.write( "\n" ) + if i % 4 == 0: + self.ItabC.write( " /* %2x */" % i) + e = table.entryAt(i) + if e is None: + self.ItabC.write("%12s," % "INVALID") + elif isinstance(e, UdOpcodeTable): + self.ItabC.write("%12s," % ("GROUP(%d)" % self.getTableIndex(e))) + elif isinstance(e, UdInsnDef): + self.ItabC.write("%12s," % self.getInsnIndex(e)) + self.ItabC.write( "\n" ) + self.ItabC.write( "};\n" ) + + + def genOpcodeTables(self): + tables = self.tables.getTableList() + for table in tables: + self.genOpcodeTable(table, table is self.tables.root) + + + def genOpcodeTablesLookupIndex(self): + self.ItabC.write( "\n\n" ); + self.ItabC.write( "struct ud_lookup_table_list_entry ud_lookup_table_list[] = {\n" ) + for table in self.tables.getTableList(): + f0 = self.getTableName(table) + "," + f1 = table.label() + "," + f2 = "\"%s\"" % table.meta() + self.ItabC.write(" /* %03d */ { %s %s %s },\n" % + (self.getTableIndex(table), f0, f1, f2)) + self.ItabC.write( "};" ) + + + def genInsnTable( self ): + self.ItabC.write( "struct ud_itab_entry ud_itab[] = {\n" ); + for insn in self.tables.getInsnList(): + opr_c = [ "O_NONE", "O_NONE", "O_NONE", "O_NONE" ] + pfx_c = [] + opr = insn.operands + for i in range(len(opr)): + if not (opr[i] in self.OperandDict.keys()): + print("error: invalid operand declaration: %s\n" % opr[i]) + opr_c[i] = "O_" + opr[i] + opr = "%s %s %s %s" % (opr_c[0] + ",", opr_c[1] + ",", + opr_c[2] + ",", opr_c[3]) + + for p in insn.prefixes: + if not ( p in self.PrefixDict.keys() ): + print("error: invalid prefix specification: %s \n" % pfx) + pfx_c.append( self.PrefixDict[p] ) + if len(insn.prefixes) == 0: + pfx_c.append( "P_none" ) + pfx = "|".join( pfx_c ) + + self.ItabC.write( " /* %04d */ { UD_I%s %s, %s },\n" \ + % ( self.getInsnIndex(insn), insn.mnemonic + ',', opr, pfx ) ) + self.ItabC.write( "};\n" ) + + + def getMnemonicsList(self): + mnemonics = self.tables.getMnemonicsList() + mnemonics.extend(self.MnemonicAliases) + return mnemonics + + def genMnemonicsList(self): + mnemonics = self.getMnemonicsList() + self.ItabC.write( "\n\n" ); + self.ItabC.write( "const char* ud_mnemonics_str[] = {\n " ) + self.ItabC.write( ",\n ".join( [ "\"%s\"" % m for m in mnemonics ] ) ) + self.ItabC.write( "\n};\n" ) + + + def genItabH( self, filePath ): + self.ItabH = open( filePath, "w" ) + + # Generate Table Type Enumeration + self.ItabH.write( "#ifndef UD_ITAB_H\n" ) + self.ItabH.write( "#define UD_ITAB_H\n\n" ) + + self.ItabH.write("/* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */\n\n") + + # table type enumeration + self.ItabH.write( "/* ud_table_type -- lookup table types (see decode.c) */\n" ) + self.ItabH.write( "enum ud_table_type {\n " ) + enum = UdOpcodeTable.getLabels() + self.ItabH.write( ",\n ".join( enum ) ) + self.ItabH.write( "\n};\n\n" ); + + # mnemonic enumeration + self.ItabH.write( "/* ud_mnemonic -- mnemonic constants */\n" ) + enum = "enum ud_mnemonic_code {\n " + enum += ",\n ".join( [ "UD_I%s" % m for m in self.getMnemonicsList() ] ) + enum += ",\n UD_MAX_MNEMONIC_CODE" + enum += "\n};\n" + self.ItabH.write( enum ) + self.ItabH.write( "\n" ) + + self.ItabH.write( "extern const char * ud_mnemonics_str[];\n" ) + + self.ItabH.write( "\n#endif /* UD_ITAB_H */\n" ) + + self.ItabH.close() + + + def genItabC(self, filePath): + self.ItabC = open(filePath, "w") + self.ItabC.write("/* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit") + self.ItabC.write(" */\n"); + self.ItabC.write("#include \"udis86_decode.h\"\n\n"); + + self.ItabC.write("#define GROUP(n) (0x8000 | (n))\n") + self.ItabC.write("#define INVALID %d\n\n" % self.getInsnIndex(self.tables.invalidInsn)) + + self.genOpcodeTables() + self.genOpcodeTablesLookupIndex() + + # + # Macros defining short-names for operands + # + self.ItabC.write("\n\n/* itab entry operand definitions (for readability) */\n"); + operands = self.OperandDict.keys() + operands = sorted(operands) + for o in operands: + self.ItabC.write("#define O_%-7s { %-12s %-8s }\n" % + (o, self.OperandDict[o][0] + ",", self.OperandDict[o][1])); + self.ItabC.write("\n"); + + self.genInsnTable() + self.genMnemonicsList() + + self.ItabC.close() + + def genItab( self, location ): + self.genItabC(os.path.join(location, "udis86_itab.c")) + self.genItabH(os.path.join(location, "udis86_itab.h")) + +def usage(): + print("usage: ud_itab.py ") + +def main(): + + if len(sys.argv) != 3: + usage() + sys.exit(1) + + tables = UdOpcodeTables(xml=sys.argv[1]) + itab = UdItabGenerator(tables) + itab.genItab(sys.argv[2]) + +if __name__ == '__main__': + main() diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ # udis86 - scripts/ud_opcode.py # -# Copyright (c) 2009 Vivek Thampi +# Copyright (c) 2009, 2013 Vivek Thampi # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -23,213 +23,600 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -class UdOpcodeTables: +import os - TableInfo = { - 'opctbl' : { 'name' : 'UD_TAB__OPC_TABLE', 'size' : 256 }, - '/sse' : { 'name' : 'UD_TAB__OPC_SSE', 'size' : 4 }, - '/reg' : { 'name' : 'UD_TAB__OPC_REG', 'size' : 8 }, - '/rm' : { 'name' : 'UD_TAB__OPC_RM', 'size' : 8 }, - '/mod' : { 'name' : 'UD_TAB__OPC_MOD', 'size' : 2 }, - '/m' : { 'name' : 'UD_TAB__OPC_MODE', 'size' : 3 }, - '/x87' : { 'name' : 'UD_TAB__OPC_X87', 'size' : 64 }, - '/a' : { 'name' : 'UD_TAB__OPC_ASIZE', 'size' : 3 }, - '/o' : { 'name' : 'UD_TAB__OPC_OSIZE', 'size' : 3 }, - '/3dnow' : { 'name' : 'UD_TAB__OPC_3DNOW', 'size' : 256 }, - 'vendor' : { 'name' : 'UD_TAB__OPC_VENDOR', 'size' : 3 }, - } +# Some compatibility stuff for supporting python 2.x as well as python 3.x +def itemslist(dict): + try: + return dict.iteritems() # python 2.x + except AttributeError: + return list(dict.items()) # python 3.x + +class UdInsnDef: + """An x86 instruction definition + """ + def __init__(self, **insnDef): + self.mnemonic = insnDef['mnemonic'] + self.prefixes = insnDef['prefixes'] + self.opcodes = insnDef['opcodes'] + self.operands = insnDef['operands'] + self._cpuid = insnDef['cpuid'] + self._opcexts = {} + + for opc in self.opcodes: + if opc.startswith('/'): + e, v = opc.split('=') + self._opcexts[e] = v + + def lookupPrefix(self, pfx): + """Lookup prefix (if any, None otherwise), by name""" + return True if pfx in self.prefixes else None + + + @property + def vendor(self): + return self._opcexts.get('/vendor', None) + + @property + def mode(self): + return self._opcexts.get('/m', None) + + @property + def osize(self): + return self._opcexts.get('/o', None) + + def isDef64(self): + return 'def64' in self.prefixes + + def __str__(self): + return self.mnemonic + " " + ', '.join(self.operands) + \ + " " + ' '.join(self.opcodes) + + +class UdOpcodeTable: + """A single table of instruction definitions, indexed by + a decode field. + """ + + class CollisionError(Exception): + pass + + class IndexError(Exception): + """Invalid Index Error""" + pass + + @classmethod + def vendor2idx(cls, v): + return (0 if v == 'amd' + else (1 if v == 'intel' + else 2)) + + @classmethod + def vex2idx(cls, v): + if v.startswith("none_"): + v = v[5:] + vexOpcExtMap = { + 'none' : 0x0, + '0f' : 0x1, + '0f38' : 0x2, + '0f3a' : 0x3, + '66' : 0x4, + '66_0f' : 0x5, + '66_0f38' : 0x6, + '66_0f3a' : 0x7, + 'f3' : 0x8, + 'f3_0f' : 0x9, + 'f3_0f38' : 0xa, + 'f3_0f3a' : 0xb, + 'f2' : 0xc, + 'f2_0f' : 0xd, + 'f2_0f38' : 0xe, + 'f2_0f3a' : 0xf, + } + return vexOpcExtMap[v] - OpcodeTable0 = { - 'type' : 'opctbl', - 'entries' : {}, - 'meta' : 'table0' + + # A mapping of opcode extensions to their representational + # values used in the opcode map. + OpcExtMap = { + '/rm' : lambda v: int(v, 16), + '/x87' : lambda v: int(v, 16), + '/3dnow' : lambda v: int(v, 16), + '/reg' : lambda v: int(v, 16), + # modrm.mod + # (!11, 11) => (00b, 01b) + '/mod' : lambda v: 0 if v == '!11' else 1, + # Mode extensions: + # (16, 32, 64) => (00, 01, 02) + '/o' : lambda v: (int(v) / 32), + '/a' : lambda v: (int(v) / 32), + # Disassembly mode + # (!64, 64) => (00b, 01b) + '/m' : lambda v: 1 if v == '64' else 0, + # SSE + # none => 0 + # f2 => 1 + # f3 => 2 + # 66 => 3 + '/sse' : lambda v: (0 if v == 'none' + else (((int(v, 16) & 0xf) + 1) / 2)), + # AVX + '/vex' : lambda v: UdOpcodeTable.vex2idx(v), + '/vexw' : lambda v: 0 if v == '0' else 1, + '/vexl' : lambda v: 0 if v == '0' else 1, + # Vendor + '/vendor': lambda v: UdOpcodeTable.vendor2idx(v) } - OpcExtIndex = { - # ssef2, ssef3, sse66 - 'sse': { - 'none' : '00', - 'f2' : '01', - 'f3' : '02', - '66' : '03' - }, - - # /mod= - 'mod': { - '!11' : '00', - '11' : '01' - }, - - # /m=, /o=, /a= - 'mode': { - '16' : '00', - '32' : '01', - '64' : '02' - }, - - 'vendor' : { - 'amd' : '00', - 'intel' : '01', - 'any' : '02' - } + _TableInfo = { + 'opctbl' : { 'label' : 'UD_TAB__OPC_TABLE', 'size' : 256 }, + '/sse' : { 'label' : 'UD_TAB__OPC_SSE', 'size' : 4 }, + '/reg' : { 'label' : 'UD_TAB__OPC_REG', 'size' : 8 }, + '/rm' : { 'label' : 'UD_TAB__OPC_RM', 'size' : 8 }, + '/mod' : { 'label' : 'UD_TAB__OPC_MOD', 'size' : 2 }, + '/m' : { 'label' : 'UD_TAB__OPC_MODE', 'size' : 2 }, + '/x87' : { 'label' : 'UD_TAB__OPC_X87', 'size' : 64 }, + '/a' : { 'label' : 'UD_TAB__OPC_ASIZE', 'size' : 3 }, + '/o' : { 'label' : 'UD_TAB__OPC_OSIZE', 'size' : 3 }, + '/3dnow' : { 'label' : 'UD_TAB__OPC_3DNOW', 'size' : 256 }, + '/vendor' : { 'label' : 'UD_TAB__OPC_VENDOR', 'size' : 3 }, + '/vex' : { 'label' : 'UD_TAB__OPC_VEX', 'size' : 16 }, + '/vexw' : { 'label' : 'UD_TAB__OPC_VEX_W', 'size' : 2 }, + '/vexl' : { 'label' : 'UD_TAB__OPC_VEX_L', 'size' : 2 }, } - InsnTable = [] - MnemonicsTable = [] - ThreeDNowTable = {} + def __init__(self, typ): + assert typ in self._TableInfo + self._typ = typ + self._entries = {} - def sizeOfTable( self, t ): - return self.TableInfo[ t ][ 'size' ] - def nameOfTable( self, t ): - return self.TableInfo[ t ][ 'name' ] - - # - # Updates a table entry: If the entry doesn't exist - # it will create the entry, otherwise, it will walk - # while validating the path. - # - def updateTable( self, table, index, type, meta ): - if not index in table[ 'entries' ]: - table[ 'entries' ][ index ] = { 'type' : type, 'entries' : {}, 'meta' : meta } - if table[ 'entries' ][ index ][ 'type' ] != type: - raise NameError( "error: violation in opcode mapping (overwrite) %s with %s." % - ( table[ 'entries' ][ index ][ 'type' ], type) ) - return table[ 'entries' ][ index ] - - class Insn: - """An abstract type representing an instruction in the opcode map. - """ - - # A mapping of opcode extensions to their representational - # values used in the opcode map. - OpcExtMap = { - '/rm' : lambda v: "%02x" % int(v, 16), - '/x87' : lambda v: "%02x" % int(v, 16), - '/3dnow' : lambda v: "%02x" % int(v, 16), - '/reg' : lambda v: "%02x" % int(v, 16), - # modrm.mod - # (!11, 11) => (00, 01) - '/mod' : lambda v: '00' if v == '!11' else '01', - # Mode extensions: - # (16, 32, 64) => (00, 01, 02) - '/o' : lambda v: "%02x" % (int(v) / 32), - '/a' : lambda v: "%02x" % (int(v) / 32), - '/m' : lambda v: "%02x" % (int(v) / 32), - '/sse' : lambda v: UdOpcodeTables.OpcExtIndex['sse'][v] - } + def size(self): + return self._TableInfo[self._typ]['size'] + + def entries(self): + return itemslist(self._entries) + + def numEntries(self): + return len(self._entries.keys()) + + def label(self): + return self._TableInfo[self._typ]['label'] + + def typ(self): + return self._typ + + def meta(self): + return self._typ + + + def __str__(self): + return "table-%s" % self._typ + + + def add(self, opc, obj): + typ = UdOpcodeTable.getOpcodeTyp(opc) + idx = UdOpcodeTable.getOpcodeIdx(opc) + if self._typ != typ or idx in self._entries: + raise CollisionError() + self._entries[idx] = obj + + + def lookup(self, opc): + typ = UdOpcodeTable.getOpcodeTyp(opc) + idx = UdOpcodeTable.getOpcodeIdx(opc) + if self._typ != typ: + raise UdOpcodeTable.CollisionError("%s <-> %s" % (self._typ, typ)) + return self._entries.get(idx, None) - def __init__(self, prefixes, mnemonic, opcodes, operands, vendor): - self.opcodes = opcodes - self.prefixes = prefixes - self.mnemonic = mnemonic - self.operands = operands - self.vendor = vendor - self.opcext = {} - - ssePrefix = None - if self.opcodes[0] in ('ssef2', 'ssef3', 'sse66'): - ssePrefix = self.opcodes[0][3:] - self.opcodes.pop(0) - - # do some preliminary decoding of the instruction type - # 1byte, 2byte or 3byte instruction? - self.nByteInsn = 1 - if self.opcodes[0] == '0f': # 2byte - # 2+ byte opcodes are always disambiguated by an - # sse prefix, unless it is a 3d now instruction - # which is 0f 0f ... - if self.opcodes[1] != '0f' and ssePrefix is None: - ssePrefix = 'none' - if self.opcodes[1] in ('38', '3a'): # 3byte - self.nByteInsn = 3 + + def entryAt(self, index): + """Returns the entry at a given index of the table, + None if there is none. Raises an exception if the + index is out of bounds. + """ + if index < self.size(): + return self._entries.get(index, None) + raise self.IndexError("index out of bounds: %s" % index) + + def setEntryAt(self, index, obj): + if index < self.size(): + self._entries[index] = obj + else: + raise self.IndexError("index out of bounds: %s" % index) + + @classmethod + def getOpcodeTyp(cls, opc): + if opc.startswith('/'): + return opc.split('=')[0] + else: + return 'opctbl' + + + @classmethod + def getOpcodeIdx(cls, opc): + if opc.startswith('/'): + typ, v = opc.split('=') + return cls.OpcExtMap[typ](v) + else: + # plain opctbl opcode + return int(opc, 16) + + + @classmethod + def getLabels(cls): + """Returns a list of all labels""" + return [cls._TableInfo[k]['label'] for k in cls._TableInfo.keys()] + + +class UdOpcodeTables(object): + """Collection of opcode tables + """ + + class CollisionError(Exception): + def __init__(self, obj1, obj2): + self.obj1, self.obj2 = obj1, obj2 + + def newTable(self, typ): + """Create a new opcode table of a give type `typ`. """ + tbl = UdOpcodeTable(typ) + self._tables.append(tbl) + return tbl + + def mkTrie(self, opcodes, obj): + """Recursively contruct a trie entry mapping a string of + opcodes to an object. + """ + if len(opcodes) == 0: + return obj + opc = opcodes[0] + tbl = self.newTable(UdOpcodeTable.getOpcodeTyp(opc)) + tbl.add(opc, self.mkTrie(opcodes[1:], obj)) + return tbl + + def walk(self, tbl, opcodes): + """Walk down the opcode trie, starting at a given opcode + table, given a string of opcodes. Return None if unable + to walk, the object at the leaf otherwise. + """ + opc = opcodes[0] + e = tbl.lookup(opc) + if e is None: + return None + elif isinstance(e, UdOpcodeTable) and len(opcodes[1:]): + return self.walk(e, opcodes[1:]) + return e + + def map(self, tbl, opcodes, obj): + """Create a mapping from a given string of opcodes to an + object in the opcode trie. Constructs trie branches as + needed. + """ + opc = opcodes[0] + e = tbl.lookup(opc) + if e is None: + tbl.add(opc, self.mkTrie(opcodes[1:], obj)) + else: + if len(opcodes[1:]) == 0: + raise self.CollisionError(e, obj) + self.map(e, opcodes[1:], obj) + + def __init__(self, xml): + self._tables = [] + self._insns = [] + self._mnemonics = {} + + # The root table is always a 256 entry opctbl, indexed + # by a plain opcode byte + self.root = self.newTable('opctbl') + + if os.getenv("UD_OPCODE_DEBUG"): + self._logFh = open("opcodeTables.log", "w") + + # add an invalid instruction entry without any mapping + # in the opcode tables. + self.invalidInsn = UdInsnDef(mnemonic="invalid", opcodes=[], cpuid=[], + operands=[], prefixes=[]) + self._insns.append(self.invalidInsn) + + # Construct UdOpcodeTables object from the given + # udis86 optable.xml + for insn in self.__class__.parseOptableXML(xml): + self.addInsnDef(insn) + self.patchAvx2byte() + self.mergeSSENONE() + self.printStats() + + def log(self, s): + if os.getenv("UD_OPCODE_DEBUG"): + self._logFh.write(s + "\n") + + + def mergeSSENONE(self): + """Merge sse tables with only one entry for /sse=none + """ + for table in self._tables: + for k, e in table.entries(): + if isinstance(e, UdOpcodeTable) and e.typ() == '/sse': + if e.numEntries() == 1: + sse = e.lookup("/sse=none") + if sse: + table.setEntryAt(k, sse) + uniqTables = {} + def genTableList(tbl): + if tbl not in uniqTables: + self._tables.append(tbl) + uniqTables[tbl] = 1 + for k, e in tbl.entries(): + if isinstance(e, UdOpcodeTable): + genTableList(e) + self._tables = [] + genTableList(self.root) + + + def patchAvx2byte(self): + # create avx tables + for pp in (None, 'f2', 'f3', '66'): + for m in (None, '0f', '0f38', '0f3a'): + if pp is None and m is None: + continue + if pp is None: + vex = m + elif m is None: + vex = pp else: - self.nByteInsn = 2 - - # The opcode that indexes into the opcode table. - self.opcode = self.opcodes[self.nByteInsn - 1] - - # Record opcode extensions - for opcode in self.opcodes[self.nByteInsn:]: - arg, val = opcode.split('=') - self.opcext[arg] = self.OpcExtMap[arg](val) - - # Record sse extension: the reason sse extension is handled - # separately is that historically sse was handled as a first - # class opcode, not as an extension. Now that sse is handled - # as an extension, we do the manual conversion here, as opposed - # to modifying the opcode xml file. - if ssePrefix is not None: - self.opcext['/sse'] = self.OpcExtMap['/sse'](ssePrefix) - - def parse(self, table, insn): - index = insn.opcodes[0]; - if insn.nByteInsn > 1: - assert index == '0f' - table = self.updateTable(table, index, 'opctbl', '0f') - index = insn.opcodes[1] - - if insn.nByteInsn == 3: - table = self.updateTable(table, index, 'opctbl', index) - index = insn.opcodes[2] + vex = pp + '_' + m + table = self.walk(self.root, ('c4', '/vex=' + vex)) + self.map(self.root, ('c5', '/vex=' + vex), table) + - # Walk down the tree, create levels as needed, for opcode - # extensions. The order is important, and determines how + def addInsn(self, **insnDef): + + # Canonicalize opcode list + opcexts = insnDef['opcexts'] + opcodes = list(insnDef['opcodes']) + + # Re-order vex + if '/vex' in opcexts: + assert opcodes[0] == 'c4' or opcodes[0] == 'c5' + opcodes.insert(1, '/vex=' + opcexts['/vex']) + + # Add extensions. The order is important, and determines how # well the opcode table is packed. Also note, /sse must be # before /o, because /sse may consume operand size prefix # affect the outcome of /o. - for ext in ('/mod', '/x87', '/reg', '/rm', '/sse', - '/o', '/a', '/m', '/3dnow'): - if ext in insn.opcext: - table = self.updateTable(table, index, ext, ext) - index = insn.opcext[ext] - - # additional table for disambiguating vendor - if len(insn.vendor): - table = self.updateTable(table, index, 'vendor', insn.vendor) - index = self.OpcExtIndex['vendor'][insn.vendor] - - # make leaf node entries - leaf = self.updateTable(table, index, 'insn', '') - - leaf['mnemonic'] = insn.mnemonic - leaf['prefixes'] = insn.prefixes - leaf['operands'] = insn.operands - - # add instruction to linear table of instruction forms - self.InsnTable.append({ 'prefixes' : insn.prefixes, - 'mnemonic' : insn.mnemonic, - 'operands' : insn.operands }) - - # add mnemonic to mnemonic table - if not insn.mnemonic in self.MnemonicsTable: - self.MnemonicsTable.append(insn.mnemonic) - - - # Adds an instruction definition to the opcode tables - def addInsnDef( self, prefixes, mnemonic, opcodes, operands, vendor ): - insn = self.Insn(prefixes=prefixes, - mnemonic=mnemonic, - opcodes=opcodes, - operands=operands, - vendor=vendor) - self.parse(self.OpcodeTable0, insn) - - def print_table( self, table, pfxs ): - print("%s |" % pfxs) - keys = table[ 'entries' ].keys() - if ( len( keys ) ): - keys.sort() - for idx in keys: - e = table[ 'entries' ][ idx ] - if e[ 'type' ] == 'insn': - print("%s |-<%s>" % ( pfxs, idx )), - print("%s %s" % ( e[ 'mnemonic' ], ' '.join( e[ 'operands'] ))) + for ext in ('/mod', '/x87', '/reg', '/rm', '/sse', '/o', '/a', '/m', + '/vexw', '/vexl', '/3dnow', '/vendor'): + if ext in opcexts: + opcodes.append(ext + '=' + opcexts[ext]) + + insn = UdInsnDef(mnemonic = insnDef['mnemonic'], + prefixes = insnDef['prefixes'], + operands = insnDef['operands'], + opcodes = opcodes, + cpuid = insnDef['cpuid']) + try: + self.map(self.root, opcodes, insn) + except self.CollisionError as e: + self.pprint() + print(opcodes, insn, str(e.obj1), str(e.obj2)) + raise + except Exception as e: + self.pprint() + raise + self._insns.append(insn) + # add to lookup by mnemonic structure + if insn.mnemonic not in self._mnemonics: + self._mnemonics[insn.mnemonic] = [ insn ] + else: + self._mnemonics[insn.mnemonic].append(insn) + + + def addInsnDef(self, insnDef): + opcodes = [] + opcexts = {} + + # pack plain opcodes first, and collect opcode + # extensions + for opc in insnDef['opcodes']: + if not opc.startswith('/'): + opcodes.append(opc) else: - print("%s |-<%s> %s" % ( pfxs, idx, e['type'] )) - self.print_table( e, pfxs + ' |' ) + e, v = opc.split('=') + opcexts[e] = v + + # treat vendor as an opcode extension + if len(insnDef['vendor']): + opcexts['/vendor'] = insnDef['vendor'][0] + + if insnDef['mnemonic'] in ('lds', 'les'): + # + # Massage lds and les, which share the same prefix as AVX + # instructions, to work well with the opcode tree. + # + opcexts['/vex'] = 'none' + elif '/vex' in opcexts: + # A proper avx instruction definition; make sure there are + # no legacy opcode extensions + assert '/sse' not in opcodes + + # make sure the opcode definitions don't already include + # the avx prefixes. + assert opcodes[0] not in ('c4', 'c5') + + # An avx only instruction is defined by the /vex= opcode + # extension. They do not include the c4 (long form) or + # c5 (short form) prefix. As part of opcode table generate, + # here we create the long form definition, and then patch + # the table for c5 in a later stage. + # Construct a long-form definition of the avx instruction + opcodes.insert(0, 'c4') + elif (opcodes[0] == '0f' and opcodes[1] != '0f' and + '/sse' not in opcexts): + # Make all 2-byte opcode form isntructions play nice with sse + # opcode maps. + opcexts['/sse'] = 'none' + + # legacy sse defs that get promoted to avx + fn = self.addInsn + if 'avx' in insnDef['cpuid'] and '/sse' in opcexts: + fn = self.addSSE2AVXInsn + + fn(mnemonic = insnDef['mnemonic'], + prefixes = insnDef['prefixes'], + opcodes = opcodes, + opcexts = opcexts, + operands = insnDef['operands'], + cpuid = insnDef['cpuid']) + + + def addSSE2AVXInsn(self, **insnDef): + """Add an instruction definition containing an avx cpuid bit, but + declared in its legacy SSE form. The function splits the + definition to create two new definitions, one for SSE and one + promoted to an AVX form. + """ + + # SSE + ssemnemonic = insnDef['mnemonic'] + sseopcodes = insnDef['opcodes'] + # remove vex opcode extensions + sseopcexts = dict([(e, v) for e, v in itemslist(insnDef['opcexts']) + if not e.startswith('/vex')]) + # strip out avx operands, preserving relative ordering + # of remaining operands + sseoperands = [opr for opr in insnDef['operands'] + if opr not in ('H', 'L')] + # strip out avx prefixes + sseprefixes = [pfx for pfx in insnDef['prefixes'] + if not pfx.startswith('vex')] + # strip out avx bits from cpuid + ssecpuid = [flag for flag in insnDef['cpuid'] + if not flag.startswith('avx')] + + self.addInsn(mnemonic = ssemnemonic, + prefixes = sseprefixes, + opcodes = sseopcodes, + opcexts = sseopcexts, + operands = sseoperands, + cpuid = ssecpuid) + + # AVX + vexmnemonic = 'v' + insnDef['mnemonic'] + vexprefixes = insnDef['prefixes'] + vexopcodes = ['c4'] + vexopcexts = dict([(e, insnDef['opcexts'][e]) + for e in insnDef['opcexts'] if e != '/sse']) + vexopcexts['/vex'] = insnDef['opcexts']['/sse'] + '_' + '0f' + if insnDef['opcodes'][1] == '38' or insnDef['opcodes'][1] == '3a': + vexopcexts['/vex'] += insnDef['opcodes'][1] + vexopcodes.extend(insnDef['opcodes'][2:]) + else: + vexopcodes.extend(insnDef['opcodes'][1:]) + vexoperands = [] + for o in insnDef['operands']: + # make the operand size explicit: x + if o in ('V', 'W', 'H', 'U'): + o = o + 'x' + vexoperands.append(o) + vexcpuid = [flag for flag in insnDef['cpuid'] + if not flag.startswith('sse')] + + self.addInsn(mnemonic = vexmnemonic, + prefixes = vexprefixes, + opcodes = vexopcodes, + opcexts = vexopcexts, + operands = vexoperands, + cpuid = vexcpuid) + + def getInsnList(self): + """Returns a list of all instructions in the collection""" + return self._insns + + + def getTableList(self): + """Returns a list of all tables in the collection""" + return self._tables + + def getMnemonicsList(self): + """Returns a sorted list of mnemonics""" + return sorted(self._mnemonics.keys()) + + + def pprint(self): + def printWalk(tbl, indent=""): + entries = tbl.entries() + for k, e in entries: + if isinstance(e, UdOpcodeTable): + self.log("%s |-<%02x> %s" % (indent, k, e)) + printWalk(e, indent + " |") + elif isinstance(e, UdInsnDef): + self.log("%s |-<%02x> %s" % (indent, k, e)) + printWalk(self.root) + + + def printStats(self): + tables = self.getTableList() + self.log("stats: ") + self.log(" Num tables = %d" % len(tables)) + self.log(" Num insnDefs = %d" % len(self.getInsnList())) + self.log(" Num insns = %d" % len(self.getMnemonicsList())) + + totalSize = 0 + totalEntries = 0 + for table in tables: + totalSize += table.size() + totalEntries += table.numEntries() + self.log(" Packing Ratio = %d%%" % ((totalEntries * 100) / totalSize)) + self.log("--------------------") + + self.pprint() + + + @staticmethod + def parseOptableXML(xml): + """Parse udis86 optable.xml file and return list of + instruction definitions. + """ + from xml.dom import minidom - def print_tree( self ): - self.print_table( self.OpcodeTable0, '' ) + xmlDoc = minidom.parse(xml) + tlNode = xmlDoc.firstChild + insns = [] + + while tlNode and tlNode.localName != "x86optable": + tlNode = tlNode.nextSibling + + for insnNode in tlNode.childNodes: + if not insnNode.localName: + continue + if insnNode.localName != "instruction": + raise Exception("warning: invalid insn node - %s" % insnNode.localName) + mnemonic = insnNode.getElementsByTagName('mnemonic')[0].firstChild.data + vendor, cpuid = '', [] + + for node in insnNode.childNodes: + if node.localName == 'vendor': + vendor = node.firstChild.data.split() + elif node.localName == 'cpuid': + cpuid = node.firstChild.data.split() + + for node in insnNode.childNodes: + if node.localName == 'def': + insnDef = { 'pfx' : [] } + for node in node.childNodes: + if not node.localName: + continue + if node.localName in ('pfx', 'opc', 'opr', 'vendor', 'cpuid'): + insnDef[node.localName] = node.firstChild.data.split() + elif node.localName == 'mode': + insnDef['pfx'].extend(node.firstChild.data.split()) + insns.append({'prefixes' : insnDef.get('pfx', []), + 'mnemonic' : mnemonic, + 'opcodes' : insnDef.get('opc', []), + 'operands' : insnDef.get('opr', []), + 'vendor' : insnDef.get('vendor', vendor), + 'cpuid' : insnDef.get('cpuid', cpuid)}) + return insns diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/ud_optable.py webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/ud_optable.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/udis86/ud_optable.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/udis86/ud_optable.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -# udis86 - scripts/ud_optable.py (optable.xml parser) -# -# Copyright (c) 2009 Vivek Thampi -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import os -import sys -from xml.dom import minidom - -class UdOptableXmlParser: - - def parseDef( self, node ): - ven = '' - pfx = [] - opc = [] - opr = [] - for def_node in node.childNodes: - if not def_node.localName: - continue - if def_node.localName == 'pfx': - pfx = def_node.firstChild.data.split(); - elif def_node.localName == 'opc': - opc = def_node.firstChild.data.split(); - elif def_node.localName == 'opr': - opr = def_node.firstChild.data.split(); - elif def_node.localName == 'mode': - pfx.extend( def_node.firstChild.data.split() ); - elif def_node.localName == 'syn': - pfx.extend( def_node.firstChild.data.split() ); - elif def_node.localName == 'vendor': - ven = ( def_node.firstChild.data ); - else: - print("warning: invalid node - %s" % def_node.localName) - continue - return ( pfx, opc, opr, ven ) - - def parse( self, xml, fn ): - xmlDoc = minidom.parse( xml ) - self.TlNode = xmlDoc.firstChild - - while self.TlNode and self.TlNode.localName != "x86optable": - self.TlNode = self.TlNode.nextSibling - - for insnNode in self.TlNode.childNodes: - if not insnNode.localName: - continue - if insnNode.localName != "instruction": - print("warning: invalid insn node - %s" % insnNode.localName) - continue - - mnemonic = insnNode.getElementsByTagName( 'mnemonic' )[ 0 ].firstChild.data - vendor = '' - - for node in insnNode.childNodes: - if node.localName == 'vendor': - vendor = node.firstChild.data - elif node.localName == 'def': - ( prefixes, opcodes, operands, local_vendor ) = \ - self.parseDef( node ) - if ( len( local_vendor ) ): - vendor = local_vendor - # callback - fn( prefixes, mnemonic, opcodes, operands, vendor ) - - -def printFn( pfx, mnm, opc, opr, ven ): - print('def: '), - if len( pfx ): - print(' '.join( pfx )), - print("%s %s %s %s" % \ - ( mnm, ' '.join( opc ), ' '.join( opr ), ven )) - - -def parse( xml, callback ): - parser = UdOptableXmlParser() - parser.parse( xml, callback ) - -def main(): - parser = UdOptableXmlParser() - parser.parse( sys.argv[ 1 ], printFn ) - -if __name__ == "__main__": - main() diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/X86Disassembler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/X86Disassembler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/disassembler/X86Disassembler.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/disassembler/X86Disassembler.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -26,7 +26,6 @@ #include "config.h" #include "Disassembler.h" -#if ENABLE(DISASSEMBLER) #if USE(UDIS86) #include "MacroAssemblerCodeRef.h" @@ -43,4 +42,3 @@ } // namespace JSC #endif // USE(UDIS86) -#endif // ENABLE(DISASSEMBLER) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/dynbench.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/dynbench.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/dynbench.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/dynbench.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -33,6 +33,7 @@ #include "JSLock.h" #include "JSObject.h" #include "VM.h" +#include using namespace JSC; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/features.json webkit2gtk-2.14.2/Source/JavaScriptCore/features.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/features.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/features.json 2016-09-19 12:18:06.000000000 +0000 @@ -4,11 +4,20 @@ "name": "ES6", "url": "http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts", "keywords": ["es6", "es2015", "ecmascript"], - "contact": { - "name": "Saam Barati", - "email": "sbarati@apple.com", - "twitter": "@saambarati" - } + "status": { + "status": "Done" + }, + "contact": [ + { + "name": "Saam Barati", + "email": "sbarati@apple.com", + "twitter": "@saambarati" + }, + { + "name": "Keith Miller", + "email": "keith_miller@apple.com" + } + ] }, { "name": "ES7", @@ -18,18 +27,13 @@ { "name": "Internationalization API", "status": { - "status": "In Development" + "status": "Done" }, "url": "http://ecma-international.org/publications/standards/Ecma-402.htm", "documentation-url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl", "webkit-url": "https://bugs.webkit.org/show_bug.cgi?id=90906", "description": "The Internationalization API provides language sensitive operations for string, number, and date.", - "keywords": ["Intl", "Collator", "ECMA-402"], - "contact": { - "name": "Andy VanWagoner", - "email": "thetalecrafter@gmail.com", - "twitter": "@thetalecrafter" - } + "keywords": ["Intl", "Collator", "ECMA-402"] }, { "name": "WebAssembly", @@ -88,7 +92,7 @@ { "name": "Arrow Functions", "status": { - "status": "In Development", + "status": "Done", "enabled-by-default": true }, "url": "http://www.ecma-international.org/ecma-262/6.0/index.html#sec-arrow-function-definitions", @@ -99,7 +103,7 @@ { "name": "Block Scoping", "status": { - "status": "In Development", + "status": "Done", "enabled-by-default": true }, "url": "http://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations", @@ -110,7 +114,7 @@ { "name": "Classes", "status": { - "status": "In Development", + "status": "Done", "enabled-by-default": true }, "url": "http://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions", @@ -141,6 +145,23 @@ "specification": "ES6" }, { + "name": "Exponentiation Syntax", + "status": { + "status": "Done", + "enabled-by-default": true + }, + "url": "https://tc39.github.io/ecma262/#prod-ExponentiationExpression", + "specification": "ES7", + "description": "Exponentiation syntax (like x ** y) provides the syntax suger for exponentiation.", + "webkit-url": "https://bugs.webkit.org/show_bug.cgi?id=159969", + "documentation-url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation_(**)", + "contact": { + "name": "Yusuke Suzuki", + "twitter": "@Constellation", + "email": "utatane.tea@gmail.com" + } + }, + { "name": "Generators", "status": { "status": "Done", @@ -178,7 +199,8 @@ "url": "http://www.ecma-international.org/ecma-262/6.0/index.html#sec-modules", "documentation-url": "https://hacks.mozilla.org/2015/08/es6-in-depth-modules/", "description": "Modules make modularizing code and splitting it across different files easy because the syntax and semantics are now standard in the JavaScript langauge.", - "specification": "ES6" + "specification": "ES6", + "comment": "ES6 work is done, however, this feature is still listed as \"In Development\" because the module loading specification has yet to be finalized <\/a>. It is possible to use Modules with the jsc command line tool by passing the -m flag, although it is primarily intended for testing." }, { "name": "Number Object Extensions", @@ -218,7 +240,7 @@ { "name": "Proxy Objects", "status": { - "status": "Under Consideration" + "status": "Done" }, "url": "http://www.ecma-international.org/ecma-262/6.0/index.html#sec-proxy-objects", "webkit-url": "https://bugs.webkit.org/show_bug.cgi?id=35731", @@ -233,7 +255,7 @@ { "name": "Reflect API", "status": { - "status": "In Development", + "status": "Done", "enabled-by-default": true }, "url": "http://www.ecma-international.org/ecma-262/6.0/#sec-reflect-object", diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRefPrivate.h webkit2gtk-2.14.2/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRefPrivate.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRefPrivate.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRefPrivate.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1 @@ +#include diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSTypedArray.h webkit2gtk-2.14.2/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSTypedArray.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSTypedArray.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSTypedArray.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1 @@ +#include diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -39,8 +39,11 @@ #include "JSPropertyNameEnumerator.h" #include "JSScope.h" #include "JSCInlines.h" +#include "RegExpConstructor.h" +#include "RegExpObject.h" #include "ScopedArguments.h" #include "ScopedArgumentsTable.h" +#include "ShadowChicken.h" namespace JSC { namespace FTL { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h 2016-11-03 07:04:20.000000000 +0000 @@ -32,6 +32,8 @@ #include "DFGArrayMode.h" #include "FTLAbstractHeap.h" #include "IndexingType.h" +#include "JSMap.h" +#include "JSSet.h" namespace JSC { namespace FTL { @@ -76,7 +78,20 @@ macro(JSString_value, JSString::offsetOfValue()) \ macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \ macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \ - macro(MarkedAllocator_freeListHead, MarkedAllocator::offsetOfFreeListHead()) \ + macro(RegExpConstructor_cachedResult_lastRegExp, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastRegExp()) \ + macro(RegExpConstructor_cachedResult_lastInput, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastInput()) \ + macro(RegExpConstructor_cachedResult_result_start, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)) \ + macro(RegExpConstructor_cachedResult_result_end, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)) \ + macro(RegExpConstructor_cachedResult_reified, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfReified()) \ + macro(RegExpObject_lastIndex, RegExpObject::offsetOfLastIndex()) \ + macro(RegExpObject_lastIndexIsWritable, RegExpObject::offsetOfLastIndexIsWritable()) \ + macro(ShadowChicken_Packet_callee, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)) \ + macro(ShadowChicken_Packet_frame, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)) \ + macro(ShadowChicken_Packet_callerFrame, OBJECT_OFFSETOF(ShadowChicken::Packet, callerFrame)) \ + macro(ShadowChicken_Packet_thisValue, OBJECT_OFFSETOF(ShadowChicken::Packet, thisValue)) \ + macro(ShadowChicken_Packet_scope, OBJECT_OFFSETOF(ShadowChicken::Packet, scope)) \ + macro(ShadowChicken_Packet_codeBlock, OBJECT_OFFSETOF(ShadowChicken::Packet, codeBlock)) \ + macro(ShadowChicken_Packet_callSiteIndex, OBJECT_OFFSETOF(ShadowChicken::Packet, callSiteIndex)) \ macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \ macro(ScopedArguments_scope, ScopedArguments::offsetOfScope()) \ macro(ScopedArguments_table, ScopedArguments::offsetOfTable()) \ @@ -89,15 +104,19 @@ macro(Structure_globalObject, Structure::globalObjectOffset()) \ macro(Structure_prototype, Structure::prototypeOffset()) \ macro(Structure_structureID, Structure::structureIDOffset()) \ - macro(Symbol_privateName, Symbol::offsetOfPrivateName()) + macro(JSMap_hashMapImpl, JSMap::offsetOfHashMapImpl()) \ + macro(JSSet_hashMapImpl, JSSet::offsetOfHashMapImpl()) \ + macro(HashMapImpl_capacity, HashMapImpl>::offsetOfCapacity()) \ + macro(HashMapImpl_buffer, HashMapImpl>::offsetOfBuffer()) \ + macro(HashMapBucket_value, HashMapBucket::offsetOfValue()) \ + macro(HashMapBucket_key, HashMapBucket::offsetOfKey()) \ #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \ macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \ macro(JSEnvironmentRecord_variables, JSEnvironmentRecord::offsetOfVariables(), sizeof(EncodedJSValue)) \ macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier)) \ macro(JSRopeString_fibers, JSRopeString::offsetOfFibers(), sizeof(WriteBarrier)) \ - macro(MarkedSpace_Subspace_impreciseAllocators, OBJECT_OFFSETOF(MarkedSpace::Subspace, impreciseAllocators), sizeof(MarkedAllocator)) \ - macro(MarkedSpace_Subspace_preciseAllocators, OBJECT_OFFSETOF(MarkedSpace::Subspace, preciseAllocators), sizeof(MarkedAllocator)) \ + macro(MarkedSpace_Subspace_allocatorForSizeStep, OBJECT_OFFSETOF(MarkedSpace::Subspace, allocatorForSizeStep), sizeof(MarkedAllocator*)) \ macro(ScopedArguments_overflowStorage, ScopedArguments::overflowStorageOffset(), sizeof(EncodedJSValue)) \ macro(WriteBarrierBuffer_bufferContents, 0, sizeof(JSCell*)) \ macro(characters8, 0, sizeof(LChar)) \ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCapabilities.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCapabilities.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCapabilities.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCapabilities.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -44,6 +44,7 @@ switch (node->op()) { case JSConstant: + case LazyJSConstant: case GetLocal: case SetLocal: case PutStack: @@ -68,7 +69,6 @@ case ArrayifyToStructure: case PutStructure: case GetButterfly: - case GetButterflyReadOnly: case NewObject: case NewArray: case NewArrayBuffer: @@ -99,6 +99,7 @@ case ArithRound: case ArithFloor: case ArithCeil: + case ArithTrunc: case ArithSqrt: case ArithLog: case ArithFRound: @@ -111,8 +112,8 @@ case ExtractOSREntryLocal: case LoopHint: case SkipScope: + case GetGlobalObject: case CreateActivation: - case NewArrowFunction: case NewFunction: case NewGeneratorFunction: case GetClosureVar: @@ -127,7 +128,7 @@ case CheckCell: case CheckBadCell: case CheckNotEmpty: - case CheckIdent: + case CheckStringIdent: case CheckWatchdogTimer: case StringCharCodeAt: case StringFromCharCode: @@ -141,6 +142,7 @@ case TailCallInlinedCaller: case Construct: case CallVarargs: + case CallEval: case TailCallVarargs: case TailCallVarargsInlinedCaller: case ConstructVarargs: @@ -159,13 +161,17 @@ case GetExecutable: case GetScope: case GetCallee: - case GetArgumentCount: + case GetArgumentCountIncludingThis: + case ToNumber: case ToString: + case CallObjectConstructor: case CallStringConstructor: case MakeRope: case NewArrayWithSize: + case TryGetById: case GetById: case GetByIdFlush: + case GetByIdWithThis: case ToThis: case MultiGetByOffset: case MultiPutByOffset: @@ -173,6 +179,13 @@ case Throw: case ThrowReferenceError: case Unreachable: + case In: + case IsJSArray: + case MapHash: + case GetMapBucket: + case LoadFromJSMapBucket: + case IsNonEmptyMapBucket: + case IsEmpty: case IsUndefined: case IsBoolean: case IsNumber: @@ -180,6 +193,8 @@ case IsObject: case IsObjectOrNull: case IsFunction: + case IsRegExpObject: + case IsTypedArrayView: case CheckTypeInfoFlags: case OverridesHasInstance: case InstanceOf: @@ -194,6 +209,7 @@ case HasStructureProperty: case GetDirectPname: case GetEnumerableLength: + case GetIndexedPropertyStorage: case GetPropertyEnumerator: case GetEnumeratorStructurePname: case GetEnumeratorGenericPname: @@ -210,20 +226,42 @@ case PhantomDirectArguments: case PhantomClonedArguments: case GetMyArgumentByVal: + case GetMyArgumentByValOutOfBounds: case ForwardVarargs: case Switch: case TypeOf: + case PutById: + case PutByIdDirect: + case PutByIdFlush: + case PutByIdWithThis: case PutGetterById: case PutSetterById: case PutGetterSetterById: case PutGetterByVal: case PutSetterByVal: - case CopyRest: + case CreateRest: case GetRestLength: case RegExpExec: case RegExpTest: case NewRegexp: case StringReplace: + case StringReplaceRegExp: + case GetRegExpObjectLastIndex: + case SetRegExpObjectLastIndex: + case RecordRegExpCachedResult: + case SetFunctionName: + case LogShadowChickenPrologue: + case LogShadowChickenTail: + case ResolveScope: + case GetDynamicVar: + case PutDynamicVar: + case CompareEq: + case CompareEqPtr: + case CompareLess: + case CompareLessEq: + case CompareGreater: + case CompareGreaterEq: + case CompareStrictEq: // These are OK. break; @@ -233,22 +271,6 @@ // case because it would prevent us from catching bugs where the FTL backend // pipeline failed to optimize out an Identity. break; - case In: - if (node->child2().useKind() == CellUse) - break; - return CannotCompile; - case PutByIdDirect: - case PutById: - case PutByIdFlush: - if (node->child1().useKind() == CellUse) - break; - return CannotCompile; - case GetIndexedPropertyStorage: - if (node->arrayMode().type() == Array::String) - break; - if (isTypedView(node->arrayMode().typedArrayType())) - break; - return CannotCompile; case CheckArray: switch (node->arrayMode().type()) { case Array::Int32: @@ -307,6 +329,8 @@ return CannotCompile; } break; + case GetByValWithThis: + break; case PutByVal: case PutByValAlias: case PutByValDirect: @@ -323,6 +347,8 @@ return CannotCompile; } break; + case PutByValWithThis: + break; case ArrayPush: case ArrayPop: switch (node->arrayMode().type()) { @@ -334,75 +360,6 @@ return CannotCompile; } break; - case CompareEq: - if (node->isBinaryUseKind(Int32Use)) - break; - if (node->isBinaryUseKind(Int52RepUse)) - break; - if (node->isBinaryUseKind(DoubleRepUse)) - break; - if (node->isBinaryUseKind(StringIdentUse)) - break; - if (node->isBinaryUseKind(StringUse)) - break; - if (node->isBinaryUseKind(SymbolUse)) - break; - if (node->isBinaryUseKind(ObjectUse)) - break; - if (node->isBinaryUseKind(UntypedUse)) - break; - if (node->isBinaryUseKind(BooleanUse)) - break; - if (node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse)) - break; - if (node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) - break; - if (node->child1().useKind() == OtherUse || node->child2().useKind() == OtherUse) - break; - return CannotCompile; - case CompareStrictEq: - if (node->isBinaryUseKind(Int32Use)) - break; - if (node->isBinaryUseKind(Int52RepUse)) - break; - if (node->isBinaryUseKind(DoubleRepUse)) - break; - if (node->isBinaryUseKind(StringIdentUse)) - break; - if (node->isBinaryUseKind(StringUse)) - break; - if (node->isBinaryUseKind(ObjectUse, UntypedUse)) - break; - if (node->isBinaryUseKind(UntypedUse, ObjectUse)) - break; - if (node->isBinaryUseKind(ObjectUse)) - break; - if (node->isBinaryUseKind(BooleanUse)) - break; - if (node->isBinaryUseKind(SymbolUse)) - break; - if (node->isBinaryUseKind(MiscUse, UntypedUse)) - break; - if (node->isBinaryUseKind(UntypedUse, MiscUse)) - break; - if (node->isBinaryUseKind(StringIdentUse, NotStringVarUse)) - break; - if (node->isBinaryUseKind(NotStringVarUse, StringIdentUse)) - break; - return CannotCompile; - case CompareLess: - case CompareLessEq: - case CompareGreater: - case CompareGreaterEq: - if (node->isBinaryUseKind(Int32Use)) - break; - if (node->isBinaryUseKind(Int52RepUse)) - break; - if (node->isBinaryUseKind(DoubleRepUse)) - break; - if (node->isBinaryUseKind(UntypedUse)) - break; - return CannotCompile; default: // Don't know how to handle anything else. return CannotCompile; @@ -423,6 +380,12 @@ dataLog("FTL rejecting ", *graph.m_codeBlock, " because it doesn't belong to a function.\n"); return CannotCompile; } + + if (UNLIKELY(graph.m_codeBlock->ownerScriptExecutable()->neverFTLOptimize())) { + if (verboseCapabilities()) + dataLog("FTL rejecting ", *graph.m_codeBlock, " because it is marked as never FTL compile.\n"); + return CannotCompile; + } CapabilityLevel result = CanCompileAndOSREnter; @@ -466,6 +429,8 @@ case StringObjectUse: case StringOrStringObjectUse: case SymbolUse: + case MapObjectUse: + case SetObjectUse: case FinalObjectUse: case RegExpObjectUse: case NotCellUse: @@ -473,8 +438,8 @@ case MiscUse: case StringIdentUse: case NotStringVarUse: - case MachineIntUse: - case DoubleRepMachineIntUse: + case AnyIntUse: + case DoubleRepAnyIntUse: // These are OK. break; default: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCommonValues.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCommonValues.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCommonValues.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCommonValues.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -42,13 +42,6 @@ using namespace B3; CommonValues::CommonValues() - : voidType(B3::Void) - , boolean(B3::Int32) - , int32(B3::Int32) - , int64(B3::Int64) - , intPtr(B3::pointerType()) - , floatType(B3::Float) - , doubleType(B3::Double) { } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCommonValues.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCommonValues.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCommonValues.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCommonValues.h 2016-11-03 07:04:20.000000000 +0000 @@ -46,13 +46,6 @@ void initializeConstants(B3::Procedure&, B3::BasicBlock*); - const LType voidType; - const LType boolean; - const LType int32; - const LType int64; - const LType intPtr; - const LType floatType; - const LType doubleType; LValue booleanTrue { nullptr }; LValue booleanFalse { nullptr }; LValue int32Zero { nullptr }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCompile.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCompile.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLCompile.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLCompile.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -42,6 +42,7 @@ #include "FTLJITCode.h" #include "FTLThunks.h" #include "JITSubGenerator.h" +#include "JSCInlines.h" #include "LinkBuffer.h" #include "PCToCodeOriginMap.h" #include "ScratchRegisterAllocator.h" @@ -103,9 +104,14 @@ inlineCallFrame->calleeRecovery.withLocalsOffset(localsOffset); } - if (graph.hasDebuggerEnabled()) - codeBlock->setScopeRegister(codeBlock->scopeRegister() + localsOffset); } + + // Note that the scope register could be invalid here if the original code had CallEval but it + // got killed. That's because it takes the CallEval to cause the scope register to be kept alive + // unless the debugger is also enabled. + if (graph.needsScopeRegister() && codeBlock->scopeRegister().isValid()) + codeBlock->setScopeRegister(codeBlock->scopeRegister() + localsOffset); + for (OSRExitDescriptor& descriptor : state.jitCode->osrExitDescriptors) { for (unsigned i = descriptor.m_values.size(); i--;) descriptor.m_values[i] = descriptor.m_values[i].withLocalsOffset(localsOffset); @@ -121,7 +127,7 @@ // Emit the exception handler. *state.exceptionHandler = jit.label(); - jit.copyCalleeSavesToVMCalleeSavesBuffer(); + jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(); jit.move(MacroAssembler::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0); jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1); CCallHelpers::Call call = jit.call(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLJITCode.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLJITCode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLJITCode.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLJITCode.h 2016-11-03 07:04:20.000000000 +0000 @@ -33,7 +33,6 @@ #include "FTLLazySlowPath.h" #include "FTLOSRExit.h" #include "JITCode.h" -#include namespace JSC { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,6 +32,7 @@ #include "DFGPlan.h" #include "FTLState.h" #include "FTLThunks.h" +#include "JSCInlines.h" #include "ProfilerDatabase.h" namespace JSC { namespace FTL { @@ -83,7 +84,7 @@ m_plan.codeBlock->setJITCode(jitCode); if (m_plan.compilation) - m_plan.vm.m_perBytecodeProfiler->addCompilation(m_plan.compilation); + m_plan.vm->m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation); return true; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLLink.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLLink.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLLink.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLLink.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -130,26 +130,29 @@ CCallHelpers::JumpList mainPathJumps; jit.load32( - frame.withOffset(sizeof(Register) * JSStack::ArgumentCount), + frame.withOffset(sizeof(Register) * CallFrameSlot::argumentCount), GPRInfo::regT1); mainPathJumps.append(jit.branch32( CCallHelpers::AboveOrEqual, GPRInfo::regT1, CCallHelpers::TrustedImm32(codeBlock->numParameters()))); jit.emitFunctionPrologue(); jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); - jit.store32( - CCallHelpers::TrustedImm32(CallSiteIndex(0).bits()), - CCallHelpers::tagFor(JSStack::ArgumentCount)); jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame); CCallHelpers::Call callArityCheck = jit.call(); -#if !ASSERT_DISABLED - // FIXME: need to make this call register with exception handling somehow. This is - // part of a bigger problem: FTL should be able to handle exceptions. - // https://bugs.webkit.org/show_bug.cgi?id=113622 - // Until then, use a JIT ASSERT. - jit.load64(vm.addressOfException(), GPRInfo::regT1); - jit.jitAssertIsNull(GPRInfo::regT1); -#endif + + auto noException = jit.branch32(CCallHelpers::GreaterThanOrEqual, GPRInfo::returnValueGPR, CCallHelpers::TrustedImm32(0)); + jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(); + jit.move(CCallHelpers::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0); + jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1); + CCallHelpers::Call callLookupExceptionHandlerFromCallerFrame = jit.call(); + jit.jumpToExceptionHandler(); + noException.link(&jit); + + if (!ASSERT_DISABLED) { + jit.load64(vm.addressOfException(), GPRInfo::regT1); + jit.jitAssertIsNull(GPRInfo::regT1); + } + jit.move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0); jit.emitFunctionEpilogue(); mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0)); @@ -164,6 +167,7 @@ return; } linkBuffer->link(callArityCheck, codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck); + linkBuffer->link(callLookupExceptionHandlerFromCallerFrame, lookupExceptionHandlerFromCallerFrame); linkBuffer->link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixupGenerator)).code().executableAddress())); linkBuffer->link(mainPathJumps, CodeLocationLabel(bitwise_cast(state.generatedFunction))); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -30,10 +30,15 @@ #include "AirGenerationContext.h" #include "AllowMacroScratchRegisterUsage.h" +#include "B3CheckValue.h" +#include "B3PatchpointValue.h" +#include "B3SlotBaseValue.h" #include "B3StackmapGenerationParams.h" +#include "B3ValueInlines.h" #include "CallFrameShuffler.h" #include "CodeBlockWithJITType.h" #include "DFGAbstractInterpreterInlines.h" +#include "DFGCapabilities.h" #include "DFGDominators.h" #include "DFGInPlaceAbstractState.h" #include "DFGOSRAvailabilityAnalysisPhase.h" @@ -58,17 +63,21 @@ #include "JITDivGenerator.h" #include "JITInlineCacheGenerator.h" #include "JITLeftShiftGenerator.h" +#include "JITMathIC.h" #include "JITMulGenerator.h" #include "JITRightShiftGenerator.h" #include "JITSubGenerator.h" #include "JSCInlines.h" #include "JSGeneratorFunction.h" #include "JSLexicalEnvironment.h" +#include "JSMap.h" #include "OperandsInlines.h" #include "ScopedArguments.h" #include "ScopedArgumentsTable.h" #include "ScratchRegisterAllocator.h" #include "SetupVarargsFrame.h" +#include "ShadowChicken.h" +#include "StructureStubInfo.h" #include "VirtualRegister.h" #include "Watchdog.h" #include @@ -88,12 +97,7 @@ std::atomic compileCounter; -#if ASSERT_DISABLED -NO_RETURN_DUE_TO_CRASH static void ftlUnreachable() -{ - CRASH(); -} -#else +#if !ASSERT_DISABLED NO_RETURN_DUE_TO_CRASH static void ftlUnreachable( CodeBlock* codeBlock, BlockIndex blockIndex, unsigned nodeIndex) { @@ -155,10 +159,7 @@ m_out.setFrequency(1); m_prologue = m_out.newBlock(); - LBasicBlock stackOverflow = m_out.newBlock(); m_handleExceptions = m_out.newBlock(); - - LBasicBlock checkArguments = m_out.newBlock(); for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { m_highBlock = m_graph.block(blockIndex); @@ -171,7 +172,7 @@ // Back to prologue frequency for any bocks that get sneakily created in the initialization code. m_out.setFrequency(1); - m_out.appendTo(m_prologue, stackOverflow); + m_out.appendTo(m_prologue, m_handleExceptions); m_out.initializeConstants(m_proc, m_prologue); createPhiVariables(); @@ -182,9 +183,6 @@ auto preOrder = m_graph.blocksInPreOrder(); - // We should not create any alloca's after this point, since they will cease to - // be mem2reg candidates. - m_callFrame = m_out.framePointer(); m_tagTypeNumber = m_out.constInt64(TagTypeNumber); m_tagMask = m_out.constInt64(TagMask); @@ -194,45 +192,55 @@ m_proc.addFastConstant(m_tagTypeNumber->key()); m_proc.addFastConstant(m_tagMask->key()); - m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(JSStack::CodeBlock)); - - m_out.branch( - didOverflowStack(), rarely(stackOverflow), usually(checkArguments)); - - m_out.appendTo(stackOverflow, m_handleExceptions); - m_out.call(m_out.voidType, m_out.operation(operationThrowStackOverflowError), m_callFrame, m_out.constIntPtr(codeBlock())); - m_out.patchpoint(Void)->setGenerator( - [=] (CCallHelpers& jit, const StackmapGenerationParams&) { - // We are terminal, so we can clobber everything. That's why we don't claim to - // clobber scratch. + m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(CallFrameSlot::codeBlock)); + + // Stack Overflow Check. + unsigned exitFrameSize = m_graph.requiredRegisterCountForExit() * sizeof(Register); + MacroAssembler::AbsoluteAddress addressOfStackLimit(vm().addressOfSoftStackLimit()); + PatchpointValue* stackOverflowHandler = m_out.patchpoint(Void); + CallSiteIndex callSiteIndex = callSiteIndexForCodeOrigin(m_ftlState, CodeOrigin(0)); + stackOverflowHandler->appendSomeRegister(m_callFrame); + stackOverflowHandler->clobber(RegisterSet::macroScratchRegisters()); + stackOverflowHandler->numGPScratchRegisters = 1; + stackOverflowHandler->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { AllowMacroScratchRegisterUsage allowScratch(jit); - - jit.copyCalleeSavesToVMCalleeSavesBuffer(); - jit.move(CCallHelpers::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0); - jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1); - CCallHelpers::Call call = jit.call(); - jit.jumpToExceptionHandler(); + GPRReg fp = params[0].gpr(); + GPRReg scratch = params.gpScratch(0); - jit.addLinkTask( - [=] (LinkBuffer& linkBuffer) { - linkBuffer.link(call, FunctionPtr(lookupExceptionHandlerFromCallerFrame)); - }); - }); - m_out.unreachable(); - - m_out.appendTo(m_handleExceptions, checkArguments); - Box exceptionHandler = state->exceptionHandler; - m_out.patchpoint(Void)->setGenerator( - [=] (CCallHelpers& jit, const StackmapGenerationParams&) { - CCallHelpers::Jump jump = jit.jump(); - jit.addLinkTask( - [=] (LinkBuffer& linkBuffer) { - linkBuffer.link(jump, linkBuffer.locationOf(*exceptionHandler)); + unsigned ftlFrameSize = params.proc().frameSize(); + + jit.addPtr(MacroAssembler::TrustedImm32(-std::max(exitFrameSize, ftlFrameSize)), fp, scratch); + MacroAssembler::Jump stackOverflow = jit.branchPtr(MacroAssembler::Above, addressOfStackLimit, scratch); + + params.addLatePath([=] (CCallHelpers& jit) { + AllowMacroScratchRegisterUsage allowScratch(jit); + + stackOverflow.link(&jit); + jit.store32( + MacroAssembler::TrustedImm32(callSiteIndex.bits()), + CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount))); + jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(); + + jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + jit.move(CCallHelpers::TrustedImmPtr(jit.codeBlock()), GPRInfo::argumentGPR1); + CCallHelpers::Call throwCall = jit.call(); + + jit.move(CCallHelpers::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0); + jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1); + CCallHelpers::Call lookupExceptionHandlerCall = jit.call(); + jit.jumpToExceptionHandler(); + + jit.addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link(throwCall, FunctionPtr(operationThrowStackOverflowError)); + linkBuffer.link(lookupExceptionHandlerCall, FunctionPtr(lookupExceptionHandlerFromCallerFrame)); }); + }); }); - m_out.unreachable(); - - m_out.appendTo(checkArguments, lowBlock(m_graph.block(0))); + + LBasicBlock firstDFGBasicBlock = lowBlock(m_graph.block(0)); + // Check Arguments. availabilityMap().clear(); availabilityMap().m_locals = Operands(codeBlock()->numParameters(), 0); for (unsigned i = codeBlock()->numParameters(); i--;) { @@ -274,8 +282,20 @@ break; } } - m_out.jump(lowBlock(m_graph.block(0))); - + m_out.jump(firstDFGBasicBlock); + + m_out.appendTo(m_handleExceptions, firstDFGBasicBlock); + Box exceptionHandler = state->exceptionHandler; + m_out.patchpoint(Void)->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams&) { + CCallHelpers::Jump jump = jit.jump(); + jit.addLinkTask( + [=] (LinkBuffer& linkBuffer) { + linkBuffer.link(jump, linkBuffer.locationOf(*exceptionHandler)); + }); + }); + m_out.unreachable(); + for (DFG::BasicBlock* block : preOrder) compileBlock(block); @@ -315,19 +335,19 @@ LType type; switch (node->flags() & NodeResultMask) { case NodeResultDouble: - type = m_out.doubleType; + type = Double; break; case NodeResultInt32: - type = m_out.int32; + type = Int32; break; case NodeResultInt52: - type = m_out.int64; + type = Int64; break; case NodeResultBoolean: - type = m_out.boolean; + type = Int32; break; case NodeResultJS: - type = m_out.int64; + type = Int64; break; default: DFG_CRASH(m_graph, node, "Bad Phi node result type"); @@ -375,7 +395,7 @@ if (!m_highBlock->cfaHasVisited) { if (verboseCompilationEnabled()) dataLog("Bailing because CFA didn't reach.\n"); - crash(m_highBlock->index, UINT_MAX); + crash(m_highBlock, nullptr); return; } @@ -430,6 +450,7 @@ m_availableRecoveries.resize(0); m_interpreter.startExecuting(); + m_interpreter.executeKnownEdgeTypes(m_node); switch (m_node->op()) { case DFG::Upsilon: @@ -446,6 +467,9 @@ case Int52Constant: compileInt52Constant(); break; + case LazyJSConstant: + compileLazyJSConstant(); + break; case DoubleRep: compileDoubleRep(); break; @@ -476,6 +500,9 @@ case DFG::Check: compileNoOp(); break; + case CallObjectConstructor: + compileCallObjectConstructor(); + break; case ToThis: compileToThis(); break; @@ -529,6 +556,9 @@ case ArithCeil: compileArithCeil(); break; + case ArithTrunc: + compileArithTrunc(); + break; case ArithSqrt: compileArithSqrt(); break; @@ -574,8 +604,8 @@ case CheckBadCell: compileCheckBadCell(); break; - case CheckIdent: - compileCheckIdent(); + case CheckStringIdent: + compileCheckStringIdent(); break; case GetExecutable: compileGetExecutable(); @@ -586,9 +616,15 @@ case PutStructure: compilePutStructure(); break; + case TryGetById: + compileGetById(AccessType::GetPure); + break; case GetById: case GetByIdFlush: - compileGetById(); + compileGetById(AccessType::Get); + break; + case GetByIdWithThis: + compileGetByIdWithThis(); break; case In: compileIn(); @@ -598,6 +634,9 @@ case PutByIdFlush: compilePutById(); break; + case PutByIdWithThis: + compilePutByIdWithThis(); + break; case PutGetterById: case PutSetterById: compilePutAccessorById(); @@ -612,9 +651,6 @@ case GetButterfly: compileGetButterfly(); break; - case GetButterflyReadOnly: - compileGetButterflyReadOnly(); - break; case ConstantStoragePointer: compileConstantStoragePointer(); break; @@ -634,13 +670,20 @@ compileGetByVal(); break; case GetMyArgumentByVal: + case GetMyArgumentByValOutOfBounds: compileGetMyArgumentByVal(); break; + case GetByValWithThis: + compileGetByValWithThis(); + break; case PutByVal: case PutByValAlias: case PutByValDirect: compilePutByVal(); break; + case PutByValWithThis: + compilePutByValWithThis(); + break; case ArrayPush: compileArrayPush(); break; @@ -651,7 +694,6 @@ compileCreateActivation(); break; case NewFunction: - case NewArrowFunction: case NewGeneratorFunction: compileNewFunction(); break; @@ -688,6 +730,9 @@ case ReallocatePropertyStorage: compileReallocatePropertyStorage(); break; + case ToNumber: + compileToNumber(); + break; case ToString: case CallStringConstructor: compileToStringOrCallStringConstructor(); @@ -739,8 +784,8 @@ case GetCallee: compileGetCallee(); break; - case GetArgumentCount: - compileGetArgumentCount(); + case GetArgumentCountIncludingThis: + compileGetArgumentCountIncludingThis(); break; case GetScope: compileGetScope(); @@ -748,6 +793,9 @@ case SkipScope: compileSkipScope(); break; + case GetGlobalObject: + compileGetGlobalObject(); + break; case GetClosureVar: compileGetClosureVar(); break; @@ -778,6 +826,9 @@ case CompareGreaterEq: compileCompareGreaterEq(); break; + case CompareEqPtr: + compileCompareEqPtr(); + break; case LogicalNot: compileLogicalNot(); break; @@ -799,6 +850,9 @@ case ConstructForwardVarargs: compileCallOrConstructVarargs(); break; + case CallEval: + compileCallEval(); + break; case LoadVarargs: compileLoadVarargs(); break; @@ -827,6 +881,9 @@ case InvalidationPoint: compileInvalidationPoint(); break; + case IsEmpty: + compileIsEmpty(); + break; case IsUndefined: compileIsUndefined(); break; @@ -839,6 +896,21 @@ case IsString: compileIsString(); break; + case IsJSArray: + compileIsJSArray(); + break; + case MapHash: + compileMapHash(); + break; + case GetMapBucket: + compileGetMapBucket(); + break; + case LoadFromJSMapBucket: + compileLoadFromJSMapBucket(); + break; + case IsNonEmptyMapBucket: + compileIsNonEmptyMapBucket(); + break; case IsObject: compileIsObject(); break; @@ -848,6 +920,12 @@ case IsFunction: compileIsFunction(); break; + case IsRegExpObject: + compileIsRegExpObject(); + break; + case IsTypedArrayView: + compileIsTypedArrayView(); + break; case TypeOf: compileTypeOf(); break; @@ -908,8 +986,8 @@ case CheckWatchdogTimer: compileCheckWatchdogTimer(); break; - case CopyRest: - compileCopyRest(); + case CreateRest: + compileCreateRest(); break; case GetRestLength: compileGetRestLength(); @@ -923,9 +1001,40 @@ case NewRegexp: compileNewRegexp(); break; + case SetFunctionName: + compileSetFunctionName(); + break; case StringReplace: + case StringReplaceRegExp: compileStringReplace(); break; + case GetRegExpObjectLastIndex: + compileGetRegExpObjectLastIndex(); + break; + case SetRegExpObjectLastIndex: + compileSetRegExpObjectLastIndex(); + break; + case LogShadowChickenPrologue: + compileLogShadowChickenPrologue(); + break; + case LogShadowChickenTail: + compileLogShadowChickenTail(); + break; + case RecordRegExpCachedResult: + compileRecordRegExpCachedResult(); + break; + case ResolveScope: + compileResolveScope(); + break; + case GetDynamicVar: + compileGetDynamicVar(); + break; + case PutDynamicVar: + compilePutDynamicVar(); + break; + case Unreachable: + compileUnreachable(); + break; case PhantomLocal: case LoopHint: @@ -1029,12 +1138,24 @@ void compileInt52Constant() { - int64_t value = m_node->asMachineInt(); + int64_t value = m_node->asAnyInt(); setInt52(m_out.constInt64(value << JSValue::int52ShiftAmount)); setStrictInt52(m_out.constInt64(value)); } + void compileLazyJSConstant() + { + PatchpointValue* patchpoint = m_out.patchpoint(Int64); + LazyJSValue value = m_node->lazyJSValue(); + patchpoint->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { + value.emit(jit, JSValueRegs(params[0].gpr())); + }); + patchpoint->effects = Effects::none(); + setJSValue(patchpoint); + } + void compileDoubleRep() { switch (m_node->child1().useKind()) { @@ -1052,16 +1173,16 @@ usually(continuation), rarely(intCase)); LBasicBlock lastNext = m_out.appendTo(intCase, continuation); - + FTL_TYPE_CHECK( jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber, - isNotInt32(value, provenType(m_node->child1()) & ~SpecFullDouble)); + isNotInt32(value, provenType(m_node->child1()) & ~SpecDoubleReal)); ValueFromBlock slowResult = m_out.anchor(m_out.intToDouble(unboxInt32(value))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setDouble(m_out.phi(m_out.doubleType, fastResult, slowResult)); + setDouble(m_out.phi(Double, fastResult, slowResult)); return; } @@ -1135,7 +1256,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setDouble(m_out.phi(m_out.doubleType, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse)); + setDouble(m_out.phi(Double, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse)); return; } m_out.appendTo(nonDoubleCase, continuation); @@ -1144,7 +1265,7 @@ m_out.appendTo(continuation, lastNext); - setDouble(m_out.phi(m_out.doubleType, intToDouble, unboxedDouble)); + setDouble(m_out.phi(Double, intToDouble, unboxedDouble)); return; } @@ -1196,13 +1317,13 @@ setStrictInt52(m_out.signExt32To64(lowInt32(m_node->child1()))); return; - case MachineIntUse: + case AnyIntUse: setStrictInt52( jsValueToStrictInt52( m_node->child1(), lowJSValue(m_node->child1(), ManualOperandSpeculation))); return; - case DoubleRepMachineIntUse: + case DoubleRepAnyIntUse: setStrictInt52( doubleToStrictInt52( m_node->child1(), lowDouble(m_node->child1()))); @@ -1257,7 +1378,7 @@ { switch (m_node->child1().useKind()) { case BooleanUse: { - setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32)); + setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), Int32)); return; } @@ -1279,11 +1400,11 @@ LBasicBlock lastNext = m_out.appendTo(booleanCase, continuation); ValueFromBlock booleanResult = m_out.anchor(m_out.bitOr( - m_out.zeroExt(unboxBoolean(value), m_out.int64), m_tagTypeNumber)); + m_out.zeroExt(unboxBoolean(value), Int64), m_tagTypeNumber)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, booleanResult, notBooleanResult)); + setJSValue(m_out.phi(Int64, booleanResult, notBooleanResult)); return; } @@ -1373,6 +1494,29 @@ { DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate); } + + void compileCallObjectConstructor() + { + JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); + LValue value = lowJSValue(m_node->child1()); + + LBasicBlock isCellCase = m_out.newBlock(); + LBasicBlock slowCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + m_out.branch(isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase)); + + LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase); + ValueFromBlock fastResult = m_out.anchor(value); + m_out.branch(isObject(value), usually(continuation), rarely(slowCase)); + + m_out.appendTo(slowCase, continuation); + ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationObjectConstructor), m_callFrame, m_out.constIntPtr(globalObject), value)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); + } void compileToThis() { @@ -1387,7 +1531,11 @@ LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase); ValueFromBlock fastResult = m_out.anchor(value); - m_out.branch(isType(value, FinalObjectType), usually(continuation), rarely(slowCase)); + m_out.branch( + m_out.testIsZero32( + m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoFlags), + m_out.constInt32(OverridesToThis)), + usually(continuation), rarely(slowCase)); m_out.appendTo(slowCase, continuation); J_JITOperation_EJ function; @@ -1396,16 +1544,113 @@ else function = operationToThis; ValueFromBlock slowResult = m_out.anchor( - vmCall(m_out.int64, m_out.operation(function), m_callFrame, value)); + vmCall(Int64, m_out.operation(function), m_callFrame, value)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); } - + void compileValueAdd() { - emitBinarySnippet(operationValueAdd); + JITAddIC* addIC = codeBlock()->addJITAddIC(); + auto repatchingFunction = operationValueAddOptimize; + auto nonRepatchingFunction = operationValueAdd; + compileMathIC(addIC, repatchingFunction, nonRepatchingFunction); + } + + template + void compileMathIC(JITMathIC* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction) + { + Node* node = m_node; + + LValue left = lowJSValue(node->child1()); + LValue right = lowJSValue(node->child2()); + + SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType()); + SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType()); + + PatchpointValue* patchpoint = m_out.patchpoint(Int64); + patchpoint->appendSomeRegister(left); + patchpoint->appendSomeRegister(right); + patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); + RefPtr exceptionHandle = + preparePatchpointForExceptions(patchpoint); + patchpoint->numGPScratchRegisters = 1; + patchpoint->numFPScratchRegisters = 2; + patchpoint->clobber(RegisterSet::macroScratchRegisters()); + State* state = &m_ftlState; + patchpoint->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + + Box exceptions = + exceptionHandle->scheduleExitCreation(params)->jumps(jit); + +#if ENABLE(MATH_IC_STATS) + auto inlineStart = jit.label(); +#endif + + Box mathICGenerationState = Box::create(); + ArithProfile* arithProfile = state->graph.baselineCodeBlockFor(node->origin.semantic)->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); + mathIC->m_generator = Generator(leftOperand, rightOperand, JSValueRegs(params[0].gpr()), + JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), params.fpScratch(0), + params.fpScratch(1), params.gpScratch(0), InvalidFPRReg, arithProfile); + + bool shouldEmitProfiling = false; + bool generatedInline = mathIC->generateInline(jit, *mathICGenerationState, shouldEmitProfiling); + + if (generatedInline) { + ASSERT(!mathICGenerationState->slowPathJumps.empty()); + auto done = jit.label(); + params.addLatePath([=] (CCallHelpers& jit) { + AllowMacroScratchRegisterUsage allowScratch(jit); + mathICGenerationState->slowPathJumps.link(&jit); + mathICGenerationState->slowPathStart = jit.label(); +#if ENABLE(MATH_IC_STATS) + auto slowPathStart = jit.label(); +#endif + + if (mathICGenerationState->shouldSlowPathRepatch) { + SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(), + repatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr(), CCallHelpers::TrustedImmPtr(mathIC)); + mathICGenerationState->slowPathCall = call.call(); + } else { + SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, + exceptions.get(), nonRepatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr()); + mathICGenerationState->slowPathCall = call.call(); + } + jit.jump().linkTo(done, &jit); + + jit.addLinkTask([=] (LinkBuffer& linkBuffer) { + mathIC->finalizeInlineCode(*mathICGenerationState, linkBuffer); + }); + +#if ENABLE(MATH_IC_STATS) + auto slowPathEnd = jit.label(); + jit.addLinkTask([=] (LinkBuffer& linkBuffer) { + size_t size = static_cast(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast(linkBuffer.locationOf(slowPathStart).executableAddress()); + mathIC->m_generatedCodeSize += size; + }); +#endif + }); + } else { + callOperation( + *state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(), + nonRepatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr()); + } + +#if ENABLE(MATH_IC_STATS) + auto inlineEnd = jit.label(); + jit.addLinkTask([=] (LinkBuffer& linkBuffer) { + size_t size = static_cast(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast(linkBuffer.locationOf(inlineStart).executableAddress()); + mathIC->m_generatedCodeSize += size; + }); +#endif + }); + + setJSValue(patchpoint); } void compileStrCat() @@ -1413,13 +1658,13 @@ LValue result; if (m_node->child3()) { result = vmCall( - m_out.int64, m_out.operation(operationStrCat3), m_callFrame, + Int64, m_out.operation(operationStrCat3), m_callFrame, lowJSValue(m_node->child1(), ManualOperandSpeculation), lowJSValue(m_node->child2(), ManualOperandSpeculation), lowJSValue(m_node->child3(), ManualOperandSpeculation)); } else { result = vmCall( - m_out.int64, m_out.operation(operationStrCat2), m_callFrame, + Int64, m_out.operation(operationStrCat2), m_callFrame, lowJSValue(m_node->child1(), ManualOperandSpeculation), lowJSValue(m_node->child2(), ManualOperandSpeculation)); } @@ -1447,8 +1692,8 @@ } case Int52RepUse: { - if (!abstractValue(m_node->child1()).couldBeType(SpecInt52) - && !abstractValue(m_node->child2()).couldBeType(SpecInt52)) { + if (!abstractValue(m_node->child1()).couldBeType(SpecInt52Only) + && !abstractValue(m_node->child2()).couldBeType(SpecInt52Only)) { Int52Kind kind; LValue left = lowWhicheverInt52(m_node->child1(), kind); LValue right = lowInt52(m_node->child2(), kind); @@ -1479,7 +1724,10 @@ break; } - emitBinarySnippet(operationValueSub); + JITSubIC* subIC = codeBlock()->addJITSubIC(); + auto repatchingFunction = operationValueSubOptimize; + auto nonRepatchingFunction = operationValueSub; + compileMathIC(subIC, repatchingFunction, nonRepatchingFunction); break; } @@ -1491,8 +1739,15 @@ void compileArithClz32() { - LValue operand = lowInt32(m_node->child1()); - setInt32(m_out.ctlz32(operand)); + if (m_node->child1().useKind() == Int32Use || m_node->child1().useKind() == KnownInt32Use) { + LValue operand = lowInt32(m_node->child1()); + setInt32(m_out.ctlz32(operand)); + return; + } + DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Int32, m_out.operation(operationArithClz32), m_callFrame, argument); + setInt32(result); } void compileArithMul() @@ -1563,7 +1818,10 @@ } case UntypedUse: { - emitBinarySnippet(operationValueMul); + JITMulIC* mulIC = codeBlock()->addJITMulIC(); + auto repatchingFunction = operationValueMulOptimize; + auto nonRepatchingFunction = operationValueMul; + compileMathIC(mulIC, repatchingFunction, nonRepatchingFunction); break; } @@ -1745,7 +2003,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setDouble(m_out.phi(m_out.doubleType, results)); + setDouble(m_out.phi(Double, results)); break; } @@ -1776,15 +2034,37 @@ break; } - default: - DFG_CRASH(m_graph, m_node, "Bad use kind"); + default: { + DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Double, m_out.operation(operationArithAbs), m_callFrame, argument); + setDouble(result); break; } + } } - void compileArithSin() { setDouble(m_out.doubleSin(lowDouble(m_node->child1()))); } + void compileArithSin() + { + if (m_node->child1().useKind() == DoubleRepUse) { + setDouble(m_out.doubleSin(lowDouble(m_node->child1()))); + return; + } + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Double, m_out.operation(operationArithSin), m_callFrame, argument); + setDouble(result); + } - void compileArithCos() { setDouble(m_out.doubleCos(lowDouble(m_node->child1()))); } + void compileArithCos() + { + if (m_node->child1().useKind() == DoubleRepUse) { + setDouble(m_out.doubleCos(lowDouble(m_node->child1()))); + return; + } + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Double, m_out.operation(operationArithCos), m_callFrame, argument); + setDouble(result); + } void compileArithPow() { @@ -1797,8 +2077,19 @@ LBasicBlock integerExponentIsSmallBlock = m_out.newBlock(); LBasicBlock integerExponentPowBlock = m_out.newBlock(); LBasicBlock doubleExponentPowBlockEntry = m_out.newBlock(); - LBasicBlock nanExceptionExponentIsInfinity = m_out.newBlock(); LBasicBlock nanExceptionBaseIsOne = m_out.newBlock(); + LBasicBlock nanExceptionExponentIsInfinity = m_out.newBlock(); + LBasicBlock testExponentIsOneHalf = m_out.newBlock(); + LBasicBlock handleBaseZeroExponentIsOneHalf = m_out.newBlock(); + LBasicBlock handleInfinityForExponentIsOneHalf = m_out.newBlock(); + LBasicBlock exponentIsOneHalfNormal = m_out.newBlock(); + LBasicBlock exponentIsOneHalfInfinity = m_out.newBlock(); + LBasicBlock testExponentIsNegativeOneHalf = m_out.newBlock(); + LBasicBlock testBaseZeroExponentIsNegativeOneHalf = m_out.newBlock(); + LBasicBlock handleBaseZeroExponentIsNegativeOneHalf = m_out.newBlock(); + LBasicBlock handleInfinityForExponentIsNegativeOneHalf = m_out.newBlock(); + LBasicBlock exponentIsNegativeOneHalfNormal = m_out.newBlock(); + LBasicBlock exponentIsNegativeOneHalfInfinity = m_out.newBlock(); LBasicBlock powBlock = m_out.newBlock(); LBasicBlock nanExceptionResultIsNaN = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); @@ -1809,33 +2100,95 @@ m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlockEntry)); LBasicBlock lastNext = m_out.appendTo(integerExponentIsSmallBlock, integerExponentPowBlock); - LValue integerExponentBelow1000 = m_out.below(integerExponent, m_out.constInt32(1000)); - m_out.branch(integerExponentBelow1000, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry)); + LValue integerExponentBelowMax = m_out.belowOrEqual(integerExponent, m_out.constInt32(maxExponentForIntegerMathPow)); + m_out.branch(integerExponentBelowMax, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry)); m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlockEntry); ValueFromBlock powDoubleIntResult = m_out.anchor(m_out.doublePowi(base, integerExponent)); m_out.jump(continuation); // If y is NaN, the result is NaN. - m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionExponentIsInfinity); + m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionBaseIsOne); LValue exponentIsNaN; if (provenType(m_node->child2()) & SpecDoubleNaN) exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent); else exponentIsNaN = m_out.booleanFalse; - m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionExponentIsInfinity)); + m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionBaseIsOne)); // If abs(x) is 1 and y is +infinity, the result is NaN. // If abs(x) is 1 and y is -infinity, the result is NaN. - m_out.appendTo(nanExceptionExponentIsInfinity, nanExceptionBaseIsOne); - LValue absoluteExponent = m_out.doubleAbs(exponent); - LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits::infinity())); - m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionBaseIsOne), usually(powBlock)); - m_out.appendTo(nanExceptionBaseIsOne, powBlock); + // Test if base == 1. + m_out.appendTo(nanExceptionBaseIsOne, nanExceptionExponentIsInfinity); LValue absoluteBase = m_out.doubleAbs(base); LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1)); - m_out.branch(absoluteBaseIsOne, unsure(nanExceptionResultIsNaN), unsure(powBlock)); + m_out.branch(absoluteBaseIsOne, rarely(nanExceptionExponentIsInfinity), usually(testExponentIsOneHalf)); + + // Test if abs(y) == Infinity. + m_out.appendTo(nanExceptionExponentIsInfinity, testExponentIsOneHalf); + LValue absoluteExponent = m_out.doubleAbs(exponent); + LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits::infinity())); + m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionResultIsNaN), usually(testExponentIsOneHalf)); + + // If y == 0.5 or y == -0.5, handle it through SQRT. + // We have be carefuly with -0 and -Infinity. + + // Test if y == 0.5 + m_out.appendTo(testExponentIsOneHalf, handleBaseZeroExponentIsOneHalf); + LValue exponentIsOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(0.5)); + m_out.branch(exponentIsOneHalf, rarely(handleBaseZeroExponentIsOneHalf), usually(testExponentIsNegativeOneHalf)); + + // Handle x == -0. + m_out.appendTo(handleBaseZeroExponentIsOneHalf, handleInfinityForExponentIsOneHalf); + LValue baseIsZeroExponentIsOneHalf = m_out.doubleEqual(base, m_out.doubleZero); + ValueFromBlock zeroResultExponentIsOneHalf = m_out.anchor(m_out.doubleZero); + m_out.branch(baseIsZeroExponentIsOneHalf, rarely(continuation), usually(handleInfinityForExponentIsOneHalf)); + + // Test if abs(x) == Infinity. + m_out.appendTo(handleInfinityForExponentIsOneHalf, exponentIsOneHalfNormal); + LValue absoluteBaseIsInfinityOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits::infinity())); + m_out.branch(absoluteBaseIsInfinityOneHalf, rarely(exponentIsOneHalfInfinity), usually(exponentIsOneHalfNormal)); + + // The exponent is 0.5, the base is finite or NaN, we can use SQRT. + m_out.appendTo(exponentIsOneHalfNormal, exponentIsOneHalfInfinity); + ValueFromBlock sqrtResult = m_out.anchor(m_out.doubleSqrt(base)); + m_out.jump(continuation); + + // The exponent is 0.5, the base is infinite, the result is always infinite. + m_out.appendTo(exponentIsOneHalfInfinity, testExponentIsNegativeOneHalf); + ValueFromBlock sqrtInfinityResult = m_out.anchor(m_out.constDouble(std::numeric_limits::infinity())); + m_out.jump(continuation); + + // Test if y == -0.5 + m_out.appendTo(testExponentIsNegativeOneHalf, testBaseZeroExponentIsNegativeOneHalf); + LValue exponentIsNegativeOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(-0.5)); + m_out.branch(exponentIsNegativeOneHalf, rarely(testBaseZeroExponentIsNegativeOneHalf), usually(powBlock)); + + // Handle x == -0. + m_out.appendTo(testBaseZeroExponentIsNegativeOneHalf, handleBaseZeroExponentIsNegativeOneHalf); + LValue baseIsZeroExponentIsNegativeOneHalf = m_out.doubleEqual(base, m_out.doubleZero); + m_out.branch(baseIsZeroExponentIsNegativeOneHalf, rarely(handleBaseZeroExponentIsNegativeOneHalf), usually(handleInfinityForExponentIsNegativeOneHalf)); + + m_out.appendTo(handleBaseZeroExponentIsNegativeOneHalf, handleInfinityForExponentIsNegativeOneHalf); + ValueFromBlock oneOverSqrtZeroResult = m_out.anchor(m_out.constDouble(std::numeric_limits::infinity())); + m_out.jump(continuation); + + // Test if abs(x) == Infinity. + m_out.appendTo(handleInfinityForExponentIsNegativeOneHalf, exponentIsNegativeOneHalfNormal); + LValue absoluteBaseIsInfinityNegativeOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits::infinity())); + m_out.branch(absoluteBaseIsInfinityNegativeOneHalf, rarely(exponentIsNegativeOneHalfInfinity), usually(exponentIsNegativeOneHalfNormal)); + + // The exponent is -0.5, the base is finite or NaN, we can use 1/SQRT. + m_out.appendTo(exponentIsNegativeOneHalfNormal, exponentIsNegativeOneHalfInfinity); + LValue sqrtBase = m_out.doubleSqrt(base); + ValueFromBlock oneOverSqrtResult = m_out.anchor(m_out.div(m_out.constDouble(1.), sqrtBase)); + m_out.jump(continuation); + + // The exponent is -0.5, the base is infinite, the result is always zero. + m_out.appendTo(exponentIsNegativeOneHalfInfinity, powBlock); + ValueFromBlock oneOverSqrtInfinityResult = m_out.anchor(m_out.doubleZero); + m_out.jump(continuation); m_out.appendTo(powBlock, nanExceptionResultIsNaN); ValueFromBlock powResult = m_out.anchor(m_out.doublePow(base, exponent)); @@ -1846,7 +2199,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, powResult, pureNan)); + setDouble(m_out.phi(Double, powDoubleIntResult, zeroResultExponentIsOneHalf, sqrtResult, sqrtInfinityResult, oneOverSqrtZeroResult, oneOverSqrtResult, oneOverSqrtInfinityResult, powResult, pureNan)); } } @@ -1922,7 +2275,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - result = m_out.phi(m_out.doubleType, integerValueResult, integerValueRoundedDownResult); + result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult); } if (producesInteger(m_node->arithRoundingMode())) { @@ -1952,13 +2305,47 @@ setDouble(integerValue); } - void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); } + void compileArithTrunc() + { + LValue value = lowDouble(m_node->child1()); + LValue result = m_out.doubleTrunc(value); + if (producesInteger(m_node->arithRoundingMode())) + setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()))); + else + setDouble(result); + } + + void compileArithSqrt() + { + if (m_node->child1().useKind() == DoubleRepUse) { + setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); + return; + } + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Double, m_out.operation(operationArithSqrt), m_callFrame, argument); + setDouble(result); + } - void compileArithLog() { setDouble(m_out.doubleLog(lowDouble(m_node->child1()))); } + void compileArithLog() + { + if (m_node->child1().useKind() == DoubleRepUse) { + setDouble(m_out.doubleLog(lowDouble(m_node->child1()))); + return; + } + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Double, m_out.operation(operationArithLog), m_callFrame, argument); + setDouble(result); + } void compileArithFRound() { - setDouble(m_out.fround(lowDouble(m_node->child1()))); + if (m_node->child1().useKind() == DoubleRepUse) { + setDouble(m_out.fround(lowDouble(m_node->child1()))); + return; + } + LValue argument = lowJSValue(m_node->child1()); + LValue result = vmCall(Double, m_out.operation(operationArithFRound), m_callFrame, argument); + setDouble(result); } void compileArithNegate() @@ -1984,7 +2371,7 @@ } case Int52RepUse: { - if (!abstractValue(m_node->child1()).couldBeType(SpecInt52)) { + if (!abstractValue(m_node->child1()).couldBeType(SpecInt52Only)) { Int52Kind kind; LValue value = lowWhicheverInt52(m_node->child1(), kind); LValue result = m_out.neg(value); @@ -2078,10 +2465,10 @@ LValue value = lowInt32(m_node->child1()); if (doesOverflow(m_node->arithMode())) { - setDouble(m_out.unsignedToDouble(value)); + setStrictInt52(m_out.zeroExtPtr(value)); return; } - + speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero)); setInt32(value); } @@ -2160,18 +2547,12 @@ speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node->child1()))); } - void compileCheckIdent() + void compileCheckStringIdent() { UniquedStringImpl* uid = m_node->uidOperand(); - if (uid->isSymbol()) { - LValue symbol = lowSymbol(m_node->child1()); - LValue stringImpl = m_out.loadPtr(symbol, m_heaps.Symbol_privateName); - speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid))); - } else { - LValue string = lowStringIdent(m_node->child1()); - LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value); - speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid))); - } + LValue string = lowStringIdent(m_node->child1()); + LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value); + speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid))); } void compileGetExecutable() @@ -2213,17 +2594,17 @@ switch (m_node->arrayMode().type()) { case Array::Int32: - vmCall(m_out.voidType, m_out.operation(operationEnsureInt32), m_callFrame, cell); + vmCall(Void, m_out.operation(operationEnsureInt32), m_callFrame, cell); break; case Array::Double: - vmCall(m_out.voidType, m_out.operation(operationEnsureDouble), m_callFrame, cell); + vmCall(Void, m_out.operation(operationEnsureDouble), m_callFrame, cell); break; case Array::Contiguous: - vmCall(m_out.voidType, m_out.operation(operationEnsureContiguous), m_callFrame, cell); + vmCall(Void, m_out.operation(operationEnsureContiguous), m_callFrame, cell); break; case Array::ArrayStorage: case Array::SlowPutArrayStorage: - vmCall(m_out.voidType, m_out.operation(operationEnsureArrayStorage), m_callFrame, cell); + vmCall(Void, m_out.operation(operationEnsureArrayStorage), m_callFrame, cell); break; default: DFG_CRASH(m_graph, m_node, "Bad array type"); @@ -2255,11 +2636,12 @@ cell, m_heaps.JSCell_structureID); } - void compileGetById() + void compileGetById(AccessType type) { + ASSERT(type == AccessType::Get || type == AccessType::GetPure); switch (m_node->child1().useKind()) { case CellUse: { - setJSValue(getById(lowCell(m_node->child1()))); + setJSValue(getById(lowCell(m_node->child1()), type)); return; } @@ -2277,18 +2659,24 @@ isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase)); LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase); - ValueFromBlock cellResult = m_out.anchor(getById(value)); + ValueFromBlock cellResult = m_out.anchor(getById(value, type)); m_out.jump(continuation); - + + J_JITOperation_EJI getByIdFunction; + if (type == AccessType::Get) + getByIdFunction = operationGetByIdGeneric; + else + getByIdFunction = operationTryGetByIdGeneric; + m_out.appendTo(notCellCase, continuation); ValueFromBlock notCellResult = m_out.anchor(vmCall( - m_out.int64, m_out.operation(operationGetByIdGeneric), + Int64, m_out.operation(getByIdFunction), m_callFrame, value, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()]))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, cellResult, notCellResult)); + setJSValue(m_out.phi(Int64, cellResult, notCellResult)); return; } @@ -2297,14 +2685,51 @@ return; } } + + void compileGetByIdWithThis() + { + LValue base = lowJSValue(m_node->child1()); + LValue thisValue = lowJSValue(m_node->child2()); + LValue result = vmCall(Int64, m_out.operation(operationGetByIdWithThis), m_callFrame, base, thisValue, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])); + setJSValue(result); + } + + void compileGetByValWithThis() + { + LValue base = lowJSValue(m_node->child1()); + LValue thisValue = lowJSValue(m_node->child2()); + LValue subscript = lowJSValue(m_node->child3()); + + LValue result = vmCall(Int64, m_out.operation(operationGetByValWithThis), m_callFrame, base, thisValue, subscript); + setJSValue(result); + } + + void compilePutByIdWithThis() + { + LValue base = lowJSValue(m_node->child1()); + LValue thisValue = lowJSValue(m_node->child2()); + LValue value = lowJSValue(m_node->child3()); + + vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutByIdWithThisStrict : operationPutByIdWithThis), + m_callFrame, base, thisValue, value, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])); + } + + void compilePutByValWithThis() + { + LValue base = lowJSValue(m_graph.varArgChild(m_node, 0)); + LValue thisValue = lowJSValue(m_graph.varArgChild(m_node, 1)); + LValue property = lowJSValue(m_graph.varArgChild(m_node, 2)); + LValue value = lowJSValue(m_graph.varArgChild(m_node, 3)); + + vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis), + m_callFrame, base, thisValue, property, value); + } void compilePutById() { - Node* node = m_node; - - // See above; CellUse is easier so we do only that for now. - ASSERT(node->child1().useKind() == CellUse); + DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == CellUse); + Node* node = m_node; LValue base = lowCell(node->child1()); LValue value = lowJSValue(node->child2()); auto uid = m_graph.identifiers()[node->identifierNumber()]; @@ -2312,6 +2737,8 @@ B3::PatchpointValue* patchpoint = m_out.patchpoint(Void); patchpoint->appendSomeRegister(base); patchpoint->appendSomeRegister(value); + patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); patchpoint->clobber(RegisterSet::macroScratchRegisters()); // FIXME: If this is a PutByIdFlush, we might want to late-clobber volatile registers. @@ -2370,15 +2797,10 @@ void compileGetButterfly() { - setStorage(loadButterflyWithBarrier(lowCell(m_node->child1()))); + setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly)); } - void compileGetButterflyReadOnly() - { - setStorage(loadButterflyReadOnly(lowCell(m_node->child1()))); - } - - void compileConstantStoragePointer() + void compileConstantStoragePointer() { setStorage(m_out.constIntPtr(m_node->storagePointer())); } @@ -2400,17 +2822,18 @@ LBasicBlock lastNext = m_out.appendTo(slowPath, continuation); ValueFromBlock slowResult = m_out.anchor( - vmCall(m_out.intPtr, m_out.operation(operationResolveRope), m_callFrame, cell)); + vmCall(pointerType(), m_out.operation(operationResolveRope), m_callFrame, cell)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setStorage(m_out.loadPtr(m_out.phi(m_out.intPtr, fastResult, slowResult), m_heaps.StringImpl_data)); + setStorage(m_out.loadPtr(m_out.phi(pointerType(), fastResult, slowResult), m_heaps.StringImpl_data)); return; } - - setStorage(loadVectorWithBarrier(cell)); + + DFG_ASSERT(m_graph, m_node, isTypedView(m_node->arrayMode().typedArrayType())); + setStorage(m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector)); } void compileCheckArray() @@ -2447,8 +2870,8 @@ m_out.appendTo(wastefulCase, continuation); - LValue vectorPtr = loadVectorReadOnly(basePtr); - LValue butterflyPtr = loadButterflyReadOnly(basePtr); + LValue vectorPtr = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector); + LValue butterflyPtr = m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly); LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer); LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data); @@ -2457,7 +2880,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setInt32(m_out.castToInt32(m_out.phi(m_out.intPtr, simpleOut, wastefulOut))); + setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, wastefulOut))); } void compileGetArrayLength() @@ -2558,11 +2981,11 @@ m_out.appendTo(slowCase, continuation); ValueFromBlock slowResult = m_out.anchor( - vmCall(m_out.int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index)); + vmCall(Int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); return; } @@ -2610,11 +3033,11 @@ m_out.appendTo(slowCase, continuation); ValueFromBlock slowResult = m_out.anchor( - vmCall(m_out.int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index)); + vmCall(Int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); return; } @@ -2694,13 +3117,13 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, namedResult, overflowResult)); + setJSValue(m_out.phi(Int64, namedResult, overflowResult)); return; } case Array::Generic: { setJSValue(vmCall( - m_out.int64, m_out.operation(operationGetByVal), m_callFrame, + Int64, m_out.operation(operationGetByVal), m_callFrame, lowJSValue(m_node->child1()), lowJSValue(m_node->child2()))); return; } @@ -2753,8 +3176,8 @@ return; } - if (m_node->shouldSpeculateMachineInt()) { - setStrictInt52(m_out.zeroExt(result, m_out.int64)); + if (m_node->shouldSpeculateAnyInt()) { + setStrictInt52(m_out.zeroExt(result, Int64)); return; } @@ -2797,32 +3220,51 @@ else { VirtualRegister argumentCountRegister; if (!inlineCallFrame) - argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); + argumentCountRegister = VirtualRegister(CallFrameSlot::argumentCount); else argumentCountRegister = inlineCallFrame->argumentCountRegister; limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One); } - speculate(ExoticObjectMode, noValue(), 0, m_out.aboveOrEqual(index, limit)); + LValue isOutOfBounds = m_out.aboveOrEqual(index, limit); + LBasicBlock continuation = nullptr; + LBasicBlock lastNext = nullptr; + ValueFromBlock slowResult; + if (m_node->op() == GetMyArgumentByValOutOfBounds) { + LBasicBlock normalCase = m_out.newBlock(); + continuation = m_out.newBlock(); + + slowResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))); + m_out.branch(isOutOfBounds, unsure(continuation), unsure(normalCase)); + + lastNext = m_out.appendTo(normalCase, continuation); + } else + speculate(ExoticObjectMode, noValue(), 0, isOutOfBounds); TypedPointer base; if (inlineCallFrame) { - if (inlineCallFrame->arguments.size() <= 1) { - // We should have already exited due to the bounds check, above. Just tell the - // compiler that anything dominated by this instruction is not reachable, so - // that we don't waste time generating such code. This will also plant some - // kind of crashing instruction so that if by some fluke the bounds check didn't - // work, we'll crash in an easy-to-see way. - didAlreadyTerminate(); - return; - } - base = addressFor(inlineCallFrame->arguments[1].virtualRegister()); + if (inlineCallFrame->arguments.size() > 1) + base = addressFor(inlineCallFrame->arguments[1].virtualRegister()); } else base = addressFor(virtualRegisterForArgument(1)); - LValue pointer = m_out.baseIndex( - base.value(), m_out.zeroExt(index, m_out.intPtr), ScaleEight); - setJSValue(m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer))); + LValue result; + if (base) { + LValue pointer = m_out.baseIndex( + base.value(), m_out.zeroExt(index, pointerType()), ScaleEight); + result = m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer)); + } else + result = m_out.constInt64(JSValue::encode(jsUndefined())); + + if (m_node->op() == GetMyArgumentByValOutOfBounds) { + ValueFromBlock normalResult = m_out.anchor(result); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + result = m_out.phi(Int64, slowResult, normalResult); + } + + setJSValue(result); } void compilePutByVal() @@ -2849,7 +3291,7 @@ } vmCall( - m_out.voidType, m_out.operation(operation), m_callFrame, + Void, m_out.operation(operation), m_callFrame, lowJSValue(child1), lowJSValue(child2), lowJSValue(child3)); return; } @@ -2875,7 +3317,7 @@ LValue value = lowJSValue(child3, ManualOperandSpeculation); if (m_node->arrayMode().type() == Array::Int32) - FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value)); + FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32Only, isNotInt32(value)); TypedPointer elementPointer = m_out.baseIndex( m_node->arrayMode().type() == Array::Int32 ? @@ -2941,7 +3383,7 @@ m_out.add( storage, m_out.shl( - m_out.zeroExt(index, m_out.intPtr), + m_out.zeroExt(index, pointerType()), m_out.constIntPtr(logElementSize(type))))); Output::StoreType storeType; @@ -2978,7 +3420,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - intValue = m_out.phi(m_out.int32, intValues); + intValue = m_out.phi(Int32, intValues); } break; } @@ -3010,7 +3452,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - intValue = m_out.phi(m_out.int32, intValues); + intValue = m_out.phi(Int32, intValues); } else intValue = doubleToInt32(doubleValue); break; @@ -3049,27 +3491,32 @@ DFG_CRASH(m_graph, m_node, "Bad typed array type"); } } - + if (m_node->arrayMode().isInBounds() || m_node->op() == PutByValAlias) m_out.store(valueToStore, pointer, storeType); else { LBasicBlock isInBounds = m_out.newBlock(); + LBasicBlock isOutOfBounds = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); m_out.branch( m_out.aboveOrEqual(index, lowInt32(child5)), - unsure(continuation), unsure(isInBounds)); + unsure(isOutOfBounds), unsure(isInBounds)); - LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation); + LBasicBlock lastNext = m_out.appendTo(isInBounds, isOutOfBounds); m_out.store(valueToStore, pointer, storeType); m_out.jump(continuation); + + m_out.appendTo(isOutOfBounds, continuation); + speculateTypedArrayIsNotNeutered(base); + m_out.jump(continuation); m_out.appendTo(continuation, lastNext); } return; } - + DFG_CRASH(m_graph, m_node, "Bad array type"); break; } @@ -3081,7 +3528,7 @@ LValue accessor = lowCell(m_node->child2()); auto uid = m_graph.identifiers()[m_node->identifierNumber()]; vmCall( - m_out.voidType, + Void, m_out.operation(m_node->op() == PutGetterById ? operationPutGetterById : operationPutSetterById), m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), accessor); } @@ -3093,7 +3540,7 @@ LValue setter = lowJSValue(m_node->child3()); auto uid = m_graph.identifiers()[m_node->identifierNumber()]; vmCall( - m_out.voidType, m_out.operation(operationPutGetterSetter), + Void, m_out.operation(operationPutGetterSetter), m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), getter, setter); } @@ -3104,7 +3551,7 @@ LValue subscript = lowJSValue(m_node->child2()); LValue accessor = lowCell(m_node->child3()); vmCall( - m_out.voidType, + Void, m_out.operation(m_node->op() == PutGetterByVal ? operationPutGetterByVal : operationPutSetterByVal), m_callFrame, base, subscript, m_out.constInt32(m_node->accessorAttributes()), accessor); } @@ -3125,7 +3572,7 @@ value = lowJSValue(m_node->child2(), ManualOperandSpeculation); if (m_node->arrayMode().type() == Array::Int32) { FTL_TYPE_CHECK( - jsValueValue(value), m_node->child2(), SpecInt32, isNotInt32(value)); + jsValueValue(value), m_node->child2(), SpecInt32Only, isNotInt32(value)); } storeType = Output::Store64; } else { @@ -3165,11 +3612,11 @@ else operation = m_out.operation(operationArrayPushDouble); ValueFromBlock slowResult = m_out.anchor( - vmCall(m_out.int64, operation, m_callFrame, value, base)); + vmCall(Int64, operation, m_callFrame, value, base)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); return; } @@ -3222,11 +3669,11 @@ m_out.appendTo(slowCase, continuation); results.append(m_out.anchor(vmCall( - m_out.int64, m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base))); + Int64, m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, results)); + setJSValue(m_out.phi(Int64, results)); return; } @@ -3245,7 +3692,7 @@ ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue()); if (table->singletonScope()->isStillValid()) { LValue callResult = vmCall( - m_out.int64, + Int64, m_out.operation(operationCreateActivationDirect), m_callFrame, weakPointer(structure), scope, weakPointer(table), m_out.constInt64(JSValue::encode(initializationValue))); setJSValue(callResult); @@ -3288,12 +3735,12 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); + setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); } void compileNewFunction() { - ASSERT(m_node->op() == NewFunction || m_node->op() == NewArrowFunction || m_node->op() == NewGeneratorFunction); + ASSERT(m_node->op() == NewFunction || m_node->op() == NewGeneratorFunction); bool isGeneratorFunction = m_node->op() == NewGeneratorFunction; LValue scope = lowCell(m_node->child1()); @@ -3301,8 +3748,8 @@ FunctionExecutable* executable = m_node->castOperand(); if (executable->singletonFunction()->isStillValid()) { LValue callResult = - isGeneratorFunction ? vmCall(m_out.int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) : - vmCall(m_out.int64, m_out.operation(operationNewFunction), m_callFrame, scope, weakPointer(executable)); + isGeneratorFunction ? vmCall(Int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) : + vmCall(Int64, m_out.operation(operationNewFunction), m_callFrame, scope, weakPointer(executable)); setJSValue(callResult); return; } @@ -3352,7 +3799,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); + setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); } void compileCreateDirectArguments() @@ -3388,7 +3835,7 @@ size, m_out.constInt32(DirectArguments::allocationSize(minCapacity))); fastObject = allocateVariableSizedObject( - size, structure, m_out.intPtrZero, slowPath); + m_out.zeroExtPtr(size), structure, m_out.intPtrZero, slowPath); } m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length); @@ -3410,7 +3857,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - LValue result = m_out.phi(m_out.intPtr, fastResult, slowResult); + LValue result = m_out.phi(pointerType(), fastResult, slowResult); m_out.storePtr(getCurrentCallee(), result, m_heaps.DirectArguments_callee); @@ -3443,7 +3890,7 @@ } lastNext = m_out.appendTo(loop, end); - LValue previousIndex = m_out.phi(m_out.intPtr, originalLength); + LValue previousIndex = m_out.phi(pointerType(), originalLength); LValue index = m_out.sub(previousIndex, m_out.intPtrOne); m_out.store64( m_out.load64(m_out.baseIndex(m_heaps.variables, stackBase, index)), @@ -3463,7 +3910,7 @@ LValue scope = lowCell(m_node->child1()); LValue result = vmCall( - m_out.int64, m_out.operation(operationCreateScopedArguments), m_callFrame, + Int64, m_out.operation(operationCreateScopedArguments), m_callFrame, weakPointer( m_graph.globalObjectFor(m_node->origin.semantic)->scopedArgumentsStructure()), getArgumentsStart(), getArgumentsLength().value, getCurrentCallee(), scope); @@ -3474,34 +3921,49 @@ void compileCreateClonedArguments() { LValue result = vmCall( - m_out.int64, m_out.operation(operationCreateClonedArguments), m_callFrame, + Int64, m_out.operation(operationCreateClonedArguments), m_callFrame, weakPointer( - m_graph.globalObjectFor(m_node->origin.semantic)->outOfBandArgumentsStructure()), + m_graph.globalObjectFor(m_node->origin.semantic)->clonedArgumentsStructure()), getArgumentsStart(), getArgumentsLength().value, getCurrentCallee()); setJSValue(result); } - void compileCopyRest() - { - LBasicBlock doCopyRest = m_out.newBlock(); - LBasicBlock continuation = m_out.newBlock(); + void compileCreateRest() + { + if (m_graph.isWatchingHavingABadTimeWatchpoint(m_node)) { + LBasicBlock continuation = m_out.newBlock(); + LValue arrayLength = lowInt32(m_node->child1()); + LBasicBlock loopStart = m_out.newBlock(); + JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); + Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous); + ArrayValues arrayValues = allocateUninitializedContiguousJSArray(arrayLength, structure); + LValue array = arrayValues.array; + LValue butterfly = arrayValues.butterfly; + ValueFromBlock startLength = m_out.anchor(arrayLength); + LValue argumentRegion = m_out.add(getArgumentsStart(), m_out.constInt64(sizeof(Register) * m_node->numberOfArgumentsToSkip())); + m_out.branch(m_out.equal(arrayLength, m_out.constInt32(0)), + unsure(continuation), unsure(loopStart)); + + LBasicBlock lastNext = m_out.appendTo(loopStart, continuation); + LValue phiOffset = m_out.phi(Int32, startLength); + LValue currentOffset = m_out.sub(phiOffset, m_out.int32One); + m_out.addIncomingToPhi(phiOffset, m_out.anchor(currentOffset)); + LValue loadedValue = m_out.load64(m_out.baseIndex(m_heaps.variables, argumentRegion, m_out.zeroExtPtr(currentOffset))); + IndexedAbstractHeap& heap = m_heaps.indexedContiguousProperties; + m_out.store64(loadedValue, m_out.baseIndex(heap, butterfly, m_out.zeroExtPtr(currentOffset))); + m_out.branch(m_out.equal(currentOffset, m_out.constInt32(0)), unsure(continuation), unsure(loopStart)); - LValue arrayLength = lowInt32(m_node->child2()); + m_out.appendTo(continuation, lastNext); + setJSValue(array); + return; + } - m_out.branch( - m_out.equal(arrayLength, m_out.constInt32(0)), - unsure(continuation), unsure(doCopyRest)); - - LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation); - // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length + LValue arrayLength = lowInt32(m_node->child1()); + LValue argumentStart = getArgumentsStart(); LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip()); - vmCall( - m_out.voidType,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()), - getArgumentsStart(), numberOfArgumentsToSkip, arrayLength); - m_out.jump(continuation); - - m_out.appendTo(continuation, lastNext); + setJSValue(vmCall( + Int64, m_out.operation(operationCreateRest), m_callFrame, argumentStart, numberOfArgumentsToSkip, arrayLength)); } void compileGetRestLength() @@ -3521,7 +3983,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setInt32(m_out.phi(m_out.int32, zeroLengthResult, nonZeroLengthResult)); + setInt32(m_out.phi(Int32, zeroLengthResult, nonZeroLengthResult)); } void compileNewObject() @@ -3546,7 +4008,8 @@ if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) { unsigned numElements = m_node->numChildren(); - ArrayValues arrayValues = allocateJSArray(structure, numElements); + ArrayValues arrayValues = + allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure); for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) { Edge edge = m_graph.varArgChild(m_node, operandIndex); @@ -3583,7 +4046,7 @@ if (!m_node->numChildren()) { setJSValue(vmCall( - m_out.int64, m_out.operation(operationNewEmptyArray), m_callFrame, + Int64, m_out.operation(operationNewEmptyArray), m_callFrame, m_out.constIntPtr(structure))); return; } @@ -3604,7 +4067,7 @@ m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->activeLengthPtr())); LValue result = vmCall( - m_out.int64, m_out.operation(operationNewArray), m_callFrame, + Int64, m_out.operation(operationNewArray), m_callFrame, m_out.constIntPtr(structure), m_out.constIntPtr(buffer), m_out.constIntPtr(m_node->numChildren())); @@ -3622,7 +4085,8 @@ if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) { unsigned numElements = m_node->numConstants(); - ArrayValues arrayValues = allocateJSArray(structure, numElements); + ArrayValues arrayValues = + allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure); JSValue* data = codeBlock()->constantBuffer(m_node->startConstant()); for (unsigned index = 0; index < m_node->numConstants(); ++index) { @@ -3643,11 +4107,11 @@ } setJSValue(vmCall( - m_out.int64, m_out.operation(operationNewArrayBuffer), m_callFrame, + Int64, m_out.operation(operationNewArrayBuffer), m_callFrame, m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()), m_out.constIntPtr(m_node->numConstants()))); } - + void compileNewArrayWithSize() { LValue publicLength = lowInt32(m_node->child1()); @@ -3657,95 +4121,11 @@ m_node->indexingType()); if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) { - ASSERT( - hasUndecided(structure->indexingType()) - || hasInt32(structure->indexingType()) - || hasDouble(structure->indexingType()) - || hasContiguous(structure->indexingType())); - - LBasicBlock fastCase = m_out.newBlock(); - LBasicBlock largeCase = m_out.newBlock(); - LBasicBlock failCase = m_out.newBlock(); - LBasicBlock slowCase = m_out.newBlock(); - LBasicBlock continuation = m_out.newBlock(); - - m_out.branch( - m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)), - rarely(largeCase), usually(fastCase)); - - LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase); - - // We don't round up to BASE_VECTOR_LEN for new Array(blah). - LValue vectorLength = publicLength; - - LValue payloadSize = - m_out.shl(m_out.zeroExt(vectorLength, m_out.intPtr), m_out.constIntPtr(3)); - - LValue butterflySize = m_out.add( - payloadSize, m_out.constIntPtr(sizeof(IndexingHeader))); - - LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase); - - LValue butterfly = m_out.sub(endOfStorage, payloadSize); - - LValue object = allocateObject(structure, butterfly, failCase); - - m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength); - m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength); - - if (hasDouble(m_node->indexingType())) { - LBasicBlock initLoop = m_out.newBlock(); - LBasicBlock initDone = m_out.newBlock(); - - ValueFromBlock originalIndex = m_out.anchor(vectorLength); - ValueFromBlock originalPointer = m_out.anchor(butterfly); - m_out.branch( - m_out.notZero32(vectorLength), unsure(initLoop), unsure(initDone)); - - LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone); - LValue index = m_out.phi(m_out.int32, originalIndex); - LValue pointer = m_out.phi(m_out.intPtr, originalPointer); - - m_out.store64( - m_out.constInt64(bitwise_cast(PNaN)), - TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer)); - - LValue nextIndex = m_out.sub(index, m_out.int32One); - m_out.addIncomingToPhi(index, m_out.anchor(nextIndex)); - m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight))); - m_out.branch( - m_out.notZero32(nextIndex), unsure(initLoop), unsure(initDone)); - - m_out.appendTo(initDone, initLastNext); - } - - ValueFromBlock fastResult = m_out.anchor(object); - m_out.jump(continuation); - - m_out.appendTo(largeCase, failCase); - ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr( - globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))); - m_out.jump(slowCase); - - m_out.appendTo(failCase, slowCase); - ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure)); - m_out.jump(slowCase); - - m_out.appendTo(slowCase, continuation); - LValue structureValue = m_out.phi( - m_out.intPtr, largeStructure, failStructure); - LValue slowResultValue = lazySlowPath( - [=] (const Vector& locations) -> RefPtr { - return createLazyCallGenerator( - operationNewArrayWithSize, locations[0].directGPR(), - locations[1].directGPR(), locations[2].directGPR()); - }, - structureValue, publicLength); - ValueFromBlock slowResult = m_out.anchor(slowResultValue); - m_out.jump(continuation); - - m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); + setJSValue( + allocateJSArray( + publicLength, + globalObject->arrayStructureForIndexingTypeDuringAllocation( + m_node->indexingType())).array); return; } @@ -3754,7 +4134,7 @@ m_out.constIntPtr( globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), m_out.constIntPtr(structure)); - setJSValue(vmCall(m_out.int64, m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength)); + setJSValue(vmCall(Int64, m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength, m_out.intPtrZero)); } void compileNewTypedArray() @@ -3764,7 +4144,7 @@ switch (m_node->child1().useKind()) { case Int32Use: { - Structure* structure = globalObject->typedArrayStructure(type); + Structure* structure = globalObject->typedArrayStructureConcurrently(type); LValue size = lowInt32(m_node->child1()); @@ -3816,7 +4196,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult)); + setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); return; } @@ -3824,8 +4204,8 @@ LValue argument = lowJSValue(m_node->child1()); LValue result = vmCall( - m_out.intPtr, m_out.operation(operationNewTypedArrayWithOneArgumentForType(type)), - m_callFrame, weakPointer(globalObject->typedArrayStructure(type)), argument); + pointerType(), m_out.operation(operationNewTypedArrayWithOneArgumentForType(type)), + m_callFrame, weakPointer(globalObject->typedArrayStructureConcurrently(type)), argument); setJSValue(result); return; @@ -3853,6 +4233,33 @@ reallocatePropertyStorage( object, oldStorage, transition->previous, transition->next)); } + + void compileToNumber() + { + LValue value = lowJSValue(m_node->child1()); + + if (!(abstractValue(m_node->child1()).m_type & SpecBytecodeNumber)) + setJSValue(vmCall(Int64, m_out.operation(operationToNumber), m_callFrame, value)); + else { + LBasicBlock notNumber = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + ValueFromBlock fastResult = m_out.anchor(value); + m_out.branch(isNumber(value, provenType(m_node->child1())), unsure(continuation), unsure(notNumber)); + + // notNumber case. + LBasicBlock lastNext = m_out.appendTo(notNumber, continuation); + // We have several attempts to remove ToNumber. But ToNumber still exists. + // It means that converting non-numbers to numbers by this ToNumber is not rare. + // Instead of the lazy slow path generator, we call the operation here. + ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationToNumber), m_callFrame, value)); + m_out.jump(continuation); + + // continuation case. + m_out.appendTo(continuation, lastNext); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); + } + } void compileToStringOrCallStringConstructor() { @@ -3885,7 +4292,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, simpleResult, unboxedResult)); + setJSValue(m_out.phi(Int64, simpleResult, unboxedResult)); m_interpreter.filter(m_node->child1(), SpecString | SpecStringObject); return; @@ -3925,11 +4332,11 @@ operation = m_out.operation(m_node->op() == ToString ? operationToStringOnCell : operationCallStringConstructorOnCell); else operation = m_out.operation(m_node->op() == ToString ? operationToString : operationCallStringConstructor); - ValueFromBlock convertedResult = m_out.anchor(vmCall(m_out.int64, operation, m_callFrame, value)); + ValueFromBlock convertedResult = m_out.anchor(vmCall(Int64, operation, m_callFrame, value)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, simpleResult, convertedResult)); + setJSValue(m_out.phi(Int64, simpleResult, convertedResult)); return; } @@ -3961,11 +4368,11 @@ m_out.appendTo(isObjectCase, continuation); results.append(m_out.anchor(vmCall( - m_out.int64, m_out.operation(operationToPrimitive), m_callFrame, value))); + Int64, m_out.operation(operationToPrimitive), m_callFrame, value))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, results)); + setJSValue(m_out.phi(Int64, results)); } void compileMakeRope() @@ -3987,13 +4394,12 @@ LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); - MarkedAllocator& allocator = + MarkedAllocator* allocator = vm().heap.allocatorForObjectWithDestructor(sizeof(JSRopeString)); + DFG_ASSERT(m_graph, m_node, allocator); LValue result = allocateCell( - m_out.constIntPtr(&allocator), - vm().stringStructure.get(), - slowPath); + m_out.constIntPtr(allocator), vm().stringStructure.get(), slowPath); m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value); for (unsigned i = 0; i < numKids; ++i) @@ -4044,7 +4450,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); } void compileStringCharAt() @@ -4100,13 +4506,13 @@ Vector results; results.append(m_out.anchor(vmCall( - m_out.int64, m_out.operation(operationSingleCharacterString), + Int64, m_out.operation(operationSingleCharacterString), m_callFrame, char16BitValue))); m_out.jump(continuation); m_out.appendTo(bitsContinuation, slowPath); - LValue character = m_out.phi(m_out.int32, char8Bit, char16Bit); + LValue character = m_out.phi(Int32, char8Bit, char16Bit); LValue smallStrings = m_out.constIntPtr(vm().smallStrings.singleCharacterStrings()); @@ -4121,7 +4527,8 @@ results.append(m_out.anchor(m_out.intPtrZero)); } else { JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); - + + bool prototypeChainIsSane = false; if (globalObject->stringPrototypeChainIsSane()) { // FIXME: This could be captured using a Speculation mode that means // "out-of-bounds loads return a trivial value", something like @@ -4131,6 +4538,9 @@ m_graph.watchpoints().addLazily(globalObject->stringPrototype()->structure()->transitionWatchpointSet()); m_graph.watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet()); + prototypeChainIsSane = globalObject->stringPrototypeChainIsSane(); + } + if (prototypeChainIsSane) { LBasicBlock negativeIndex = m_out.newBlock(); results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())))); @@ -4142,13 +4552,13 @@ } results.append(m_out.anchor(vmCall( - m_out.int64, m_out.operation(operationGetByValStringInt), m_callFrame, base, index))); + Int64, m_out.operation(operationGetByValStringInt), m_callFrame, base, index))); } m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, results)); + setJSValue(m_out.phi(Int64, results)); } void compileStringCharCodeAt() @@ -4192,7 +4602,7 @@ m_out.appendTo(continuation, lastNext); - setInt32(m_out.phi(m_out.int32, char8Bit, char16Bit)); + setInt32(m_out.phi(Int32, char8Bit, char16Bit)); } void compileStringFromCharCode() @@ -4201,7 +4611,7 @@ if (childEdge.useKind() == UntypedUse) { LValue result = vmCall( - m_out.int64, m_out.operation(operationStringFromCharCodeUntyped), m_callFrame, + Int64, m_out.operation(operationStringFromCharCodeUntyped), m_callFrame, lowJSValue(childEdge)); setJSValue(result); return; @@ -4230,13 +4640,13 @@ m_out.appendTo(slowCase, continuation); LValue slowResultValue = vmCall( - m_out.intPtr, m_out.operation(operationStringFromCharCode), m_callFrame, value); + pointerType(), m_out.operation(operationStringFromCharCode), m_callFrame, value); ValueFromBlock slowResult = m_out.anchor(slowResultValue); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); + setJSValue(m_out.phi(Int64, fastResult, slowResult)); } void compileGetByOffset() @@ -4318,7 +4728,7 @@ else propertyBase = weakPointer(method.prototype()->value().asCell()); if (!isInlineOffset(method.offset())) - propertyBase = loadButterflyReadOnly(propertyBase); + propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly); result = loadProperty( propertyBase, data.identifierNumber, method.offset()); break; @@ -4334,7 +4744,7 @@ m_out.unreachable(); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, results)); + setJSValue(m_out.phi(Int64, results)); } void compilePutByOffset() @@ -4386,7 +4796,7 @@ if (isInlineOffset(variant.offset())) storage = base; else - storage = loadButterflyWithBarrier(base); + storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly); } else { m_graph.m_plan.transitions.addLazily( codeBlock(), m_node->origin.semantic.codeOriginOwner(), @@ -4452,12 +4862,12 @@ void compileGetCallee() { - setJSValue(m_out.loadPtr(addressFor(JSStack::Callee))); + setJSValue(m_out.loadPtr(addressFor(CallFrameSlot::callee))); } - void compileGetArgumentCount() + void compileGetArgumentCountIncludingThis() { - setInt32(m_out.load32(payloadFor(JSStack::ArgumentCount))); + setInt32(m_out.load32(payloadFor(CallFrameSlot::argumentCount))); } void compileGetScope() @@ -4469,6 +4879,12 @@ { setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSScope_next)); } + + void compileGetGlobalObject() + { + LValue structure = loadStructure(lowCell(m_node->child1())); + setJSValue(m_out.loadPtr(structure, m_heaps.Structure_globalObject)); + } void compileGetClosureVar() { @@ -4525,15 +4941,6 @@ compareEqObjectOrOtherToObject(m_node->child1(), m_node->child2()); return; } - - if (m_node->isBinaryUseKind(UntypedUse)) { - nonSpeculativeCompare( - [&] (LValue left, LValue right) { - return m_out.equal(left, right); - }, - operationCompareEq); - return; - } if (m_node->child1().useKind() == OtherUse) { ASSERT(!m_interpreter.needsTypeCheck(m_node->child1(), SpecOther)); @@ -4547,7 +4954,12 @@ return; } - DFG_CRASH(m_graph, m_node, "Bad use kinds"); + DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse)); + nonSpeculativeCompare( + [&] (LValue left, LValue right) { + return m_out.equal(left, right); + }, + operationCompareEq); } void compileCompareStrictEq() @@ -4599,7 +5011,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, fastResult, slowResult)); + setBoolean(m_out.phi(Int32, fastResult, slowResult)); return; } @@ -4634,11 +5046,23 @@ } if (m_node->isBinaryUseKind(SymbolUse)) { - LValue left = lowSymbol(m_node->child1()); - LValue right = lowSymbol(m_node->child2()); - LValue leftStringImpl = m_out.loadPtr(left, m_heaps.Symbol_privateName); - LValue rightStringImpl = m_out.loadPtr(right, m_heaps.Symbol_privateName); - setBoolean(m_out.equal(leftStringImpl, rightStringImpl)); + LValue leftSymbol = lowSymbol(m_node->child1()); + LValue rightSymbol = lowSymbol(m_node->child2()); + setBoolean(m_out.equal(leftSymbol, rightSymbol)); + return; + } + + if (m_node->isBinaryUseKind(SymbolUse, UntypedUse) + || m_node->isBinaryUseKind(UntypedUse, SymbolUse)) { + Edge symbolEdge = m_node->child1(); + Edge untypedEdge = m_node->child2(); + if (symbolEdge.useKind() != SymbolUse) + std::swap(symbolEdge, untypedEdge); + + LValue leftSymbol = lowSymbol(symbolEdge); + LValue untypedValue = lowJSValue(untypedEdge); + + setBoolean(m_out.equal(leftSymbol, untypedValue)); return; } @@ -4682,21 +5106,72 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, notCellResult, notStringResult, isStringResult)); + setBoolean(m_out.phi(Int32, notCellResult, notStringResult, isStringResult)); return; } - - DFG_CRASH(m_graph, m_node, "Bad use kinds"); + + if (m_node->isBinaryUseKind(StringUse, UntypedUse)) { + compileStringToUntypedStrictEquality(m_node->child1(), m_node->child2()); + return; + } + if (m_node->isBinaryUseKind(UntypedUse, StringUse)) { + compileStringToUntypedStrictEquality(m_node->child2(), m_node->child1()); + return; + } + + DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse)); + nonSpeculativeCompare( + [&] (LValue left, LValue right) { + return m_out.equal(left, right); + }, + operationCompareStrictEq); } - - void compileCompareStrictEqConstant() + + void compileStringToUntypedStrictEquality(Edge stringEdge, Edge untypedEdge) { - JSValue constant = m_node->child2()->asJSValue(); + ASSERT(stringEdge.useKind() == StringUse); + ASSERT(untypedEdge.useKind() == UntypedUse); + + LValue leftString = lowCell(stringEdge); + LValue rightValue = lowJSValue(untypedEdge); + SpeculatedType rightValueType = provenType(untypedEdge); + + // Verify left is string. + speculateString(stringEdge, leftString); + + LBasicBlock testUntypedEdgeIsCell = m_out.newBlock(); + LBasicBlock testUntypedEdgeIsString = m_out.newBlock(); + LBasicBlock testStringEquality = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + // Given left is string. If the value are strictly equal, rightValue has to be the same string. + ValueFromBlock fastTrue = m_out.anchor(m_out.booleanTrue); + m_out.branch(m_out.equal(leftString, rightValue), unsure(continuation), unsure(testUntypedEdgeIsCell)); + + LBasicBlock lastNext = m_out.appendTo(testUntypedEdgeIsCell, testUntypedEdgeIsString); + ValueFromBlock fastFalse = m_out.anchor(m_out.booleanFalse); + m_out.branch(isNotCell(rightValue, rightValueType), unsure(continuation), unsure(testUntypedEdgeIsString)); + + // Check if the untyped edge is a string. + m_out.appendTo(testUntypedEdgeIsString, testStringEquality); + m_out.branch(isNotString(rightValue, rightValueType), unsure(continuation), unsure(testStringEquality)); + + // Full String compare. + m_out.appendTo(testStringEquality, continuation); + ValueFromBlock slowResult = m_out.anchor(stringsEqual(leftString, rightValue)); + m_out.jump(continuation); + + // Continuation. + m_out.appendTo(continuation, lastNext); + setBoolean(m_out.phi(Int32, fastTrue, fastFalse, slowResult)); + } + + void compileCompareEqPtr() + { setBoolean( m_out.equal( lowJSValue(m_node->child1()), - m_out.constInt64(JSValue::encode(constant)))); + weakPointer(m_node->cellOperand()->cell()))); } void compileCompareLess() @@ -4708,6 +5183,8 @@ [&] (LValue left, LValue right) { return m_out.doubleLessThan(left, right); }, + operationCompareStringImplLess, + operationCompareStringLess, operationCompareLess); } @@ -4720,6 +5197,8 @@ [&] (LValue left, LValue right) { return m_out.doubleLessThanOrEqual(left, right); }, + operationCompareStringImplLessEq, + operationCompareStringLessEq, operationCompareLessEq); } @@ -4732,6 +5211,8 @@ [&] (LValue left, LValue right) { return m_out.doubleGreaterThan(left, right); }, + operationCompareStringImplGreater, + operationCompareStringGreater, operationCompareGreater); } @@ -4744,6 +5225,8 @@ [&] (LValue left, LValue right) { return m_out.doubleGreaterThanOrEqual(left, right); }, + operationCompareStringImplGreaterEq, + operationCompareStringGreaterEq, operationCompareGreaterEq); } @@ -4759,7 +5242,7 @@ LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0)); - unsigned frameSize = JSStack::CallFrameHeaderSize + numArgs; + unsigned frameSize = CallFrame::headerSizeInRegisters + numArgs; unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize); // JS->JS calling convention requires that the caller allows this much space on top of stack to @@ -4782,12 +5265,12 @@ auto addArgument = [&] (LValue value, VirtualRegister reg, int offset) { intptr_t offsetFromSP = - (reg.offset() - JSStack::CallerFrameAndPCSize) * sizeof(EncodedJSValue) + offset; + (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset; arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP))); }; - addArgument(jsCallee, VirtualRegister(JSStack::Callee), 0); - addArgument(m_out.constInt32(numArgs), VirtualRegister(JSStack::ArgumentCount), PayloadOffset); + addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0); + addArgument(m_out.constInt32(numArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset); for (unsigned i = 0; i < numArgs; ++i) addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0); @@ -4797,6 +5280,8 @@ RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); + patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); patchpoint->clobber(RegisterSet::macroScratchRegisters()); patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall()); patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR); @@ -4812,7 +5297,7 @@ jit.store32( CCallHelpers::TrustedImm32(callSiteIndex.bits()), - CCallHelpers::tagFor(VirtualRegister(JSStack::ArgumentCount))); + CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount))); CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo(); @@ -4886,6 +5371,9 @@ PatchpointValue* patchpoint = m_out.patchpoint(Void); patchpoint->appendVector(arguments); + patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); + // Prevent any of the arguments from using the scratch register. patchpoint->clobberEarly(RegisterSet::macroScratchRegisters()); @@ -4927,7 +5415,7 @@ // with the call site index of our frame. Bad things happen if it's not set. jit.store32( CCallHelpers::TrustedImm32(callSiteIndex.bits()), - CCallHelpers::tagFor(VirtualRegister(JSStack::ArgumentCount))); + CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount))); CallFrameShuffler slowPathShuffler(jit, shuffleData); slowPathShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0)); @@ -4960,7 +5448,7 @@ { Node* node = m_node; LValue jsCallee = lowJSValue(m_node->child1()); - LValue thisArg = lowJSValue(m_node->child3()); + LValue thisArg = lowJSValue(m_node->child2()); LValue jsArguments = nullptr; bool forwarding = false; @@ -4970,7 +5458,7 @@ case TailCallVarargs: case TailCallVarargsInlinedCaller: case ConstructVarargs: - jsArguments = lowJSValue(node->child2()); + jsArguments = lowJSValue(node->child3()); break; case CallForwardVarargs: case TailCallForwardVarargs: @@ -5003,6 +5491,9 @@ RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); + patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); + patchpoint->clobber(RegisterSet::macroScratchRegisters()); patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall()); patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR); @@ -5029,7 +5520,7 @@ jit.store32( CCallHelpers::TrustedImm32(callSiteIndex.bits()), - CCallHelpers::tagFor(VirtualRegister(JSStack::ArgumentCount))); + CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount))); CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo(); CallVarargsData* data = node->callVarargsData(); @@ -5120,7 +5611,12 @@ jit.move(CCallHelpers::TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR2); CCallHelpers::JumpList slowCase; - emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node->child2()->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); + InlineCallFrame* inlineCallFrame; + if (node->child3()) + inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame; + else + inlineCallFrame = node->origin.semantic.inlineCallFrame; + emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase); CCallHelpers::Jump done = jit.jump(); slowCase.link(&jit); @@ -5153,7 +5649,7 @@ thisLateRep.emitRestore(jit, thisGPR); } - jit.store64(GPRInfo::regT0, CCallHelpers::calleeFrameSlot(JSStack::Callee)); + jit.store64(GPRInfo::regT0, CCallHelpers::calleeFrameSlot(CallFrameSlot::callee)); jit.store64(thisGPR, CCallHelpers::calleeArgumentSlot(0)); CallLinkInfo::CallType callType; @@ -5226,13 +5722,97 @@ } } + void compileCallEval() + { + Node* node = m_node; + unsigned numArgs = node->numChildren() - 1; + + LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0)); + + unsigned frameSize = CallFrame::headerSizeInRegisters + numArgs; + unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), frameSize); + + m_proc.requestCallArgAreaSize(alignedFrameSize); + + Vector arguments; + arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0))); + + auto addArgument = [&] (LValue value, VirtualRegister reg, int offset) { + intptr_t offsetFromSP = + (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset; + arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP))); + }; + + addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0); + addArgument(m_out.constInt32(numArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset); + for (unsigned i = 0; i < numArgs; ++i) + addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0); + + PatchpointValue* patchpoint = m_out.patchpoint(Int64); + patchpoint->appendVector(arguments); + + RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); + + patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); + patchpoint->clobber(RegisterSet::macroScratchRegisters()); + patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall()); + patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR); + + CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite(); + State* state = &m_ftlState; + patchpoint->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { + AllowMacroScratchRegisterUsage allowScratch(jit); + CallSiteIndex callSiteIndex = state->jitCode->common.addUniqueCallSiteIndex(codeOrigin); + + Box exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit); + + exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex); + + jit.store32( + CCallHelpers::TrustedImm32(callSiteIndex.bits()), + CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount))); + + CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo(); + callLinkInfo->setUpCall(CallLinkInfo::Call, node->origin.semantic, GPRInfo::regT0); + + jit.addPtr(CCallHelpers::TrustedImm32(-static_cast(sizeof(CallerFrameAndPC))), CCallHelpers::stackPointerRegister, GPRInfo::regT1); + jit.storePtr(GPRInfo::callFrameRegister, CCallHelpers::Address(GPRInfo::regT1, CallFrame::callerFrameOffset())); + + // Now we need to make room for: + // - The caller frame and PC for a call to operationCallEval. + // - Potentially two arguments on the stack. + unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2; + requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes); + jit.subPtr(CCallHelpers::TrustedImm32(requiredBytes), CCallHelpers::stackPointerRegister); + jit.setupArgumentsWithExecState(GPRInfo::regT1); + jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast(operationCallEval)), GPRInfo::nonPreservedNonArgumentGPR); + jit.call(GPRInfo::nonPreservedNonArgumentGPR); + exceptions->append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth)); + + CCallHelpers::Jump done = jit.branchTest64(CCallHelpers::NonZero, GPRInfo::returnValueGPR); + + jit.addPtr(CCallHelpers::TrustedImm32(requiredBytes), CCallHelpers::stackPointerRegister); + jit.load64(CCallHelpers::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0); + jit.emitDumbVirtualCall(callLinkInfo); + + done.link(&jit); + jit.addPtr( + CCallHelpers::TrustedImm32(-params.proc().frameSize()), + GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister); + }); + + setJSValue(patchpoint); + } + void compileLoadVarargs() { LoadVarargsData* data = m_node->loadVarargsData(); LValue jsArguments = lowJSValue(m_node->child1()); LValue length = vmCall( - m_out.int32, m_out.operation(operationSizeOfVarargs), m_callFrame, jsArguments, + Int32, m_out.operation(operationSizeOfVarargs), m_callFrame, jsArguments, m_out.constInt32(data->offset)); // FIXME: There is a chance that we will call an effectful length property twice. This is safe @@ -5256,7 +5836,7 @@ m_out.constIntPtr(3)); vmCall( - m_out.voidType, m_out.operation(operationLoadVarargs), m_callFrame, + Void, m_out.operation(operationLoadVarargs), m_callFrame, m_out.castToInt32(machineStart), jsArguments, m_out.constInt32(data->offset), length, m_out.constInt32(data->mandatoryMinimum)); } @@ -5264,7 +5844,11 @@ void compileForwardVarargs() { LoadVarargsData* data = m_node->loadVarargsData(); - InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame; + InlineCallFrame* inlineCallFrame; + if (m_node->child1()) + inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame; + else + inlineCallFrame = m_node->origin.semantic.inlineCallFrame; LValue length = getArgumentsLength(inlineCallFrame).value; LValue lengthIncludingThis = m_out.add(length, m_out.constInt32(1 - data->offset)); @@ -5290,7 +5874,7 @@ m_out.above(loopBoundValue, lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry)); LBasicBlock lastNext = m_out.appendTo(undefinedLoop, mainLoopEntry); - LValue previousIndex = m_out.phi(m_out.intPtr, loopBound); + LValue previousIndex = m_out.phi(pointerType(), loopBound); LValue currentIndex = m_out.sub(previousIndex, m_out.intPtrOne); m_out.store64( m_out.constInt64(JSValue::encode(jsUndefined())), @@ -5305,7 +5889,7 @@ m_out.branch(m_out.notNull(lengthAsPtr), unsure(mainLoop), unsure(continuation)); m_out.appendTo(mainLoop, continuation); - previousIndex = m_out.phi(m_out.intPtr, loopBound); + previousIndex = m_out.phi(pointerType(), loopBound); currentIndex = m_out.sub(previousIndex, m_out.intPtrOne); LValue value = m_out.load64( m_out.baseIndex( @@ -5387,7 +5971,7 @@ } m_out.appendTo(switchOnInts, lastNext); - buildSwitch(data, m_out.int32, m_out.phi(m_out.int32, intValues)); + buildSwitch(data, Int32, m_out.phi(Int32, intValues)); return; } @@ -5453,11 +6037,11 @@ m_out.appendTo(needResolution, resolved); values.append(m_out.anchor( - vmCall(m_out.intPtr, m_out.operation(operationResolveRope), m_callFrame, stringValue))); + vmCall(pointerType(), m_out.operation(operationResolveRope), m_callFrame, stringValue))); m_out.jump(resolved); m_out.appendTo(resolved, is8Bit); - LValue value = m_out.phi(m_out.intPtr, values); + LValue value = m_out.phi(pointerType(), values); LValue characterData = m_out.loadPtr(value, m_heaps.StringImpl_data); m_out.branch( m_out.testNonZero32( @@ -5475,7 +6059,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - buildSwitch(data, m_out.int32, m_out.phi(m_out.int32, characters)); + buildSwitch(data, Int32, m_out.phi(Int32, characters)); return; } @@ -5556,7 +6140,7 @@ return; } - buildSwitch(m_node->switchData(), m_out.intPtr, cell); + buildSwitch(m_node->switchData(), pointerType(), cell); return; } } @@ -5632,6 +6216,11 @@ // When this abruptly terminates, it could read any heap location. patchpoint->effects.reads = HeapRange::top(); } + + void compileIsEmpty() + { + setBoolean(m_out.isZero64(lowJSValue(m_node->child1()))); + } void compileIsUndefined() { @@ -5664,7 +6253,26 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult)); + setBoolean(m_out.phi(Int32, notCellResult, cellResult)); + } + + void compileIsJSArray() + { + LValue value = lowJSValue(m_node->child1()); + + LBasicBlock isCellCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse); + m_out.branch( + isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation)); + + LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation); + ValueFromBlock cellResult = m_out.anchor(isArray(value, provenType(m_node->child1()))); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setBoolean(m_out.phi(Int32, notCellResult, cellResult)); } void compileIsObject() @@ -5683,39 +6291,262 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult)); + setBoolean(m_out.phi(Int32, notCellResult, cellResult)); } - void compileIsObjectOrNull() + void compileMapHash() { - JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); - - Edge child = m_node->child1(); - LValue value = lowJSValue(child); - - LBasicBlock cellCase = m_out.newBlock(); - LBasicBlock notFunctionCase = m_out.newBlock(); - LBasicBlock objectCase = m_out.newBlock(); - LBasicBlock slowPath = m_out.newBlock(); - LBasicBlock notCellCase = m_out.newBlock(); + LValue value = lowJSValue(m_node->child1()); + + LBasicBlock isCellCase = m_out.newBlock(); + LBasicBlock notCell = m_out.newBlock(); + LBasicBlock slowCase = m_out.newBlock(); + LBasicBlock straightHash = m_out.newBlock(); + LBasicBlock isNumberCase = m_out.newBlock(); + LBasicBlock isStringCase = m_out.newBlock(); + LBasicBlock nonEmptyStringCase = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); - - m_out.branch(isCell(value, provenType(child)), unsure(cellCase), unsure(notCellCase)); - - LBasicBlock lastNext = m_out.appendTo(cellCase, notFunctionCase); - ValueFromBlock isFunctionResult = m_out.anchor(m_out.booleanFalse); + m_out.branch( - isFunction(value, provenType(child)), - unsure(continuation), unsure(notFunctionCase)); - - m_out.appendTo(notFunctionCase, objectCase); - ValueFromBlock notObjectResult = m_out.anchor(m_out.booleanFalse); + isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(notCell)); + + LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase); + LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType)); m_out.branch( - isObject(value, provenType(child)), - unsure(objectCase), unsure(continuation)); - - m_out.appendTo(objectCase, slowPath); - ValueFromBlock objectResult = m_out.anchor(m_out.booleanTrue); + isString, unsure(isStringCase), unsure(straightHash)); + + m_out.appendTo(isStringCase, nonEmptyStringCase); + LValue stringImpl = m_out.loadPtr(value, m_heaps.JSString_value); + m_out.branch( + m_out.equal(stringImpl, m_out.constIntPtr(0)), rarely(slowCase), usually(nonEmptyStringCase)); + + m_out.appendTo(nonEmptyStringCase, notCell); + LValue hash = m_out.lShr(m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount)); + ValueFromBlock nonEmptyStringHashResult = m_out.anchor(hash); + m_out.branch(m_out.equal(hash, m_out.constInt32(0)), + rarely(slowCase), usually(continuation)); + + m_out.appendTo(notCell, isNumberCase); + m_out.branch( + isNumber(value), unsure(isNumberCase), unsure(straightHash)); + + m_out.appendTo(isNumberCase, straightHash); + m_out.branch( + isInt32(value), unsure(straightHash), unsure(slowCase)); + + m_out.appendTo(straightHash, slowCase); + // key += ~(key << 32); + LValue key = value; + LValue temp = key; + temp = m_out.shl(temp, m_out.constInt32(32)); + temp = m_out.bitNot(temp); + key = m_out.add(key, temp); + // key ^= (key >> 22); + temp = key; + temp = m_out.lShr(temp, m_out.constInt32(22)); + key = m_out.bitXor(key, temp); + // key += ~(key << 13); + temp = key; + temp = m_out.shl(temp, m_out.constInt32(13)); + temp = m_out.bitNot(temp); + key = m_out.add(key, temp); + // key ^= (key >> 8); + temp = key; + temp = m_out.lShr(temp, m_out.constInt32(8)); + key = m_out.bitXor(key, temp); + // key += (key << 3); + temp = key; + temp = m_out.shl(temp, m_out.constInt32(3)); + key = m_out.add(key, temp); + // key ^= (key >> 15); + temp = key; + temp = m_out.lShr(temp, m_out.constInt32(15)); + key = m_out.bitXor(key, temp); + // key += ~(key << 27); + temp = key; + temp = m_out.shl(temp, m_out.constInt32(27)); + temp = m_out.bitNot(temp); + key = m_out.add(key, temp); + // key ^= (key >> 31); + temp = key; + temp = m_out.lShr(temp, m_out.constInt32(31)); + key = m_out.bitXor(key, temp); + key = m_out.castToInt32(key); + + ValueFromBlock fastResult = m_out.anchor(key); + m_out.jump(continuation); + + m_out.appendTo(slowCase, continuation); + ValueFromBlock slowResult = m_out.anchor( + vmCall(Int32, m_out.operation(operationMapHash), m_callFrame, value)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setInt32(m_out.phi(Int32, fastResult, slowResult, nonEmptyStringHashResult)); + } + + void compileGetMapBucket() + { + LBasicBlock loopStart = m_out.newBlock(); + LBasicBlock loopAround = m_out.newBlock(); + LBasicBlock slowPath = m_out.newBlock(); + LBasicBlock notPresentInTable = m_out.newBlock(); + LBasicBlock notEmptyValue = m_out.newBlock(); + LBasicBlock notDeletedValue = m_out.newBlock(); + LBasicBlock notBitEqual = m_out.newBlock(); + LBasicBlock bucketKeyNotCell = m_out.newBlock(); + LBasicBlock bucketKeyIsCell = m_out.newBlock(); + LBasicBlock bothAreCells = m_out.newBlock(); + LBasicBlock bucketKeyIsString = m_out.newBlock(); + LBasicBlock bucketKeyIsNumber = m_out.newBlock(); + LBasicBlock bothAreNumbers = m_out.newBlock(); + LBasicBlock bucketKeyIsInt32 = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart); + + LValue map; + if (m_node->child1().useKind() == MapObjectUse) + map = lowMapObject(m_node->child1()); + else if (m_node->child1().useKind() == SetObjectUse) + map = lowSetObject(m_node->child1()); + else + RELEASE_ASSERT_NOT_REACHED(); + + LValue key = lowJSValue(m_node->child2()); + LValue hash = lowInt32(m_node->child3()); + + LValue hashMapImpl = m_out.loadPtr(map, m_node->child1().useKind() == MapObjectUse ? m_heaps.JSMap_hashMapImpl : m_heaps.JSSet_hashMapImpl); + LValue buffer = m_out.loadPtr(hashMapImpl, m_heaps.HashMapImpl_buffer); + LValue mask = m_out.sub(m_out.load32(hashMapImpl, m_heaps.HashMapImpl_capacity), m_out.int32One); + + ValueFromBlock indexStart = m_out.anchor(hash); + m_out.jump(loopStart); + + m_out.appendTo(loopStart, notEmptyValue); + LValue unmaskedIndex = m_out.phi(Int32, indexStart); + LValue index = m_out.bitAnd(mask, unmaskedIndex); + LValue hashMapBucket = m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), buffer, m_out.zeroExt(index, Int64), ScaleEight)); + ValueFromBlock bucketResult = m_out.anchor(hashMapBucket); + m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl>::emptyValue())), + unsure(notPresentInTable), unsure(notEmptyValue)); + + m_out.appendTo(notEmptyValue, notDeletedValue); + m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl>::deletedValue())), + unsure(loopAround), unsure(notDeletedValue)); + + m_out.appendTo(notDeletedValue, notBitEqual); + LValue bucketKey = m_out.load64(hashMapBucket, m_heaps.HashMapBucket_key); + // Perform Object.is() + m_out.branch(m_out.equal(key, bucketKey), + unsure(continuation), unsure(notBitEqual)); + + m_out.appendTo(notBitEqual, bucketKeyIsCell); + m_out.branch(isCell(bucketKey), + unsure(bucketKeyIsCell), unsure(bucketKeyNotCell)); + + m_out.appendTo(bucketKeyIsCell, bothAreCells); + m_out.branch(isCell(key), + unsure(bothAreCells), unsure(loopAround)); + + m_out.appendTo(bothAreCells, bucketKeyIsString); + m_out.branch(isString(bucketKey), + unsure(bucketKeyIsString), unsure(loopAround)); + + m_out.appendTo(bucketKeyIsString, bucketKeyNotCell); + m_out.branch(isString(key), + unsure(slowPath), unsure(loopAround)); + + m_out.appendTo(bucketKeyNotCell, bucketKeyIsNumber); + m_out.branch(isNotNumber(bucketKey), + unsure(loopAround), unsure(bucketKeyIsNumber)); + + m_out.appendTo(bucketKeyIsNumber, bothAreNumbers); + m_out.branch(isNotNumber(key), + unsure(loopAround), unsure(bothAreNumbers)); + + m_out.appendTo(bothAreNumbers, bucketKeyIsInt32); + m_out.branch(isNotInt32(bucketKey), + unsure(slowPath), unsure(bucketKeyIsInt32)); + + m_out.appendTo(bucketKeyIsInt32, loopAround); + m_out.branch(isNotInt32(key), + unsure(slowPath), unsure(loopAround)); + + m_out.appendTo(loopAround, slowPath); + m_out.addIncomingToPhi(unmaskedIndex, m_out.anchor(m_out.add(index, m_out.int32One))); + m_out.jump(loopStart); + + m_out.appendTo(slowPath, notPresentInTable); + ValueFromBlock slowPathResult = m_out.anchor(vmCall(pointerType(), + m_out.operation(m_node->child1().useKind() == MapObjectUse ? operationJSMapFindBucket : operationJSSetFindBucket), m_callFrame, map, key, hash)); + m_out.jump(continuation); + + m_out.appendTo(notPresentInTable, continuation); + ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult)); + } + + void compileLoadFromJSMapBucket() + { + LValue mapBucket = lowMapBucket(m_node->child1()); + + LBasicBlock continuation = m_out.newBlock(); + LBasicBlock hasBucket = m_out.newBlock(); + + ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))); + + m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)), + unsure(continuation), unsure(hasBucket)); + + LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation); + ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setJSValue(m_out.phi(Int64, noBucketResult, bucketResult)); + } + + void compileIsNonEmptyMapBucket() + { + LValue bucket = lowMapBucket(m_node->child1()); + LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0)); + setBoolean(result); + } + + void compileIsObjectOrNull() + { + JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); + + Edge child = m_node->child1(); + LValue value = lowJSValue(child); + + LBasicBlock cellCase = m_out.newBlock(); + LBasicBlock notFunctionCase = m_out.newBlock(); + LBasicBlock objectCase = m_out.newBlock(); + LBasicBlock slowPath = m_out.newBlock(); + LBasicBlock notCellCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + m_out.branch(isCell(value, provenType(child)), unsure(cellCase), unsure(notCellCase)); + + LBasicBlock lastNext = m_out.appendTo(cellCase, notFunctionCase); + ValueFromBlock isFunctionResult = m_out.anchor(m_out.booleanFalse); + m_out.branch( + isFunction(value, provenType(child)), + unsure(continuation), unsure(notFunctionCase)); + + m_out.appendTo(notFunctionCase, objectCase); + ValueFromBlock notObjectResult = m_out.anchor(m_out.booleanFalse); + m_out.branch( + isObject(value, provenType(child)), + unsure(objectCase), unsure(continuation)); + + m_out.appendTo(objectCase, slowPath); + ValueFromBlock objectResult = m_out.anchor(m_out.booleanTrue); m_out.branch( isExoticForTypeof(value, provenType(child)), rarely(slowPath), usually(continuation)); @@ -5737,7 +6568,7 @@ m_out.appendTo(continuation, lastNext); LValue result = m_out.phi( - m_out.boolean, + Int32, isFunctionResult, notObjectResult, objectResult, slowResult, notCellResult); setBoolean(result); } @@ -5782,10 +6613,47 @@ m_out.appendTo(continuation, lastNext); LValue result = m_out.phi( - m_out.boolean, notCellResult, functionResult, objectResult, slowResult); + Int32, notCellResult, functionResult, objectResult, slowResult); setBoolean(result); } - + + void compileIsRegExpObject() + { + LValue value = lowJSValue(m_node->child1()); + + LBasicBlock isCellCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse); + m_out.branch( + isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation)); + + LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation); + ValueFromBlock cellResult = m_out.anchor(isRegExpObject(value, provenType(m_node->child1()))); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setBoolean(m_out.phi(Int32, notCellResult, cellResult)); + } + + void compileIsTypedArrayView() + { + LValue value = lowJSValue(m_node->child1()); + + LBasicBlock isCellCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse); + m_out.branch(isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation)); + + LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation); + ValueFromBlock cellResult = m_out.anchor(isTypedArrayView(value, provenType(m_node->child1()))); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + setBoolean(m_out.phi(Int32, notCellResult, cellResult)); + } + void compileTypeOf() { Edge child = m_node->child1(); @@ -5804,11 +6672,13 @@ }); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, results)); + setJSValue(m_out.phi(Int64, results)); } void compileIn() { + DFG_ASSERT(m_graph, m_node, m_node->child2().useKind() == CellUse); + Node* node = m_node; Edge base = node->child2(); LValue cell = lowCell(base); @@ -5817,13 +6687,21 @@ UniquedStringImpl* str = bitwise_cast(string->tryGetValueImpl()); B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64); patchpoint->appendSomeRegister(cell); + patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); patchpoint->clobber(RegisterSet::macroScratchRegisters()); + RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); + State* state = &m_ftlState; patchpoint->setGenerator( [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { AllowMacroScratchRegisterUsage allowScratch(jit); + // This is the direct exit target for operation calls. We don't need a JS exceptionHandle because we don't + // cache Proxy objects. + Box exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit); + GPRReg baseGPR = params[1].gpr(); GPRReg resultGPR = params[0].gpr(); @@ -5847,28 +6725,26 @@ CCallHelpers::Label slowPathBegin = jit.label(); CCallHelpers::Call slowPathCall = callOperation( *state, params.unavailableRegisters(), jit, - node->origin.semantic, nullptr, operationInOptimize, + node->origin.semantic, exceptions.get(), operationInOptimize, resultGPR, CCallHelpers::TrustedImmPtr(stubInfo), baseGPR, CCallHelpers::TrustedImmPtr(str)).call(); jit.jump().linkTo(done, &jit); jit.addLinkTask( [=] (LinkBuffer& linkBuffer) { - CodeLocationCall callReturnLocation = - linkBuffer.locationOf(slowPathCall); - stubInfo->patch.deltaCallToDone = - CCallHelpers::differenceBetweenCodePtr( - callReturnLocation, - linkBuffer.locationOf(done)); - stubInfo->patch.deltaCallToJump = - CCallHelpers::differenceBetweenCodePtr( - callReturnLocation, - linkBuffer.locationOf(jump)); - stubInfo->callReturnLocation = callReturnLocation; - stubInfo->patch.deltaCallToSlowCase = - CCallHelpers::differenceBetweenCodePtr( - callReturnLocation, - linkBuffer.locationOf(slowPathBegin)); + CodeLocationLabel start = linkBuffer.locationOf(jump); + stubInfo->patch.start = start; + ptrdiff_t inlineSize = MacroAssembler::differenceBetweenCodePtr( + start, linkBuffer.locationOf(done)); + RELEASE_ASSERT(inlineSize >= 0); + stubInfo->patch.inlineSize = inlineSize; + + stubInfo->patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr( + start, linkBuffer.locationOf(slowPathCall)); + + stubInfo->patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr( + start, linkBuffer.locationOf(slowPathBegin)); + }); }); }); @@ -5878,7 +6754,7 @@ } } - setJSValue(vmCall(m_out.int64, m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1()))); + setJSValue(vmCall(Int64, m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1()))); } void compileOverridesHasInstance() @@ -5893,8 +6769,6 @@ // Unlike in the DFG, we don't worry about cleaning this code up for the case where we have proven the hasInstanceValue is a constant as B3 should fix it for us. - ASSERT(!m_node->child2().node()->isCellConstant() || defaultHasInstanceFunction == m_node->child2().node()->asCell()); - ValueFromBlock notDefaultHasInstanceResult = m_out.anchor(m_out.booleanTrue); m_out.branch(m_out.notEqual(hasInstance, m_out.constIntPtr(defaultHasInstanceFunction)), unsure(continuation), unsure(defaultHasInstance)); @@ -5905,7 +6779,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, implementsDefaultHasInstanceResult, notDefaultHasInstanceResult)); + setBoolean(m_out.phi(Int32, implementsDefaultHasInstanceResult, notDefaultHasInstanceResult)); } void compileCheckTypeInfoFlags() @@ -5932,6 +6806,8 @@ LBasicBlock loop = m_out.newBlock(); LBasicBlock notYetInstance = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); + LBasicBlock loadPrototypeDirect = m_out.newBlock(); + LBasicBlock defaultHasInstanceSlow = m_out.newBlock(); LValue condition; if (m_node->child1().useKind() == UntypedUse) @@ -5949,8 +6825,14 @@ ValueFromBlock originalValue = m_out.anchor(cell); m_out.jump(loop); - m_out.appendTo(loop, notYetInstance); - LValue value = m_out.phi(m_out.int64, originalValue); + m_out.appendTo(loop, loadPrototypeDirect); + LValue value = m_out.phi(Int64, originalValue); + LValue type = m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType); + m_out.branch( + m_out.notEqual(type, m_out.constInt32(ProxyObjectType)), + usually(loadPrototypeDirect), rarely(defaultHasInstanceSlow)); + + m_out.appendTo(loadPrototypeDirect, notYetInstance); LValue structure = loadStructure(value); LValue currentPrototype = m_out.load64(structure, m_heaps.Structure_prototype); ValueFromBlock isInstanceResult = m_out.anchor(m_out.booleanTrue); @@ -5958,14 +6840,22 @@ m_out.equal(currentPrototype, prototype), unsure(continuation), unsure(notYetInstance)); - m_out.appendTo(notYetInstance, continuation); + m_out.appendTo(notYetInstance, defaultHasInstanceSlow); ValueFromBlock notInstanceResult = m_out.anchor(m_out.booleanFalse); m_out.addIncomingToPhi(value, m_out.anchor(currentPrototype)); m_out.branch(isCell(currentPrototype), unsure(loop), unsure(continuation)); + + m_out.appendTo(defaultHasInstanceSlow, continuation); + // We can use the value that we're looping with because we + // can just continue off from wherever we bailed from the + // loop. + ValueFromBlock defaultHasInstanceResult = m_out.anchor( + vmCall(Int32, m_out.operation(operationDefaultHasInstance), m_callFrame, value, prototype)); + m_out.jump(continuation); m_out.appendTo(continuation, lastNext); setBoolean( - m_out.phi(m_out.boolean, notCellResult, isInstanceResult, notInstanceResult)); + m_out.phi(Int32, notCellResult, isInstanceResult, notInstanceResult, defaultHasInstanceResult)); } void compileInstanceOfCustom() @@ -5974,7 +6864,7 @@ LValue constructor = lowCell(m_node->child2()); LValue hasInstance = lowJSValue(m_node->child3()); - setBoolean(m_out.logicalNot(m_out.equal(m_out.constInt32(0), vmCall(m_out.int32, m_out.operation(operationInstanceOfCustom), m_callFrame, value, constructor, hasInstance)))); + setBoolean(m_out.logicalNot(m_out.equal(m_out.constInt32(0), vmCall(Int32, m_out.operation(operationInstanceOfCustom), m_callFrame, value, constructor, hasInstance)))); } void compileCountExecution() @@ -6021,11 +6911,11 @@ m_out.appendTo(slowCase, continuation); ValueFromBlock slowResult = m_out.anchor(m_out.equal( m_out.constInt64(JSValue::encode(jsBoolean(true))), - vmCall(m_out.int64, m_out.operation(operationHasIndexedProperty), m_callFrame, base, index))); + vmCall(Int64, m_out.operation(operationHasIndexedProperty), m_callFrame, base, index))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, checkHoleResult, slowResult)); + setBoolean(m_out.phi(Int32, checkHoleResult, slowResult)); return; } case Array::Double: { @@ -6056,11 +6946,11 @@ m_out.appendTo(slowCase, continuation); ValueFromBlock slowResult = m_out.anchor(m_out.equal( m_out.constInt64(JSValue::encode(jsBoolean(true))), - vmCall(m_out.int64, m_out.operation(operationHasIndexedProperty), m_callFrame, base, index))); + vmCall(Int64, m_out.operation(operationHasIndexedProperty), m_callFrame, base, index))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, checkHoleResult, slowResult)); + setBoolean(m_out.phi(Int32, checkHoleResult, slowResult)); return; } @@ -6074,7 +6964,7 @@ { LValue base = lowJSValue(m_node->child1()); LValue property = lowCell(m_node->child2()); - setJSValue(vmCall(m_out.int64, m_out.operation(operationHasGenericProperty), m_callFrame, base, property)); + setJSValue(vmCall(Int64, m_out.operation(operationHasGenericProperty), m_callFrame, base, property)); } void compileHasStructureProperty() @@ -6100,11 +6990,11 @@ ValueFromBlock wrongStructureResult = m_out.anchor( m_out.equal( m_out.constInt64(JSValue::encode(jsBoolean(true))), - vmCall(m_out.int64, m_out.operation(operationHasGenericProperty), m_callFrame, base, property))); + vmCall(Int64, m_out.operation(operationHasGenericProperty), m_callFrame, base, property))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, correctStructureResult, wrongStructureResult)); + setBoolean(m_out.phi(Int32, correctStructureResult, wrongStructureResult)); } void compileGetDirectPname() @@ -6132,11 +7022,11 @@ m_out.appendTo(inlineLoad, outOfLineLoad); ValueFromBlock inlineResult = m_out.anchor( m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), - base, m_out.zeroExt(index, m_out.int64), ScaleEight, JSObject::offsetOfInlineStorage()))); + base, m_out.zeroExt(index, Int64), ScaleEight, JSObject::offsetOfInlineStorage()))); m_out.jump(continuation); m_out.appendTo(outOfLineLoad, slowCase); - LValue storage = loadButterflyReadOnly(base); + LValue storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly); LValue realIndex = m_out.signExt32To64( m_out.neg(m_out.sub(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity)))); int32_t offsetOfFirstProperty = static_cast(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue); @@ -6146,11 +7036,11 @@ m_out.appendTo(slowCase, continuation); ValueFromBlock slowCaseResult = m_out.anchor( - vmCall(m_out.int64, m_out.operation(operationGetByVal), m_callFrame, base, property)); + vmCall(Int64, m_out.operation(operationGetByVal), m_callFrame, base, property)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, inlineResult, outOfLineResult, slowCaseResult)); + setJSValue(m_out.phi(Int64, inlineResult, outOfLineResult, slowCaseResult)); } void compileGetEnumerableLength() @@ -6162,7 +7052,7 @@ void compileGetPropertyEnumerator() { LValue base = lowCell(m_node->child1()); - setJSValue(vmCall(m_out.int64, m_out.operation(operationGetPropertyEnumerator), m_callFrame, base)); + setJSValue(vmCall(Int64, m_out.operation(operationGetPropertyEnumerator), m_callFrame, base)); } void compileGetEnumeratorStructurePname() @@ -6188,7 +7078,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult)); + setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult)); } void compileGetEnumeratorGenericPname() @@ -6214,13 +7104,13 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult)); + setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult)); } void compileToIndexString() { LValue index = lowInt32(m_node->child1()); - setJSValue(vmCall(m_out.int64, m_out.operation(operationToIndexString), m_callFrame, index)); + setJSValue(vmCall(Int64, m_out.operation(operationToIndexString), m_callFrame, index)); } void compileCheckStructureImmediate() @@ -6240,11 +7130,21 @@ // Lower the values first, to avoid creating values inside a control flow diamond. Vector values; - for (unsigned i = 0; i < data.m_properties.size(); ++i) - values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i))); + for (unsigned i = 0; i < data.m_properties.size(); ++i) { + Edge edge = m_graph.varArgChild(m_node, 1 + i); + switch (data.m_properties[i].kind()) { + case PublicLengthPLoc: + case VectorLengthPLoc: + values.append(lowInt32(edge)); + break; + default: + values.append(lowJSValue(edge)); + break; + } + } const StructureSet& set = m_node->structureSet(); - + Vector blocks(set.size()); for (unsigned i = set.size(); i--;) blocks[i] = m_out.newBlock(); @@ -6269,37 +7169,90 @@ LValue object; LValue butterfly; - if (structure->outOfLineCapacity()) { + if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) { size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity()); - MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize); + MarkedAllocator* cellAllocator = vm().heap.allocatorForObjectWithoutDestructor(allocationSize); + DFG_ASSERT(m_graph, m_node, cellAllocator); + + bool hasIndexingHeader = hasIndexedProperties(structure->indexingType()); + unsigned indexingHeaderSize = 0; + LValue indexingPayloadSizeInBytes = m_out.intPtrZero; + LValue vectorLength = m_out.int32Zero; + LValue publicLength = m_out.int32Zero; + if (hasIndexingHeader) { + indexingHeaderSize = sizeof(IndexingHeader); + for (unsigned i = data.m_properties.size(); i--;) { + PromotedLocationDescriptor descriptor = data.m_properties[i]; + switch (descriptor.kind()) { + case PublicLengthPLoc: + publicLength = values[i]; + break; + case VectorLengthPLoc: + vectorLength = values[i]; + break; + default: + break; + } + } + indexingPayloadSizeInBytes = + m_out.mul(m_out.zeroExtPtr(vectorLength), m_out.intPtrEight); + } + + LValue butterflySize = m_out.add( + m_out.constIntPtr( + structure->outOfLineCapacity() * sizeof(JSValue) + indexingHeaderSize), + indexingPayloadSizeInBytes); LBasicBlock slowPath = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); - LValue endOfStorage = allocateBasicStorageAndGetEnd( - m_out.constIntPtr(structure->outOfLineCapacity() * sizeof(JSValue)), - slowPath); + ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero); + LValue startOfStorage = allocateHeapCell( + allocatorForSize(vm().heap.subspaceForAuxiliaryData(), butterflySize, slowPath), + slowPath); + LValue fastButterflyValue = m_out.add( - m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage); + startOfStorage, + m_out.constIntPtr( + structure->outOfLineCapacity() * sizeof(JSValue) + sizeof(IndexingHeader))); + + ValueFromBlock haveButterfly = m_out.anchor(fastButterflyValue); + + m_out.store32(vectorLength, fastButterflyValue, m_heaps.Butterfly_vectorLength); LValue fastObjectValue = allocateObject( - m_out.constIntPtr(allocator), structure, fastButterflyValue, slowPath); + m_out.constIntPtr(cellAllocator), structure, fastButterflyValue, slowPath); ValueFromBlock fastObject = m_out.anchor(fastObjectValue); ValueFromBlock fastButterfly = m_out.anchor(fastButterflyValue); m_out.jump(continuation); m_out.appendTo(slowPath, continuation); + + LValue butterflyValue = m_out.phi(pointerType(), noButterfly, haveButterfly); - LValue slowObjectValue = lazySlowPath( - [=] (const Vector& locations) -> RefPtr { - return createLazyCallGenerator( - operationNewObjectWithButterfly, locations[0].directGPR(), - CCallHelpers::TrustedImmPtr(structure)); - }); + LValue slowObjectValue; + if (hasIndexingHeader) { + slowObjectValue = lazySlowPath( + [=] (const Vector& locations) -> RefPtr { + return createLazyCallGenerator( + operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength, + locations[0].directGPR(), CCallHelpers::TrustedImmPtr(structure), + locations[1].directGPR(), locations[2].directGPR()); + }, + vectorLength, butterflyValue); + } else { + slowObjectValue = lazySlowPath( + [=] (const Vector& locations) -> RefPtr { + return createLazyCallGenerator( + operationNewObjectWithButterfly, locations[0].directGPR(), + CCallHelpers::TrustedImmPtr(structure), locations[1].directGPR()); + }, + butterflyValue); + } ValueFromBlock slowObject = m_out.anchor(slowObjectValue); ValueFromBlock slowButterfly = m_out.anchor( m_out.loadPtr(slowObjectValue, m_heaps.JSObject_butterfly)); @@ -6308,8 +7261,113 @@ m_out.appendTo(continuation, lastNext); - object = m_out.phi(m_out.intPtr, fastObject, slowObject); - butterfly = m_out.phi(m_out.intPtr, fastButterfly, slowButterfly); + object = m_out.phi(pointerType(), fastObject, slowObject); + butterfly = m_out.phi(pointerType(), fastButterfly, slowButterfly); + + m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength); + + initializeArrayElements(structure->indexingType(), m_out.int32Zero, vectorLength, butterfly); + + HashMap::Hash, WTF::UnsignedWithZeroKeyHashTraits> indexMap; + Vector indices; + for (unsigned i = data.m_properties.size(); i--;) { + PromotedLocationDescriptor descriptor = data.m_properties[i]; + if (descriptor.kind() != IndexedPropertyPLoc) + continue; + int32_t index = static_cast(descriptor.info()); + + auto result = indexMap.add(index, values[i]); + DFG_ASSERT(m_graph, m_node, result); // Duplicates are illegal. + + indices.append(index); + } + + if (!indices.isEmpty()) { + std::sort(indices.begin(), indices.end()); + + Vector blocksWithStores(indices.size()); + Vector blocksWithChecks(indices.size()); + + for (unsigned i = indices.size(); i--;) { + blocksWithStores[i] = m_out.newBlock(); + blocksWithChecks[i] = m_out.newBlock(); // blocksWithChecks[0] is the continuation. + } + + LBasicBlock indexLastNext = m_out.m_nextBlock; + + for (unsigned i = indices.size(); i--;) { + int32_t index = indices[i]; + LValue value = indexMap.get(index); + + m_out.branch( + m_out.below(m_out.constInt32(index), publicLength), + unsure(blocksWithStores[i]), unsure(blocksWithChecks[i])); + + m_out.appendTo(blocksWithStores[i], blocksWithChecks[i]); + + // This has to type-check and convert its inputs, but it cannot do so in a + // way that updates AI. That's a bit annoying, but if you think about how + // sinking works, it's actually not a bad thing. We are virtually guaranteed + // that these type checks will not fail, since the type checks that guarded + // the original stores to the array are still somewhere above this point. + Output::StoreType storeType; + IndexedAbstractHeap* heap; + switch (structure->indexingType()) { + case ALL_INT32_INDEXING_TYPES: + // FIXME: This could use the proven type if we had the Edge for the + // value. https://bugs.webkit.org/show_bug.cgi?id=155311 + speculate(BadType, noValue(), nullptr, isNotInt32(value)); + storeType = Output::Store64; + heap = &m_heaps.indexedInt32Properties; + break; + + case ALL_DOUBLE_INDEXING_TYPES: { + // FIXME: If the source is ValueRep, we should avoid emitting any + // checks. We could also avoid emitting checks if we had the Edge of + // this value. https://bugs.webkit.org/show_bug.cgi?id=155311 + + LBasicBlock intCase = m_out.newBlock(); + LBasicBlock doubleCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + m_out.branch(isInt32(value), unsure(intCase), unsure(doubleCase)); + + LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase); + + ValueFromBlock intResult = + m_out.anchor(m_out.intToDouble(unboxInt32(value))); + m_out.jump(continuation); + + m_out.appendTo(doubleCase, continuation); + + speculate(BadType, noValue(), nullptr, isNumber(value)); + ValueFromBlock doubleResult = m_out.anchor(unboxDouble(value)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + value = m_out.phi(Double, intResult, doubleResult); + storeType = Output::StoreDouble; + heap = &m_heaps.indexedDoubleProperties; + break; + } + + case ALL_CONTIGUOUS_INDEXING_TYPES: + storeType = Output::Store64; + heap = &m_heaps.indexedContiguousProperties; + break; + + default: + DFG_CRASH(m_graph, m_node, "Invalid indexing type"); + break; + } + + m_out.store(value, m_out.address(butterfly, heap->at(index)), storeType); + + m_out.jump(blocksWithChecks[i]); + m_out.appendTo( + blocksWithChecks[i], i ? blocksWithStores[i - 1] : indexLastNext); + } + } } else { // In the easy case where we can do a one-shot allocation, we simply allocate the // object to directly have the desired structure. @@ -6319,12 +7377,14 @@ for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) { for (unsigned i = data.m_properties.size(); i--;) { - PhantomPropertyValue value = data.m_properties[i]; - if (m_graph.identifiers()[value.m_identifierNumber] != entry.key) + PromotedLocationDescriptor descriptor = data.m_properties[i]; + if (descriptor.kind() != NamedPropertyPLoc) + continue; + if (m_graph.identifiers()[descriptor.info()] != entry.key) continue; LValue base = isInlineOffset(entry.offset) ? object : butterfly; - storeProperty(values[i], base, value.m_identifierNumber, entry.offset); + storeProperty(values[i], base, descriptor.info(), entry.offset); break; } } @@ -6337,7 +7397,7 @@ m_out.unreachable(); m_out.appendTo(outerContinuation, outerLastNext); - setJSValue(m_out.phi(m_out.intPtr, results)); + setJSValue(m_out.phi(pointerType(), results)); } void compileMaterializeCreateActivation() @@ -6386,12 +7446,14 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult); + LValue activation = m_out.phi(pointerType(), fastResult, slowResult); RELEASE_ASSERT(data.m_properties.size() == table->scopeSize()); for (unsigned i = 0; i < data.m_properties.size(); ++i) { - m_out.store64(values[i], - activation, - m_heaps.JSEnvironmentRecord_variables[data.m_properties[i].m_identifierNumber]); + PromotedLocationDescriptor descriptor = data.m_properties[i]; + ASSERT(descriptor.kind() == ClosureVarPLoc); + m_out.store64( + values[i], activation, + m_heaps.JSEnvironmentRecord_variables[descriptor.info()]); } if (validationEnabled()) { @@ -6400,7 +7462,9 @@ for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) { bool found = false; for (unsigned i = 0; i < data.m_properties.size(); ++i) { - if (iter->value.scopeOffset().offset() == data.m_properties[i].m_identifierNumber) { + PromotedLocationDescriptor descriptor = data.m_properties[i]; + ASSERT(descriptor.kind() == ClosureVarPLoc); + if (iter->value.scopeOffset().offset() == descriptor.info()) { found = true; break; } @@ -6434,52 +7498,85 @@ void compileRegExpExec() { - if (m_node->child1().useKind() == CellUse - && m_node->child2().useKind() == CellUse) { - LValue base = lowCell(m_node->child1()); - LValue argument = lowCell(m_node->child2()); - setJSValue( - vmCall(Int64, m_out.operation(operationRegExpExec), m_callFrame, base, argument)); + LValue globalObject = lowCell(m_node->child1()); + + if (m_node->child2().useKind() == RegExpObjectUse) { + LValue base = lowRegExpObject(m_node->child2()); + + if (m_node->child3().useKind() == StringUse) { + LValue argument = lowString(m_node->child3()); + LValue result = vmCall( + Int64, m_out.operation(operationRegExpExecString), m_callFrame, globalObject, + base, argument); + setJSValue(result); + return; + } + + LValue argument = lowJSValue(m_node->child3()); + LValue result = vmCall( + Int64, m_out.operation(operationRegExpExec), m_callFrame, globalObject, base, + argument); + setJSValue(result); return; } - LValue base = lowJSValue(m_node->child1()); - LValue argument = lowJSValue(m_node->child2()); - setJSValue( - vmCall(Int64, m_out.operation(operationRegExpExecGeneric), m_callFrame, base, argument)); + LValue base = lowJSValue(m_node->child2()); + LValue argument = lowJSValue(m_node->child3()); + LValue result = vmCall( + Int64, m_out.operation(operationRegExpExecGeneric), m_callFrame, globalObject, base, + argument); + setJSValue(result); } void compileRegExpTest() { - if (m_node->child1().useKind() == CellUse - && m_node->child2().useKind() == CellUse) { - LValue base = lowCell(m_node->child1()); - LValue argument = lowCell(m_node->child2()); - setBoolean( - vmCall(Int32, m_out.operation(operationRegExpTest), m_callFrame, base, argument)); + LValue globalObject = lowCell(m_node->child1()); + + if (m_node->child2().useKind() == RegExpObjectUse) { + LValue base = lowRegExpObject(m_node->child2()); + + if (m_node->child3().useKind() == StringUse) { + LValue argument = lowString(m_node->child3()); + LValue result = vmCall( + Int32, m_out.operation(operationRegExpTestString), m_callFrame, globalObject, + base, argument); + setBoolean(result); + return; + } + + LValue argument = lowJSValue(m_node->child3()); + LValue result = vmCall( + Int32, m_out.operation(operationRegExpTest), m_callFrame, globalObject, base, + argument); + setBoolean(result); return; } - LValue base = lowJSValue(m_node->child1()); - LValue argument = lowJSValue(m_node->child2()); - setBoolean( - vmCall(Int32, m_out.operation(operationRegExpTestGeneric), m_callFrame, base, argument)); + LValue base = lowJSValue(m_node->child2()); + LValue argument = lowJSValue(m_node->child3()); + LValue result = vmCall( + Int32, m_out.operation(operationRegExpTestGeneric), m_callFrame, globalObject, base, + argument); + setBoolean(result); } void compileNewRegexp() { - // FIXME: We really should be able to inline code that uses NewRegexp. That means not - // reaching into the CodeBlock here. - // https://bugs.webkit.org/show_bug.cgi?id=154808 - + RegExp* regexp = m_node->castOperand(); LValue result = vmCall( pointerType(), m_out.operation(operationNewRegexp), m_callFrame, - m_out.constIntPtr(codeBlock()->regexp(m_node->regexpIndex()))); + m_out.constIntPtr(regexp)); setJSValue(result); } + void compileSetFunctionName() + { + vmCall(Void, m_out.operation(operationSetFunctionName), m_callFrame, + lowCell(m_node->child1()), lowJSValue(m_node->child2())); + } + void compileStringReplace() { if (m_node->child1().useKind() == StringUse @@ -6489,8 +7586,7 @@ if (JSString* replace = m_node->child3()->dynamicCastConstant()) { if (!replace->length()) { LValue string = lowString(m_node->child1()); - LValue regExp = lowCell(m_node->child2()); - speculateRegExpObject(m_node->child2(), regExp); + LValue regExp = lowRegExpObject(m_node->child2()); LValue result = vmCall( Int64, m_out.operation(operationStringProtoFuncReplaceRegExpEmptyStr), @@ -6502,8 +7598,7 @@ } LValue string = lowString(m_node->child1()); - LValue regExp = lowCell(m_node->child2()); - speculateRegExpObject(m_node->child2(), regExp); + LValue regExp = lowRegExpObject(m_node->child2()); LValue replace = lowString(m_node->child3()); LValue result = vmCall( @@ -6513,49 +7608,85 @@ setJSValue(result); return; } - + + LValue search; + if (m_node->child2().useKind() == StringUse) + search = lowString(m_node->child2()); + else + search = lowJSValue(m_node->child2()); + LValue result = vmCall( Int64, m_out.operation(operationStringProtoFuncReplaceGeneric), m_callFrame, - lowJSValue(m_node->child1()), lowJSValue(m_node->child2()), + lowJSValue(m_node->child1()), search, lowJSValue(m_node->child3())); setJSValue(result); } - LValue didOverflowStack() + void compileGetRegExpObjectLastIndex() { - // This does a very simple leaf function analysis. The invariant of FTL call - // frames is that the caller had already done enough of a stack check to - // prove that this call frame has enough stack to run, and also enough stack - // to make runtime calls. So, we only need to stack check when making calls - // to other JS functions. If we don't find such calls then we don't need to - // do any stack checks. - - for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { - DFG::BasicBlock* block = m_graph.block(blockIndex); - if (!block) - continue; - - for (unsigned nodeIndex = block->size(); nodeIndex--;) { - Node* node = block->at(nodeIndex); - - switch (node->op()) { - case GetById: - case PutById: - case Call: - case Construct: - return m_out.below( - m_callFrame, - m_out.loadPtr( - m_out.absolute(vm().addressOfFTLStackLimit()))); - - default: - break; - } - } - } + setJSValue(m_out.load64(lowRegExpObject(m_node->child1()), m_heaps.RegExpObject_lastIndex)); + } + + void compileSetRegExpObjectLastIndex() + { + LValue regExp = lowRegExpObject(m_node->child1()); + LValue value = lowJSValue(m_node->child2()); + + speculate( + ExoticObjectMode, noValue(), nullptr, + m_out.isZero32(m_out.load8ZeroExt32(regExp, m_heaps.RegExpObject_lastIndexIsWritable))); - return m_out.booleanFalse; + m_out.store64(value, regExp, m_heaps.RegExpObject_lastIndex); + } + + void compileLogShadowChickenPrologue() + { + LValue packet = ensureShadowChickenPacket(); + LValue scope = lowCell(m_node->child1()); + + m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame); + m_out.storePtr(m_out.loadPtr(addressFor(0)), packet, m_heaps.ShadowChicken_Packet_callerFrame); + m_out.storePtr(m_out.loadPtr(payloadFor(CallFrameSlot::callee)), packet, m_heaps.ShadowChicken_Packet_callee); + m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope); + } + + void compileLogShadowChickenTail() + { + LValue packet = ensureShadowChickenPacket(); + LValue thisValue = lowJSValue(m_node->child1()); + LValue scope = lowCell(m_node->child2()); + CallSiteIndex callSiteIndex = m_ftlState.jitCode->common.addCodeOrigin(m_node->origin.semantic); + + m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame); + m_out.storePtr(m_out.constIntPtr(ShadowChicken::Packet::tailMarker()), packet, m_heaps.ShadowChicken_Packet_callee); + m_out.store64(thisValue, packet, m_heaps.ShadowChicken_Packet_thisValue); + m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope); + m_out.storePtr(m_out.constIntPtr(codeBlock()), packet, m_heaps.ShadowChicken_Packet_codeBlock); + m_out.store32(m_out.constInt32(callSiteIndex.bits()), packet, m_heaps.ShadowChicken_Packet_callSiteIndex); + } + + void compileRecordRegExpCachedResult() + { + Edge constructorEdge = m_graph.varArgChild(m_node, 0); + Edge regExpEdge = m_graph.varArgChild(m_node, 1); + Edge stringEdge = m_graph.varArgChild(m_node, 2); + Edge startEdge = m_graph.varArgChild(m_node, 3); + Edge endEdge = m_graph.varArgChild(m_node, 4); + + LValue constructor = lowCell(constructorEdge); + LValue regExp = lowCell(regExpEdge); + LValue string = lowCell(stringEdge); + LValue start = lowInt32(startEdge); + LValue end = lowInt32(endEdge); + + m_out.storePtr(regExp, constructor, m_heaps.RegExpConstructor_cachedResult_lastRegExp); + m_out.storePtr(string, constructor, m_heaps.RegExpConstructor_cachedResult_lastInput); + m_out.store32(start, constructor, m_heaps.RegExpConstructor_cachedResult_result_start); + m_out.store32(end, constructor, m_heaps.RegExpConstructor_cachedResult_result_end); + m_out.store32As8( + m_out.constInt32(0), + m_out.address(constructor, m_heaps.RegExpConstructor_cachedResult_reified)); } struct ArgumentsLength { @@ -6584,7 +7715,7 @@ VirtualRegister argumentCountRegister; if (!inlineCallFrame) - argumentCountRegister = VirtualRegister(JSStack::ArgumentCount); + argumentCountRegister = VirtualRegister(CallFrameSlot::argumentCount); else argumentCountRegister = inlineCallFrame->argumentCountRegister; length.value = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One); @@ -6605,7 +7736,7 @@ return m_out.loadPtr(addressFor(frame->calleeRecovery.virtualRegister())); return weakPointer(frame->calleeRecovery.constant().asCell()); } - return m_out.loadPtr(addressFor(JSStack::Callee)); + return m_out.loadPtr(addressFor(CallFrameSlot::callee)); } LValue getArgumentsStart(InlineCallFrame* inlineCallFrame) @@ -6701,7 +7832,7 @@ } m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.int32, results); + return m_out.phi(Int32, results); } void checkInferredType(Edge edge, LValue value, const InferredType::Descriptor& type) @@ -6864,14 +7995,14 @@ return object; if (previousStructure->outOfLineCapacity() == nextStructure->outOfLineCapacity()) - return loadButterflyWithBarrier(object); + return m_out.loadPtr(object, m_heaps.JSObject_butterfly); LValue result; if (!previousStructure->outOfLineCapacity()) result = allocatePropertyStorage(object, previousStructure); else { result = reallocatePropertyStorage( - object, loadButterflyWithBarrier(object), + object, m_out.loadPtr(object, m_heaps.JSObject_butterfly), previousStructure, nextStructure); } @@ -6879,12 +8010,64 @@ return result; } + + void initializeArrayElements(IndexingType indexingType, LValue begin, LValue end, LValue butterfly) + { + if (hasUndecided(indexingType)) + return; + + if (begin == end) + return; + + IndexedAbstractHeap* heap = m_heaps.forIndexingType(indexingType); + DFG_ASSERT(m_graph, m_node, heap); + + LValue hole; + if (hasDouble(indexingType)) + hole = m_out.constInt64(bitwise_cast(PNaN)); + else + hole = m_out.constInt64(JSValue::encode(JSValue())); + + const uint64_t unrollingLimit = 10; + if (begin->hasInt() && end->hasInt()) { + uint64_t beginConst = static_cast(begin->asInt()); + uint64_t endConst = static_cast(end->asInt()); + + if (endConst - beginConst <= unrollingLimit) { + for (uint64_t i = beginConst; i < endConst; ++i) + m_out.store64(hole, butterfly, heap->at(i)); + return; + } + } + + // Doubles must be initialized to PNaN. + LBasicBlock initLoop = m_out.newBlock(); + LBasicBlock initDone = m_out.newBlock(); + + ValueFromBlock originalIndex = m_out.anchor(end); + ValueFromBlock originalPointer = m_out.anchor(butterfly); + m_out.branch(m_out.notEqual(end, begin), unsure(initLoop), unsure(initDone)); + + LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone); + LValue index = m_out.phi(Int32, originalIndex); + LValue pointer = m_out.phi(pointerType(), originalPointer); + + m_out.store64(hole, TypedPointer(heap->atAnyIndex(), pointer)); + + LValue nextIndex = m_out.sub(index, m_out.int32One); + m_out.addIncomingToPhi(index, m_out.anchor(nextIndex)); + m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight))); + m_out.branch( + m_out.notEqual(nextIndex, begin), unsure(initLoop), unsure(initDone)); + + m_out.appendTo(initDone, initLastNext); + } LValue allocatePropertyStorage(LValue object, Structure* previousStructure) { if (previousStructure->couldHaveIndexingHeader()) { return vmCall( - m_out.intPtr, + pointerType(), m_out.operation( operationReallocateButterflyToHavePropertyStorageWithInitialCapacity), m_callFrame, object); @@ -6905,7 +8088,7 @@ if (previous->couldHaveIndexingHeader()) { LValue newAllocSize = m_out.constIntPtr(newSize); - return vmCall(m_out.intPtr, m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize); + return vmCall(pointerType(), m_out.operation(operationReallocateButterflyToGrowPropertyStorage), m_callFrame, object, newAllocSize); } LValue result = allocatePropertyStorageWithSizeImpl(newSize); @@ -6930,13 +8113,12 @@ LBasicBlock continuation = m_out.newBlock(); LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); - - LValue endOfStorage = allocateBasicStorageAndGetEnd( - m_out.constIntPtr(sizeInValues * sizeof(JSValue)), slowPath); - + + size_t sizeInBytes = sizeInValues * sizeof(JSValue); + MarkedAllocator* allocator = vm().heap.allocatorForAuxiliaryData(sizeInBytes); + LValue startOfStorage = allocateHeapCell(m_out.constIntPtr(allocator), slowPath); ValueFromBlock fastButterfly = m_out.anchor( - m_out.add(m_out.constIntPtr(sizeof(IndexingHeader)), endOfStorage)); - + m_out.add(m_out.constIntPtr(sizeInBytes + sizeof(IndexingHeader)), startOfStorage)); m_out.jump(continuation); m_out.appendTo(slowPath, continuation); @@ -6963,16 +8145,18 @@ m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.intPtr, fastButterfly, slowButterfly); + return m_out.phi(pointerType(), fastButterfly, slowButterfly); } - LValue getById(LValue base) + LValue getById(LValue base, AccessType type) { Node* node = m_node; UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()]; B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64); patchpoint->appendSomeRegister(base); + patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); // FIXME: If this is a GetByIdFlush, we might get some performance boost if we claim that it // clobbers volatile registers late. It's not necessary for correctness, though, since the @@ -7003,8 +8187,8 @@ auto generator = Box::create( jit.codeBlock(), node->origin.semantic, callSiteIndex, - params.unavailableRegisters(), JSValueRegs(params[1].gpr()), - JSValueRegs(params[0].gpr())); + params.unavailableRegisters(), uid, JSValueRegs(params[1].gpr()), + JSValueRegs(params[0].gpr()), type); generator->generateFastPath(jit); CCallHelpers::Label done = jit.label(); @@ -7013,11 +8197,17 @@ [=] (CCallHelpers& jit) { AllowMacroScratchRegisterUsage allowScratch(jit); + J_JITOperation_ESsiJI optimizationFunction; + if (type == AccessType::Get) + optimizationFunction = operationGetByIdOptimize; + else + optimizationFunction = operationTryGetByIdOptimize; + generator->slowPathJump().link(&jit); CCallHelpers::Label slowPathBegin = jit.label(); CCallHelpers::Call slowPathCall = callOperation( *state, params.unavailableRegisters(), jit, node->origin.semantic, - exceptions.get(), operationGetByIdOptimize, params[0].gpr(), + exceptions.get(), optimizationFunction, params[0].gpr(), CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(), CCallHelpers::TrustedImmPtr(uid)).call(); jit.jump().linkTo(done, &jit); @@ -7026,116 +8216,12 @@ jit.addLinkTask( [=] (LinkBuffer& linkBuffer) { - generator->finalize(linkBuffer); - }); - }); - }); - - return patchpoint; - } - - LValue loadButterflyWithBarrier(LValue object) - { - return copyBarrier( - object, m_out.loadPtr(object, m_heaps.JSObject_butterfly), operationGetButterfly); - } - - LValue loadVectorWithBarrier(LValue object) - { - LValue fastResultValue = m_out.loadPtr(object, m_heaps.JSArrayBufferView_vector); - return copyBarrier( - fastResultValue, - [&] () -> LValue { - LBasicBlock slowPath = m_out.newBlock(); - LBasicBlock continuation = m_out.newBlock(); - - ValueFromBlock fastResult = m_out.anchor(fastResultValue); - m_out.branch(isFastTypedArray(object), rarely(slowPath), usually(continuation)); - - LBasicBlock lastNext = m_out.appendTo(slowPath, continuation); - - LValue slowResultValue = lazySlowPath( - [=] (const Vector& locations) -> RefPtr { - return createLazyCallGenerator( - operationGetArrayBufferVector, locations[0].directGPR(), - locations[1].directGPR()); - }, object); - ValueFromBlock slowResult = m_out.anchor(slowResultValue); - m_out.jump(continuation); - - m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.intPtr, fastResult, slowResult); - }); - } - - LValue copyBarrier(LValue object, LValue pointer, P_JITOperation_EC slowPathFunction) - { - return copyBarrier( - pointer, - [&] () -> LValue { - return lazySlowPath( - [=] (const Vector& locations) -> RefPtr { - return createLazyCallGenerator( - slowPathFunction, locations[0].directGPR(), locations[1].directGPR()); - }, object); - }); - } - - template - LValue copyBarrier(LValue pointer, const Functor& functor) - { - LBasicBlock slowPath = m_out.newBlock(); - LBasicBlock continuation = m_out.newBlock(); - - ValueFromBlock fastResult = m_out.anchor(pointer); - m_out.branch(isInToSpace(pointer), usually(continuation), rarely(slowPath)); - - LBasicBlock lastNext = m_out.appendTo(slowPath, continuation); - - ValueFromBlock slowResult = m_out.anchor(functor()); - m_out.jump(continuation); - - m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.intPtr, fastResult, slowResult); - } - - LValue isInToSpace(LValue pointer) - { - return m_out.testIsZeroPtr(pointer, m_out.constIntPtr(CopyBarrierBase::spaceBits)); - } - - LValue loadButterflyReadOnly(LValue object) - { - return removeSpaceBits(m_out.loadPtr(object, m_heaps.JSObject_butterfly)); - } - - LValue loadVectorReadOnly(LValue object) - { - LValue fastResultValue = m_out.loadPtr(object, m_heaps.JSArrayBufferView_vector); - - LBasicBlock possiblyFromSpace = m_out.newBlock(); - LBasicBlock continuation = m_out.newBlock(); - - ValueFromBlock fastResult = m_out.anchor(fastResultValue); - - m_out.branch(isInToSpace(fastResultValue), usually(continuation), rarely(possiblyFromSpace)); - - LBasicBlock lastNext = m_out.appendTo(possiblyFromSpace, continuation); - - LValue slowResultValue = m_out.select( - isFastTypedArray(object), removeSpaceBits(fastResultValue), fastResultValue); - ValueFromBlock slowResult = m_out.anchor(slowResultValue); - m_out.jump(continuation); - - m_out.appendTo(continuation, lastNext); - - return m_out.phi(m_out.intPtr, fastResult, slowResult); - } + generator->finalize(linkBuffer); + }); + }); + }); - LValue removeSpaceBits(LValue storage) - { - return m_out.bitAnd( - storage, m_out.constIntPtr(~static_cast(CopyBarrierBase::spaceBits))); + return patchpoint; } LValue isFastTypedArray(LValue object) @@ -7154,7 +8240,9 @@ template void compare( const IntFunctor& intFunctor, const DoubleFunctor& doubleFunctor, - S_JITOperation_EJJ helperFunction) + C_JITOperation_TT stringIdentFunction, + C_JITOperation_B_EJssJss stringFunction, + S_JITOperation_EJJ fallbackFunction) { if (m_node->isBinaryUseKind(Int32Use)) { LValue left = lowInt32(m_node->child1()); @@ -7177,13 +8265,62 @@ setBoolean(doubleFunctor(left, right)); return; } - - if (m_node->isBinaryUseKind(UntypedUse)) { - nonSpeculativeCompare(intFunctor, helperFunction); + + if (m_node->isBinaryUseKind(StringIdentUse)) { + LValue left = lowStringIdent(m_node->child1()); + LValue right = lowStringIdent(m_node->child2()); + setBoolean(m_out.callWithoutSideEffects(Int32, stringIdentFunction, left, right)); + return; + } + + if (m_node->isBinaryUseKind(StringUse)) { + LValue left = lowCell(m_node->child1()); + LValue right = lowCell(m_node->child2()); + speculateString(m_node->child1(), left); + speculateString(m_node->child2(), right); + + LValue result = vmCall( + Int32, m_out.operation(stringFunction), + m_callFrame, left, right); + setBoolean(result); return; } + + DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse)); + nonSpeculativeCompare(intFunctor, fallbackFunction); + } + + void compileResolveScope() + { + UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()]; + setJSValue(vmCall(pointerType(), m_out.operation(operationResolveScope), + m_callFrame, lowCell(m_node->child1()), m_out.constIntPtr(uid))); + } + + void compileGetDynamicVar() + { + UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()]; + setJSValue(vmCall(Int64, m_out.operation(operationGetDynamicVar), + m_callFrame, lowCell(m_node->child1()), m_out.constIntPtr(uid), m_out.constInt32(m_node->getPutInfo()))); + } + + void compilePutDynamicVar() + { + UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()]; + setJSValue(vmCall(Void, m_out.operation(operationPutDynamicVar), + m_callFrame, lowCell(m_node->child1()), lowJSValue(m_node->child2()), m_out.constIntPtr(uid), m_out.constInt32(m_node->getPutInfo()))); + } + + void compileUnreachable() + { + // It's so tempting to assert that AI has proved that this is unreachable. But that's + // simply not a requirement of the Unreachable opcode at all. If you emit an opcode that + // *you* know will not return, then it's fine to end the basic block with Unreachable + // after that opcode. You don't have to also prove to AI that your opcode does not return. + // Hence, there is nothing to do here but emit code that will crash, so that we catch + // cases where you said Unreachable but you lied. - DFG_CRASH(m_graph, m_node, "Bad use kinds"); + crash(); } void compareEqObjectOrOtherToObject(Edge leftChild, Edge rightChild) @@ -7213,7 +8350,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, cellResult, notCellResult)); + setBoolean(m_out.phi(Int32, cellResult, notCellResult)); } void speculateTruthyObject(Edge edge, LValue cell, SpeculatedType filter) @@ -7242,10 +8379,10 @@ LBasicBlock slowPath = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); - m_out.branch(isNotInt32(left), rarely(slowPath), usually(leftIsInt)); + m_out.branch(isNotInt32(left, provenType(m_node->child1())), rarely(slowPath), usually(leftIsInt)); LBasicBlock lastNext = m_out.appendTo(leftIsInt, fastPath); - m_out.branch(isNotInt32(right), rarely(slowPath), usually(fastPath)); + m_out.branch(isNotInt32(right, provenType(m_node->child2())), rarely(slowPath), usually(fastPath)); m_out.appendTo(fastPath, slowPath); ValueFromBlock fastResult = m_out.anchor(intFunctor(unboxInt32(left), unboxInt32(right))); @@ -7253,11 +8390,11 @@ m_out.appendTo(slowPath, continuation); ValueFromBlock slowResult = m_out.anchor(m_out.notNull(vmCall( - m_out.intPtr, m_out.operation(helperFunction), m_callFrame, left, right))); + pointerType(), m_out.operation(helperFunction), m_callFrame, left, right))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - setBoolean(m_out.phi(m_out.boolean, fastResult, slowResult)); + setBoolean(m_out.phi(Int32, fastResult, slowResult)); } LValue stringsEqual(LValue leftJSString, LValue rightJSString) @@ -7323,7 +8460,7 @@ m_out.appendTo(loop, bytesEqual); - LValue indexAtLoopTop = m_out.phi(m_out.int32, indexAtStart); + LValue indexAtLoopTop = m_out.phi(Int32, indexAtStart); LValue indexInLoop = m_out.sub(indexAtLoopTop, m_out.int32One); LValue leftByte = m_out.load8ZeroExt32( @@ -7352,13 +8489,13 @@ m_out.appendTo(slowCase, continuation); LValue slowResultValue = vmCall( - m_out.int64, m_out.operation(operationCompareStringEq), m_callFrame, + Int64, m_out.operation(operationCompareStringEq), m_callFrame, leftJSString, rightJSString); ValueFromBlock slowResult = m_out.anchor(unboxBoolean(slowResultValue)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.boolean, trueResult, falseResult, slowResult); + return m_out.phi(Int32, trueResult, falseResult, slowResult); } enum ScratchFPRUsage { @@ -7379,8 +8516,8 @@ PatchpointValue* patchpoint = m_out.patchpoint(Int64); patchpoint->appendSomeRegister(left); patchpoint->appendSomeRegister(right); - patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); - patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); + patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); patchpoint->numGPScratchRegisters = 1; @@ -7388,6 +8525,7 @@ if (scratchFPRUsage == NeedScratchFPR) patchpoint->numFPScratchRegisters++; patchpoint->clobber(RegisterSet::macroScratchRegisters()); + patchpoint->resultConstraint = ValueRep::SomeEarlyRegister; State* state = &m_ftlState; patchpoint->setGenerator( [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { @@ -7435,9 +8573,6 @@ { Node* node = m_node; - // FIXME: Make this do exceptions. - // https://bugs.webkit.org/show_bug.cgi?id=151686 - LValue left = lowJSValue(node->child1()); LValue right = lowJSValue(node->child2()); @@ -7447,12 +8582,13 @@ PatchpointValue* patchpoint = m_out.patchpoint(Int64); patchpoint->appendSomeRegister(left); patchpoint->appendSomeRegister(right); - patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); - patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); + patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); patchpoint->numGPScratchRegisters = 1; patchpoint->clobber(RegisterSet::macroScratchRegisters()); + patchpoint->resultConstraint = ValueRep::SomeEarlyRegister; State* state = &m_ftlState; patchpoint->setGenerator( [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { @@ -7501,13 +8637,14 @@ PatchpointValue* patchpoint = m_out.patchpoint(Int64); patchpoint->appendSomeRegister(left); patchpoint->appendSomeRegister(right); - patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); - patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); + patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); + patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); patchpoint->numGPScratchRegisters = 1; patchpoint->numFPScratchRegisters = 1; patchpoint->clobber(RegisterSet::macroScratchRegisters()); + patchpoint->resultConstraint = ValueRep::SomeEarlyRegister; State* state = &m_ftlState; patchpoint->setGenerator( [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { @@ -7546,29 +8683,64 @@ setJSValue(patchpoint); } - LValue allocateCell(LValue allocator, LBasicBlock slowPath) + LValue allocateHeapCell(LValue allocator, LBasicBlock slowPath) { - LBasicBlock success = m_out.newBlock(); - - LValue result; - LValue condition; - if (Options::forceGCSlowPaths()) { - result = m_out.intPtrZero; - condition = m_out.booleanFalse; - } else { - result = m_out.loadPtr( - allocator, m_heaps.MarkedAllocator_freeListHead); - condition = m_out.notNull(result); + MarkedAllocator* actualAllocator = nullptr; + if (allocator->hasIntPtr()) + actualAllocator = bitwise_cast(allocator->asIntPtr()); + + if (!actualAllocator) { + // This means that either we know that the allocator is null or we don't know what the + // allocator is. In either case, we need the null check. + LBasicBlock haveAllocator = m_out.newBlock(); + LBasicBlock lastNext = m_out.insertNewBlocksBefore(haveAllocator); + m_out.branch(allocator, usually(haveAllocator), rarely(slowPath)); + m_out.appendTo(haveAllocator, lastNext); } - m_out.branch(condition, usually(success), rarely(slowPath)); - m_out.appendTo(success); + LBasicBlock continuation = m_out.newBlock(); - m_out.storePtr( - m_out.loadPtr(result, m_heaps.JSCell_freeListNext), - allocator, m_heaps.MarkedAllocator_freeListHead); - - return result; + LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation); + + PatchpointValue* patchpoint = m_out.patchpoint(pointerType()); + patchpoint->effects.terminal = true; + patchpoint->appendSomeRegister(allocator); + patchpoint->numGPScratchRegisters++; + patchpoint->resultConstraint = ValueRep::SomeEarlyRegister; + + m_out.appendSuccessor(usually(continuation)); + m_out.appendSuccessor(rarely(slowPath)); + + patchpoint->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { + CCallHelpers::JumpList jumpToSlowPath; + + // We use a patchpoint to emit the allocation path because whenever we mess with + // allocation paths, we already reason about them at the machine code level. We know + // exactly what instruction sequence we want. We're confident that no compiler + // optimization could make this code better. So, it's best to have the code in + // AssemblyHelpers::emitAllocate(). That way, the same optimized path is shared by + // all of the compiler tiers. + jit.emitAllocateWithNonNullAllocator( + params[0].gpr(), actualAllocator, params[1].gpr(), params.gpScratch(0), + jumpToSlowPath); + + CCallHelpers::Jump jumpToSuccess; + if (!params.fallsThroughToSuccessor(0)) + jumpToSuccess = jit.jump(); + + Vector> labels = params.successorLabels(); + + params.addLatePath( + [=] (CCallHelpers& jit) { + jumpToSlowPath.linkTo(*labels[1], &jit); + if (jumpToSuccess.isSet()) + jumpToSuccess.linkTo(*labels[0], &jit); + }); + }); + + m_out.appendTo(continuation, lastNext); + return patchpoint; } void storeStructure(LValue object, Structure* structure) @@ -7581,7 +8753,7 @@ LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath) { - LValue result = allocateCell(allocator, slowPath); + LValue result = allocateHeapCell(allocator, slowPath); storeStructure(result, structure); return result; } @@ -7598,7 +8770,7 @@ LValue allocateObject( size_t size, Structure* structure, LValue butterfly, LBasicBlock slowPath) { - MarkedAllocator* allocator = &vm().heap.allocatorForObjectOfType(size); + MarkedAllocator* allocator = vm().heap.allocatorForObjectOfType(size); return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath); } @@ -7609,46 +8781,60 @@ ClassType::allocationSize(0), structure, butterfly, slowPath); } - template - LValue allocateVariableSizedObject( - LValue size, Structure* structure, LValue butterfly, LBasicBlock slowPath) + LValue allocatorForSize(LValue subspace, LValue size, LBasicBlock slowPath) { - static_assert(!(MarkedSpace::preciseStep & (MarkedSpace::preciseStep - 1)), "MarkedSpace::preciseStep must be a power of two."); - static_assert(!(MarkedSpace::impreciseStep & (MarkedSpace::impreciseStep - 1)), "MarkedSpace::impreciseStep must be a power of two."); - - LValue subspace = m_out.constIntPtr(&vm().heap.subspaceForObjectOfType()); + static_assert(!(MarkedSpace::sizeStep & (MarkedSpace::sizeStep - 1)), "MarkedSpace::sizeStep must be a power of two."); + + // Try to do some constant-folding here. + if (subspace->hasIntPtr() && size->hasIntPtr()) { + MarkedSpace::Subspace* actualSubspace = bitwise_cast(subspace->asIntPtr()); + size_t actualSize = size->asIntPtr(); + + MarkedAllocator* actualAllocator = MarkedSpace::allocatorFor(*actualSubspace, actualSize); + if (!actualAllocator) { + LBasicBlock continuation = m_out.newBlock(); + LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation); + m_out.jump(slowPath); + m_out.appendTo(continuation, lastNext); + return m_out.intPtrZero; + } + + return m_out.constIntPtr(actualAllocator); + } + + unsigned stepShift = getLSBSet(MarkedSpace::sizeStep); - LBasicBlock smallCaseBlock = m_out.newBlock(); - LBasicBlock largeOrOversizeCaseBlock = m_out.newBlock(); - LBasicBlock largeCaseBlock = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); - LValue uproundedSize = m_out.add(size, m_out.constInt32(MarkedSpace::preciseStep - 1)); - LValue isSmall = m_out.below(uproundedSize, m_out.constInt32(MarkedSpace::preciseCutoff)); - m_out.branch(isSmall, unsure(smallCaseBlock), unsure(largeOrOversizeCaseBlock)); + LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation); - LBasicBlock lastNext = m_out.appendTo(smallCaseBlock, largeOrOversizeCaseBlock); - TypedPointer address = m_out.baseIndex( - m_heaps.MarkedSpace_Subspace_preciseAllocators, subspace, - m_out.zeroExtPtr(m_out.lShr(uproundedSize, m_out.constInt32(getLSBSet(MarkedSpace::preciseStep))))); - ValueFromBlock smallAllocator = m_out.anchor(address.value()); - m_out.jump(continuation); + LValue sizeClassIndex = m_out.lShr( + m_out.add(size, m_out.constIntPtr(MarkedSpace::sizeStep - 1)), + m_out.constInt32(stepShift)); - m_out.appendTo(largeOrOversizeCaseBlock, largeCaseBlock); m_out.branch( - m_out.below(uproundedSize, m_out.constInt32(MarkedSpace::impreciseCutoff)), - usually(largeCaseBlock), rarely(slowPath)); - - m_out.appendTo(largeCaseBlock, continuation); - address = m_out.baseIndex( - m_heaps.MarkedSpace_Subspace_impreciseAllocators, subspace, - m_out.zeroExtPtr(m_out.lShr(uproundedSize, m_out.constInt32(getLSBSet(MarkedSpace::impreciseStep))))); - ValueFromBlock largeAllocator = m_out.anchor(address.value()); - m_out.jump(continuation); + m_out.above(sizeClassIndex, m_out.constIntPtr(MarkedSpace::largeCutoff >> stepShift)), + rarely(slowPath), usually(continuation)); m_out.appendTo(continuation, lastNext); - LValue allocator = m_out.phi(m_out.intPtr, smallAllocator, largeAllocator); + return m_out.loadPtr( + m_out.baseIndex( + m_heaps.MarkedSpace_Subspace_allocatorForSizeStep, + subspace, m_out.sub(sizeClassIndex, m_out.intPtrOne))); + } + + LValue allocatorForSize(MarkedSpace::Subspace& subspace, LValue size, LBasicBlock slowPath) + { + return allocatorForSize(m_out.constIntPtr(&subspace), size, slowPath); + } + + template + LValue allocateVariableSizedObject( + LValue size, Structure* structure, LValue butterfly, LBasicBlock slowPath) + { + LValue allocator = allocatorForSize( + vm().heap.subspaceForObjectOfType(), size, slowPath); return allocateObject(allocator, structure, butterfly, slowPath); } @@ -7681,7 +8867,11 @@ LValue allocateObject(Structure* structure) { size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity()); - MarkedAllocator* allocator = &vm().heap.allocatorForObjectWithoutDestructor(allocationSize); + MarkedAllocator* allocator = vm().heap.allocatorForObjectWithoutDestructor(allocationSize); + + // FIXME: If the allocator is null, we could simply emit a normal C call to the allocator + // instead of putting it on the slow path. + // https://bugs.webkit.org/show_bug.cgi?id=161062 LBasicBlock slowPath = m_out.newBlock(); LBasicBlock continuation = m_out.newBlock(); @@ -7705,7 +8895,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.intPtr, fastResult, slowResult); + return m_out.phi(pointerType(), fastResult, slowResult); } struct ArrayValues { @@ -7724,73 +8914,151 @@ LValue array; LValue butterfly; }; - ArrayValues allocateJSArray( - Structure* structure, unsigned numElements, LBasicBlock slowPath) + + ArrayValues allocateJSArray(LValue publicLength, Structure* structure, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true) { + JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic); + IndexingType indexingType = structure->indexingType(); ASSERT( - hasUndecided(structure->indexingType()) - || hasInt32(structure->indexingType()) - || hasDouble(structure->indexingType()) - || hasContiguous(structure->indexingType())); - - unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements); + hasUndecided(indexingType) + || hasInt32(indexingType) + || hasDouble(indexingType) + || hasContiguous(indexingType)); + + LBasicBlock fastCase = m_out.newBlock(); + LBasicBlock largeCase = m_out.newBlock(); + LBasicBlock failCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + LBasicBlock slowCase = m_out.newBlock(); - LValue endOfStorage = allocateBasicStorageAndGetEnd( - m_out.constIntPtr(sizeof(JSValue) * vectorLength + sizeof(IndexingHeader)), - slowPath); + LBasicBlock lastNext = m_out.insertNewBlocksBefore(fastCase); - LValue butterfly = m_out.sub( - endOfStorage, m_out.constIntPtr(sizeof(JSValue) * vectorLength)); + ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero); - LValue object = allocateObject( - structure, butterfly, slowPath); + LValue predicate; + if (shouldLargeArraySizeCreateArrayStorage) + predicate = m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)); + else + predicate = m_out.booleanFalse; - m_out.store32(m_out.constInt32(numElements), butterfly, m_heaps.Butterfly_publicLength); - m_out.store32(m_out.constInt32(vectorLength), butterfly, m_heaps.Butterfly_vectorLength); + m_out.branch(predicate, rarely(largeCase), usually(fastCase)); - if (hasDouble(structure->indexingType())) { - for (unsigned i = numElements; i < vectorLength; ++i) { - m_out.store64( - m_out.constInt64(bitwise_cast(PNaN)), - butterfly, m_heaps.indexedDoubleProperties[i]); + m_out.appendTo(fastCase, largeCase); + + LValue vectorLength = nullptr; + if (publicLength->hasInt32()) { + unsigned publicLengthConst = static_cast(publicLength->asInt32()); + if (publicLengthConst <= MAX_STORAGE_VECTOR_LENGTH) { + vectorLength = m_out.constInt32( + Butterfly::optimalContiguousVectorLength( + structure->outOfLineCapacity(), publicLengthConst)); } } - return ArrayValues(object, butterfly); - } - - ArrayValues allocateJSArray(Structure* structure, unsigned numElements) - { - LBasicBlock slowPath = m_out.newBlock(); - LBasicBlock continuation = m_out.newBlock(); + if (!vectorLength) { + // We don't compute the optimal vector length for new Array(blah) where blah is not + // statically known, since the compute effort of doing it here is probably not worth it. + vectorLength = publicLength; + } + + LValue payloadSize = + m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3)); + + LValue butterflySize = m_out.add( + payloadSize, m_out.constIntPtr(sizeof(IndexingHeader))); + + LValue allocator = allocatorForSize( + vm().heap.subspaceForAuxiliaryData(), butterflySize, failCase); + LValue startOfStorage = allocateHeapCell(allocator, failCase); + + LValue butterfly = m_out.add(startOfStorage, m_out.constIntPtr(sizeof(IndexingHeader))); - LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath); + m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength); + m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength); + + initializeArrayElements( + indexingType, + shouldInitializeElements ? m_out.int32Zero : publicLength, vectorLength, + butterfly); - ArrayValues fastValues = allocateJSArray(structure, numElements, slowPath); - ValueFromBlock fastArray = m_out.anchor(fastValues.array); - ValueFromBlock fastButterfly = m_out.anchor(fastValues.butterfly); + ValueFromBlock haveButterfly = m_out.anchor(butterfly); + LValue object = allocateObject(structure, butterfly, failCase); + + ValueFromBlock fastResult = m_out.anchor(object); + ValueFromBlock fastButterfly = m_out.anchor(butterfly); m_out.jump(continuation); - m_out.appendTo(slowPath, continuation); + m_out.appendTo(largeCase, failCase); + ValueFromBlock largeStructure = m_out.anchor( + m_out.constIntPtr( + globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))); + m_out.jump(slowCase); + + m_out.appendTo(failCase, slowCase); + ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure)); + m_out.jump(slowCase); + + m_out.appendTo(slowCase, continuation); + LValue structureValue = m_out.phi(pointerType(), largeStructure, failStructure); + LValue butterflyValue = m_out.phi(pointerType(), noButterfly, haveButterfly); - LValue slowArrayValue = lazySlowPath( + LValue slowResultValue = lazySlowPath( [=] (const Vector& locations) -> RefPtr { return createLazyCallGenerator( operationNewArrayWithSize, locations[0].directGPR(), - CCallHelpers::TrustedImmPtr(structure), CCallHelpers::TrustedImm32(numElements)); - }); - ValueFromBlock slowArray = m_out.anchor(slowArrayValue); + locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR()); + }, + structureValue, publicLength, butterflyValue); + ValueFromBlock slowResult = m_out.anchor(slowResultValue); ValueFromBlock slowButterfly = m_out.anchor( - m_out.loadPtr(slowArrayValue, m_heaps.JSObject_butterfly)); - + m_out.loadPtr(slowResultValue, m_heaps.JSObject_butterfly)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return ArrayValues( - m_out.phi(m_out.intPtr, fastArray, slowArray), - m_out.phi(m_out.intPtr, fastButterfly, slowButterfly)); + m_out.phi(pointerType(), fastResult, slowResult), + m_out.phi(pointerType(), fastButterfly, slowButterfly)); + } + + ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, Structure* structure) + { + bool shouldInitializeElements = false; + bool shouldLargeArraySizeCreateArrayStorage = false; + return allocateJSArray( + publicLength, structure, shouldInitializeElements, + shouldLargeArraySizeCreateArrayStorage); + } + + LValue ensureShadowChickenPacket() + { + LBasicBlock slowCase = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + TypedPointer addressOfLogCursor = m_out.absolute(vm().shadowChicken().addressOfLogCursor()); + LValue logCursor = m_out.loadPtr(addressOfLogCursor); + + ValueFromBlock fastResult = m_out.anchor(logCursor); + + m_out.branch( + m_out.below(logCursor, m_out.constIntPtr(vm().shadowChicken().logEnd())), + usually(continuation), rarely(slowCase)); + + LBasicBlock lastNext = m_out.appendTo(slowCase, continuation); + + vmCall(Void, m_out.operation(operationProcessShadowChickenLog), m_callFrame); + + ValueFromBlock slowResult = m_out.anchor(m_out.loadPtr(addressOfLogCursor)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + LValue result = m_out.phi(pointerType(), fastResult, slowResult); + + m_out.storePtr( + m_out.add(result, m_out.constIntPtr(sizeof(ShadowChicken::Packet))), + addressOfLogCursor); + + return result; } LValue boolify(Edge edge) @@ -7933,7 +9201,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.boolean, results); + return m_out.phi(Int32, results); } default: DFG_CRASH(m_graph, m_node, "Bad use kind"); @@ -8028,7 +9296,7 @@ m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.boolean, results); + return m_out.phi(Int32, results); } template @@ -8064,7 +9332,7 @@ LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase); vmCall( - m_out.voidType, m_out.operation(slowPathFunction), + Void, m_out.operation(slowPathFunction), m_callFrame, base, index, value); m_out.jump(continuation); @@ -8083,16 +9351,16 @@ void buildSwitch(SwitchData* data, LType type, LValue switchValue) { - ASSERT(type == m_out.intPtr || type == m_out.int32); + ASSERT(type == pointerType() || type == Int32); Vector cases; for (unsigned i = 0; i < data->cases.size(); ++i) { SwitchCase newCase; - if (type == m_out.intPtr) { + if (type == pointerType()) { newCase = SwitchCase(m_out.constIntPtr(data->cases[i].value.switchLookupValue(data->kind)), lowBlock(data->cases[i].target.block), Weight(data->cases[i].target.count)); - } else if (type == m_out.int32) { + } else if (type == Int32) { newCase = SwitchCase(m_out.constInt32(data->cases[i].value.switchLookupValue(data->kind)), lowBlock(data->cases[i].target.block), Weight(data->cases[i].target.count)); } else @@ -8340,7 +9608,7 @@ // https://bugs.webkit.org/show_bug.cgi?id=144369 LValue branchOffset = vmCall( - m_out.int32, m_out.operation(operationSwitchStringAndGetBranchOffset), + Int32, m_out.operation(operationSwitchStringAndGetBranchOffset), m_callFrame, m_out.constIntPtr(data->switchTableIndex), string); StringJumpTable& table = codeBlock()->stringSwitchJumpTable(data->switchTableIndex); @@ -8565,11 +9833,11 @@ m_out.jump(continuation); m_out.appendTo(slowPath, continuation); - results.append(m_out.anchor(m_out.call(m_out.int32, m_out.operation(toInt32), doubleValue))); + results.append(m_out.anchor(m_out.call(Int32, m_out.operation(operationToInt32), doubleValue))); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.int32, results); + return m_out.phi(Int32, results); } LValue doubleToInt32(LValue doubleValue) @@ -8594,11 +9862,11 @@ LBasicBlock lastNext = m_out.appendTo(slowPath, continuation); ValueFromBlock slowResult = m_out.anchor( - m_out.call(m_out.int32, m_out.operation(toInt32), doubleValue)); + m_out.call(Int32, m_out.operation(operationToInt32), doubleValue)); m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.int32, fastResult, slowResult); + return m_out.phi(Int32, fastResult, slowResult); } // This is a mechanism for creating a code generator that fills in a gap in the code using our @@ -8830,13 +10098,13 @@ if (isValid(value)) { LValue boxedResult = value.value(); FTL_TYPE_CHECK( - jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult)); + jsValueValue(boxedResult), edge, SpecInt32Only, isNotInt32(boxedResult)); LValue result = unboxInt32(boxedResult); setInt32(edge.node(), result); return result; } - DFG_ASSERT(m_graph, m_node, !(provenType(edge) & SpecInt32)); + DFG_ASSERT(m_graph, m_node, !(provenType(edge) & SpecInt32Only)); terminate(Uncountable); return m_out.int32Zero; } @@ -8950,6 +10218,27 @@ speculateObject(edge, result); return result; } + + LValue lowRegExpObject(Edge edge) + { + LValue result = lowCell(edge); + speculateRegExpObject(edge, result); + return result; + } + + LValue lowMapObject(Edge edge) + { + LValue result = lowCell(edge); + speculateMapObject(edge, result); + return result; + } + + LValue lowSetObject(Edge edge) + { + LValue result = lowCell(edge); + speculateSetObject(edge, result); + return result; + } LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) { @@ -8978,7 +10267,7 @@ speculateSymbol(edge, result); return result; } - + LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) { ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse); @@ -9073,12 +10362,23 @@ setStorage(edge.node(), result); return result; } + + LValue lowMapBucket(Edge edge) + { + LoweredNodeValue value = m_mapBucketValues.get(edge.node()); + if (isValid(value)) + return value.value(); + + LValue result = lowCell(edge); + setStorage(edge.node(), result); + return result; + } LValue strictInt52ToInt32(Edge edge, LValue value) { LValue result = m_out.castToInt32(value); FTL_TYPE_CHECK( - noValue(), edge, SpecInt32, + noValue(), edge, SpecInt32Only, m_out.notEqual(m_out.signExt32To64(result), value)); setInt32(edge.node(), result); return result; @@ -9113,7 +10413,7 @@ m_out.jump(continuation); m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.int64, results); + return m_out.phi(Int64, results); } LValue strictInt52ToInt52(LValue value) @@ -9128,13 +10428,13 @@ LValue isInt32(LValue jsValue, SpeculatedType type = SpecFullTop) { - if (LValue proven = isProvenValue(type, SpecInt32)) + if (LValue proven = isProvenValue(type, SpecInt32Only)) return proven; return m_out.aboveOrEqual(jsValue, m_tagTypeNumber); } LValue isNotInt32(LValue jsValue, SpeculatedType type = SpecFullTop) { - if (LValue proven = isProvenValue(type, ~SpecInt32)) + if (LValue proven = isProvenValue(type, ~SpecInt32Only)) return proven; return m_out.below(jsValue, m_tagTypeNumber); } @@ -9144,7 +10444,7 @@ } LValue boxInt32(LValue value) { - return m_out.add(m_out.zeroExt(value, m_out.int64), m_tagTypeNumber); + return m_out.add(m_out.zeroExt(value, Int64), m_tagTypeNumber); } LValue isCellOrMisc(LValue jsValue, SpeculatedType type = SpecFullTop) @@ -9159,14 +10459,14 @@ return proven; return m_out.testNonZero64(jsValue, m_tagTypeNumber); } - + LValue unboxDouble(LValue jsValue) { - return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType); + return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), Double); } LValue boxDouble(LValue doubleValue) { - return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber); + return m_out.sub(m_out.bitCast(doubleValue, Int64), m_tagTypeNumber); } LValue jsValueToStrictInt52(Edge edge, LValue boxedValue) @@ -9176,9 +10476,9 @@ LBasicBlock continuation = m_out.newBlock(); LValue isNotInt32; - if (!m_interpreter.needsTypeCheck(edge, SpecInt32)) + if (!m_interpreter.needsTypeCheck(edge, SpecInt32Only)) isNotInt32 = m_out.booleanFalse; - else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32)) + else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32Only)) isNotInt32 = m_out.booleanTrue; else isNotInt32 = this->isNotInt32(boxedValue); @@ -9193,9 +10493,9 @@ m_out.appendTo(doubleCase, continuation); LValue possibleResult = m_out.call( - m_out.int64, m_out.operation(operationConvertBoxedDoubleToInt52), boxedValue); + Int64, m_out.operation(operationConvertBoxedDoubleToInt52), boxedValue); FTL_TYPE_CHECK( - jsValueValue(boxedValue), edge, SpecInt32 | SpecInt52AsDouble, + jsValueValue(boxedValue), edge, SpecInt32Only | SpecAnyIntAsDouble, m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52))); ValueFromBlock doubleToInt52 = m_out.anchor(possibleResult); @@ -9203,15 +10503,15 @@ m_out.appendTo(continuation, lastNext); - return m_out.phi(m_out.int64, intToInt52, doubleToInt52); + return m_out.phi(Int64, intToInt52, doubleToInt52); } LValue doubleToStrictInt52(Edge edge, LValue value) { LValue possibleResult = m_out.call( - m_out.int64, m_out.operation(operationConvertDoubleToInt52), value); + Int64, m_out.operation(operationConvertDoubleToInt52), value); FTL_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow, - doubleValue(value), edge, SpecInt52AsDouble, + doubleValue(value), edge, SpecAnyIntAsDouble, m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52))); return possibleResult; @@ -9231,7 +10531,7 @@ LBasicBlock lastNext = m_out.appendTo(valueIsZero, continuation); - LValue doubleBitcastToInt64 = m_out.bitCast(value, m_out.int64); + LValue doubleBitcastToInt64 = m_out.bitCast(value, Int64); LValue signBitSet = m_out.lessThan(doubleBitcastToInt64, m_out.constInt64(0)); speculate(NegativeZero, FormattedValue(DataFormatDouble, value), m_node, signBitSet); @@ -9358,8 +10658,8 @@ case KnownCellUse: ASSERT(!m_interpreter.needsTypeCheck(edge)); break; - case MachineIntUse: - speculateMachineInt(edge); + case AnyIntUse: + speculateAnyInt(edge); break; case ObjectUse: speculateObject(edge); @@ -9376,6 +10676,12 @@ case RegExpObjectUse: speculateRegExpObject(edge); break; + case MapObjectUse: + speculateMapObject(edge); + break; + case SetObjectUse: + speculateSetObject(edge); + break; case StringUse: speculateString(edge); break; @@ -9403,8 +10709,8 @@ case DoubleRepRealUse: speculateDoubleRepReal(edge); break; - case DoubleRepMachineIntUse: - speculateDoubleRepMachineInt(edge); + case DoubleRepAnyIntUse: + speculateDoubleRepAnyInt(edge); break; case BooleanUse: speculateBoolean(edge); @@ -9457,13 +10763,34 @@ m_out.appendTo(continuation, lastNext); } - void speculateMachineInt(Edge edge) + void speculateAnyInt(Edge edge) { if (!m_interpreter.needsTypeCheck(edge)) return; jsValueToStrictInt52(edge, lowJSValue(edge, ManualOperandSpeculation)); } + + LValue isArray(LValue cell, SpeculatedType type = SpecFullTop) + { + if (LValue proven = isProvenValue(type & SpecCell, SpecArray)) + return proven; + return m_out.equal( + m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType), + m_out.constInt32(ArrayType)); + } + + LValue isTypedArrayView(LValue cell, SpeculatedType type = SpecFullTop) + { + if (LValue proven = isProvenValue(type & SpecCell, SpecTypedArrayView)) + return proven; + LValue jsType = m_out.sub( + m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType), + m_out.constInt32(Int8ArrayType)); + return m_out.belowOrEqual( + jsType, + m_out.constInt32(Float64ArrayType - Int8ArrayType)); + } LValue isObject(LValue cell, SpeculatedType type = SpecFullTop) { @@ -9509,6 +10836,15 @@ m_out.load32(cell, m_heaps.JSCell_structureID), m_out.constInt32(vm().symbolStructure->id())); } + + LValue isSymbol(LValue cell, SpeculatedType type = SpecFullTop) + { + if (LValue proven = isProvenValue(type & SpecCell, SpecSymbol)) + return proven; + return m_out.equal( + m_out.load32(cell, m_heaps.JSCell_structureID), + m_out.constInt32(vm().symbolStructure->id())); + } LValue isArrayType(LValue cell, ArrayMode arrayMode) { @@ -9581,7 +10917,16 @@ m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoFlags), m_out.constInt32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData)); } - + + LValue isRegExpObject(LValue cell, SpeculatedType type = SpecFullTop) + { + if (LValue proven = isProvenValue(type & SpecCell, SpecRegExpObject)) + return proven; + return m_out.equal( + m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType), + m_out.constInt32(RegExpObjectType)); + } + LValue isType(LValue cell, JSType type) { return m_out.equal( @@ -9665,6 +11010,28 @@ { speculateRegExpObject(edge, lowCell(edge)); } + + void speculateMapObject(Edge edge, LValue cell) + { + FTL_TYPE_CHECK( + jsValueValue(cell), edge, SpecMapObject, isNotType(cell, JSMapType)); + } + + void speculateMapObject(Edge edge) + { + speculateMapObject(edge, lowCell(edge)); + } + + void speculateSetObject(Edge edge, LValue cell) + { + FTL_TYPE_CHECK( + jsValueValue(cell), edge, SpecSetObject, isNotType(cell, JSSetType)); + } + + void speculateSetObject(Edge edge) + { + speculateSetObject(edge, lowCell(edge)); + } void speculateString(Edge edge, LValue cell) { @@ -9837,7 +11204,7 @@ m_out.doubleNotEqualOrUnordered(value, value)); } - void speculateDoubleRepMachineInt(Edge edge) + void speculateDoubleRepAnyInt(Edge edge) { if (!m_interpreter.needsTypeCheck(edge)) return; @@ -9899,7 +11266,24 @@ LValue value = lowJSValue(edge, ManualOperandSpeculation); typeCheck(jsValueValue(value), edge, SpecMisc, isNotMisc(value)); } - + + void speculateTypedArrayIsNotNeutered(LValue base) + { + LBasicBlock isWasteful = m_out.newBlock(); + LBasicBlock continuation = m_out.newBlock(); + + LValue mode = m_out.load32(base, m_heaps.JSArrayBufferView_mode); + m_out.branch(m_out.equal(mode, m_out.constInt32(WastefulTypedArray)), + unsure(isWasteful), unsure(continuation)); + + LBasicBlock lastNext = m_out.appendTo(isWasteful, continuation); + LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_vector); + speculate(Uncountable, jsValueValue(vector), m_node, m_out.isZero64(vector)); + m_out.jump(continuation); + + m_out.appendTo(continuation, lastNext); + } + bool masqueradesAsUndefinedWatchpointIsStillValid() { return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->origin.semantic); @@ -9992,7 +11376,7 @@ CallSiteIndex callSiteIndex = m_ftlState.jitCode->common.addCodeOrigin(codeOrigin); m_out.store32( m_out.constInt32(callSiteIndex.bits()), - tagFor(JSStack::ArgumentCount)); + tagFor(CallFrameSlot::argumentCount)); } void callPreflight() @@ -10020,7 +11404,7 @@ void callCheck() { if (Options::useExceptionFuzz()) - m_out.call(m_out.voidType, m_out.operation(operationExceptionFuzz), m_callFrame); + m_out.call(Void, m_out.operation(operationExceptionFuzz), m_callFrame); LValue exception = m_out.load64(m_out.absolute(vm().addressOfException())); LValue hadException = m_out.notZero64(exception); @@ -10104,8 +11488,11 @@ } DFG_ASSERT(m_graph, m_node, origin.exitOK); - - if (doOSRExitFuzzing() && !isExceptionHandler) { + + if (!isExceptionHandler + && Options::useOSRExitFuzz() + && canUseOSRExitFuzzing(m_graph.baselineCodeBlockFor(m_node->origin.semantic)) + && doOSRExitFuzzing()) { LValue numberOfFuzzChecks = m_out.add( m_out.load32(m_out.absolute(&g_numberOfOSRExitFuzzChecks)), m_out.int32One); @@ -10187,10 +11574,11 @@ Availability availability = availabilityMap.m_locals[i]; - if (Options::validateFTLOSRExitLiveness()) { - DFG_ASSERT( - m_graph, m_node, - (!(availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitOrigin))) || m_graph.m_plan.mode == FTLForOSREntryMode); + if (Options::validateFTLOSRExitLiveness() + && m_graph.m_plan.mode != FTLForOSREntryMode) { + + if (availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitOrigin)) + DFG_CRASH(m_graph, m_node, toCString("Live bytecode local not available: operand = ", VirtualRegister(operand), ", availability = ", availability, ", origin = ", exitOrigin).data()); } ExitValue exitValue = exitValueForAvailability(arguments, map, availability); if (exitValue.hasIndexInStackmapLocations()) @@ -10361,17 +11749,6 @@ // Doubles and Int52 have been converted by ValueRep() DFG_CRASH(m_graph, m_node, toCString("Cannot find value for node: ", node).data()); } - - bool doesKill(Edge edge) - { - if (edge.doesNotKill()) - return false; - - if (edge->hasConstant()) - return false; - - return true; - } void addAvailableRecovery( Node* node, RecoveryOpcode opcode, LValue left, LValue right, DataFormat format) @@ -10423,6 +11800,10 @@ { m_storageValues.set(node, LoweredNodeValue(value, m_highBlock)); } + void setMapBucket(Node* node, LValue value) + { + m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock)); + } void setDouble(Node* node, LValue value) { m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock)); @@ -10456,6 +11837,10 @@ { setStorage(m_node, value); } + void setMapBucket(LValue value) + { + setMapBucket(m_node, value); + } void setDouble(LValue value) { setDouble(m_node, value); @@ -10586,17 +11971,26 @@ void crash() { - crash(m_highBlock->index, m_node->index()); + crash(m_highBlock, m_node); } - void crash(BlockIndex blockIndex, unsigned nodeIndex) + void crash(DFG::BasicBlock* block, Node* node) { + BlockIndex blockIndex = block->index; + unsigned nodeIndex = node ? node->index() : UINT_MAX; #if ASSERT_DISABLED - m_out.call(m_out.voidType, m_out.operation(ftlUnreachable)); - UNUSED_PARAM(blockIndex); - UNUSED_PARAM(nodeIndex); + m_out.patchpoint(Void)->setGenerator( + [=] (CCallHelpers& jit, const StackmapGenerationParams&) { + AllowMacroScratchRegisterUsage allowScratch(jit); + + jit.move(CCallHelpers::TrustedImm32(blockIndex), GPRInfo::regT0); + jit.move(CCallHelpers::TrustedImm32(nodeIndex), GPRInfo::regT1); + if (node) + jit.move(CCallHelpers::TrustedImm32(node->op()), GPRInfo::regT2); + jit.abortWithReason(FTLCrash); + }); #else m_out.call( - m_out.voidType, + Void, m_out.constIntPtr(ftlUnreachable), m_out.constIntPtr(codeBlock()), m_out.constInt32(blockIndex), m_out.constInt32(nodeIndex)); @@ -10630,6 +12024,7 @@ HashMap m_jsValueValues; HashMap m_booleanValues; HashMap m_storageValues; + HashMap m_mapBucketValues; HashMap m_doubleValues; // This is a bit of a hack. It prevents B3 from having to do CSE on loading of arguments. diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOperations.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOperations.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOperations.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOperations.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -41,19 +41,6 @@ using namespace JSC::DFG; -extern "C" JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure) -{ - VM& vm = exec->vm(); - NativeCallFrameTracer tracer(&vm, exec); - - Butterfly* butterfly = Butterfly::create( - vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0); - - JSObject* result = JSFinalObject::create(exec, structure, butterfly); - result->butterfly(); // Ensure that the butterfly is in to-space. - return result; -} - extern "C" void JIT_OPERATION operationPopulateObjectInOSR( ExecState* exec, ExitTimeObjectMaterialization* materialization, EncodedJSValue* encodedValue, EncodedJSValue* values) @@ -328,7 +315,7 @@ case PhantomClonedArguments: { unsigned length = argumentCount - 1; ClonedArguments* result = ClonedArguments::createEmpty( - vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee); + vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length); for (unsigned i = materialization->properties().size(); i--;) { const ExitPropertyValue& property = materialization->properties()[i]; @@ -338,10 +325,9 @@ unsigned index = property.location().info(); if (index >= length) continue; - result->putDirectIndex(exec, index, JSValue::decode(values[i])); + result->initializeIndex(vm, index, JSValue::decode(values[i])); } - result->putDirect(vm, vm.propertyNames->length, jsNumber(length)); return result; } default: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOperations.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOperations.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOperations.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOperations.h 2016-11-03 07:04:20.000000000 +0000 @@ -37,8 +37,6 @@ extern "C" { -JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState*, Structure*) WTF_INTERNAL; - JSCell* JIT_OPERATION operationMaterializeObjectInOSR( ExecState*, ExitTimeObjectMaterialization*, EncodedJSValue*) WTF_INTERNAL; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSREntry.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSREntry.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSREntry.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSREntry.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,9 +30,9 @@ #include "CodeBlock.h" #include "DFGJITCode.h" #include "FTLForOSREntryJITCode.h" -#include "JSStackInlines.h" #include "OperandsInlines.h" #include "JSCInlines.h" +#include "VMInlines.h" #if ENABLE(FTL_JIT) @@ -92,7 +92,7 @@ scratch[local] = JSValue::encode(values.local(local)); int stackFrameSize = entryCode->common.requiredRegisterCountForExecutionAndExit(); - if (!vm.interpreter->stack().ensureCapacityFor(&exec->registers()[virtualRegisterForLocal(stackFrameSize - 1).offset()])) { + if (UNLIKELY(!vm.ensureStackCapacityFor(&exec->registers()[virtualRegisterForLocal(stackFrameSize - 1).offset()]))) { if (Options::verboseOSR()) dataLog(" OSR failed because stack growth failed.\n"); return 0; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -186,7 +186,7 @@ // The first thing we need to do is restablish our frame in the case of an exception. if (exit.isGenericUnwindHandler()) { RELEASE_ASSERT(vm->callFrameForCatch); // The first time we hit this exit, like at all other times, this field should be non-null. - jit.restoreCalleeSavesFromVMCalleeSavesBuffer(); + jit.restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(); jit.loadPtr(vm->addressOfCallFrameForCatch(), MacroAssembler::framePointerRegister); jit.addPtr(CCallHelpers::TrustedImm32(codeBlock->stackPointerOffset() * sizeof(Register)), MacroAssembler::framePointerRegister, CCallHelpers::stackPointerRegister); @@ -284,8 +284,8 @@ } } - if (!!exit.m_descriptor->m_valueProfile) - jit.store64(GPRInfo::regT0, exit.m_descriptor->m_valueProfile.getSpecFailBucket(0)); + if (exit.m_descriptor->m_valueProfile) + exit.m_descriptor->m_valueProfile.emitReportValue(jit, JSValueRegs(GPRInfo::regT0)); } // Materialize all objects. Don't materialize an object until all @@ -394,7 +394,7 @@ jit.store64(GPRInfo::regT0, unwindScratch + i); } - jit.load32(CCallHelpers::payloadFor(JSStack::ArgumentCount), GPRInfo::regT2); + jit.load32(CCallHelpers::payloadFor(CallFrameSlot::argumentCount), GPRInfo::regT2); // Let's say that the FTL function had failed its arity check. In that case, the stack will // contain some extra stuff. @@ -441,8 +441,10 @@ RegisterAtOffsetList* baselineCalleeSaves = baselineCodeBlock->calleeSaveRegisters(); RegisterAtOffsetList* vmCalleeSaves = vm->getAllCalleeSaveRegisterOffsets(); RegisterSet vmCalleeSavesToSkip = RegisterSet::stackRegisters(); - if (exit.isExceptionHandler()) - jit.move(CCallHelpers::TrustedImmPtr(vm->calleeSaveRegistersBuffer), GPRInfo::regT1); + if (exit.isExceptionHandler()) { + jit.loadPtr(&vm->topVMEntryFrame, GPRInfo::regT1); + jit.addPtr(CCallHelpers::TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), GPRInfo::regT1); + } for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) { if (!allFTLCalleeSaves.get(reg)) { @@ -532,8 +534,6 @@ extern "C" void* compileFTLOSRExit(ExecState* exec, unsigned exitID) { - SamplingRegion samplingRegion("FTL OSR Exit Compilation"); - if (shouldDumpDisassembly() || Options::verboseOSR() || Options::verboseFTLOSRExit()) dataLog("Compiling OSR exit with exitID = ", exitID, "\n"); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSRExit.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSRExit.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSRExit.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSRExit.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -92,7 +92,7 @@ { unsigned index = state.jitCode->osrExit.size(); OSRExit& exit = state.jitCode->osrExit.alloc( - this, exitKind, nodeOrigin.forExit, nodeOrigin.semantic); + this, exitKind, nodeOrigin.forExit, nodeOrigin.semantic, nodeOrigin.wasHoisted); RefPtr handle = adoptRef(new OSRExitHandle(index, exit)); for (unsigned i = offset; i < params.size(); ++i) exit.m_valueReps.append(params[i]); @@ -101,9 +101,9 @@ } OSRExit::OSRExit( - OSRExitDescriptor* descriptor, - ExitKind exitKind, CodeOrigin codeOrigin, CodeOrigin codeOriginForExitProfile) - : OSRExitBase(exitKind, codeOrigin, codeOriginForExitProfile) + OSRExitDescriptor* descriptor, ExitKind exitKind, CodeOrigin codeOrigin, + CodeOrigin codeOriginForExitProfile, bool wasHoisted) + : OSRExitBase(exitKind, codeOrigin, codeOriginForExitProfile, wasHoisted) , m_descriptor(descriptor) { } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSRExit.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSRExit.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOSRExit.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOSRExit.h 2016-11-03 07:04:20.000000000 +0000 @@ -117,10 +117,7 @@ }; struct OSRExit : public DFG::OSRExitBase { - OSRExit( - OSRExitDescriptor*, ExitKind, - CodeOrigin, CodeOrigin codeOriginForExitProfile - ); + OSRExit(OSRExitDescriptor*, ExitKind, CodeOrigin, CodeOrigin codeOriginForExitProfile, bool wasHoisted); OSRExitDescriptor* m_descriptor; MacroAssemblerCodeRef m_code; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOutput.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOutput.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOutput.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOutput.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -28,8 +28,19 @@ #if ENABLE(FTL_JIT) +#include "B3ArgumentRegValue.h" +#include "B3BasicBlockInlines.h" +#include "B3CCallValue.h" +#include "B3Const32Value.h" +#include "B3ConstPtrValue.h" #include "B3MathExtras.h" +#include "B3MemoryValue.h" +#include "B3SlotBaseValue.h" #include "B3StackmapGenerationParams.h" +#include "B3SwitchValue.h" +#include "B3UpsilonValue.h" +#include "B3ValueInlines.h" +#include "SuperSampler.h" namespace JSC { namespace FTL { @@ -77,16 +88,157 @@ m_block = block; } +LValue Output::framePointer() +{ + return m_block->appendNew(m_proc, B3::FramePointer, origin()); +} + SlotBaseValue* Output::lockedStackSlot(size_t bytes) { return m_block->appendNew(m_proc, origin(), m_proc.addStackSlot(bytes)); } +LValue Output::constBool(bool value) +{ + if (value) + return booleanTrue; + return booleanFalse; +} + +LValue Output::constInt32(int32_t value) +{ + return m_block->appendNew(m_proc, origin(), value); +} + +LValue Output::constInt64(int64_t value) +{ + return m_block->appendNew(m_proc, origin(), value); +} + +LValue Output::constDouble(double value) +{ + return m_block->appendNew(m_proc, origin(), value); +} + +LValue Output::phi(LType type) +{ + return m_block->appendNew(m_proc, B3::Phi, type, origin()); +} + +LValue Output::add(LValue left, LValue right) +{ + if (Value* result = left->addConstant(m_proc, right)) { + m_block->append(result); + return result; + } + return m_block->appendNew(m_proc, B3::Add, origin(), left, right); +} + +LValue Output::sub(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Sub, origin(), left, right); +} + +LValue Output::mul(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Mul, origin(), left, right); +} + +LValue Output::div(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Div, origin(), left, right); +} + +LValue Output::chillDiv(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::ChillDiv, origin(), left, right); +} + +LValue Output::mod(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Mod, origin(), left, right); +} + +LValue Output::chillMod(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::ChillMod, origin(), left, right); +} + LValue Output::neg(LValue value) { return m_block->appendNew(m_proc, B3::Neg, origin(), value); } +LValue Output::doubleAdd(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Add, origin(), left, right); +} + +LValue Output::doubleSub(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Sub, origin(), left, right); +} + +LValue Output::doubleMul(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Mul, origin(), left, right); +} + +LValue Output::doubleDiv(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Div, origin(), left, right); +} + +LValue Output::doubleMod(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Mod, origin(), left, right); +} + +LValue Output::bitAnd(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::BitAnd, origin(), left, right); +} + +LValue Output::bitOr(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::BitOr, origin(), left, right); +} + +LValue Output::bitXor(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::BitXor, origin(), left, right); +} + +LValue Output::shl(LValue left, LValue right) +{ + right = castToInt32(right); + if (Value* result = left->shlConstant(m_proc, right)) { + m_block->append(result); + return result; + } + return m_block->appendNew(m_proc, B3::Shl, origin(), left, right); +} + +LValue Output::aShr(LValue left, LValue right) +{ + right = castToInt32(right); + if (Value* result = left->sShrConstant(m_proc, right)) { + m_block->append(result); + return result; + } + return m_block->appendNew(m_proc, B3::SShr, origin(), left, right); +} + +LValue Output::lShr(LValue left, LValue right) +{ + right = castToInt32(right); + if (Value* result = left->zShrConstant(m_proc, right)) { + m_block->append(result); + return result; + } + return m_block->appendNew(m_proc, B3::ZShr, origin(), left, right); +} + LValue Output::bitNot(LValue value) { return m_block->appendNew(m_proc, B3::BitXor, origin(), @@ -99,11 +251,58 @@ return m_block->appendNew(m_proc, B3::Equal, origin(), value, int32Zero); } -LValue Output::load(TypedPointer pointer, LType type) +LValue Output::ctlz32(LValue operand) { - LValue load = m_block->appendNew(m_proc, Load, type, origin(), pointer.value()); - m_heaps->decorateMemory(pointer.heap(), load); - return load; + return m_block->appendNew(m_proc, B3::Clz, origin(), operand); +} + +LValue Output::doubleAbs(LValue value) +{ + return m_block->appendNew(m_proc, B3::Abs, origin(), value); +} + +LValue Output::doubleCeil(LValue operand) +{ + return m_block->appendNew(m_proc, B3::Ceil, origin(), operand); +} + +LValue Output::doubleFloor(LValue operand) +{ + return m_block->appendNew(m_proc, B3::Floor, origin(), operand); +} + +LValue Output::doubleTrunc(LValue value) +{ + if (MacroAssembler::supportsFloatingPointRounding()) { + PatchpointValue* result = patchpoint(Double); + result->append(value, ValueRep::SomeRegister); + result->setGenerator( + [] (CCallHelpers& jit, const StackmapGenerationParams& params) { + jit.roundTowardZeroDouble(params[1].fpr(), params[0].fpr()); + }); + result->effects = Effects::none(); + return result; + } + double (*truncDouble)(double) = trunc; + return callWithoutSideEffects(Double, truncDouble, value); +} + +LValue Output::doubleSin(LValue value) +{ + double (*sinDouble)(double) = sin; + return callWithoutSideEffects(B3::Double, sinDouble, value); +} + +LValue Output::doubleCos(LValue value) +{ + double (*cosDouble)(double) = cos; + return callWithoutSideEffects(B3::Double, cosDouble, value); +} + +LValue Output::doublePow(LValue xOperand, LValue yOperand) +{ + double (*powDouble)(double, double) = pow; + return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand); } LValue Output::doublePowi(LValue x, LValue y) @@ -116,6 +315,17 @@ return result.second; } +LValue Output::doubleSqrt(LValue value) +{ + return m_block->appendNew(m_proc, B3::Sqrt, origin(), value); +} + +LValue Output::doubleLog(LValue value) +{ + double (*logDouble)(double) = log; + return callWithoutSideEffects(B3::Double, logDouble, value); +} + bool Output::hasSensibleDoubleToInt() { return optimizeForX86(); @@ -145,11 +355,56 @@ return result; } +LValue Output::signExt32To64(LValue value) +{ + return m_block->appendNew(m_proc, B3::SExt32, origin(), value); +} + +LValue Output::zeroExt(LValue value, LType type) +{ + if (value->type() == type) + return value; + if (value->hasInt32()) + return m_block->appendIntConstant(m_proc, origin(), Int64, static_cast(static_cast(value->asInt32()))); + return m_block->appendNew(m_proc, B3::ZExt32, origin(), value); +} + +LValue Output::intToDouble(LValue value) +{ + return m_block->appendNew(m_proc, B3::IToD, origin(), value); +} + LValue Output::unsignedToDouble(LValue value) { return intToDouble(zeroExt(value, Int64)); } +LValue Output::castToInt32(LValue value) +{ + if (value->type() == Int32) + return value; + if (value->hasInt64()) + return constInt32(static_cast(value->asInt64())); + return m_block->appendNew(m_proc, B3::Trunc, origin(), value); +} + +LValue Output::doubleToFloat(LValue value) +{ + return m_block->appendNew(m_proc, B3::DoubleToFloat, origin(), value); +} + +LValue Output::floatToDouble(LValue value) +{ + return m_block->appendNew(m_proc, B3::FloatToDouble, origin(), value); +} + +LValue Output::load(TypedPointer pointer, LType type) +{ + LValue load = m_block->appendNew(m_proc, Load, type, origin(), pointer.value()); + m_heaps->decorateMemory(pointer.heap(), load); + return load; +} + LValue Output::load8SignExt32(TypedPointer pointer) { LValue load = m_block->appendNew(m_proc, Load8S, Int32, origin(), pointer.value()); @@ -222,9 +477,185 @@ return add(base, accumulatedOffset); } +LValue Output::equal(LValue left, LValue right) +{ + TriState result = left->equalConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::Equal, origin(), left, right); +} + +LValue Output::notEqual(LValue left, LValue right) +{ + TriState result = left->notEqualConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::NotEqual, origin(), left, right); +} + +LValue Output::above(LValue left, LValue right) +{ + TriState result = left->aboveConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::Above, origin(), left, right); +} + +LValue Output::aboveOrEqual(LValue left, LValue right) +{ + TriState result = left->aboveEqualConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::AboveEqual, origin(), left, right); +} + +LValue Output::below(LValue left, LValue right) +{ + TriState result = left->belowConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::Below, origin(), left, right); +} + +LValue Output::belowOrEqual(LValue left, LValue right) +{ + TriState result = left->belowEqualConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::BelowEqual, origin(), left, right); +} + +LValue Output::greaterThan(LValue left, LValue right) +{ + TriState result = left->greaterThanConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::GreaterThan, origin(), left, right); +} + +LValue Output::greaterThanOrEqual(LValue left, LValue right) +{ + TriState result = left->greaterEqualConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::GreaterEqual, origin(), left, right); +} + +LValue Output::lessThan(LValue left, LValue right) +{ + TriState result = left->lessThanConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::LessThan, origin(), left, right); +} + +LValue Output::lessThanOrEqual(LValue left, LValue right) +{ + TriState result = left->lessEqualConstant(right); + if (result != MixedTriState) + return constBool(result == TrueTriState); + return m_block->appendNew(m_proc, B3::LessEqual, origin(), left, right); +} + +LValue Output::doubleEqual(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::Equal, origin(), left, right); +} + +LValue Output::doubleEqualOrUnordered(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::EqualOrUnordered, origin(), left, right); +} + +LValue Output::doubleNotEqualOrUnordered(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::NotEqual, origin(), left, right); +} + +LValue Output::doubleLessThan(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::LessThan, origin(), left, right); +} + +LValue Output::doubleLessThanOrEqual(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::LessEqual, origin(), left, right); +} + +LValue Output::doubleGreaterThan(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::GreaterThan, origin(), left, right); +} + +LValue Output::doubleGreaterThanOrEqual(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::GreaterEqual, origin(), left, right); +} + +LValue Output::doubleNotEqualAndOrdered(LValue left, LValue right) +{ + return logicalNot(doubleEqualOrUnordered(left, right)); +} + +LValue Output::doubleLessThanOrUnordered(LValue left, LValue right) +{ + return logicalNot(doubleGreaterThanOrEqual(left, right)); +} + +LValue Output::doubleLessThanOrEqualOrUnordered(LValue left, LValue right) +{ + return logicalNot(doubleGreaterThan(left, right)); +} + +LValue Output::doubleGreaterThanOrUnordered(LValue left, LValue right) +{ + return logicalNot(doubleLessThanOrEqual(left, right)); +} + +LValue Output::doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) +{ + return logicalNot(doubleLessThan(left, right)); +} + +LValue Output::isZero32(LValue value) +{ + return m_block->appendNew(m_proc, B3::Equal, origin(), value, int32Zero); +} + +LValue Output::notZero32(LValue value) +{ + return m_block->appendNew(m_proc, B3::NotEqual, origin(), value, int32Zero); +} + +LValue Output::isZero64(LValue value) +{ + return m_block->appendNew(m_proc, B3::Equal, origin(), value, int64Zero); +} + +LValue Output::notZero64(LValue value) +{ + return m_block->appendNew(m_proc, B3::NotEqual, origin(), value, int64Zero); +} + +LValue Output::select(LValue value, LValue taken, LValue notTaken) +{ + if (value->hasInt32()) { + if (value->asInt32()) + return taken; + else + return notTaken; + } + return m_block->appendNew(m_proc, B3::Select, origin(), value, taken, notTaken); +} + +void Output::jump(LBasicBlock destination) +{ + m_block->appendNewControlValue(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination)); +} + void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight) { - m_block->appendNew( + m_block->appendNewControlValue( m_proc, B3::Branch, origin(), condition, FrequentedBlock(taken, takenWeight.frequencyClass()), FrequentedBlock(notTaken, notTakenWeight.frequencyClass())); @@ -242,6 +673,68 @@ check(condition, taken, taken.weight().inverse()); } +void Output::ret(LValue value) +{ + m_block->appendNewControlValue(m_proc, B3::Return, origin(), value); +} + +void Output::unreachable() +{ + m_block->appendNewControlValue(m_proc, B3::Oops, origin()); +} + +void Output::appendSuccessor(WeightedTarget target) +{ + m_block->appendSuccessor(target.frequentedBlock()); +} + +CheckValue* Output::speculate(LValue value) +{ + return m_block->appendNew(m_proc, B3::Check, origin(), value); +} + +CheckValue* Output::speculateAdd(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::CheckAdd, origin(), left, right); +} + +CheckValue* Output::speculateSub(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::CheckSub, origin(), left, right); +} + +CheckValue* Output::speculateMul(LValue left, LValue right) +{ + return m_block->appendNew(m_proc, B3::CheckMul, origin(), left, right); +} + +PatchpointValue* Output::patchpoint(LType type) +{ + return m_block->appendNew(m_proc, type, origin()); +} + +void Output::trap() +{ + m_block->appendNewControlValue(m_proc, B3::Oops, origin()); +} + +ValueFromBlock Output::anchor(LValue value) +{ + B3::UpsilonValue* upsilon = m_block->appendNew(m_proc, origin(), value); + return ValueFromBlock(upsilon, m_block); +} + +LValue Output::bitCast(LValue value, LType type) +{ + ASSERT_UNUSED(type, type == Int64 || type == Double); + return m_block->appendNew(m_proc, B3::BitwiseCast, origin(), value); +} + +LValue Output::fround(LValue doubleValue) +{ + return floatToDouble(doubleToFloat(doubleValue)); +} + LValue Output::load(TypedPointer pointer, LoadType type) { switch (type) { @@ -296,6 +789,29 @@ RELEASE_ASSERT_NOT_REACHED(); } +TypedPointer Output::absolute(void* address) +{ + return TypedPointer(m_heaps->absolute[address], constIntPtr(address)); +} + +void Output::incrementSuperSamplerCount() +{ + TypedPointer counter = absolute(bitwise_cast(&g_superSamplerCount)); + store32(add(load32(counter), int32One), counter); +} + +void Output::decrementSuperSamplerCount() +{ + TypedPointer counter = absolute(bitwise_cast(&g_superSamplerCount)); + store32(sub(load32(counter), int32One), counter); +} + +void Output::addIncomingToPhi(LValue phi, ValueFromBlock value) +{ + if (value) + value.value()->as()->setPhi(phi); +} + } } // namespace JSC::FTL #endif // ENABLE(FTL_JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOutput.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOutput.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLOutput.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLOutput.h 2016-11-03 07:04:20.000000000 +0000 @@ -30,19 +30,12 @@ #if ENABLE(FTL_JIT) -#include "B3ArgumentRegValue.h" #include "B3BasicBlockInlines.h" #include "B3CCallValue.h" #include "B3Compilation.h" -#include "B3Const32Value.h" -#include "B3ConstPtrValue.h" -#include "B3ControlValue.h" -#include "B3MemoryValue.h" +#include "B3FrequentedBlock.h" #include "B3Procedure.h" -#include "B3SlotBaseValue.h" #include "B3SwitchValue.h" -#include "B3UpsilonValue.h" -#include "B3ValueInlines.h" #include "FTLAbbreviatedTypes.h" #include "FTLAbstractHeapRepository.h" #include "FTLCommonValues.h" @@ -64,7 +57,13 @@ namespace JSC { -namespace DFG { struct Node; } +namespace DFG { +struct Node; +} // namespace DFG + +namespace B3 { +class SlotBaseValue; +} // namespace B3 namespace FTL { @@ -99,20 +98,30 @@ void setOrigin(DFG::Node* node) { m_origin = node; } B3::Origin origin() { return B3::Origin(m_origin); } - LValue framePointer() { return m_block->appendNew(m_proc, B3::FramePointer, origin()); } + LValue framePointer(); B3::SlotBaseValue* lockedStackSlot(size_t bytes); - LValue constBool(bool value) { return m_block->appendNew(m_proc, origin(), value); } - LValue constInt32(int32_t value) { return m_block->appendNew(m_proc, origin(), value); } + LValue constBool(bool value); + LValue constInt32(int32_t value); template - LValue constIntPtr(T* value) { return m_block->appendNew(m_proc, origin(), value); } + LValue constIntPtr(T* value) + { + if (sizeof(void*) == 8) + return constInt64(bitwise_cast(value)); + return constInt32(bitwise_cast(value)); + } template - LValue constIntPtr(T value) { return m_block->appendNew(m_proc, origin(), value); } - LValue constInt64(int64_t value) { return m_block->appendNew(m_proc, origin(), value); } - LValue constDouble(double value) { return m_block->appendNew(m_proc, origin(), value); } + LValue constIntPtr(T value) + { + if (sizeof(void*) == 8) + return constInt64(static_cast(value)); + return constInt32(static_cast(value)); + } + LValue constInt64(int64_t value); + LValue constDouble(double value); - LValue phi(LType type) { return m_block->appendNew(m_proc, B3::Phi, type, origin()); } + LValue phi(LType); template LValue phi(LType, ValueFromBlock, Params... theRest); template @@ -121,92 +130,61 @@ template void addIncomingToPhi(LValue phi, ValueFromBlock, Params... theRest); - LValue add(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Add, origin(), left, right); } - LValue sub(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Sub, origin(), left, right); } - LValue mul(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Mul, origin(), left, right); } - LValue div(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Div, origin(), left, right); } - LValue chillDiv(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::ChillDiv, origin(), left, right); } - LValue mod(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Mod, origin(), left, right); } - LValue chillMod(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::ChillMod, origin(), left, right); } + LValue add(LValue, LValue); + LValue sub(LValue, LValue); + LValue mul(LValue, LValue); + LValue div(LValue, LValue); + LValue chillDiv(LValue, LValue); + LValue mod(LValue, LValue); + LValue chillMod(LValue, LValue); LValue neg(LValue); - LValue doubleAdd(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Add, origin(), left, right); } - LValue doubleSub(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Sub, origin(), left, right); } - LValue doubleMul(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Mul, origin(), left, right); } - LValue doubleDiv(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Div, origin(), left, right); } - LValue doubleMod(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Mod, origin(), left, right); } + LValue doubleAdd(LValue, LValue); + LValue doubleSub(LValue, LValue); + LValue doubleMul(LValue, LValue); + LValue doubleDiv(LValue, LValue); + LValue doubleMod(LValue, LValue); LValue doubleNeg(LValue value) { return neg(value); } - LValue bitAnd(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::BitAnd, origin(), left, right); } - LValue bitOr(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::BitOr, origin(), left, right); } - LValue bitXor(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::BitXor, origin(), left, right); } - LValue shl(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Shl, origin(), left, castToInt32(right)); } - LValue aShr(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::SShr, origin(), left, castToInt32(right)); } - LValue lShr(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::ZShr, origin(), left, castToInt32(right)); } + LValue bitAnd(LValue, LValue); + LValue bitOr(LValue, LValue); + LValue bitXor(LValue, LValue); + LValue shl(LValue, LValue shiftAmount); + LValue aShr(LValue, LValue shiftAmount); + LValue lShr(LValue, LValue shiftAmount); LValue bitNot(LValue); LValue logicalNot(LValue); - LValue ctlz32(LValue operand) { return m_block->appendNew(m_proc, B3::Clz, origin(), operand); } - LValue addWithOverflow32(LValue left, LValue right) { CRASH(); } - LValue subWithOverflow32(LValue left, LValue right) { CRASH(); } - LValue mulWithOverflow32(LValue left, LValue right) { CRASH(); } - LValue addWithOverflow64(LValue left, LValue right) { CRASH(); } - LValue subWithOverflow64(LValue left, LValue right) { CRASH(); } - LValue mulWithOverflow64(LValue left, LValue right) { CRASH(); } - LValue doubleAbs(LValue value) { return m_block->appendNew(m_proc, B3::Abs, origin(), value); } - LValue doubleCeil(LValue operand) { return m_block->appendNew(m_proc, B3::Ceil, origin(), operand); } - LValue doubleFloor(LValue operand) { return m_block->appendNew(m_proc, B3::Floor, origin(), operand); } + LValue ctlz32(LValue); + LValue doubleAbs(LValue); + LValue doubleCeil(LValue); + LValue doubleFloor(LValue); + LValue doubleTrunc(LValue); - LValue doubleSin(LValue value) - { - double (*sinDouble)(double) = sin; - return callWithoutSideEffects(B3::Double, sinDouble, value); - } - LValue doubleCos(LValue value) - { - double (*cosDouble)(double) = cos; - return callWithoutSideEffects(B3::Double, cosDouble, value); - } + LValue doubleSin(LValue); + LValue doubleCos(LValue); - LValue doublePow(LValue xOperand, LValue yOperand) - { - double (*powDouble)(double, double) = pow; - return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand); - } + LValue doublePow(LValue base, LValue exponent); + LValue doublePowi(LValue base, LValue exponent); - LValue doublePowi(LValue xOperand, LValue yOperand); + LValue doubleSqrt(LValue); - LValue doubleSqrt(LValue value) { return m_block->appendNew(m_proc, B3::Sqrt, origin(), value); } - - LValue doubleLog(LValue value) - { - double (*logDouble)(double) = log; - return callWithoutSideEffects(B3::Double, logDouble, value); - } + LValue doubleLog(LValue); static bool hasSensibleDoubleToInt(); LValue doubleToInt(LValue); LValue doubleToUInt(LValue); - LValue signExt32To64(LValue value) { return m_block->appendNew(m_proc, B3::SExt32, origin(), value); } - LValue zeroExt(LValue value, LType type) - { - if (value->type() == type) - return value; - return m_block->appendNew(m_proc, B3::ZExt32, origin(), value); - } + LValue signExt32To64(LValue); + LValue zeroExt(LValue, LType); LValue zeroExtPtr(LValue value) { return zeroExt(value, B3::Int64); } - LValue intToDouble(LValue value) { return m_block->appendNew(m_proc, B3::IToD, origin(), value); } + LValue intToDouble(LValue); LValue unsignedToDouble(LValue); - LValue castToInt32(LValue value) - { - return value->type() == B3::Int32 ? value : - m_block->appendNew(m_proc, B3::Trunc, origin(), value); - } - LValue doubleToFloat(LValue value) { return m_block->appendNew(m_proc, B3::DoubleToFloat, origin(), value); } - LValue floatToDouble(LValue value) { return m_block->appendNew(m_proc, B3::FloatToDouble, origin(), value); } + LValue castToInt32(LValue); + LValue doubleToFloat(LValue); + LValue floatToDouble(LValue); LValue bitCast(LValue, LType); - LValue fround(LValue doubleValue); + LValue fround(LValue); LValue load(TypedPointer, LType); void store(LValue, TypedPointer); @@ -220,8 +198,8 @@ LValue loadPtr(TypedPointer pointer) { return load(pointer, B3::pointerType()); } LValue loadFloat(TypedPointer pointer) { return load(pointer, B3::Float); } LValue loadDouble(TypedPointer pointer) { return load(pointer, B3::Double); } - void store32As8(LValue value, TypedPointer pointer); - void store32As16(LValue value, TypedPointer pointer); + void store32As8(LValue, TypedPointer); + void store32As16(LValue, TypedPointer); void store32(LValue value, TypedPointer pointer) { ASSERT(value->type() == B3::Int32); @@ -306,10 +284,7 @@ return heap.baseIndex(*this, base, index, indexAsConstant, offset); } - TypedPointer absolute(void* address) - { - return TypedPointer(m_heaps->absolute[address], constIntPtr(address)); - } + TypedPointer absolute(void* address); LValue load8SignExt32(LValue base, const AbstractHeap& field) { return load8SignExt32(address(base, field)); } LValue load8ZeroExt32(LValue base, const AbstractHeap& field) { return load8ZeroExt32(address(base, field)); } @@ -332,34 +307,34 @@ LValue load32NonNegative(TypedPointer pointer) { return load32(pointer); } LValue load32NonNegative(LValue base, const AbstractHeap& field) { return load32(base, field); } - LValue equal(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Equal, origin(), left, right); } - LValue notEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::NotEqual, origin(), left, right); } - LValue above(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Above, origin(), left, right); } - LValue aboveOrEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::AboveEqual, origin(), left, right); } - LValue below(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Below, origin(), left, right); } - LValue belowOrEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::BelowEqual, origin(), left, right); } - LValue greaterThan(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::GreaterThan, origin(), left, right); } - LValue greaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::GreaterEqual, origin(), left, right); } - LValue lessThan(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::LessThan, origin(), left, right); } - LValue lessThanOrEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::LessEqual, origin(), left, right); } - - LValue doubleEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::Equal, origin(), left, right); } - LValue doubleEqualOrUnordered(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::EqualOrUnordered, origin(), left, right); } - LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::NotEqual, origin(), left, right); } - LValue doubleLessThan(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::LessThan, origin(), left, right); } - LValue doubleLessThanOrEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::LessEqual, origin(), left, right); } - LValue doubleGreaterThan(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::GreaterThan, origin(), left, right); } - LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew(m_proc, B3::GreaterEqual, origin(), left, right); } - LValue doubleNotEqualAndOrdered(LValue left, LValue right) { return logicalNot(doubleEqualOrUnordered(left, right)); } - LValue doubleLessThanOrUnordered(LValue left, LValue right) { return logicalNot(doubleGreaterThanOrEqual(left, right)); } - LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return logicalNot(doubleGreaterThan(left, right)); } - LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return logicalNot(doubleLessThanOrEqual(left, right)); } - LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return logicalNot(doubleLessThan(left, right)); } - - LValue isZero32(LValue value) { return m_block->appendNew(m_proc, B3::Equal, origin(), value, int32Zero); } - LValue notZero32(LValue value) { return m_block->appendNew(m_proc, B3::NotEqual, origin(), value, int32Zero); } - LValue isZero64(LValue value) { return m_block->appendNew(m_proc, B3::Equal, origin(), value, int64Zero); } - LValue notZero64(LValue value) { return m_block->appendNew(m_proc, B3::NotEqual, origin(), value, int64Zero); } + LValue equal(LValue, LValue); + LValue notEqual(LValue, LValue); + LValue above(LValue, LValue); + LValue aboveOrEqual(LValue, LValue); + LValue below(LValue, LValue); + LValue belowOrEqual(LValue, LValue); + LValue greaterThan(LValue, LValue); + LValue greaterThanOrEqual(LValue, LValue); + LValue lessThan(LValue, LValue); + LValue lessThanOrEqual(LValue, LValue); + + LValue doubleEqual(LValue, LValue); + LValue doubleEqualOrUnordered(LValue, LValue); + LValue doubleNotEqualOrUnordered(LValue, LValue); + LValue doubleLessThan(LValue, LValue); + LValue doubleLessThanOrEqual(LValue, LValue); + LValue doubleGreaterThan(LValue, LValue); + LValue doubleGreaterThanOrEqual(LValue, LValue); + LValue doubleNotEqualAndOrdered(LValue, LValue); + LValue doubleLessThanOrUnordered(LValue, LValue); + LValue doubleLessThanOrEqualOrUnordered(LValue, LValue); + LValue doubleGreaterThanOrUnordered(LValue, LValue); + LValue doubleGreaterThanOrEqualOrUnordered(LValue, LValue); + + LValue isZero32(LValue); + LValue notZero32(LValue); + LValue isZero64(LValue); + LValue notZero64(LValue); LValue isNull(LValue value) { return isZero64(value); } LValue notNull(LValue value) { return notZero64(value); } @@ -370,8 +345,7 @@ LValue testIsZeroPtr(LValue value, LValue mask) { return isNull(bitAnd(value, mask)); } LValue testNonZeroPtr(LValue value, LValue mask) { return notNull(bitAnd(value, mask)); } - LValue select(LValue value, LValue taken, LValue notTaken) { return m_block->appendNew(m_proc, B3::Select, origin(), value, taken, notTaken); } - LValue extractValue(LValue aggVal, unsigned index) { CRASH(); } + LValue select(LValue value, LValue taken, LValue notTaken); template LValue call(LType type, LValue function, const VectorType& vector) @@ -385,10 +359,17 @@ template LValue call(LType type, LValue function, LValue arg1, Args... args) { return m_block->appendNew(m_proc, type, origin(), function, arg1, args...); } + template + LValue callWithoutSideEffects(B3::Type type, Function function, LValue arg1, Args... args) + { + return m_block->appendNew(m_proc, type, origin(), B3::Effects::none(), + constIntPtr(bitwise_cast(function)), arg1, args...); + } + template LValue operation(FunctionType function) { return constIntPtr(bitwise_cast(function)); } - void jump(LBasicBlock destination) { m_block->appendNew(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination)); } + void jump(LBasicBlock); void branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight); void branch(LValue condition, WeightedTarget taken, WeightedTarget notTaken) { @@ -405,8 +386,8 @@ template void switchInstruction(LValue value, const VectorType& cases, LBasicBlock fallThrough, Weight fallThroughWeight) { - B3::SwitchValue* switchValue = m_block->appendNew( - m_proc, origin(), value, B3::FrequentedBlock(fallThrough)); + B3::SwitchValue* switchValue = m_block->appendNew(m_proc, origin(), value); + switchValue->setFallThrough(B3::FrequentedBlock(fallThrough)); for (const SwitchCase& switchCase : cases) { int64_t value = switchCase.value()->asInt(); B3::FrequentedBlock target(switchCase.target(), switchCase.weight().frequencyClass()); @@ -414,45 +395,25 @@ } } - void ret(LValue value) { m_block->appendNew(m_proc, B3::Return, origin(), value); } - - void unreachable() { m_block->appendNew(m_proc, B3::Oops, origin()); } - - B3::CheckValue* speculate(LValue value) - { - return m_block->appendNew(m_proc, B3::Check, origin(), value); - } + void ret(LValue); - B3::CheckValue* speculateAdd(LValue left, LValue right) - { - return m_block->appendNew(m_proc, B3::CheckAdd, origin(), left, right); - } + void unreachable(); + + void appendSuccessor(WeightedTarget); - B3::CheckValue* speculateSub(LValue left, LValue right) - { - return m_block->appendNew(m_proc, B3::CheckSub, origin(), left, right); - } + B3::CheckValue* speculate(LValue); + B3::CheckValue* speculateAdd(LValue, LValue); + B3::CheckValue* speculateSub(LValue, LValue); + B3::CheckValue* speculateMul(LValue, LValue); - B3::CheckValue* speculateMul(LValue left, LValue right) - { - return m_block->appendNew(m_proc, B3::CheckMul, origin(), left, right); - } + B3::PatchpointValue* patchpoint(LType); - B3::PatchpointValue* patchpoint(LType type) - { - return m_block->appendNew(m_proc, type, origin()); - } + void trap(); - void trap() - { - m_block->appendNew(m_proc, B3::Oops, origin()); - } + ValueFromBlock anchor(LValue); - ValueFromBlock anchor(LValue value) - { - B3::UpsilonValue* upsilon = m_block->appendNew(m_proc, origin(), value); - return ValueFromBlock(upsilon, m_block); - } + void incrementSuperSamplerCount(); + void decrementSuperSamplerCount(); #if PLATFORM(COCOA) #pragma mark - States @@ -469,15 +430,6 @@ private: OrderMaker m_blockOrder; - - template - LValue callWithoutSideEffects(B3::Type type, Function function, LValue arg1, Args... args) - { - return m_block->appendNew(m_proc, type, origin(), B3::Effects::none(), - m_block->appendNew(m_proc, origin(), bitwise_cast(function)), - arg1, args...); - } - }; template @@ -497,11 +449,6 @@ return phiNode; } -inline void Output::addIncomingToPhi(LValue phi, ValueFromBlock value) -{ - value.value()->as()->setPhi(phi); -} - template inline void Output::addIncomingToPhi(LValue phi, ValueFromBlock value, Params... theRest) { @@ -509,17 +456,6 @@ addIncomingToPhi(phi, theRest...); } -inline LValue Output::bitCast(LValue value, LType type) -{ - ASSERT_UNUSED(type, type == int64 || type == doubleType); - return m_block->appendNew(m_proc, B3::BitwiseCast, origin(), value); -} - -inline LValue Output::fround(LValue doubleValue) -{ - return floatToDouble(doubleToFloat(doubleValue)); -} - #if COMPILER(GCC_OR_CLANG) #pragma GCC diagnostic pop #endif // COMPILER(GCC_OR_CLANG) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLPatchpointExceptionHandle.h 2016-11-03 07:04:20.000000000 +0000 @@ -78,11 +78,11 @@ // Schedules the creation of an OSR exit jump destination. You don't know when this will be // created, but it will happen before linking. You can link jumps to it during link time. That's // why this returns an ExceptionTarget. That will contain the jump destination (target->label()) - // at link time. + // at link time. This function should be used for exceptions from C calls. RefPtr scheduleExitCreation(const B3::StackmapGenerationParams&); // Schedules the creation of an OSR exit jump destination, and ensures that it gets associated - // with the handler for some callsite index. + // with the handler for some callsite index. This function should be used for exceptions from JS. void scheduleExitCreationForUnwind(const B3::StackmapGenerationParams&, CallSiteIndex); private: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLSlowPathCall.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLSlowPathCall.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLSlowPathCall.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLSlowPathCall.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,7 +31,6 @@ #include "CCallHelpers.h" #include "FTLSlowPathCallKey.h" #include "JITOperations.h" -#include "StructureStubInfo.h" namespace JSC { namespace FTL { @@ -104,7 +103,7 @@ if (callSiteIndex) { jit.store32( CCallHelpers::TrustedImm32(callSiteIndex.bits()), - CCallHelpers::tagFor(JSStack::ArgumentCount)); + CCallHelpers::tagFor(CallFrameSlot::argumentCount)); } return callOperation(usedRegisters, jit, exceptionTarget, function, resultGPR, arguments...); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLTypedPointer.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLTypedPointer.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLTypedPointer.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLTypedPointer.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -47,10 +47,10 @@ { } - bool operator!() const + explicit operator bool() const { ASSERT(!m_heap == !m_value); - return !m_heap; + return !!m_heap; } const AbstractHeap* heap() const { return m_heap; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLValueFromBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLValueFromBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLValueFromBlock.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLValueFromBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -45,6 +45,8 @@ , m_block(block) { } + + explicit operator bool() const { return m_value || m_block; } LValue value() const { return m_value; } LBasicBlock block() const { return m_block; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLWeightedTarget.h webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLWeightedTarget.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/ftl/FTLWeightedTarget.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/ftl/FTLWeightedTarget.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,6 +55,11 @@ LBasicBlock target() const { return m_target; } Weight weight() const { return m_weight; } + B3::FrequentedBlock frequentedBlock() const + { + return B3::FrequentedBlock(target(), weight().frequencyClass()); + } + private: LBasicBlock m_target; Weight m_weight; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/generateYarrCanonicalizeUnicode webkit2gtk-2.14.2/Source/JavaScriptCore/generateYarrCanonicalizeUnicode --- webkit2gtk-2.12.3/Source/JavaScriptCore/generateYarrCanonicalizeUnicode 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/generateYarrCanonicalizeUnicode 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,200 @@ +#! /usr/bin/python + +# Copyright (C) 2016 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This tool processes the Unicode Character Database file CaseFolding.txt to create +# canonicalization table as decribed in ECMAScript 6 standard in section +# "21.2.2.8.2 Runtime Semantics: Canonicalize()", step 2. + +import optparse +import re +import sys +from sets import Set + +header = """/* +* Copyright (C) 2016 Apple Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// DO NO EDIT! - This file was generated by generateYarrCanonicalizeUnicode + +#include "config.h" +#include "YarrCanonicalize.h" + +namespace JSC { namespace Yarr { + +""" + +footer = """} } // JSC::Yarr +""" + +MaxUnicode = 0x10ffff +commonAndSimpleLinesRE = re.compile(r"(?P[0-9A-F]+)\s*;\s*[CS]\s*;\s*(?P[0-9A-F]+)", re.IGNORECASE) + +def openOrExit(path, mode): + try: + return open(path, mode) + except IOError as e: + print "I/O error opening {0}, ({1}): {2}".format(path, e.errno, e.strerror) + exit(1) + +class Canonicalize: + def __init__(self): + self.canonicalGroups = {}; + + def addMapping(self, code, mapping): + if mapping not in self.canonicalGroups: + self.canonicalGroups[mapping] = [] + self.canonicalGroups[mapping].append(code) + + def readCaseFolding(self, file): + codesSeen = Set() + for line in file: + line = line.split('#', 1)[0] + line = line.rstrip() + if (not len(line)): + continue + + fields = commonAndSimpleLinesRE.match(line) + if (not fields): + continue + + code = int(fields.group('code'), 16) + mapping = int(fields.group('mapping'), 16) + + codesSeen.add(code) + self.addMapping(code, mapping) + + for i in range(MaxUnicode + 1): + if i in codesSeen: + continue; + + self.addMapping(i, i) + + def createTables(self, file): + typeInfo = [""] * (MaxUnicode + 1) + characterSets = [] + + for mapping in sorted(self.canonicalGroups.keys()): + characters = self.canonicalGroups[mapping] + if len(characters) == 1: + typeInfo[characters[0]] = "CanonicalizeUnique:0" + else: + characters.sort() + if len(characters) > 2: + for ch in characters: + typeInfo[ch] = "CanonicalizeSet:%d" % len(characterSets) + characterSets.append(characters) + else: + low = characters[0] + high = characters[1] + delta = high - low + if delta == 1: + type = "CanonicalizeAlternatingUnaligned:0" if low & 1 else "CanonicalizeAlternatingAligned:0" + typeInfo[low] = type + typeInfo[high] = type + else: + typeInfo[low] = "CanonicalizeRangeLo:%d" % delta + typeInfo[high] = "CanonicalizeRangeHi:%d" % delta + + rangeInfo = [] + end = 0 + while end <= MaxUnicode: + begin = end + type = typeInfo[end] + while end < MaxUnicode and typeInfo[end + 1] == type: + end = end + 1 + rangeInfo.append({"begin": begin, "end": end, "type": type}) + end = end + 1 + + for i in range(len(characterSets)): + characters = "" + set = characterSets[i] + for ch in set: + characters = characters + "0x{character:04x}, ".format(character=ch) + file.write("const UChar32 unicodeCharacterSet{index:d}[] = {{ {characters}0 }};\n".format(index=i, characters=characters)) + + file.write("\n") + file.write("static const size_t UNICODE_CANONICALIZATION_SETS = {setCount:d};\n".format(setCount=len(characterSets))) + file.write("const UChar32* const unicodeCharacterSetInfo[UNICODE_CANONICALIZATION_SETS] = {\n") + + for i in range(len(characterSets)): + file.write(" unicodeCharacterSet{setNumber:d},\n".format(setNumber=i)) + + file.write("};\n") + file.write("\n") + file.write("const size_t UNICODE_CANONICALIZATION_RANGES = {rangeCount:d};\n".format(rangeCount=len(rangeInfo))) + file.write("const CanonicalizationRange unicodeRangeInfo[UNICODE_CANONICALIZATION_RANGES] = {\n") + + for info in rangeInfo: + typeAndValue = info["type"].split(":") + file.write(" {{ 0x{begin:04x}, 0x{end:04x}, 0x{value:04x}, {type} }},\n".format(begin=info["begin"], end=info["end"], value=int(typeAndValue[1]), type=typeAndValue[0])) + + file.write("};\n") + file.write("\n") + + +if __name__ == "__main__": + parser = optparse.OptionParser(usage = "usage: %prog ") + (options, args) = parser.parse_args() + + if len(args) != 2: + parser.error(" ") + + caseFoldingTxtPath = args[0] + canonicalizeHPath = args[1] + caseFoldingTxtFile = openOrExit(caseFoldingTxtPath, "r") + canonicalizeHFile = openOrExit(canonicalizeHPath, "wb") + + canonicalize = Canonicalize() + canonicalize.readCaseFolding(caseFoldingTxtFile) + + canonicalizeHFile.write(header); + canonicalize.createTables(canonicalizeHFile) + canonicalizeHFile.write(footer); + + caseFoldingTxtFile.close() + canonicalizeHFile.close() + + exit(0) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/AllocatorAttributes.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/AllocatorAttributes.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/AllocatorAttributes.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/AllocatorAttributes.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AllocatorAttributes.h" + +#include + +namespace JSC { + +void AllocatorAttributes::dump(PrintStream& out) const +{ + out.print("{", destruction, ", ", cellKind, "}"); +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/AllocatorAttributes.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/AllocatorAttributes.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/AllocatorAttributes.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/AllocatorAttributes.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "DestructionMode.h" +#include "HeapCell.h" +#include + +namespace JSC { + +struct AllocatorAttributes { + AllocatorAttributes() { } + + void dump(PrintStream& out) const; + + DestructionMode destruction { DoesNotNeedDestruction }; + HeapCell::Kind cellKind { HeapCell::JSCell }; +}; + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CellContainer.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CellContainer.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CellContainer.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CellContainer.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace JSC { + +class HeapCell; +class LargeAllocation; +class MarkedBlock; +class WeakSet; + +typedef uint32_t HeapVersion; + +// This is how we abstract over either MarkedBlock& or LargeAllocation&. Put things in here as you +// find need for them. + +class CellContainer { +public: + CellContainer() + : m_encodedPointer(0) + { + } + + CellContainer(MarkedBlock& markedBlock) + : m_encodedPointer(bitwise_cast(&markedBlock)) + { + } + + CellContainer(LargeAllocation& largeAllocation) + : m_encodedPointer(bitwise_cast(&largeAllocation) | isLargeAllocationBit) + { + } + + explicit operator bool() const { return !!m_encodedPointer; } + + bool isMarkedBlock() const { return m_encodedPointer && !(m_encodedPointer & isLargeAllocationBit); } + bool isLargeAllocation() const { return m_encodedPointer & isLargeAllocationBit; } + + MarkedBlock& markedBlock() const + { + ASSERT(isMarkedBlock()); + return *bitwise_cast(m_encodedPointer); + } + + LargeAllocation& largeAllocation() const + { + ASSERT(isLargeAllocation()); + return *bitwise_cast(m_encodedPointer - isLargeAllocationBit); + } + + void flipIfNecessary(HeapVersion); + void flipIfNecessary(); + + bool isMarked() const; + bool isMarked(HeapCell*) const; + bool isMarkedOrNewlyAllocated(HeapCell*) const; + + void noteMarked(); + + size_t cellSize() const; + + WeakSet& weakSet() const; + +private: + static const uintptr_t isLargeAllocationBit = 1; + uintptr_t m_encodedPointer; +}; + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CellContainerInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CellContainerInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CellContainerInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CellContainerInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CellContainer.h" +#include "JSCell.h" +#include "LargeAllocation.h" +#include "MarkedBlock.h" + +namespace JSC { + +inline bool CellContainer::isMarked() const +{ + if (isLargeAllocation()) + return true; + return markedBlock().handle().isMarked(); +} + +inline bool CellContainer::isMarked(HeapCell* cell) const +{ + if (isLargeAllocation()) + return largeAllocation().isMarked(); + return markedBlock().isMarked(cell); +} + +inline bool CellContainer::isMarkedOrNewlyAllocated(HeapCell* cell) const +{ + if (isLargeAllocation()) + return largeAllocation().isMarkedOrNewlyAllocated(); + return markedBlock().isMarkedOrNewlyAllocated(cell); +} + +inline void CellContainer::noteMarked() +{ + if (!isLargeAllocation()) + markedBlock().noteMarked(); +} + +inline size_t CellContainer::cellSize() const +{ + if (isLargeAllocation()) + return largeAllocation().cellSize(); + return markedBlock().cellSize(); +} + +inline WeakSet& CellContainer::weakSet() const +{ + if (isLargeAllocation()) + return largeAllocation().weakSet(); + return markedBlock().weakSet(); +} + +inline void CellContainer::flipIfNecessary(HeapVersion heapVersion) +{ + if (!isLargeAllocation()) + markedBlock().flipIfNecessary(heapVersion); +} + +inline void CellContainer::flipIfNecessary() +{ + if (!isLargeAllocation()) + markedBlock().flipIfNecessary(); +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CodeBlockSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CodeBlockSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CodeBlockSet.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CodeBlockSet.h 2016-11-03 07:04:20.000000000 +0000 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -82,7 +81,7 @@ // Visits each CodeBlock in the heap until the visitor function returns true // to indicate that it is done iterating, or until every CodeBlock has been // visited. - template void iterate(Functor& functor) + template void iterate(const Functor& functor) { LockHolder locker(m_lock); for (auto& codeBlock : m_oldCodeBlocks) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/ConservativeRoots.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/ConservativeRoots.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/ConservativeRoots.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/ConservativeRoots.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +31,8 @@ #include "CopiedSpace.h" #include "CopiedSpaceInlines.h" #include "HeapInlines.h" +#include "HeapUtil.h" +#include "JITStubRoutineSet.h" #include "JSCell.h" #include "JSObject.h" #include "JSCInlines.h" @@ -39,46 +41,46 @@ namespace JSC { -ConservativeRoots::ConservativeRoots(MarkedBlockSet* blocks, CopiedSpace* copiedSpace) +ConservativeRoots::ConservativeRoots(Heap& heap) : m_roots(m_inlineRoots) , m_size(0) , m_capacity(inlineCapacity) - , m_blocks(blocks) - , m_copiedSpace(copiedSpace) + , m_heap(heap) { } ConservativeRoots::~ConservativeRoots() { if (m_roots != m_inlineRoots) - OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); + OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(HeapCell*)); } void ConservativeRoots::grow() { size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2; - JSCell** newRoots = static_cast(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); - memcpy(newRoots, m_roots, m_size * sizeof(JSCell*)); + HeapCell** newRoots = static_cast(OSAllocator::reserveAndCommit(newCapacity * sizeof(HeapCell*))); + memcpy(newRoots, m_roots, m_size * sizeof(HeapCell*)); if (m_roots != m_inlineRoots) - OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); + OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(HeapCell*)); m_capacity = newCapacity; m_roots = newRoots; } template -inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook) +inline void ConservativeRoots::genericAddPointer(void* p, HeapVersion version, TinyBloomFilter filter, MarkHook& markHook) { markHook.mark(p); - m_copiedSpace->pinIfNecessary(p); + m_heap.storageSpace().pinIfNecessary(p); - if (!Heap::isPointerGCObject(filter, *m_blocks, p)) - return; - - if (m_size == m_capacity) - grow(); - - m_roots[m_size++] = static_cast(p); + HeapUtil::findGCObjectPointersForMarking( + m_heap, version, filter, p, + [&] (void* p) { + if (m_size == m_capacity) + grow(); + + m_roots[m_size++] = bitwise_cast(p); + }); } template @@ -94,9 +96,10 @@ RELEASE_ASSERT(isPointerAligned(begin)); RELEASE_ASSERT(isPointerAligned(end)); - TinyBloomFilter filter = m_blocks->filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated. + TinyBloomFilter filter = m_heap.objectSpace().blocks().filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated. + HeapVersion version = m_heap.objectSpace().version(); for (char** it = static_cast(begin); it != static_cast(end); ++it) - genericAddPointer(*it, filter, markHook); + genericAddPointer(*it, version, filter, markHook); } class DummyMarkHook { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/ConservativeRoots.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/ConservativeRoots.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/ConservativeRoots.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/ConservativeRoots.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,12 +31,12 @@ namespace JSC { class CodeBlockSet; +class HeapCell; class JITStubRoutineSet; -class JSCell; class ConservativeRoots { public: - ConservativeRoots(MarkedBlockSet*, CopiedSpace*); + ConservativeRoots(Heap&); ~ConservativeRoots(); void add(void* begin, void* end); @@ -44,26 +44,25 @@ void add(void* begin, void* end, JITStubRoutineSet&, CodeBlockSet&); size_t size(); - JSCell** roots(); + HeapCell** roots(); private: static const size_t inlineCapacity = 128; - static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*); + static const size_t nonInlineCapacity = 8192 / sizeof(HeapCell*); template - void genericAddPointer(void*, TinyBloomFilter, MarkHook&); + void genericAddPointer(void*, HeapVersion, TinyBloomFilter, MarkHook&); template void genericAddSpan(void*, void* end, MarkHook&); void grow(); - JSCell** m_roots; + HeapCell** m_roots; size_t m_size; size_t m_capacity; - MarkedBlockSet* m_blocks; - CopiedSpace* m_copiedSpace; - JSCell* m_inlineRoots[inlineCapacity]; + Heap& m_heap; + HeapCell* m_inlineRoots[inlineCapacity]; }; inline size_t ConservativeRoots::size() @@ -71,7 +70,7 @@ return m_size; } -inline JSCell** ConservativeRoots::roots() +inline HeapCell** ConservativeRoots::roots() { return m_roots; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CopiedBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CopiedBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CopiedBlock.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CopiedBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -79,7 +79,7 @@ size_t size(); size_t capacity(); - static const size_t blockSize = 32 * KB; + static const size_t blockSize = 64 * KB; bool hasWorkList(); CopyWorkList& workList(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CopyBarrier.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CopyBarrier.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CopyBarrier.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CopyBarrier.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,91 +27,24 @@ #define CopyBarrier_h #include "Heap.h" +#include "VM.h" namespace JSC { -enum class CopyState { - // The backing store is not planned to get copied in this epoch. If you keep a pointer to the backing - // store on the stack, it will not get copied. If you don't keep it on the stack, it may get copied - // starting at the next handshake (that is, it may transition from ToSpace to CopyPlanned, but - // CopyPlanned means ToSpace prior to the handshake that starts the copy phase). - ToSpace, - - // The marking phase has selected this backing store to be copied. If we are not yet in the copying - // phase, this backing store is still in to-space. All that is needed in such a case is to mask off the - // low bits. If we are in the copying phase, this means that the object points to from-space. The - // barrier should first copy the object - or wait for copying to finish - before using the object. - CopyPlanned, - - // The object is being copied right now. Anyone wanting to use the object must wait for the object to - // finish being copied. Notifications about copying use the ParkingLot combined with these bits. If the - // state is CopyingAndWaiting, then when the copying finishes, whatever thread was doing it will - // unparkAll() on the address of the CopyBarrierBase. So, to wait for copying to finish, CAS this to - // CopyingAndWaiting and then parkConditionally on the barrier address. - Copying, - - // The object is being copied right now, and there are one or more threads parked. Those threads want - // to be unparked when copying is done. So, whichever thread does the copying needs to call unparkAll() - // on the barrier address after copying is done. - CopyingAndWaiting -}; - class CopyBarrierBase { public: - static const unsigned spaceBits = 3; - CopyBarrierBase() : m_value(nullptr) { } - bool operator!() const { return !m_value; } - explicit operator bool() const { return m_value; } - void* getWithoutBarrier() const + void* get() const { return m_value; } - // Use this version of get() if you only want to execute the barrier slow path if some condition - // holds, and you only want to evaluate that condition after first checking the barrier's - // condition. Usually, you just want to use get(). - template - void* getPredicated(const JSCell* owner, const Functor& functor) const - { - void* result = m_value; - if (UNLIKELY(bitwise_cast(result) & spaceBits)) { - if (functor()) - return Heap::copyBarrier(owner, m_value); - } - return result; - } - - // When we are in the concurrent copying phase, this method may lock the barrier object (i.e. the field - // pointing to copied space) and call directly into the owning object's copyBackingStore() method. - void* get(const JSCell* owner) const - { - return getPredicated(owner, [] () -> bool { return true; }); - } - - CopyState copyState() const - { - return static_cast(bitwise_cast(m_value) & spaceBits); - } - - // This only works when you know that there is nobody else concurrently messing with this CopyBarrier. - // That's hard to guarantee, though there are a few unusual places where this ends up being safe. - // Usually you want to use CopyBarrier::weakCAS(). - void setCopyState(CopyState copyState) - { - WTF::storeStoreFence(); - uintptr_t value = bitwise_cast(m_value); - value &= ~static_cast(spaceBits); - value |= static_cast(copyState); - m_value = bitwise_cast(value); - } - void clear() { m_value = nullptr; } protected: @@ -131,15 +64,6 @@ this->m_value = value; } - bool weakCASWithoutBarrier( - void* oldPointer, CopyState oldCopyState, void* newPointer, CopyState newCopyState) - { - uintptr_t oldValue = bitwise_cast(oldPointer) | static_cast(oldCopyState); - uintptr_t newValue = bitwise_cast(newPointer) | static_cast(newCopyState); - return WTF::weakCompareAndSwap( - &m_value, bitwise_cast(oldValue), bitwise_cast(newValue)); - } - private: mutable void* m_value; }; @@ -161,22 +85,11 @@ { } - T* getWithoutBarrier() const - { - return bitwise_cast(CopyBarrierBase::getWithoutBarrier()); - } - - T* get(const JSCell* owner) const + T* get() const { - return bitwise_cast(CopyBarrierBase::get(owner)); + return bitwise_cast(CopyBarrierBase::get()); } - template - T* getPredicated(const JSCell* owner, const Functor& functor) const - { - return bitwise_cast(CopyBarrierBase::getPredicated(owner, functor)); - } - void set(VM& vm, const JSCell* owner, T* value) { CopyBarrierBase::set(vm, owner, value); @@ -186,11 +99,6 @@ { CopyBarrierBase::setWithoutBarrier(value); } - - bool weakCASWithoutBarrier(T* oldPointer, CopyState oldCopyState, T* newPointer, CopyState newCopyState) - { - return CopyBarrierBase::weakCASWithoutBarrier(oldPointer, oldCopyState, newPointer, newCopyState); - } }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CopyToken.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CopyToken.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/CopyToken.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/CopyToken.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ namespace JSC { enum CopyToken { - ButterflyCopyToken, TypedArrayVectorCopyToken, MapBackingStoreCopyToken, DirectArgumentsOverridesCopyToken diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/DestructionMode.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/DestructionMode.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/DestructionMode.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/DestructionMode.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DestructionMode.h" + +#include + +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, DestructionMode mode) +{ + switch (mode) { + case NeedsDestruction: + out.print("NeedsDestruction"); + return; + case DoesNotNeedDestruction: + out.print("DoesNotNeedDestruction"); + return; + } + + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/DestructionMode.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/DestructionMode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/DestructionMode.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/DestructionMode.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace JSC { + +enum DestructionMode : int8_t { + DoesNotNeedDestruction, + NeedsDestruction +}; + +} // namespace JSC + +namespace WTF { + +class PrintStream; +void printInternal(PrintStream&, JSC::DestructionMode); + +} // namespace WTF + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/EdenGCActivityCallback.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/EdenGCActivityCallback.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/EdenGCActivityCallback.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/EdenGCActivityCallback.h 2016-11-03 07:04:20.000000000 +0000 @@ -34,7 +34,7 @@ public: EdenGCActivityCallback(Heap*); - virtual void doCollection() override; + void doCollection() override; protected: #if USE(CF) @@ -44,9 +44,9 @@ } #endif - virtual double lastGCLength() override; - virtual double gcTimeSlice(size_t bytes) override; - virtual double deathRate() override; + double lastGCLength() override; + double gcTimeSlice(size_t bytes) override; + double deathRate() override; }; inline RefPtr GCActivityCallback::createEdenTimer(Heap* heap) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/FreeList.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/FreeList.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/FreeList.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/FreeList.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FreeList.h" + +namespace JSC { + +void FreeList::dump(PrintStream& out) const +{ + out.print("{head = ", RawPointer(head), ", payloadEnd = ", RawPointer(payloadEnd), ", remaining = ", remaining, ", originalSize = ", originalSize, "}"); +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/FreeList.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/FreeList.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/FreeList.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/FreeList.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace JSC { + +struct FreeCell { + FreeCell* next; +}; + +// This representation of a FreeList is convenient for the MarkedAllocator. + +struct FreeList { + FreeCell* head { nullptr }; + char* payloadEnd { nullptr }; + unsigned remaining { 0 }; + unsigned originalSize { 0 }; + + FreeList() + { + } + + static FreeList list(FreeCell* head, unsigned bytes) + { + FreeList result; + result.head = head; + result.remaining = 0; + result.originalSize = bytes; + return result; + } + + static FreeList bump(char* payloadEnd, unsigned remaining) + { + FreeList result; + result.payloadEnd = payloadEnd; + result.remaining = remaining; + result.originalSize = remaining; + return result; + } + + bool operator==(const FreeList& other) const + { + return head == other.head + && payloadEnd == other.payloadEnd + && remaining == other.remaining + && originalSize == other.originalSize; + } + + bool operator!=(const FreeList& other) const + { + return !(*this == other); + } + + explicit operator bool() const + { + return *this != FreeList(); + } + + bool allocationWillFail() const { return !head && !remaining; } + bool allocationWillSucceed() const { return !allocationWillFail(); } + + void dump(PrintStream&) const; +}; + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/FullGCActivityCallback.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/FullGCActivityCallback.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/FullGCActivityCallback.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/FullGCActivityCallback.h 2016-11-03 07:04:20.000000000 +0000 @@ -34,7 +34,7 @@ public: FullGCActivityCallback(Heap*); - virtual void doCollection() override; + void doCollection() override; bool didSyncGCRecently() const { return m_didSyncGCRecently; } void setDidSyncGCRecently() { m_didSyncGCRecently = true; } @@ -47,9 +47,9 @@ } #endif - virtual double lastGCLength() override; - virtual double gcTimeSlice(size_t bytes) override; - virtual double deathRate() override; + double lastGCLength() override; + double gcTimeSlice(size_t bytes) override; + double deathRate() override; bool m_didSyncGCRecently { false }; }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCActivityCallback.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCActivityCallback.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCActivityCallback.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCActivityCallback.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -34,9 +34,6 @@ #include "JSObject.h" #include "VM.h" -#include -#include - #if PLATFORM(EFL) #include #elif USE(GLIB) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCActivityCallback.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCActivityCallback.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCActivityCallback.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCActivityCallback.h 2016-11-03 07:04:20.000000000 +0000 @@ -49,7 +49,7 @@ GCActivityCallback(Heap*); - virtual void doWork() override; + void doWork() override; virtual void doCollection() = 0; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCIncomingRefCountedSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCIncomingRefCountedSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCIncomingRefCountedSet.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCIncomingRefCountedSet.h 2016-11-03 07:04:20.000000000 +0000 @@ -36,8 +36,9 @@ class GCIncomingRefCountedSet { public: GCIncomingRefCountedSet(); - ~GCIncomingRefCountedSet(); - + + void lastChanceToFinalize(); + // Returns true if the native object is new to this set. bool addReference(JSCell*, T*); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCIncomingRefCountedSetInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCIncomingRefCountedSetInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCIncomingRefCountedSetInlines.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCIncomingRefCountedSetInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -38,7 +38,7 @@ } template -GCIncomingRefCountedSet::~GCIncomingRefCountedSet() +void GCIncomingRefCountedSet::lastChanceToFinalize() { for (size_t i = m_vector.size(); i--;) m_vector[i]->filterIncomingReferences(removeAll); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCLogging.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCLogging.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCLogging.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCLogging.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -50,69 +50,6 @@ } } -class LoggingFunctor { -public: - LoggingFunctor(SlotVisitor& slotVisitor) - : m_slotVisitor(slotVisitor) - { - m_savedMarkStack.resize(m_slotVisitor.markStack().size()); - m_slotVisitor.markStack().fillVector(m_savedMarkStack); - } - - ~LoggingFunctor() - { - reviveCells(); - } - - IterationStatus operator()(JSCell* cell) - { - m_liveCells.append(cell); - MarkedBlock::blockFor(cell)->clearMarked(cell); - return IterationStatus::Continue; - } - - void log() - { - m_slotVisitor.clearMarkStack(); - for (JSCell* cell : m_liveCells) { - cell->methodTable()->visitChildren(cell, m_slotVisitor); - dataLog("\n", *cell, ":\n", m_slotVisitor); - for (const JSCell* neighbor : m_slotVisitor.markStack()) - MarkedBlock::blockFor(neighbor)->clearMarked(neighbor); - m_slotVisitor.clearMarkStack(); - } - m_slotVisitor.reset(); - } - - void reviveCells() - { - for (JSCell* cell : m_liveCells) - MarkedBlock::blockFor(cell)->setMarked(cell); - - for (const JSCell* cell : m_savedMarkStack) { - m_slotVisitor.markStack().append(cell); - cell->setCellState(CellState::OldGrey); - } - } - - typedef void ReturnType; - - void returnValue() { }; - -private: - Vector m_savedMarkStack; - Vector m_liveCells; - SlotVisitor& m_slotVisitor; -}; - -void GCLogging::dumpObjectGraph(Heap* heap) -{ - LoggingFunctor loggingFunctor(heap->m_slotVisitor); - HeapIterationScope iterationScope(*heap); - heap->objectSpace().forEachLiveCell(iterationScope, loggingFunctor); - loggingFunctor.log(); -} - } // namespace JSC namespace WTF { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCTypeMap.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCTypeMap.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/GCTypeMap.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/GCTypeMap.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "HeapOperation.h" +#include + +namespace JSC { + +template +struct GCTypeMap { + T eden; + T full; + + T& operator[](HeapOperation operation) + { + if (operation == FullCollection) + return full; + ASSERT(operation == EdenCollection); + return eden; + } + + const T& operator[](HeapOperation operation) const + { + if (operation == FullCollection) + return full; + ASSERT(operation == EdenCollection); + return eden; + } +}; + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HandleSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HandleSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HandleSet.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HandleSet.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,7 @@ #include "Handle.h" #include "HandleBlock.h" +#include "HeapCell.h" #include #include #include @@ -79,7 +80,7 @@ unsigned protectedGlobalObjectCount(); - template void forEachStrongHandle(Functor&, const HashCountedSet& skipSet); + template void forEachStrongHandle(const Functor&, const HashCountedSet& skipSet); private: typedef HandleNode Node; @@ -180,7 +181,7 @@ return m_next; } -template void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet& skipSet) +template void HandleSet::forEachStrongHandle(const Functor& functor, const HashCountedSet& skipSet) { HandleSet::Node* end = m_strongList.end(); for (HandleSet::Node* node = m_strongList.begin(); node != end; node = node->next()) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapCell.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapCell.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapCell.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapCell.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HeapCell.h" + +#include + +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, HeapCell::Kind kind) +{ + switch (kind) { + case HeapCell::JSCell: + out.print("JSCell"); + return; + case HeapCell::Auxiliary: + out.print("Auxiliary"); + return; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapCell.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapCell.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapCell.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapCell.h 2016-10-27 10:23:40.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "DestructionMode.h" + +namespace JSC { + +class CellContainer; +class Heap; +class LargeAllocation; +class MarkedBlock; +class VM; +struct AllocatorAttributes; + +class HeapCell { +public: + enum Kind : int8_t { + JSCell, + Auxiliary + }; + + HeapCell() { } + + void zap() { *reinterpret_cast_ptr(this) = 0; } + bool isZapped() const { return !*reinterpret_cast_ptr(this); } + + bool isLargeAllocation() const; + CellContainer cellContainer() const; + MarkedBlock& markedBlock() const; + LargeAllocation& largeAllocation() const; + + // If you want performance and you know that your cell is small, you can do this instead: + // ASSERT(!cell->isLargeAllocation()); + // cell->markedBlock().vm() + // We currently only use this hack for callees to make ExecState::vm() fast. It's not + // recommended to use it for too many other things, since the large allocation cutoff is + // a runtime option and its default value is small (400 bytes). + Heap* heap() const; + VM* vm() const; + + size_t cellSize() const; + AllocatorAttributes allocatorAttributes() const; + DestructionMode destructionMode() const; + Kind cellKind() const; +}; + +} // namespace JSC + +namespace WTF { + +class PrintStream; + +void printInternal(PrintStream&, JSC::HeapCell::Kind); + +} // namespace WTF + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapCellInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapCellInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapCellInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapCellInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CellContainer.h" +#include "HeapCell.h" +#include "LargeAllocation.h" +#include "MarkedBlock.h" + +namespace JSC { + +ALWAYS_INLINE bool HeapCell::isLargeAllocation() const +{ + return LargeAllocation::isLargeAllocation(const_cast(this)); +} + +ALWAYS_INLINE CellContainer HeapCell::cellContainer() const +{ + if (isLargeAllocation()) + return largeAllocation(); + return markedBlock(); +} + +ALWAYS_INLINE MarkedBlock& HeapCell::markedBlock() const +{ + return *MarkedBlock::blockFor(this); +} + +ALWAYS_INLINE LargeAllocation& HeapCell::largeAllocation() const +{ + return *LargeAllocation::fromCell(const_cast(this)); +} + +ALWAYS_INLINE Heap* HeapCell::heap() const +{ + return &vm()->heap; +} + +ALWAYS_INLINE VM* HeapCell::vm() const +{ + if (isLargeAllocation()) + return largeAllocation().vm(); + return markedBlock().vm(); +} + +ALWAYS_INLINE size_t HeapCell::cellSize() const +{ + if (isLargeAllocation()) + return largeAllocation().cellSize(); + return markedBlock().cellSize(); +} + +ALWAYS_INLINE AllocatorAttributes HeapCell::allocatorAttributes() const +{ + if (isLargeAllocation()) + return largeAllocation().attributes(); + return markedBlock().attributes(); +} + +ALWAYS_INLINE DestructionMode HeapCell::destructionMode() const +{ + return allocatorAttributes().destruction; +} + +ALWAYS_INLINE HeapCell::Kind HeapCell::cellKind() const +{ + return allocatorAttributes().cellKind; +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/Heap.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/Heap.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/Heap.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/Heap.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2009, 2011, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2003-2009, 2011, 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * This library is free software; you can redistribute it and/or @@ -31,28 +31,45 @@ #include "FullGCActivityCallback.h" #include "GCActivityCallback.h" #include "GCIncomingRefCountedSetInlines.h" +#include "GCTypeMap.h" #include "HeapHelperPool.h" #include "HeapIterationScope.h" +#include "HeapProfiler.h" #include "HeapRootVisitor.h" +#include "HeapSnapshot.h" #include "HeapStatistics.h" #include "HeapVerifier.h" #include "IncrementalSweeper.h" #include "Interpreter.h" +#include "JITStubRoutineSet.h" +#include "JITWorklist.h" #include "JSCInlines.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "JSVirtualMachineInternal.h" #include "SamplingProfiler.h" -#include "Tracing.h" +#include "ShadowChicken.h" +#include "SuperSampler.h" #include "TypeProfilerLog.h" #include "UnlinkedCodeBlock.h" #include "VM.h" #include "WeakSetInlines.h" #include #include +#include #include #include #include +#include + +#if USE(FOUNDATION) +#if __has_include() +#include +#else +extern "C" void* objc_autoreleasePoolPush(void); +extern "C" void objc_autoreleasePoolPop(void *context); +#endif +#endif // USE(FOUNDATION) using namespace std; @@ -61,159 +78,16 @@ namespace { static const size_t largeHeapSize = 32 * MB; // About 1.5X the average webpage. -static const size_t smallHeapSize = 1 * MB; // Matches the FastMalloc per-thread cache. - -#define ENABLE_GC_LOGGING 0 - -#if ENABLE(GC_LOGGING) -#if COMPILER(CLANG) -#define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \ -_Pragma("clang diagnostic push") \ -_Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \ -_Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ -static type name arguments; \ -_Pragma("clang diagnostic pop") -#else -#define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \ -static type name arguments; -#endif // COMPILER(CLANG) - -struct GCTimer { - GCTimer(const char* name) - : name(name) - { - } - ~GCTimer() - { - logData(allCollectionData, "(All)"); - logData(edenCollectionData, "(Eden)"); - logData(fullCollectionData, "(Full)"); - } - - struct TimeRecord { - TimeRecord() - : time(0) - , min(std::numeric_limits::infinity()) - , max(0) - , count(0) - { - } - - double time; - double min; - double max; - size_t count; - }; - - void logData(const TimeRecord& data, const char* extra) - { - dataLogF("[%d] %s (Parent: %s) %s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf, count %lu)\n", - getCurrentProcessID(), - name, - parent ? parent->name : "nullptr", - extra, - data.time * 1000, - data.time * 1000 / data.count, - data.min * 1000, - data.max * 1000, - data.count); - } - - void updateData(TimeRecord& data, double duration) - { - if (duration < data.min) - data.min = duration; - if (duration > data.max) - data.max = duration; - data.count++; - data.time += duration; - } - - void didFinishPhase(HeapOperation collectionType, double duration) - { - TimeRecord& data = collectionType == EdenCollection ? edenCollectionData : fullCollectionData; - updateData(data, duration); - updateData(allCollectionData, duration); - } - - static GCTimer* s_currentGlobalTimer; - - TimeRecord allCollectionData; - TimeRecord fullCollectionData; - TimeRecord edenCollectionData; - const char* name; - GCTimer* parent { nullptr }; -}; - -GCTimer* GCTimer::s_currentGlobalTimer = nullptr; - -struct GCTimerScope { - GCTimerScope(GCTimer& timer, HeapOperation collectionType) - : timer(timer) - , start(WTF::monotonicallyIncreasingTime()) - , collectionType(collectionType) - { - timer.parent = GCTimer::s_currentGlobalTimer; - GCTimer::s_currentGlobalTimer = &timer; - } - ~GCTimerScope() - { - double delta = WTF::monotonicallyIncreasingTime() - start; - timer.didFinishPhase(collectionType, delta); - GCTimer::s_currentGlobalTimer = timer.parent; - } - GCTimer& timer; - double start; - HeapOperation collectionType; -}; - -struct GCCounter { - GCCounter(const char* name) - : name(name) - , count(0) - , total(0) - , min(10000000) - , max(0) - { - } - - void add(size_t amount) - { - count++; - total += amount; - if (amount < min) - min = amount; - if (amount > max) - max = amount; - } - ~GCCounter() - { - dataLogF("[%d] %s: %zu values (avg. %zu, min. %zu, max. %zu)\n", getCurrentProcessID(), name, total, total / count, min, max); - } - const char* name; - size_t count; - size_t total; - size_t min; - size_t max; -}; - -#define GCPHASE(name) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name##Timer, (#name)); GCTimerScope name##TimerScope(name##Timer, m_operationInProgress) -#define GCCOUNTER(name, value) do { DEFINE_GC_LOGGING_GLOBAL(GCCounter, name##Counter, (#name)); name##Counter.add(value); } while (false) - -#else +const size_t smallHeapSize = 1 * MB; // Matches the FastMalloc per-thread cache. -#define GCPHASE(name) do { } while (false) -#define GCCOUNTER(name, value) do { } while (false) -#endif - -static inline size_t minHeapSize(HeapType heapType, size_t ramSize) +size_t minHeapSize(HeapType heapType, size_t ramSize) { if (heapType == LargeHeap) return min(largeHeapSize, ramSize / 4); return smallHeapSize; } -static inline size_t proportionalHeapSize(size_t heapSize, size_t ramSize) +size_t proportionalHeapSize(size_t heapSize, size_t ramSize) { // Try to stay under 1/2 RAM size to leave room for the DOM, rendering, networking, etc. if (heapSize < ramSize / 4) @@ -223,12 +97,12 @@ return 1.25 * heapSize; } -static inline bool isValidSharedInstanceThreadState(VM* vm) +bool isValidSharedInstanceThreadState(VM* vm) { return vm->currentThreadIsHoldingAPILock(); } -static inline bool isValidThreadState(VM* vm) +bool isValidThreadState(VM* vm) { if (vm->atomicStringTable() != wtfThreadData().atomicStringTable()) return false; @@ -239,77 +113,78 @@ return true; } -struct MarkObject : public MarkedBlock::VoidFunctor { - inline void visit(JSCell* cell) - { - if (cell->isZapped()) - return; - Heap::heap(cell)->setMarked(cell); - } - IterationStatus operator()(JSCell* cell) - { - visit(cell); - return IterationStatus::Continue; - } -}; - -struct Count : public MarkedBlock::CountFunctor { - void operator()(JSCell*) { count(1); } -}; - -struct CountIfGlobalObject : MarkedBlock::CountFunctor { - inline void visit(JSCell* cell) - { - if (!cell->isObject()) - return; - if (!asObject(cell)->isGlobalObject()) - return; - count(1); - } - IterationStatus operator()(JSCell* cell) - { - visit(cell); - return IterationStatus::Continue; - } -}; - -class RecordType { -public: - typedef std::unique_ptr ReturnType; - - RecordType(); - IterationStatus operator()(JSCell*); - ReturnType returnValue(); - -private: - const char* typeName(JSCell*); - std::unique_ptr m_typeCountSet; -}; - -inline RecordType::RecordType() - : m_typeCountSet(std::make_unique()) +void recordType(TypeCountSet& set, JSCell* cell) { + const char* typeName = "[unknown]"; + const ClassInfo* info = cell->classInfo(); + if (info && info->className) + typeName = info->className; + set.add(typeName); } -inline const char* RecordType::typeName(JSCell* cell) +bool measurePhaseTiming() { - const ClassInfo* info = cell->classInfo(); - if (!info || !info->className) - return "[unknown]"; - return info->className; + return false; } -inline IterationStatus RecordType::operator()(JSCell* cell) +HashMap>& timingStats() { - m_typeCountSet->add(typeName(cell)); - return IterationStatus::Continue; + static HashMap>* result; + static std::once_flag once; + std::call_once( + once, + [] { + result = new HashMap>(); + }); + return *result; } -inline std::unique_ptr RecordType::returnValue() +SimpleStats& timingStats(const char* name, HeapOperation operation) { - return WTFMove(m_typeCountSet); + return timingStats().add(name, GCTypeMap()).iterator->value[operation]; } +class TimingScope { +public: + TimingScope(HeapOperation operation, const char* name) + : m_operation(operation) + , m_name(name) + { + if (measurePhaseTiming()) + m_before = monotonicallyIncreasingTimeMS(); + } + + TimingScope(Heap& heap, const char* name) + : TimingScope(heap.operationInProgress(), name) + { + } + + void setOperation(HeapOperation operation) + { + m_operation = operation; + } + + void setOperation(Heap& heap) + { + setOperation(heap.operationInProgress()); + } + + ~TimingScope() + { + if (measurePhaseTiming()) { + double after = monotonicallyIncreasingTimeMS(); + double timing = after - m_before; + SimpleStats& stats = timingStats(m_name, m_operation); + stats.add(timing); + dataLog("[GC:", m_operation, "] ", m_name, " took: ", timing, " ms (average ", stats.mean(), " ms).\n"); + } + } +private: + HeapOperation m_operation; + double m_before; + const char* m_name; +}; + } // anonymous namespace Heap::Heap(VM* vm, HeapType heapType) @@ -336,6 +211,8 @@ , m_machineThreads(this) , m_slotVisitor(*this) , m_handleSet(vm) + , m_codeBlocks(std::make_unique()) + , m_jitStubRoutines(std::make_unique()) , m_isSafeToCollect(false) , m_writeBarrierBuffer(256) , m_vm(vm) @@ -351,7 +228,7 @@ , m_sweeper(std::make_unique(this)) #endif , m_deferralDepth(0) -#if USE(CF) +#if USE(FOUNDATION) , m_delayedReleaseRecursionCount(0) #endif , m_helperClient(&heapHelperPool()) @@ -379,7 +256,8 @@ RELEASE_ASSERT(!m_vm->entryScope); RELEASE_ASSERT(m_operationInProgress == NoOperation); - m_codeBlocks.lastChanceToFinalize(); + m_arrayBuffers.lastChanceToFinalize(); + m_codeBlocks->lastChanceToFinalize(); m_objectSpace.lastChanceToFinalize(); releaseDelayedReleasedObjects(); @@ -388,7 +266,7 @@ void Heap::releaseDelayedReleasedObjects() { -#if USE(CF) +#if USE(FOUNDATION) // We need to guard against the case that releasing an object can create more objects due to the // release calling into JS. When those JS call(s) exit and all locks are being dropped we end up // back here and could try to recursively release objects. We guard that with a recursive entry @@ -406,7 +284,9 @@ // We need to drop locks before calling out to arbitrary code. JSLock::DropAllLocks dropAllLocks(m_vm); + void* context = objc_autoreleasePoolPush(); objectsToRelease.clear(); + objc_autoreleasePoolPop(context); } } } @@ -430,22 +310,17 @@ { // Our clients don't know exactly how much memory they // are abandoning so we just guess for them. - double abandonedBytes = 0.1 * m_sizeAfterLastCollect; + size_t abandonedBytes = static_cast(0.1 * capacity()); // We want to accelerate the next collection. Because memory has just // been abandoned, the next collection has the potential to // be more profitable. Since allocation is the trigger for collection, // we hasten the next collection by pretending that we've allocated more memory. - didAbandon(abandonedBytes); -} - -void Heap::didAbandon(size_t bytes) -{ if (m_fullActivityCallback) { m_fullActivityCallback->didAllocate( m_sizeAfterLastCollect - m_sizeAfterLastFullCollect + m_bytesAllocatedThisCycle + m_bytesAbandonedSinceLastFullCollect); } - m_bytesAbandonedSinceLastFullCollect += bytes; + m_bytesAbandonedSinceLastFullCollect += abandonedBytes; } void Heap::protect(JSValue k) @@ -485,15 +360,9 @@ void Heap::finalizeUnconditionalFinalizers() { - GCPHASE(FinalizeUnconditionalFinalizers); m_slotVisitor.finalizeUnconditionalFinalizers(); } -inline JSStack& Heap::stack() -{ - return m_vm->interpreter->stack(); -} - void Heap::willStartIterating() { m_objectSpace.willStartIterating(); @@ -504,8 +373,11 @@ m_objectSpace.didFinishIterating(); } -void Heap::completeAllDFGPlans() +void Heap::completeAllJITPlans() { +#if ENABLE(JIT) + JITWorklist::instance()->completeAllForVM(*m_vm); +#endif // ENABLE(JIT) #if ENABLE(DFG_JIT) DFG::completeAllPlansForVM(*m_vm); #endif @@ -513,78 +385,86 @@ void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters) { - SamplingRegion samplingRegion("Garbage Collection: Marking"); - - GCPHASE(MarkRoots); + TimingScope markRootsTimingScope(*this, "Heap::markRoots"); + ASSERT(isValidThreadState(m_vm)); - // We gather conservative roots before clearing mark bits because conservative - // gathering uses the mark bits to determine whether a reference is valid. - ConservativeRoots conservativeRoots(&m_objectSpace.blocks(), &m_storageSpace); - gatherStackRoots(conservativeRoots, stackOrigin, stackTop, calleeSavedRegisters); - gatherJSStackRoots(conservativeRoots); - gatherScratchBufferRoots(conservativeRoots); + HeapRootVisitor heapRootVisitor(m_slotVisitor); + + ConservativeRoots conservativeRoots(*this); + { + TimingScope preConvergenceTimingScope(*this, "Heap::markRoots before convergence"); + // We gather conservative roots before clearing mark bits because conservative + // gathering uses the mark bits to determine whether a reference is valid. + { + TimingScope preConvergenceTimingScope(*this, "Heap::markRoots conservative scan"); + SuperSamplerScope superSamplerScope(false); + gatherStackRoots(conservativeRoots, stackOrigin, stackTop, calleeSavedRegisters); + gatherJSStackRoots(conservativeRoots); + gatherScratchBufferRoots(conservativeRoots); + } #if ENABLE(DFG_JIT) - DFG::rememberCodeBlocks(*m_vm); + DFG::rememberCodeBlocks(*m_vm); #endif #if ENABLE(SAMPLING_PROFILER) - if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) { - // Note that we need to own the lock from now until we're done - // marking the SamplingProfiler's data because once we verify the - // SamplingProfiler's stack traces, we don't want it to accumulate - // more stack traces before we get the chance to mark it. - // This lock is released inside visitSamplingProfiler(). - samplingProfiler->getLock().lock(); - samplingProfiler->processUnverifiedStackTraces(); - } + if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) { + // Note that we need to own the lock from now until we're done + // marking the SamplingProfiler's data because once we verify the + // SamplingProfiler's stack traces, we don't want it to accumulate + // more stack traces before we get the chance to mark it. + // This lock is released inside visitSamplingProfiler(). + samplingProfiler->getLock().lock(); + samplingProfiler->processUnverifiedStackTraces(); + } #endif // ENABLE(SAMPLING_PROFILER) - if (m_operationInProgress == FullCollection) { - m_opaqueRoots.clear(); - m_slotVisitor.clearMarkStack(); - } - - clearLivenessData(); - - m_parallelMarkersShouldExit = false; + if (m_operationInProgress == FullCollection) { + m_opaqueRoots.clear(); + m_slotVisitor.clearMarkStack(); + } - m_helperClient.setFunction( - [this] () { - SlotVisitor* slotVisitor; - { - LockHolder locker(m_parallelSlotVisitorLock); - if (m_availableParallelSlotVisitors.isEmpty()) { - std::unique_ptr newVisitor = - std::make_unique(*this); - slotVisitor = newVisitor.get(); - m_parallelSlotVisitors.append(WTFMove(newVisitor)); - } else - slotVisitor = m_availableParallelSlotVisitors.takeLast(); - } + clearLivenessData(); - WTF::registerGCThread(); + m_parallelMarkersShouldExit = false; - { - ParallelModeEnabler parallelModeEnabler(*slotVisitor); - slotVisitor->didStartMarking(); - slotVisitor->drainFromShared(SlotVisitor::SlaveDrain); - } - - { - LockHolder locker(m_parallelSlotVisitorLock); - m_availableParallelSlotVisitors.append(slotVisitor); - } - }); + m_helperClient.setFunction( + [this] () { + SlotVisitor* slotVisitor; + { + LockHolder locker(m_parallelSlotVisitorLock); + if (m_availableParallelSlotVisitors.isEmpty()) { + std::unique_ptr newVisitor = + std::make_unique(*this); + slotVisitor = newVisitor.get(); + m_parallelSlotVisitors.append(WTFMove(newVisitor)); + } else + slotVisitor = m_availableParallelSlotVisitors.takeLast(); + } + + WTF::registerGCThread(); + + { + ParallelModeEnabler parallelModeEnabler(*slotVisitor); + slotVisitor->didStartMarking(); + slotVisitor->drainFromShared(SlotVisitor::SlaveDrain); + } + + { + LockHolder locker(m_parallelSlotVisitorLock); + m_availableParallelSlotVisitors.append(slotVisitor); + } + }); - m_slotVisitor.didStartMarking(); + m_slotVisitor.didStartMarking(); + } - HeapRootVisitor heapRootVisitor(m_slotVisitor); - { + SuperSamplerScope superSamplerScope(false); + TimingScope convergenceTimingScope(*this, "Heap::markRoots convergence"); ParallelModeEnabler enabler(m_slotVisitor); - + m_slotVisitor.donateAndDrain(); visitExternalRememberedSet(); visitSmallStrings(); @@ -595,9 +475,12 @@ visitStrongHandles(heapRootVisitor); visitHandleStack(heapRootVisitor); visitSamplingProfiler(); + visitShadowChicken(); traceCodeBlocksAndJITStubRoutines(); converge(); } + + TimingScope postConvergenceTimingScope(*this, "Heap::markRoots after convergence"); // Weak references must be marked last because their liveness depends on // the liveness of the rest of the object graph. @@ -615,7 +498,7 @@ void Heap::copyBackingStores() { - GCPHASE(CopyBackingStores); + SuperSamplerScope superSamplerScope(false); if (m_operationInProgress == EdenCollection) m_storageSpace.startedCopying(); else { @@ -652,12 +535,6 @@ CopyWorkList& workList = block->workList(); for (CopyWorklistItem item : workList) { - if (item.token() == ButterflyCopyToken) { - JSObject::copyBackingStore( - item.cell(), copyVisitor, ButterflyCopyToken); - continue; - } - item.cell()->methodTable()->copyBackingStore( item.cell(), copyVisitor, item.token()); } @@ -673,16 +550,14 @@ void Heap::gatherStackRoots(ConservativeRoots& roots, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters) { - GCPHASE(GatherStackRoots); - m_jitStubRoutines.clearMarks(); - m_machineThreads.gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks, stackOrigin, stackTop, calleeSavedRegisters); + m_jitStubRoutines->clearMarks(); + m_machineThreads.gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks, stackOrigin, stackTop, calleeSavedRegisters); } void Heap::gatherJSStackRoots(ConservativeRoots& roots) { #if !ENABLE(JIT) - GCPHASE(GatherJSStackRoots); - stack().gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks); + m_vm->interpreter->cloopStack().gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks); #else UNUSED_PARAM(roots); #endif @@ -691,7 +566,6 @@ void Heap::gatherScratchBufferRoots(ConservativeRoots& roots) { #if ENABLE(DFG_JIT) - GCPHASE(GatherScratchBufferRoots); m_vm->gatherConservativeRoots(roots); #else UNUSED_PARAM(roots); @@ -700,12 +574,19 @@ void Heap::clearLivenessData() { - GCPHASE(ClearLivenessData); + TimingScope timingScope(*this, "Heap::clearLivenessData"); if (m_operationInProgress == FullCollection) - m_codeBlocks.clearMarksForFullCollection(); - - m_objectSpace.clearNewlyAllocated(); - m_objectSpace.clearMarks(); + m_codeBlocks->clearMarksForFullCollection(); + + { + TimingScope clearNewlyAllocatedTimingScope(*this, "m_objectSpace.clearNewlyAllocated"); + m_objectSpace.clearNewlyAllocated(); + } + + { + TimingScope clearMarksTimingScope(*this, "m_objectSpace.clearMarks"); + m_objectSpace.flip(); + } } void Heap::visitExternalRememberedSet() @@ -717,7 +598,6 @@ void Heap::visitSmallStrings() { - GCPHASE(VisitSmallStrings); if (!m_vm->smallStrings.needsToBeVisited(m_operationInProgress)) return; @@ -729,7 +609,6 @@ void Heap::visitConservativeRoots(ConservativeRoots& roots) { - GCPHASE(VisitConservativeRoots); m_slotVisitor.append(roots); if (Options::logGC() == GCLogging::Verbose) @@ -752,16 +631,74 @@ void Heap::removeDeadCompilerWorklistEntries() { #if ENABLE(DFG_JIT) - GCPHASE(FinalizeDFGWorklists); for (auto worklist : m_suspendedCompilerWorklists) worklist->removeDeadPlans(*m_vm); #endif } -void Heap::visitProtectedObjects(HeapRootVisitor& heapRootVisitor) +bool Heap::isHeapSnapshotting() const +{ + HeapProfiler* heapProfiler = m_vm->heapProfiler(); + if (UNLIKELY(heapProfiler)) + return heapProfiler->activeSnapshotBuilder(); + return false; +} + +struct GatherHeapSnapshotData : MarkedBlock::CountFunctor { + GatherHeapSnapshotData(HeapSnapshotBuilder& builder) + : m_builder(builder) + { + } + + IterationStatus operator()(HeapCell* heapCell, HeapCell::Kind kind) const + { + if (kind == HeapCell::JSCell) { + JSCell* cell = static_cast(heapCell); + cell->methodTable()->heapSnapshot(cell, m_builder); + } + return IterationStatus::Continue; + } + + HeapSnapshotBuilder& m_builder; +}; + +void Heap::gatherExtraHeapSnapshotData(HeapProfiler& heapProfiler) { - GCPHASE(VisitProtectedObjects); + if (HeapSnapshotBuilder* builder = heapProfiler.activeSnapshotBuilder()) { + HeapIterationScope heapIterationScope(*this); + GatherHeapSnapshotData functor(*builder); + m_objectSpace.forEachLiveCell(heapIterationScope, functor); + } +} +struct RemoveDeadHeapSnapshotNodes : MarkedBlock::CountFunctor { + RemoveDeadHeapSnapshotNodes(HeapSnapshot& snapshot) + : m_snapshot(snapshot) + { + } + + IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const + { + if (kind == HeapCell::JSCell) + m_snapshot.sweepCell(static_cast(cell)); + return IterationStatus::Continue; + } + + HeapSnapshot& m_snapshot; +}; + +void Heap::removeDeadHeapSnapshotNodes(HeapProfiler& heapProfiler) +{ + if (HeapSnapshot* snapshot = heapProfiler.mostRecentSnapshot()) { + HeapIterationScope heapIterationScope(*this); + RemoveDeadHeapSnapshotNodes functor(*snapshot); + m_objectSpace.forEachDeadCell(heapIterationScope, functor); + snapshot->shrinkToFit(); + } +} + +void Heap::visitProtectedObjects(HeapRootVisitor& heapRootVisitor) +{ for (auto& pair : m_protectedValues) heapRootVisitor.visit(&pair.key); @@ -773,7 +710,6 @@ void Heap::visitArgumentBuffers(HeapRootVisitor& visitor) { - GCPHASE(MarkingArgumentBuffers); if (!m_markListSet || !m_markListSet->size()) return; @@ -787,7 +723,6 @@ void Heap::visitException(HeapRootVisitor& visitor) { - GCPHASE(MarkingException); if (!m_vm->exception() && !m_vm->lastException()) return; @@ -802,7 +737,6 @@ void Heap::visitStrongHandles(HeapRootVisitor& visitor) { - GCPHASE(VisitStrongHandles); m_handleSet.visitStrongHandles(visitor); if (Options::logGC() == GCLogging::Verbose) @@ -813,7 +747,6 @@ void Heap::visitHandleStack(HeapRootVisitor& visitor) { - GCPHASE(VisitHandleStack); m_handleStack.visit(visitor); if (Options::logGC() == GCLogging::Verbose) @@ -827,7 +760,6 @@ #if ENABLE(SAMPLING_PROFILER) if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) { ASSERT(samplingProfiler->getLock().isLocked()); - GCPHASE(VisitSamplingProfiler); samplingProfiler->visit(m_slotVisitor); if (Options::logGC() == GCLogging::Verbose) dataLog("Sampling Profiler data:\n", m_slotVisitor); @@ -838,10 +770,14 @@ #endif // ENABLE(SAMPLING_PROFILER) } +void Heap::visitShadowChicken() +{ + m_vm->shadowChicken().visitChildren(m_slotVisitor); +} + void Heap::traceCodeBlocksAndJITStubRoutines() { - GCPHASE(TraceCodeBlocksAndJITStubRoutines); - m_jitStubRoutines.traceMarkedStubRoutines(m_slotVisitor); + m_jitStubRoutines->traceMarkedStubRoutines(m_slotVisitor); if (Options::logGC() == GCLogging::Verbose) dataLog("Code Blocks and JIT Stub Routines:\n", m_slotVisitor); @@ -851,15 +787,17 @@ void Heap::converge() { - GCPHASE(Convergence); m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain); } void Heap::visitWeakHandles(HeapRootVisitor& visitor) { - GCPHASE(VisitingLiveWeakHandles); + TimingScope timingScope(*this, "Heap::visitWeakHandles"); while (true) { - m_objectSpace.visitWeakSets(visitor); + { + TimingScope timingScope(*this, "m_objectSpace.visitWeakSets"); + m_objectSpace.visitWeakSets(visitor); + } harvestWeakReferences(); visitCompilerWorklistWeakReferences(); if (m_slotVisitor.isEmpty()) @@ -878,8 +816,6 @@ void Heap::updateObjectCounts(double gcStartTime) { - GCCOUNTER(VisitedValueCount, m_slotVisitor.visitCount() + threadVisitCount()); - if (Options::logGC() == GCLogging::Verbose) { size_t visitCount = m_slotVisitor.visitCount(); visitCount += threadVisitCount(); @@ -935,29 +871,64 @@ size_t Heap::protectedGlobalObjectCount() { - return forEachProtectedCell(); + size_t result = 0; + forEachProtectedCell( + [&] (JSCell* cell) { + if (cell->isObject() && asObject(cell)->isGlobalObject()) + result++; + }); + return result; } size_t Heap::globalObjectCount() { HeapIterationScope iterationScope(*this); - return m_objectSpace.forEachLiveCell(iterationScope); + size_t result = 0; + m_objectSpace.forEachLiveCell( + iterationScope, + [&] (HeapCell* heapCell, HeapCell::Kind kind) -> IterationStatus { + if (kind != HeapCell::JSCell) + return IterationStatus::Continue; + JSCell* cell = static_cast(heapCell); + if (cell->isObject() && asObject(cell)->isGlobalObject()) + result++; + return IterationStatus::Continue; + }); + return result; } size_t Heap::protectedObjectCount() { - return forEachProtectedCell(); + size_t result = 0; + forEachProtectedCell( + [&] (JSCell*) { + result++; + }); + return result; } std::unique_ptr Heap::protectedObjectTypeCounts() { - return forEachProtectedCell(); + std::unique_ptr result = std::make_unique(); + forEachProtectedCell( + [&] (JSCell* cell) { + recordType(*result, cell); + }); + return result; } std::unique_ptr Heap::objectTypeCounts() { + std::unique_ptr result = std::make_unique(); HeapIterationScope iterationScope(*this); - return m_objectSpace.forEachLiveCell(iterationScope); + m_objectSpace.forEachLiveCell( + iterationScope, + [&] (HeapCell* cell, HeapCell::Kind kind) -> IterationStatus { + if (kind == HeapCell::JSCell) + recordType(*result, static_cast(cell)); + return IterationStatus::Continue; + }); + return result; } void Heap::deleteAllCodeBlocks() @@ -967,7 +938,7 @@ RELEASE_ASSERT(!m_vm->entryScope); ASSERT(m_operationInProgress == NoOperation); - completeAllDFGPlans(); + completeAllJITPlans(); for (ExecutableBase* executable : m_executables) executable->clearCode(); @@ -984,7 +955,6 @@ void Heap::clearUnmarkedExecutables() { - GCPHASE(ClearUnmarkedExecutables); for (unsigned i = m_executables.size(); i--;) { ExecutableBase* current = m_executables[i]; if (isMarked(current)) @@ -1002,10 +972,9 @@ void Heap::deleteUnmarkedCompiledCode() { - GCPHASE(DeleteCodeBlocks); clearUnmarkedExecutables(); - m_codeBlocks.deleteUnmarkedAndUnreferenced(m_operationInProgress); - m_jitStubRoutines.deleteUnmarkedJettisonedStubRoutines(); + m_codeBlocks->deleteUnmarkedAndUnreferenced(m_operationInProgress); + m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines(); } void Heap::addToRememberedSet(const JSCell* cell) @@ -1022,33 +991,36 @@ m_slotVisitor.appendToMarkStack(const_cast(cell)); } -void* Heap::copyBarrier(const JSCell*, void*& pointer) -{ - // Do nothing for now, except making sure that the low bits are masked off. This helps to - // simulate enough of this barrier that at least we can test the low bits assumptions. - pointer = bitwise_cast( - bitwise_cast(pointer) & ~static_cast(CopyBarrierBase::spaceBits)); - - return pointer; -} - -void Heap::collectAndSweep(HeapOperation collectionType) +void Heap::collectAllGarbage() { + SuperSamplerScope superSamplerScope(false); if (!m_isSafeToCollect) return; - collect(collectionType); - - SamplingRegion samplingRegion("Garbage Collection: Sweeping"); + collectWithoutAnySweep(FullCollection); DeferGCForAWhile deferGC(*this); - m_objectSpace.sweep(); - m_objectSpace.shrink(); + if (UNLIKELY(Options::useImmortalObjects())) + sweeper()->willFinishSweeping(); + else { + m_objectSpace.sweep(); + m_objectSpace.shrink(); + } + ASSERT(m_blockSnapshot.isEmpty()); sweepAllLogicallyEmptyWeakBlocks(); } -NEVER_INLINE void Heap::collect(HeapOperation collectionType) +void Heap::collect(HeapOperation collectionType) +{ + SuperSamplerScope superSamplerScope(false); + if (!m_isSafeToCollect) + return; + + collectWithoutAnySweep(collectionType); +} + +NEVER_INLINE void Heap::collectWithoutAnySweep(HeapOperation collectionType) { void* stackTop; ALLOCATE_AND_GET_REGISTER_STATE(registers); @@ -1060,6 +1032,9 @@ NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters) { + SuperSamplerScope superSamplerScope(false); + TimingScope collectImplTimingScope(collectionType, "Heap::collectImpl"); + #if ENABLE(ALLOCATION_LOGGING) dataLogF("JSC GC starting collection.\n"); #endif @@ -1070,45 +1045,60 @@ before = currentTimeMS(); } - SamplingRegion samplingRegion("Garbage Collection"); - - if (vm()->typeProfiler()) { - DeferGCForAWhile awhile(*this); - vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC")); - } - - RELEASE_ASSERT(!m_deferralDepth); - ASSERT(vm()->currentThreadIsHoldingAPILock()); - RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable()); - ASSERT(m_isSafeToCollect); - JAVASCRIPTCORE_GC_BEGIN(); - RELEASE_ASSERT(m_operationInProgress == NoOperation); + double gcStartTime; + { + TimingScope earlyTimingScope(collectionType, "Heap::collectImpl before markRoots"); - suspendCompilerThreads(); - willStartCollection(collectionType); - GCPHASE(Collect); + if (vm()->typeProfiler()) { + DeferGCForAWhile awhile(*this); + vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC")); + } - double gcStartTime = WTF::monotonicallyIncreasingTime(); - if (m_verifier) { - // Verify that live objects from the last GC cycle haven't been corrupted by - // mutators before we begin this new GC cycle. - m_verifier->verify(HeapVerifier::Phase::BeforeGC); +#if ENABLE(JIT) + { + DeferGCForAWhile awhile(*this); + JITWorklist::instance()->completeAllForVM(*m_vm); + } +#endif // ENABLE(JIT) - m_verifier->initializeGCCycle(); - m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking); - } + vm()->shadowChicken().update(*vm(), vm()->topCallFrame); + + RELEASE_ASSERT(!m_deferralDepth); + ASSERT(vm()->currentThreadIsHoldingAPILock()); + RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable()); + ASSERT(m_isSafeToCollect); + RELEASE_ASSERT(m_operationInProgress == NoOperation); + + suspendCompilerThreads(); + willStartCollection(collectionType); + + collectImplTimingScope.setOperation(*this); + earlyTimingScope.setOperation(*this); - flushOldStructureIDTables(); - stopAllocation(); - flushWriteBarrierBuffer(); + gcStartTime = WTF::monotonicallyIncreasingTime(); + if (m_verifier) { + // Verify that live objects from the last GC cycle haven't been corrupted by + // mutators before we begin this new GC cycle. + m_verifier->verify(HeapVerifier::Phase::BeforeGC); + + m_verifier->initializeGCCycle(); + m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking); + } + + flushOldStructureIDTables(); + stopAllocation(); + prepareForMarking(); + flushWriteBarrierBuffer(); + } markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters); + + TimingScope lateTimingScope(*this, "Heap::collectImpl after markRoots"); if (m_verifier) { m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking); m_verifier->verify(HeapVerifier::Phase::AfterMarking); } - JAVASCRIPTCORE_GC_MARKED(); if (vm()->typeProfiler()) vm()->typeProfiler()->invalidateTypeSetCache(); @@ -1117,13 +1107,12 @@ pruneStaleEntriesFromWeakGCMaps(); sweepArrayBuffers(); snapshotMarkedSpace(); - copyBackingStores(); - finalizeUnconditionalFinalizers(); removeDeadCompilerWorklistEntries(); deleteUnmarkedCompiledCode(); deleteSourceProviderCaches(); + notifyIncrementalSweeper(); writeBarrierCurrentlyExecutingCodeBlocks(); @@ -1131,7 +1120,8 @@ updateAllocationLimits(); didFinishCollection(gcStartTime); resumeCompilerThreads(); - + sweepLargeAllocations(); + if (m_verifier) { m_verifier->trimDeadObjects(); m_verifier->verify(HeapVerifier::Phase::AfterGC); @@ -1143,10 +1133,14 @@ } } +void Heap::sweepLargeAllocations() +{ + m_objectSpace.sweepLargeAllocations(); +} + void Heap::suspendCompilerThreads() { #if ENABLE(DFG_JIT) - GCPHASE(SuspendCompilerThreads); ASSERT(m_suspendedCompilerWorklists.isEmpty()); for (unsigned i = DFG::numberOfWorklists(); i--;) { if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) { @@ -1159,8 +1153,6 @@ void Heap::willStartCollection(HeapOperation collectionType) { - GCPHASE(StartingCollection); - if (Options::logGC()) dataLog("=> "); @@ -1178,6 +1170,9 @@ m_sizeBeforeLastFullCollect = m_sizeAfterLastCollect + m_bytesAllocatedThisCycle; m_extraMemorySize = 0; m_deprecatedExtraMemorySize = 0; +#if ENABLE(RESOURCE_USAGE) + m_externalMemorySize = 0; +#endif if (m_fullActivityCallback) m_fullActivityCallback->willCollect(); @@ -1195,13 +1190,11 @@ void Heap::flushOldStructureIDTables() { - GCPHASE(FlushOldStructureIDTables); m_structureIDTable.flushOldTables(); } void Heap::flushWriteBarrierBuffer() { - GCPHASE(FlushWriteBarrierBuffer); if (m_operationInProgress == EdenCollection) { m_writeBarrierBuffer.flush(*this); return; @@ -1211,21 +1204,23 @@ void Heap::stopAllocation() { - GCPHASE(StopAllocation); m_objectSpace.stopAllocating(); if (m_operationInProgress == FullCollection) m_storageSpace.didStartFullCollection(); } +void Heap::prepareForMarking() +{ + m_objectSpace.prepareForMarking(); +} + void Heap::reapWeakHandles() { - GCPHASE(ReapingWeakHandles); m_objectSpace.reapWeakSets(); } void Heap::pruneStaleEntriesFromWeakGCMaps() { - GCPHASE(PruningStaleEntriesFromWeakGCMaps); if (m_operationInProgress != FullCollection) return; for (auto& pruneCallback : m_weakGCMaps.values()) @@ -1234,32 +1229,42 @@ void Heap::sweepArrayBuffers() { - GCPHASE(SweepingArrayBuffers); m_arrayBuffers.sweep(); } struct MarkedBlockSnapshotFunctor : public MarkedBlock::VoidFunctor { - MarkedBlockSnapshotFunctor(Vector& blocks) + MarkedBlockSnapshotFunctor(Vector& blocks) : m_index(0) , m_blocks(blocks) { } - void operator()(MarkedBlock* block) { m_blocks[m_index++] = block; } + void operator()(MarkedBlock::Handle* block) const + { + block->setIsOnBlocksToSweep(true); + m_blocks[m_index++] = block; + } - size_t m_index; - Vector& m_blocks; + // FIXME: This is a mutable field becaue this isn't a C++ lambda. + // https://bugs.webkit.org/show_bug.cgi?id=159644 + mutable size_t m_index; + Vector& m_blocks; }; void Heap::snapshotMarkedSpace() { - GCPHASE(SnapshotMarkedSpace); - + TimingScope timingScope(*this, "Heap::snapshotMarkedSpace"); + // FIXME: This should probably be renamed. It's not actually snapshotting all of MarkedSpace. + // This is used by IncrementalSweeper, so it only needs to snapshot blocks. However, if we ever + // wanted to add other snapshotting login, we'd probably put it here. + if (m_operationInProgress == EdenCollection) { - m_blockSnapshot.appendVector(m_objectSpace.blocksWithNewObjects()); - // Sort and deduplicate the block snapshot since we might be appending to an unfinished work list. - std::sort(m_blockSnapshot.begin(), m_blockSnapshot.end()); - m_blockSnapshot.shrink(std::unique(m_blockSnapshot.begin(), m_blockSnapshot.end()) - m_blockSnapshot.begin()); + for (MarkedBlock::Handle* handle : m_objectSpace.blocksWithNewObjects()) { + if (handle->isOnBlocksToSweep()) + continue; + m_blockSnapshot.append(handle); + handle->setIsOnBlocksToSweep(true); + } } else { m_blockSnapshot.resizeToFit(m_objectSpace.blocks().set().size()); MarkedBlockSnapshotFunctor functor(m_blockSnapshot); @@ -1269,14 +1274,11 @@ void Heap::deleteSourceProviderCaches() { - GCPHASE(DeleteSourceProviderCaches); m_vm->clearSourceProviderCaches(); } void Heap::notifyIncrementalSweeper() { - GCPHASE(NotifyIncrementalSweeper); - if (m_operationInProgress == FullCollection) { if (!m_logicallyEmptyWeakBlocks.isEmpty()) m_indexOfNextLogicallyEmptyWeakBlockToSweep = 0; @@ -1287,19 +1289,22 @@ void Heap::writeBarrierCurrentlyExecutingCodeBlocks() { - GCPHASE(WriteBarrierCurrentlyExecutingCodeBlocks); - m_codeBlocks.writeBarrierCurrentlyExecutingCodeBlocks(this); + m_codeBlocks->writeBarrierCurrentlyExecutingCodeBlocks(this); } void Heap::resetAllocators() { - GCPHASE(ResetAllocators); m_objectSpace.resetAllocators(); } void Heap::updateAllocationLimits() { - GCPHASE(UpdateAllocationLimits); + static const bool verbose = false; + + if (verbose) { + dataLog("\n"); + dataLog("bytesAllocatedThisCycle = ", m_bytesAllocatedThisCycle, "\n"); + } // Calculate our current heap size threshold for the purpose of figuring out when we should // run another collection. This isn't the same as either size() or capacity(), though it should @@ -1316,6 +1321,8 @@ // of fragmentation, this may be substantial. Fortunately, marked space rarely fragments because // cells usually have a narrow range of sizes. So, the underestimation is probably OK. currentHeapSize += m_totalBytesVisited; + if (verbose) + dataLog("totalBytesVisited = ", m_totalBytesVisited, ", currentHeapSize = ", currentHeapSize, "\n"); // For copied space, we use the capacity of storage space. This is because copied space may get // badly fragmented between full collections. This arises when each eden collection evacuates @@ -1331,10 +1338,15 @@ // https://bugs.webkit.org/show_bug.cgi?id=150268 ASSERT(m_totalBytesCopied <= m_storageSpace.size()); currentHeapSize += m_storageSpace.capacity(); + if (verbose) + dataLog("storageSpace.capacity() = ", m_storageSpace.capacity(), ", currentHeapSize = ", currentHeapSize, "\n"); // It's up to the user to ensure that extraMemorySize() ends up corresponding to allocation-time // extra memory reporting. currentHeapSize += extraMemorySize(); + + if (verbose) + dataLog("extraMemorySize() = ", extraMemorySize(), ", currentHeapSize = ", currentHeapSize, "\n"); if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize()) HeapStatistics::exitWithFailure(); @@ -1344,29 +1356,38 @@ // the new allocation limit based on the current size of the heap, with a // fixed minimum. m_maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize)); + if (verbose) + dataLog("Full: maxHeapSize = ", m_maxHeapSize, "\n"); m_maxEdenSize = m_maxHeapSize - currentHeapSize; + if (verbose) + dataLog("Full: maxEdenSize = ", m_maxEdenSize, "\n"); m_sizeAfterLastFullCollect = currentHeapSize; + if (verbose) + dataLog("Full: sizeAfterLastFullCollect = ", currentHeapSize, "\n"); m_bytesAbandonedSinceLastFullCollect = 0; + if (verbose) + dataLog("Full: bytesAbandonedSinceLastFullCollect = ", 0, "\n"); } else { - static const bool verbose = false; - ASSERT(currentHeapSize >= m_sizeAfterLastCollect); - m_maxEdenSize = m_maxHeapSize - currentHeapSize; + // Theoretically, we shouldn't ever scan more memory than the heap size we planned to have. + // But we are sloppy, so we have to defend against the overflow. + m_maxEdenSize = currentHeapSize > m_maxHeapSize ? 0 : m_maxHeapSize - currentHeapSize; + if (verbose) + dataLog("Eden: maxEdenSize = ", m_maxEdenSize, "\n"); m_sizeAfterLastEdenCollect = currentHeapSize; - if (verbose) { - dataLog("Max heap size: ", m_maxHeapSize, "\n"); - dataLog("Current heap size: ", currentHeapSize, "\n"); - dataLog("Size after last eden collection: ", m_sizeAfterLastEdenCollect, "\n"); - } - double edenToOldGenerationRatio = (double)m_maxEdenSize / (double)m_maxHeapSize; if (verbose) - dataLog("Eden to old generation ratio: ", edenToOldGenerationRatio, "\n"); + dataLog("Eden: sizeAfterLastEdenCollect = ", currentHeapSize, "\n"); + double edenToOldGenerationRatio = (double)m_maxEdenSize / (double)m_maxHeapSize; double minEdenToOldGenerationRatio = 1.0 / 3.0; if (edenToOldGenerationRatio < minEdenToOldGenerationRatio) m_shouldDoFullCollection = true; // This seems suspect at first, but what it does is ensure that the nursery size is fixed. m_maxHeapSize += currentHeapSize - m_sizeAfterLastCollect; + if (verbose) + dataLog("Eden: maxHeapSize = ", m_maxHeapSize, "\n"); m_maxEdenSize = m_maxHeapSize - currentHeapSize; + if (verbose) + dataLog("Eden: maxEdenSize = ", m_maxEdenSize, "\n"); if (m_fullActivityCallback) { ASSERT(currentHeapSize >= m_sizeAfterLastFullCollect); m_fullActivityCallback->didAllocate(currentHeapSize - m_sizeAfterLastFullCollect); @@ -1374,6 +1395,8 @@ } m_sizeAfterLastCollect = currentHeapSize; + if (verbose) + dataLog("sizeAfterLastCollect = ", m_sizeAfterLastCollect, "\n"); m_bytesAllocatedThisCycle = 0; if (Options::logGC()) @@ -1382,7 +1405,6 @@ void Heap::didFinishCollection(double gcStartTime) { - GCPHASE(FinishingCollection); double gcEndTime = WTF::monotonicallyIncreasingTime(); HeapOperation operation = m_operationInProgress; if (m_operationInProgress == FullCollection) @@ -1390,24 +1412,26 @@ else m_lastEdenGCLength = gcEndTime - gcStartTime; +#if ENABLE(RESOURCE_USAGE) + ASSERT(externalMemorySize() <= extraMemorySize()); +#endif + if (Options::recordGCPauseTimes()) HeapStatistics::recordGCPauseTime(gcStartTime, gcEndTime); if (Options::useZombieMode()) zombifyDeadObjects(); - if (Options::useImmortalObjects()) - markDeadObjects(); - if (Options::dumpObjectStatistics()) HeapStatistics::dumpObjectStatistics(this); - if (Options::logGC() == GCLogging::Verbose) - GCLogging::dumpObjectGraph(this); + if (HeapProfiler* heapProfiler = m_vm->heapProfiler()) { + gatherExtraHeapSnapshotData(*heapProfiler); + removeDeadHeapSnapshotNodes(*heapProfiler); + } RELEASE_ASSERT(m_operationInProgress == EdenCollection || m_operationInProgress == FullCollection); m_operationInProgress = NoOperation; - JAVASCRIPTCORE_GC_END(); for (auto* observer : m_observers) observer->didGarbageCollect(operation); @@ -1416,19 +1440,12 @@ void Heap::resumeCompilerThreads() { #if ENABLE(DFG_JIT) - GCPHASE(ResumeCompilerThreads); for (auto worklist : m_suspendedCompilerWorklists) worklist->resumeAllThreads(); m_suspendedCompilerWorklists.clear(); #endif } -void Heap::markDeadObjects() -{ - HeapIterationScope iterationScope(*this); - m_objectSpace.forEachDeadCell(iterationScope); -} - void Heap::setFullActivityCallback(PassRefPtr activityCallback) { m_fullActivityCallback = activityCallback; @@ -1522,20 +1539,20 @@ class Zombify : public MarkedBlock::VoidFunctor { public: - inline void visit(JSCell* cell) + inline void visit(HeapCell* cell) const { - void** current = reinterpret_cast(cell); + void** current = reinterpret_cast_ptr(cell); // We want to maintain zapped-ness because that's how we know if we've called // the destructor. if (cell->isZapped()) current++; - void* limit = static_cast(reinterpret_cast(cell) + MarkedBlock::blockFor(cell)->cellSize()); + void* limit = static_cast(reinterpret_cast(cell) + cell->cellSize()); for (; current < limit; current++) *current = zombifiedBits; } - IterationStatus operator()(JSCell* cell) + IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const { visit(cell); return IterationStatus::Continue; @@ -1545,12 +1562,9 @@ void Heap::zombifyDeadObjects() { // Sweep now because destructors will crash once we're zombified. - { - SamplingRegion samplingRegion("Garbage Collection: Sweeping"); - m_objectSpace.zombifySweep(); - } + m_objectSpace.zombifySweep(); HeapIterationScope iterationScope(*this); - m_objectSpace.forEachDeadCell(iterationScope); + m_objectSpace.forEachDeadCell(iterationScope, Zombify()); } void Heap::flushWriteBarrierBuffer(JSCell* cell) @@ -1640,4 +1654,12 @@ return result; } +void Heap::forEachCodeBlockImpl(const ScopedLambda& func) +{ + // We don't know the full set of CodeBlocks until compilation has terminated. + completeAllJITPlans(); + + return m_codeBlocks->iterate(func); +} + } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/Heap.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/Heap.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/Heap.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/Heap.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003-2009, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2003-2009, 2013-2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,14 +23,12 @@ #define Heap_h #include "ArrayBuffer.h" -#include "CodeBlockSet.h" #include "CopyVisitor.h" #include "GCIncomingRefCountedSet.h" #include "HandleSet.h" #include "HandleStack.h" #include "HeapObserver.h" #include "HeapOperation.h" -#include "JITStubRoutineSet.h" #include "ListableHandler.h" #include "MachineStackMarker.h" #include "MarkedAllocator.h" @@ -53,6 +51,7 @@ namespace JSC { class CodeBlock; +class CodeBlockSet; class CopiedSpace; class EdenGCActivityCallback; class ExecutableBase; @@ -60,12 +59,13 @@ class GCActivityCallback; class GCAwareJITStubRoutine; class Heap; +class HeapProfiler; class HeapRootVisitor; class HeapVerifier; class IncrementalSweeper; class JITStubRoutine; +class JITStubRoutineSet; class JSCell; -class JSStack; class JSValue; class LLIntOffsetsExtractor; class MarkedArgumentBuffer; @@ -83,13 +83,15 @@ enum HeapType { SmallHeap, LargeHeap }; +class HeapUtil; + class Heap { WTF_MAKE_NONCOPYABLE(Heap); public: friend class JIT; friend class DFG::SpeculativeJIT; static Heap* heap(const JSValue); // 0 for immediate values - static Heap* heap(const JSCell*); + static Heap* heap(const HeapCell*); // This constant determines how many blocks we iterate between checks of our // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect @@ -99,20 +101,16 @@ static bool isLive(const void*); static bool isMarked(const void*); - static bool testAndSetMarked(const void*); + static bool isMarkedConcurrently(const void*); + static bool testAndSetMarked(HeapVersion, const void*); static void setMarked(const void*); - - // This function must be run after stopAllocation() is called and - // before liveness data is cleared to be accurate. - static bool isPointerGCObject(TinyBloomFilter, MarkedBlockSet&, void* pointer); - static bool isValueGCObject(TinyBloomFilter, MarkedBlockSet&, JSValue); + + static size_t cellSize(const void*); void writeBarrier(const JSCell*); void writeBarrier(const JSCell*, JSValue); void writeBarrier(const JSCell*, JSCell*); - JS_EXPORT_PRIVATE static void* copyBarrier(const JSCell* owner, void*& copiedSpacePointer); - WriteBarrierBuffer& writeBarrierBuffer() { return m_writeBarrierBuffer; } void flushWriteBarrierBuffer(JSCell*); @@ -147,11 +145,16 @@ bool isBusy(); MarkedSpace::Subspace& subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); } MarkedSpace::Subspace& subspaceForObjectDestructor() { return m_objectSpace.subspaceForObjectsWithDestructor(); } + MarkedSpace::Subspace& subspaceForAuxiliaryData() { return m_objectSpace.subspaceForAuxiliaryData(); } template MarkedSpace::Subspace& subspaceForObjectOfType(); - MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); } - MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); } - template MarkedAllocator& allocatorForObjectOfType(size_t bytes); + MarkedAllocator* allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); } + MarkedAllocator* allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); } + template MarkedAllocator* allocatorForObjectOfType(size_t bytes); + MarkedAllocator* allocatorForAuxiliaryData(size_t bytes) { return m_objectSpace.auxiliaryAllocatorFor(bytes); } CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); } + void* allocateAuxiliary(JSCell* intendedOwner, size_t); + void* tryAllocateAuxiliary(JSCell* intendedOwner, size_t); + void* tryReallocateAuxiliary(JSCell* intendedOwner, void* oldBase, size_t oldSize, size_t newSize); CheckedBoolean tryAllocateStorage(JSCell* intendedOwner, size_t, void**); CheckedBoolean tryReallocateStorage(JSCell* intendedOwner, void**, size_t, size_t); void ascribeOwner(JSCell* intendedOwner, void*); @@ -163,14 +166,17 @@ void notifyIsSafeToCollect() { m_isSafeToCollect = true; } bool isSafeToCollect() const { return m_isSafeToCollect; } + JS_EXPORT_PRIVATE bool isHeapSnapshotting() const; + JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently(); - void collectAllGarbage() { collectAndSweep(FullCollection); } - JS_EXPORT_PRIVATE void collectAndSweep(HeapOperation collectionType = AnyCollection); + JS_EXPORT_PRIVATE void collectAllGarbage(); + bool shouldCollect(); JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection); bool collectIfNecessaryOrDefer(); // Returns true if it did collect. + void collectAccordingToDeferGCProbability(); - void completeAllDFGPlans(); + void completeAllJITPlans(); // Use this API to report non-GC memory referenced by GC objects. Be sure to // call both of these functions: Calling only one may trigger catastropic @@ -178,6 +184,12 @@ void reportExtraMemoryAllocated(size_t); void reportExtraMemoryVisited(CellState cellStateBeforeVisiting, size_t); +#if ENABLE(RESOURCE_USAGE) + // Use this API to report the subset of extra memory that lives outside this process. + void reportExternalMemoryVisited(CellState cellStateBeforeVisiting, size_t); + size_t externalMemorySize() { return m_externalMemorySize; } +#endif + // Use this API to report non-GC memory if you can't use the better API above. void deprecatedReportExtraMemory(size_t); @@ -198,9 +210,8 @@ HashSet& markListSet(); - template typename Functor::ReturnType forEachProtectedCell(Functor&); - template typename Functor::ReturnType forEachProtectedCell(); - template void forEachCodeBlock(Functor&); + template void forEachProtectedCell(const Functor&); + template void forEachCodeBlock(const Functor&); HandleSet* handleSet() { return &m_handleSet; } HandleStack* handleStack() { return &m_handleStack; } @@ -221,11 +232,9 @@ void deleteAllUnlinkedCodeBlocks(); void didAllocate(size_t); - void didAbandon(size_t); - bool isPagedOut(double deadline); - const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; } + const JITStubRoutineSet& jitStubRoutines() { return *m_jitStubRoutines; } void addReference(JSCell*, ArrayBuffer*); @@ -233,10 +242,10 @@ StructureIDTable& structureIDTable() { return m_structureIDTable; } - CodeBlockSet& codeBlockSet() { return m_codeBlocks; } + CodeBlockSet& codeBlockSet() { return *m_codeBlocks; } -#if USE(CF) - template void releaseSoon(RetainPtr&&); +#if USE(FOUNDATION) + template void releaseSoon(RetainPtr&&); #endif static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; } @@ -262,6 +271,7 @@ friend class GCLogging; friend class GCThread; friend class HandleSet; + friend class HeapUtil; friend class HeapVerifier; friend class JITStubRoutine; friend class LLIntOffsetsExtractor; @@ -278,6 +288,8 @@ template friend void* allocateCell(Heap&); template friend void* allocateCell(Heap&, size_t); + void collectWithoutAnySweep(HeapOperation collectionType = AnyCollection); + void* allocateWithDestructor(size_t); // For use with objects with destructors. void* allocateWithoutDestructor(size_t); // For use with objects without destructors. template void* allocateObjectOfType(size_t); // Chooses one of the methods above based on type. @@ -285,7 +297,7 @@ static const size_t minExtraMemory = 256; class FinalizerOwner : public WeakHandleOwner { - virtual void finalize(Handle, void* context) override; + void finalize(Handle, void* context) override; }; JS_EXPORT_PRIVATE bool isValidAllocation(size_t); @@ -299,6 +311,7 @@ void flushOldStructureIDTables(); void flushWriteBarrierBuffer(); void stopAllocation(); + void prepareForMarking(); void markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&); void gatherStackRoots(ConservativeRoots&, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&); @@ -316,6 +329,7 @@ void visitStrongHandles(HeapRootVisitor&); void visitHandleStack(HeapRootVisitor&); void visitSamplingProfiler(); + void visitShadowChicken(); void traceCodeBlocksAndJITStubRoutines(); void converge(); void visitWeakHandles(HeapRootVisitor&); @@ -340,15 +354,15 @@ void didFinishCollection(double gcStartTime); void resumeCompilerThreads(); void zombifyDeadObjects(); - void markDeadObjects(); - + void gatherExtraHeapSnapshotData(HeapProfiler&); + void removeDeadHeapSnapshotNodes(HeapProfiler&); + void sweepLargeAllocations(); + void sweepAllLogicallyEmptyWeakBlocks(); bool sweepNextLogicallyEmptyWeakBlock(); bool shouldDoFullCollection(HeapOperation requestedCollectionType) const; - JSStack& stack(); - void incrementDeferralDepth(); void decrementDeferralDepth(); void decrementDeferralDepthAndGCIfNeeded(); @@ -356,6 +370,8 @@ size_t threadVisitCount(); size_t threadBytesVisited(); size_t threadBytesCopied(); + + void forEachCodeBlockImpl(const ScopedLambda&); const HeapType m_heapType; const size_t m_ramSize; @@ -403,8 +419,8 @@ HandleSet m_handleSet; HandleStack m_handleStack; - CodeBlockSet m_codeBlocks; - JITStubRoutineSet m_jitStubRoutines; + std::unique_ptr m_codeBlocks; + std::unique_ptr m_jitStubRoutines; FinalizerOwner m_finalizerOwner; bool m_isSafeToCollect; @@ -423,7 +439,7 @@ RefPtr m_fullActivityCallback; RefPtr m_edenActivityCallback; std::unique_ptr m_sweeper; - Vector m_blockSnapshot; + Vector m_blockSnapshot; Vector m_observers; @@ -431,7 +447,8 @@ Vector m_suspendedCompilerWorklists; std::unique_ptr m_verifier; -#if USE(CF) + +#if USE(FOUNDATION) Vector> m_delayedReleaseObjects; unsigned m_delayedReleaseRecursionCount; #endif @@ -458,6 +475,7 @@ #if ENABLE(RESOURCE_USAGE) size_t m_blockBytesAllocated { 0 }; + size_t m_externalMemorySize { 0 }; #endif }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapInlines.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,10 +28,15 @@ #include "CopyBarrier.h" #include "Heap.h" +#include "HeapCellInlines.h" +#include "IndexingHeader.h" +#include "JSCallee.h" #include "JSCell.h" #include "Structure.h" #include #include +#include +#include namespace JSC { @@ -58,9 +63,9 @@ return m_operationInProgress == FullCollection || m_operationInProgress == EdenCollection; } -inline Heap* Heap::heap(const JSCell* cell) +ALWAYS_INLINE Heap* Heap::heap(const HeapCell* cell) { - return MarkedBlock::blockFor(cell)->heap(); + return cell->heap(); } inline Heap* Heap::heap(const JSValue v) @@ -70,24 +75,66 @@ return heap(v.asCell()); } -inline bool Heap::isLive(const void* cell) +inline bool Heap::isLive(const void* rawCell) { - return MarkedBlock::blockFor(cell)->isLiveCell(cell); + ASSERT(!mayBeGCThread()); + HeapCell* cell = bitwise_cast(rawCell); + if (cell->isLargeAllocation()) + return cell->largeAllocation().isLive(); + MarkedBlock& block = cell->markedBlock(); + block.flipIfNecessary(block.vm()->heap.objectSpace().version()); + return block.handle().isLiveCell(cell); +} + +ALWAYS_INLINE bool Heap::isMarked(const void* rawCell) +{ + ASSERT(!mayBeGCThread()); + HeapCell* cell = bitwise_cast(rawCell); + if (cell->isLargeAllocation()) + return cell->largeAllocation().isMarked(); + MarkedBlock& block = cell->markedBlock(); + if (block.needsFlip(block.vm()->heap.objectSpace().version())) + return false; + return block.isMarked(cell); +} + +ALWAYS_INLINE bool Heap::isMarkedConcurrently(const void* rawCell) +{ + HeapCell* cell = bitwise_cast(rawCell); + if (cell->isLargeAllocation()) + return cell->largeAllocation().isMarked(); + MarkedBlock& block = cell->markedBlock(); + if (block.needsFlip(block.vm()->heap.objectSpace().version())) + return false; + WTF::loadLoadFence(); + return block.isMarked(cell); } -inline bool Heap::isMarked(const void* cell) +ALWAYS_INLINE bool Heap::testAndSetMarked(HeapVersion version, const void* rawCell) { - return MarkedBlock::blockFor(cell)->isMarked(cell); + HeapCell* cell = bitwise_cast(rawCell); + if (cell->isLargeAllocation()) + return cell->largeAllocation().testAndSetMarked(); + MarkedBlock& block = cell->markedBlock(); + block.flipIfNecessaryConcurrently(version); + return block.testAndSetMarked(cell); } -inline bool Heap::testAndSetMarked(const void* cell) +inline void Heap::setMarked(const void* rawCell) { - return MarkedBlock::blockFor(cell)->testAndSetMarked(cell); + HeapCell* cell = bitwise_cast(rawCell); + if (cell->isLargeAllocation()) { + cell->largeAllocation().setMarked(); + return; + } + MarkedBlock& block = cell->markedBlock(); + block.flipIfNecessary(block.vm()->heap.objectSpace().version()); + block.setMarked(cell); } -inline void Heap::setMarked(const void* cell) +ALWAYS_INLINE size_t Heap::cellSize(const void* rawCell) { - MarkedBlock::blockFor(cell)->setMarked(cell); + return bitwise_cast(rawCell)->cellSize(); } inline void Heap::writeBarrier(const JSCell* from, JSValue to) @@ -141,33 +188,39 @@ } } +#if ENABLE(RESOURCE_USAGE) +inline void Heap::reportExternalMemoryVisited(CellState dataBeforeVisiting, size_t size) +{ + // We don't want to double-count the external memory that was reported in previous collections. + if (operationInProgress() == EdenCollection && dataBeforeVisiting == CellState::OldGrey) + return; + + size_t* counter = &m_externalMemorySize; + + for (;;) { + size_t oldSize = *counter; + if (WTF::weakCompareAndSwap(counter, oldSize, oldSize + size)) + return; + } +} +#endif + inline void Heap::deprecatedReportExtraMemory(size_t size) { if (size > minExtraMemory) deprecatedReportExtraMemorySlowCase(size); } -template inline void Heap::forEachCodeBlock(Functor& functor) +template inline void Heap::forEachCodeBlock(const Functor& func) { - // We don't know the full set of CodeBlocks until compilation has terminated. - completeAllDFGPlans(); - - return m_codeBlocks.iterate(functor); + forEachCodeBlockImpl(scopedLambdaRef(func)); } -template inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor) +template inline void Heap::forEachProtectedCell(const Functor& functor) { for (auto& pair : m_protectedValues) functor(pair.key); m_handleSet.forEachStrongHandle(functor, m_protectedValues); - - return functor.returnValue(); -} - -template inline typename Functor::ReturnType Heap::forEachProtectedCell() -{ - Functor functor; - return forEachProtectedCell(functor); } inline void* Heap::allocateWithDestructor(size_t bytes) @@ -189,7 +242,7 @@ } template -void* Heap::allocateObjectOfType(size_t bytes) +inline void* Heap::allocateObjectOfType(size_t bytes) { // JSCell::classInfo() expects objects allocated with normal destructor to derive from JSDestructibleObject. ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags & StructureIsImmortal) || std::is_convertible::value)); @@ -200,7 +253,7 @@ } template -MarkedSpace::Subspace& Heap::subspaceForObjectOfType() +inline MarkedSpace::Subspace& Heap::subspaceForObjectOfType() { // JSCell::classInfo() expects objects allocated with normal destructor to derive from JSDestructibleObject. ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags & StructureIsImmortal) || std::is_convertible::value)); @@ -211,14 +264,50 @@ } template -MarkedAllocator& Heap::allocatorForObjectOfType(size_t bytes) +inline MarkedAllocator* Heap::allocatorForObjectOfType(size_t bytes) { // JSCell::classInfo() expects objects allocated with normal destructor to derive from JSDestructibleObject. ASSERT((!ClassType::needsDestruction || (ClassType::StructureFlags & StructureIsImmortal) || std::is_convertible::value)); - + + MarkedAllocator* result; if (ClassType::needsDestruction) - return allocatorForObjectWithDestructor(bytes); - return allocatorForObjectWithoutDestructor(bytes); + result = allocatorForObjectWithDestructor(bytes); + else + result = allocatorForObjectWithoutDestructor(bytes); + + ASSERT(result || !ClassType::info()->isSubClassOf(JSCallee::info())); + return result; +} + +inline void* Heap::allocateAuxiliary(JSCell* intendedOwner, size_t bytes) +{ + void* result = m_objectSpace.allocateAuxiliary(bytes); +#if ENABLE(ALLOCATION_LOGGING) + dataLogF("JSC GC allocating %lu bytes of auxiliary for %p: %p.\n", bytes, intendedOwner, result); +#else + UNUSED_PARAM(intendedOwner); +#endif + return result; +} + +inline void* Heap::tryAllocateAuxiliary(JSCell* intendedOwner, size_t bytes) +{ + void* result = m_objectSpace.tryAllocateAuxiliary(bytes); +#if ENABLE(ALLOCATION_LOGGING) + dataLogF("JSC GC allocating %lu bytes of auxiliary for %p: %p.\n", bytes, intendedOwner, result); +#else + UNUSED_PARAM(intendedOwner); +#endif + return result; +} + +inline void* Heap::tryReallocateAuxiliary(JSCell* intendedOwner, void* oldBase, size_t oldSize, size_t newSize) +{ + void* newBase = tryAllocateAuxiliary(intendedOwner, newSize); + if (!newBase) + return nullptr; + memcpy(newBase, oldBase, oldSize); + return newBase; } inline CheckedBoolean Heap::tryAllocateStorage(JSCell* intendedOwner, size_t bytes, void** outPtr) @@ -256,7 +345,7 @@ #endif } -#if USE(CF) +#if USE(FOUNDATION) template inline void Heap::releaseSoon(RetainPtr&& object) { @@ -285,10 +374,28 @@ return true; } +inline void Heap::collectAccordingToDeferGCProbability() +{ + if (isDeferred() || !m_isSafeToCollect || m_operationInProgress != NoOperation) + return; + + if (randomNumber() < Options::deferGCProbability()) { + collect(); + return; + } + + // If our coin flip told us not to GC, we still might GC, + // but we GC according to our memory pressure markers. + collectIfNecessaryOrDefer(); +} + inline void Heap::decrementDeferralDepthAndGCIfNeeded() { decrementDeferralDepth(); - collectIfNecessaryOrDefer(); + if (UNLIKELY(Options::deferGCShouldCollectWithProbability())) + collectAccordingToDeferGCProbability(); + else + collectIfNecessaryOrDefer(); } inline HashSet& Heap::markListSet() @@ -326,33 +433,6 @@ #endif } -inline bool Heap::isPointerGCObject(TinyBloomFilter filter, MarkedBlockSet& markedBlockSet, void* pointer) -{ - MarkedBlock* candidate = MarkedBlock::blockFor(pointer); - if (filter.ruleOut(bitwise_cast(candidate))) { - ASSERT(!candidate || !markedBlockSet.set().contains(candidate)); - return false; - } - - if (!MarkedBlock::isAtomAligned(pointer)) - return false; - - if (!markedBlockSet.set().contains(candidate)) - return false; - - if (!candidate->isLiveCell(pointer)) - return false; - - return true; -} - -inline bool Heap::isValueGCObject(TinyBloomFilter filter, MarkedBlockSet& markedBlockSet, JSValue value) -{ - if (!value.isCell()) - return false; - return isPointerGCObject(filter, markedBlockSet, static_cast(value.asCell())); -} - } // namespace JSC #endif // HeapInlines_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapOperation.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapOperation.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapOperation.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapOperation.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HeapOperation.h" + +#include + +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, HeapOperation operation) +{ + switch (operation) { + case NoOperation: + out.print("None"); + return; + case Allocation: + out.print("Alloc"); + return; + case FullCollection: + out.print("Full"); + return; + case EdenCollection: + out.print("Eden"); + return; + case AnyCollection: + out.print("Any"); + return; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF + + + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapOperation.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapOperation.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapOperation.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapOperation.h 2016-11-03 07:04:20.000000000 +0000 @@ -32,4 +32,12 @@ } // namespace JSC +namespace WTF { + +class PrintStream; + +void printInternal(PrintStream& out, JSC::HeapOperation); + +} // namespace WTF + #endif // HeapOperation_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapProfiler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapProfiler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapProfiler.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapProfiler.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HeapProfiler.h" + +#include "HeapSnapshot.h" +#include "VM.h" + +namespace JSC { + +HeapProfiler::HeapProfiler(VM& vm) + : m_vm(vm) +{ +} + +HeapProfiler::~HeapProfiler() +{ +} + +HeapSnapshot* HeapProfiler::mostRecentSnapshot() +{ + if (m_snapshots.isEmpty()) + return nullptr; + return m_snapshots.last().get(); +} + +void HeapProfiler::appendSnapshot(std::unique_ptr snapshot) +{ + m_snapshots.append(WTFMove(snapshot)); +} + +void HeapProfiler::clearSnapshots() +{ + m_snapshots.clear(); +} + +void HeapProfiler::setActiveSnapshotBuilder(HeapSnapshotBuilder* builder) +{ + ASSERT(!!m_activeBuilder != !!builder); + m_activeBuilder = builder; +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapProfiler.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapProfiler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapProfiler.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapProfiler.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HeapProfiler_h +#define HeapProfiler_h + +#include + +namespace JSC { + +class HeapSnapshot; +class HeapSnapshotBuilder; +class VM; + +class HeapProfiler { + WTF_MAKE_FAST_ALLOCATED; +public: + HeapProfiler(VM&); + ~HeapProfiler(); + + VM& vm() const { return m_vm; } + + HeapSnapshot* mostRecentSnapshot(); + void appendSnapshot(std::unique_ptr); + void clearSnapshots(); + + HeapSnapshotBuilder* activeSnapshotBuilder() const { return m_activeBuilder; } + void setActiveSnapshotBuilder(HeapSnapshotBuilder*); + +private: + VM& m_vm; + Vector> m_snapshots; + HeapSnapshotBuilder* m_activeBuilder { nullptr }; +}; + +} // namespace JSC + +#endif // HeapProfiler_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp 2016-10-13 08:26:50.000000000 +0000 @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HeapSnapshotBuilder.h" + +#include "DeferGC.h" +#include "Heap.h" +#include "HeapProfiler.h" +#include "HeapSnapshot.h" +#include "JSCInlines.h" +#include "JSCell.h" +#include "VM.h" +#include + +namespace JSC { + +unsigned HeapSnapshotBuilder::nextAvailableObjectIdentifier = 1; +unsigned HeapSnapshotBuilder::getNextObjectIdentifier() { return nextAvailableObjectIdentifier++; } +void HeapSnapshotBuilder::resetNextAvailableObjectIdentifier() { HeapSnapshotBuilder::nextAvailableObjectIdentifier = 1; } + +HeapSnapshotBuilder::HeapSnapshotBuilder(HeapProfiler& profiler) + : m_profiler(profiler) +{ +} + +HeapSnapshotBuilder::~HeapSnapshotBuilder() +{ +} + +void HeapSnapshotBuilder::buildSnapshot() +{ + m_snapshot = std::make_unique(m_profiler.mostRecentSnapshot()); + { + m_profiler.setActiveSnapshotBuilder(this); + m_profiler.vm().heap.collectAllGarbage(); + m_profiler.setActiveSnapshotBuilder(nullptr); + } + m_snapshot->finalize(); + + m_profiler.appendSnapshot(WTFMove(m_snapshot)); +} + +void HeapSnapshotBuilder::appendNode(JSCell* cell) +{ + ASSERT(m_profiler.activeSnapshotBuilder() == this); + ASSERT(Heap::isMarkedConcurrently(cell)); + + if (hasExistingNodeForCell(cell)) + return; + + std::lock_guard lock(m_buildingNodeMutex); + + m_snapshot->appendNode(HeapSnapshotNode(cell, getNextObjectIdentifier())); +} + +void HeapSnapshotBuilder::appendEdge(JSCell* from, JSCell* to) +{ + ASSERT(m_profiler.activeSnapshotBuilder() == this); + ASSERT(to); + + // Avoid trivial edges. + if (from == to) + return; + + std::lock_guard lock(m_buildingEdgeMutex); + + m_edges.append(HeapSnapshotEdge(from, to)); +} + +void HeapSnapshotBuilder::appendPropertyNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* propertyName) +{ + ASSERT(m_profiler.activeSnapshotBuilder() == this); + ASSERT(to); + + std::lock_guard lock(m_buildingEdgeMutex); + + m_edges.append(HeapSnapshotEdge(from, to, EdgeType::Property, propertyName)); +} + +void HeapSnapshotBuilder::appendVariableNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* variableName) +{ + ASSERT(m_profiler.activeSnapshotBuilder() == this); + ASSERT(to); + + std::lock_guard lock(m_buildingEdgeMutex); + + m_edges.append(HeapSnapshotEdge(from, to, EdgeType::Variable, variableName)); +} + +void HeapSnapshotBuilder::appendIndexEdge(JSCell* from, JSCell* to, uint32_t index) +{ + ASSERT(m_profiler.activeSnapshotBuilder() == this); + ASSERT(to); + + std::lock_guard lock(m_buildingEdgeMutex); + + m_edges.append(HeapSnapshotEdge(from, to, index)); +} + +bool HeapSnapshotBuilder::hasExistingNodeForCell(JSCell* cell) +{ + if (!m_snapshot->previous()) + return false; + + return !!m_snapshot->previous()->nodeForCell(cell); +} + + +// Heap Snapshot JSON Format: +// +// { +// "version": 1.0, +// "nodes": [ +// , , , , +// , , , , +// ... +// ], +// "nodeClassNames": [ +// "string", "Structure", "Object", ... +// ], +// "edges": [ +// , , , , +// , , , , +// ... +// ], +// "edgeTypes": [ +// "Internal", "Property", "Index", "Variable" +// ], +// "edgeNames": [ +// "propertyName", "variableName", ... +// ] +// } +// +// Notes: +// +// +// - index into the "nodeClassNames" list. +// +// +// - 0 = false, 1 = true. +// +// +// - index into the "edgeTypes" list. +// +// +// - for Internal edges this should be ignored (0). +// - for Index edges this is the index value. +// - for Property or Variable edges this is an index into the "edgeNames" list. + +static uint8_t edgeTypeToNumber(EdgeType type) +{ + return static_cast(type); +} + +static const char* edgeTypeToString(EdgeType type) +{ + switch (type) { + case EdgeType::Internal: + return "Internal"; + case EdgeType::Property: + return "Property"; + case EdgeType::Index: + return "Index"; + case EdgeType::Variable: + return "Variable"; + } + ASSERT_NOT_REACHED(); + return "Internal"; +} + +String HeapSnapshotBuilder::json() +{ + return json([] (const HeapSnapshotNode&) { return true; }); +} + +String HeapSnapshotBuilder::json(std::function allowNodeCallback) +{ + VM& vm = m_profiler.vm(); + DeferGCForAWhile deferGC(vm.heap); + + // Build a node to identifier map of allowed nodes to use when serializing edges. + HashMap allowedNodeIdentifiers; + + // Build a list of used class names. + HashMap classNameIndexes; + classNameIndexes.set("", 0); + unsigned nextClassNameIndex = 1; + + // Build a list of used edge names. + HashMap edgeNameIndexes; + unsigned nextEdgeNameIndex = 0; + + StringBuilder json; + + auto appendNodeJSON = [&] (const HeapSnapshotNode& node) { + // Let the client decide if they want to allow or disallow certain nodes. + if (!allowNodeCallback(node)) + return; + + allowedNodeIdentifiers.set(node.cell, node.identifier); + + auto result = classNameIndexes.add(node.cell->classInfo()->className, nextClassNameIndex); + if (result.isNewEntry) + nextClassNameIndex++; + unsigned classNameIndex = result.iterator->value; + + bool isInternal = false; + if (!node.cell->isString()) { + Structure* structure = node.cell->structure(vm); + isInternal = !structure || !structure->globalObject(); + } + + // , , , + json.append(','); + json.appendNumber(node.identifier); + json.append(','); + json.appendNumber(node.cell->estimatedSizeInBytes()); + json.append(','); + json.appendNumber(classNameIndex); + json.append(','); + json.append(isInternal ? '1' : '0'); + }; + + bool firstEdge = true; + auto appendEdgeJSON = [&] (const HeapSnapshotEdge& edge) { + if (!firstEdge) + json.append(','); + firstEdge = false; + + // , , , + json.appendNumber(edge.from.identifier); + json.append(','); + json.appendNumber(edge.to.identifier); + json.append(','); + json.appendNumber(edgeTypeToNumber(edge.type)); + json.append(','); + switch (edge.type) { + case EdgeType::Property: + case EdgeType::Variable: { + auto result = edgeNameIndexes.add(edge.u.name, nextEdgeNameIndex); + if (result.isNewEntry) + nextEdgeNameIndex++; + unsigned edgeNameIndex = result.iterator->value; + json.appendNumber(edgeNameIndex); + break; + } + case EdgeType::Index: + json.appendNumber(edge.u.index); + break; + default: + // No data for this edge type. + json.append('0'); + break; + } + }; + + json.append('{'); + + // version + json.appendLiteral("\"version\":1"); + + // nodes + json.append(','); + json.appendLiteral("\"nodes\":"); + json.append('['); + json.appendLiteral("0,0,0,0"); // + for (HeapSnapshot* snapshot = m_profiler.mostRecentSnapshot(); snapshot; snapshot = snapshot->previous()) { + for (auto& node : snapshot->m_nodes) + appendNodeJSON(node); + } + json.append(']'); + + // node class names + json.append(','); + json.appendLiteral("\"nodeClassNames\":"); + json.append('['); + Vector orderedClassNames(classNameIndexes.size()); + for (auto& entry : classNameIndexes) + orderedClassNames[entry.value] = entry.key; + classNameIndexes.clear(); + bool firstClassName = true; + for (auto& className : orderedClassNames) { + if (!firstClassName) + json.append(','); + firstClassName = false; + json.appendQuotedJSONString(className); + } + orderedClassNames.clear(); + json.append(']'); + + // Process edges. + // Replace pointers with identifiers. + // Remove any edges that we won't need. + m_edges.removeAllMatching([&] (HeapSnapshotEdge& edge) { + // If the from cell is null, this means a edge. + if (!edge.from.cell) + edge.from.identifier = 0; + else { + auto fromLookup = allowedNodeIdentifiers.find(edge.from.cell); + if (fromLookup == allowedNodeIdentifiers.end()) + return true; + edge.from.identifier = fromLookup->value; + } + + if (!edge.to.cell) + edge.to.identifier = 0; + else { + auto toLookup = allowedNodeIdentifiers.find(edge.to.cell); + if (toLookup == allowedNodeIdentifiers.end()) + return true; + edge.to.identifier = toLookup->value; + } + + return false; + }); + allowedNodeIdentifiers.clear(); + m_edges.shrinkToFit(); + + // Sort edges based on from identifier. + std::sort(m_edges.begin(), m_edges.end(), [&] (const HeapSnapshotEdge& a, const HeapSnapshotEdge& b) { + return a.from.identifier < b.from.identifier; + }); + + // edges + json.append(','); + json.appendLiteral("\"edges\":"); + json.append('['); + for (auto& edge : m_edges) + appendEdgeJSON(edge); + json.append(']'); + + // edge types + json.append(','); + json.appendLiteral("\"edgeTypes\":"); + json.append('['); + json.appendQuotedJSONString(edgeTypeToString(EdgeType::Internal)); + json.append(','); + json.appendQuotedJSONString(edgeTypeToString(EdgeType::Property)); + json.append(','); + json.appendQuotedJSONString(edgeTypeToString(EdgeType::Index)); + json.append(','); + json.appendQuotedJSONString(edgeTypeToString(EdgeType::Variable)); + json.append(']'); + + // edge names + json.append(','); + json.appendLiteral("\"edgeNames\":"); + json.append('['); + Vector orderedEdgeNames(edgeNameIndexes.size()); + for (auto& entry : edgeNameIndexes) + orderedEdgeNames[entry.value] = entry.key; + edgeNameIndexes.clear(); + bool firstEdgeName = true; + for (auto& edgeName : orderedEdgeNames) { + if (!firstEdgeName) + json.append(','); + firstEdgeName = false; + json.appendQuotedJSONString(edgeName); + } + orderedEdgeNames.clear(); + json.append(']'); + + json.append('}'); + return json.toString(); +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshotBuilder.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshotBuilder.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshotBuilder.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshotBuilder.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HeapSnapshotBuilder_h +#define HeapSnapshotBuilder_h + +#include +#include +#include +#include +#include + +namespace JSC { + +class HeapProfiler; +class HeapSnapshot; +class JSCell; + +struct HeapSnapshotNode { + HeapSnapshotNode(JSCell* cell, unsigned identifier) + : cell(cell) + , identifier(identifier) + { } + + JSCell* cell; + unsigned identifier; +}; + +enum class EdgeType : uint8_t { + Internal, // Normal strong reference. No name. + Property, // Named property. In `object.property` the name is "property" + Index, // Indexed property. In `array[0]` name is index "0". + Variable, // Variable held by a scope. In `let x, f=() => x++` name is "x" in f's captured scope. + // FIXME: Heap Snapshot should include "Weak" edges +}; + +struct HeapSnapshotEdge { + HeapSnapshotEdge(JSCell* fromCell, JSCell* toCell) + : type(EdgeType::Internal) + { + from.cell = fromCell; + to.cell = toCell; + } + + HeapSnapshotEdge(JSCell* fromCell, JSCell* toCell, EdgeType type, UniquedStringImpl* name) + : type(type) + { + ASSERT(type == EdgeType::Property || type == EdgeType::Variable); + from.cell = fromCell; + to.cell = toCell; + u.name = name; + } + + HeapSnapshotEdge(JSCell* fromCell, JSCell* toCell, uint32_t index) + : type(EdgeType::Index) + { + from.cell = fromCell; + to.cell = toCell; + u.index = index; + } + + union { + JSCell *cell; + unsigned identifier; + } from; + + union { + JSCell *cell; + unsigned identifier; + } to; + + union { + UniquedStringImpl* name; + uint32_t index; + } u; + + EdgeType type; +}; + +class JS_EXPORT_PRIVATE HeapSnapshotBuilder { + WTF_MAKE_FAST_ALLOCATED; +public: + HeapSnapshotBuilder(HeapProfiler&); + ~HeapSnapshotBuilder(); + + static unsigned nextAvailableObjectIdentifier; + static unsigned getNextObjectIdentifier(); + static void resetNextAvailableObjectIdentifier(); + + // Performs a garbage collection that builds a snapshot of all live cells. + void buildSnapshot(); + + // A marked cell. + void appendNode(JSCell*); + + // A reference from one cell to another. + void appendEdge(JSCell* from, JSCell* to); + void appendPropertyNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* propertyName); + void appendVariableNameEdge(JSCell* from, JSCell* to, UniquedStringImpl* variableName); + void appendIndexEdge(JSCell* from, JSCell* to, uint32_t index); + + String json(); + String json(std::function allowNodeCallback); + +private: + // Finalized snapshots are not modified during building. So searching them + // for an existing node can be done concurrently without a lock. + bool hasExistingNodeForCell(JSCell*); + + HeapProfiler& m_profiler; + + // SlotVisitors run in parallel. + Lock m_buildingNodeMutex; + std::unique_ptr m_snapshot; + Lock m_buildingEdgeMutex; + Vector m_edges; +}; + +} // namespace JSC + +#endif // HeapSnapshotBuilder_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshot.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshot.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshot.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshot.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HeapSnapshot.h" + +#include "JSCInlines.h" + +namespace JSC { + +HeapSnapshot::HeapSnapshot(HeapSnapshot* previousSnapshot) + : m_previous(previousSnapshot) +{ +} + +HeapSnapshot::~HeapSnapshot() +{ +} + +void HeapSnapshot::appendNode(const HeapSnapshotNode& node) +{ + ASSERT(!m_finalized); + ASSERT(!m_previous || !m_previous->nodeForCell(node.cell)); + + m_nodes.append(node); + m_filter.add(bitwise_cast(node.cell)); +} + +void HeapSnapshot::sweepCell(JSCell* cell) +{ + ASSERT(cell); + + if (m_finalized && !m_filter.ruleOut(bitwise_cast(cell))) { + ASSERT_WITH_MESSAGE(!isEmpty(), "Our filter should have ruled us out if we are empty."); + unsigned start = 0; + unsigned end = m_nodes.size(); + while (start != end) { + unsigned middle = start + ((end - start) / 2); + HeapSnapshotNode& node = m_nodes[middle]; + if (cell == node.cell) { + // Cells should always have 0 as low bits. + // Mark this cell for removal by setting the low bit. + ASSERT(!(reinterpret_cast(node.cell) & CellToSweepTag)); + node.cell = reinterpret_cast(reinterpret_cast(node.cell) | CellToSweepTag); + m_hasCellsToSweep = true; + return; + } + if (cell < node.cell) + end = middle; + else + start = middle + 1; + } + } + + if (m_previous) + m_previous->sweepCell(cell); +} + +void HeapSnapshot::shrinkToFit() +{ + if (m_finalized && m_hasCellsToSweep) { + m_filter.reset(); + m_nodes.removeAllMatching( + [&] (const HeapSnapshotNode& node) -> bool { + bool willRemoveCell = bitwise_cast(node.cell) & CellToSweepTag; + if (!willRemoveCell) + m_filter.add(bitwise_cast(node.cell)); + return willRemoveCell; + }); + m_nodes.shrinkToFit(); + m_hasCellsToSweep = false; + } + + if (m_previous) + m_previous->shrinkToFit(); +} + +void HeapSnapshot::finalize() +{ + ASSERT(!m_finalized); + m_finalized = true; + + // Nodes are appended to the snapshot in identifier order. + // Now that we have the complete list of nodes we will sort + // them in a different order. Remember the range of identifiers + // in this snapshot. + if (!isEmpty()) { + m_firstObjectIdentifier = m_nodes.first().identifier; + m_lastObjectIdentifier = m_nodes.last().identifier; + } + + std::sort(m_nodes.begin(), m_nodes.end(), [] (const HeapSnapshotNode& a, const HeapSnapshotNode& b) { + return a.cell < b.cell; + }); + +#ifndef NDEBUG + // Assert there are no duplicates or nullptr cells. + JSCell* previousCell = nullptr; + for (auto& node : m_nodes) { + ASSERT(node.cell); + ASSERT(!(reinterpret_cast(node.cell) & CellToSweepTag)); + if (previousCell) + ASSERT(node.cell != previousCell); + previousCell = node.cell; + } +#endif +} + +Optional HeapSnapshot::nodeForCell(JSCell* cell) +{ + ASSERT(m_finalized); + + if (!m_filter.ruleOut(bitwise_cast(cell))) { + ASSERT_WITH_MESSAGE(!isEmpty(), "Our filter should have ruled us out if we are empty."); + unsigned start = 0; + unsigned end = m_nodes.size(); + while (start != end) { + unsigned middle = start + ((end - start) / 2); + HeapSnapshotNode& node = m_nodes[middle]; + if (cell == node.cell) + return Optional(node); + if (cell < node.cell) + end = middle; + else + start = middle + 1; + } + } + + if (m_previous) + return m_previous->nodeForCell(cell); + + return Nullopt; +} + +Optional HeapSnapshot::nodeForObjectIdentifier(unsigned objectIdentifier) +{ + if (isEmpty()) { + if (m_previous) + return m_previous->nodeForObjectIdentifier(objectIdentifier); + return Nullopt; + } + + if (objectIdentifier > m_lastObjectIdentifier) + return Nullopt; + + if (objectIdentifier < m_firstObjectIdentifier) { + if (m_previous) + return m_previous->nodeForObjectIdentifier(objectIdentifier); + return Nullopt; + } + + for (auto& node : m_nodes) { + if (node.identifier == objectIdentifier) + return Optional(node); + } + + return Nullopt; +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshot.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshot.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapSnapshot.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapSnapshot.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HeapSnapshot_h +#define HeapSnapshot_h + +#include "HeapSnapshotBuilder.h" +#include "TinyBloomFilter.h" +#include + +namespace JSC { + +class HeapSnapshot { + WTF_MAKE_FAST_ALLOCATED; +public: + HeapSnapshot(HeapSnapshot*); + ~HeapSnapshot(); + + HeapSnapshot* previous() const { return m_previous; } + + void appendNode(const HeapSnapshotNode&); + void sweepCell(JSCell*); + void shrinkToFit(); + void finalize(); + + bool isEmpty() const { return m_nodes.isEmpty(); } + Optional nodeForCell(JSCell*); + Optional nodeForObjectIdentifier(unsigned objectIdentifier); + +private: + friend class HeapSnapshotBuilder; + static const intptr_t CellToSweepTag = 1; + + Vector m_nodes; + TinyBloomFilter m_filter; + HeapSnapshot* m_previous { nullptr }; + unsigned m_firstObjectIdentifier { 0 }; + unsigned m_lastObjectIdentifier { 0 }; + bool m_finalized { false }; + bool m_hasCellsToSweep { false }; +}; + +} // namespace JSC + +#endif // HeapSnapshot_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapStatistics.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapStatistics.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapStatistics.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapStatistics.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -146,7 +146,7 @@ public: StorageStatistics(); - IterationStatus operator()(JSCell*); + IterationStatus operator()(HeapCell*, HeapCell::Kind) const; size_t objectWithOutOfLineStorageCount(); size_t objectCount(); @@ -190,9 +190,13 @@ m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase); } -inline IterationStatus StorageStatistics::operator()(JSCell* cell) +inline IterationStatus StorageStatistics::operator()(HeapCell* cell, HeapCell::Kind kind) const { - visit(cell); + if (kind == HeapCell::JSCell) { + // FIXME: This const_cast exists because this isn't a C++ lambda. + // https://bugs.webkit.org/show_bug.cgi?id=159644 + const_cast(this)->visit(static_cast(cell)); + } return IterationStatus::Continue; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapTimer.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapTimer.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapTimer.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapTimer.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -80,9 +80,9 @@ JSLock* apiLock = static_cast(context); apiLock->lock(); - VM* vm = apiLock->vm(); - // The VM has been destroyed, so we should just give up. + RefPtr vm = apiLock->vm(); if (!vm) { + // The VM has been destroyed, so we should just give up. apiLock->unlock(); return; } @@ -98,7 +98,7 @@ RELEASE_ASSERT_NOT_REACHED(); { - JSLockHolder locker(vm); + JSLockHolder locker(vm.get()); heapTimer->doWork(); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapUtil.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapUtil.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapUtil.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapUtil.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace JSC { + +// Are you tired of waiting for all of WebKit to build because you changed the implementation of a +// function in HeapInlines.h? Does it bother you that you're waiting on rebuilding the JS DOM +// bindings even though your change is in a function called from only 2 .cpp files? Then HeapUtil.h +// is for you! Everything in this class should be a static method that takes a Heap& if needed. +// This is a friend of Heap, so you can access all of Heap's privates. +// +// This ends up being an issue because Heap exposes a lot of methods that ought to be inline for +// performance or that must be inline because they are templates. This class ought to contain +// methods that are used for the implementation of the collector, or for unusual clients that need +// to reach deep into the collector for some reason. Don't put things in here that would cause you +// to have to include it from more than a handful of places, since that would defeat the purpose. +// This class isn't here to look pretty. It's to let us hack the GC more easily! + +class HeapUtil { +public: + // This function must be run after stopAllocation() is called and + // before liveness data is cleared to be accurate. + template + static void findGCObjectPointersForMarking( + Heap& heap, HeapVersion heapVersion, TinyBloomFilter filter, void* passedPointer, + const Func& func) + { + const HashSet& set = heap.objectSpace().blocks().set(); + + char* pointer = static_cast(passedPointer); + + // It could point to a large allocation. + if (heap.objectSpace().largeAllocationsForThisCollectionSize()) { + if (heap.objectSpace().largeAllocationsForThisCollectionBegin()[0]->aboveLowerBound(pointer) + && heap.objectSpace().largeAllocationsForThisCollectionEnd()[-1]->belowUpperBound(pointer)) { + LargeAllocation** result = approximateBinarySearch( + heap.objectSpace().largeAllocationsForThisCollectionBegin(), + heap.objectSpace().largeAllocationsForThisCollectionSize(), + LargeAllocation::fromCell(pointer), + [] (LargeAllocation** ptr) -> LargeAllocation* { return *ptr; }); + if (result) { + if (result > heap.objectSpace().largeAllocationsForThisCollectionBegin() + && result[-1]->contains(pointer)) + func(result[-1]->cell()); + if (result[0]->contains(pointer)) + func(result[0]->cell()); + if (result + 1 < heap.objectSpace().largeAllocationsForThisCollectionEnd() + && result[1]->contains(pointer)) + func(result[1]->cell()); + } + } + } + + MarkedBlock* candidate = MarkedBlock::blockFor(pointer); + // It's possible for a butterfly pointer to point past the end of a butterfly. Check this now. + if (pointer <= bitwise_cast(candidate) + sizeof(IndexingHeader)) { + // We may be interested in the last cell of the previous MarkedBlock. + char* previousPointer = pointer - sizeof(IndexingHeader) - 1; + MarkedBlock* previousCandidate = MarkedBlock::blockFor(previousPointer); + if (!filter.ruleOut(bitwise_cast(previousCandidate)) + && set.contains(previousCandidate) + && previousCandidate->handle().cellKind() == HeapCell::Auxiliary) { + previousCandidate->flipIfNecessary(heapVersion); + previousPointer = static_cast(previousCandidate->handle().cellAlign(previousPointer)); + if (previousCandidate->handle().isLiveCell(previousPointer)) + func(previousPointer); + } + } + + if (filter.ruleOut(bitwise_cast(candidate))) { + ASSERT(!candidate || !set.contains(candidate)); + return; + } + + if (!set.contains(candidate)) + return; + + candidate->flipIfNecessary(heapVersion); + + auto tryPointer = [&] (void* pointer) { + if (candidate->handle().isLiveCell(pointer)) + func(pointer); + }; + + if (candidate->handle().cellKind() == HeapCell::JSCell) { + if (!MarkedBlock::isAtomAligned(pointer)) + return; + + tryPointer(pointer); + return; + } + + // A butterfly could point into the middle of an object. + char* alignedPointer = static_cast(candidate->handle().cellAlign(pointer)); + tryPointer(alignedPointer); + + // Also, a butterfly could point at the end of an object plus sizeof(IndexingHeader). In that + // case, this is pointing to the object to the right of the one we should be marking. + if (candidate->atomNumber(alignedPointer) > MarkedBlock::firstAtom() + && pointer <= alignedPointer + sizeof(IndexingHeader)) + tryPointer(alignedPointer - candidate->cellSize()); + } + + static bool isPointerGCObjectJSCell( + Heap& heap, TinyBloomFilter filter, const void* pointer) + { + // It could point to a large allocation. + const Vector& largeAllocations = heap.objectSpace().largeAllocations(); + if (!largeAllocations.isEmpty()) { + if (largeAllocations[0]->aboveLowerBound(pointer) + && largeAllocations.last()->belowUpperBound(pointer)) { + LargeAllocation*const* result = approximateBinarySearch( + largeAllocations.begin(), largeAllocations.size(), + LargeAllocation::fromCell(pointer), + [] (LargeAllocation*const* ptr) -> LargeAllocation* { return *ptr; }); + if (result) { + if (result > largeAllocations.begin() + && result[-1]->cell() == pointer + && result[-1]->attributes().cellKind == HeapCell::JSCell) + return true; + if (result[0]->cell() == pointer + && result[0]->attributes().cellKind == HeapCell::JSCell) + return true; + if (result + 1 < largeAllocations.end() + && result[1]->cell() == pointer + && result[1]->attributes().cellKind == HeapCell::JSCell) + return true; + } + } + } + + const HashSet& set = heap.objectSpace().blocks().set(); + + MarkedBlock* candidate = MarkedBlock::blockFor(pointer); + if (filter.ruleOut(bitwise_cast(candidate))) { + ASSERT(!candidate || !set.contains(candidate)); + return false; + } + + if (!MarkedBlock::isAtomAligned(pointer)) + return false; + + if (!set.contains(candidate)) + return false; + + if (candidate->handle().cellKind() != HeapCell::JSCell) + return false; + + candidate->flipIfNecessary(); + if (!candidate->handle().isLiveCell(pointer)) + return false; + + return true; + } + + static bool isValueGCObject( + Heap& heap, TinyBloomFilter filter, JSValue value) + { + if (!value.isCell()) + return false; + return isPointerGCObjectJSCell(heap, filter, static_cast(value.asCell())); + } +}; + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapVerifier.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapVerifier.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/HeapVerifier.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/HeapVerifier.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -120,9 +120,13 @@ m_list.liveObjects.append(data); } - IterationStatus operator()(JSCell* cell) + IterationStatus operator()(HeapCell* cell, HeapCell::Kind kind) const { - visit(cell); + if (kind == HeapCell::JSCell) { + // FIXME: This const_cast exists because this isn't a C++ lambda. + // https://bugs.webkit.org/show_bug.cgi?id=159644 + const_cast(this)->visit(static_cast(cell)); + } return IterationStatus::Continue; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/IncrementalSweeper.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/IncrementalSweeper.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/IncrementalSweeper.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/IncrementalSweeper.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,9 +32,6 @@ #include "MarkedBlock.h" #include "JSCInlines.h" -#include -#include - #if PLATFORM(EFL) #include #include @@ -131,7 +128,8 @@ bool IncrementalSweeper::sweepNextBlock() { while (!m_blocksToSweep.isEmpty()) { - MarkedBlock* block = m_blocksToSweep.takeLast(); + MarkedBlock::Handle* block = m_blocksToSweep.takeLast(); + block->setIsOnBlocksToSweep(false); if (!block->needsSweeping()) continue; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/IncrementalSweeper.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/IncrementalSweeper.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/IncrementalSweeper.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/IncrementalSweeper.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,7 @@ #define IncrementalSweeper_h #include "HeapTimer.h" +#include "MarkedBlock.h" #include namespace JSC { @@ -45,7 +46,7 @@ void startSweeping(); - JS_EXPORT_PRIVATE virtual void doWork() override; + JS_EXPORT_PRIVATE void doWork() override; bool sweepNextBlock(); void willFinishSweeping(); @@ -55,7 +56,7 @@ void scheduleTimer(); void cancelTimer(); - Vector& m_blocksToSweep; + Vector& m_blocksToSweep; #endif }; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/LargeAllocation.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/LargeAllocation.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/LargeAllocation.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/LargeAllocation.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LargeAllocation.h" + +#include "Heap.h" +#include "JSCInlines.h" +#include "Operations.h" + +namespace JSC { + +LargeAllocation* LargeAllocation::tryCreate(Heap& heap, size_t size, const AllocatorAttributes& attributes) +{ + void* space = tryFastAlignedMalloc(alignment, headerSize() + size); + if (!space) + return nullptr; + if (scribbleFreeCells()) + scribble(space, size); + return new (NotNull, space) LargeAllocation(heap, size, attributes); +} + +LargeAllocation::LargeAllocation(Heap& heap, size_t size, const AllocatorAttributes& attributes) + : m_cellSize(size) + , m_isNewlyAllocated(true) + , m_hasValidCell(true) + , m_attributes(attributes) + , m_weakSet(heap.vm(), *this) +{ + m_isMarked.store(0); +} + +void LargeAllocation::lastChanceToFinalize() +{ + m_weakSet.lastChanceToFinalize(); + clearMarked(); + clearNewlyAllocated(); + sweep(); +} + +void LargeAllocation::shrink() +{ + m_weakSet.shrink(); +} + +void LargeAllocation::visitWeakSet(HeapRootVisitor& visitor) +{ + m_weakSet.visit(visitor); +} + +void LargeAllocation::reapWeakSet() +{ + return m_weakSet.reap(); +} + +void LargeAllocation::flip() +{ + ASSERT(heap()->operationInProgress() == FullCollection); + clearMarked(); +} + +bool LargeAllocation::isEmpty() +{ + return !isMarked() && m_weakSet.isEmpty() && !isNewlyAllocated(); +} + +void LargeAllocation::sweep() +{ + m_weakSet.sweep(); + + if (m_hasValidCell && !isLive()) { + if (m_attributes.destruction == NeedsDestruction) + static_cast(cell())->callDestructor(*vm()); + m_hasValidCell = false; + } +} + +void LargeAllocation::destroy() +{ + this->~LargeAllocation(); + fastAlignedFree(this); +} + +void LargeAllocation::dump(PrintStream& out) const +{ + out.print(RawPointer(this), ":(cell at ", RawPointer(cell()), " with size ", m_cellSize, " and attributes ", m_attributes, ")"); +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/LargeAllocation.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/LargeAllocation.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/LargeAllocation.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/LargeAllocation.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "MarkedBlock.h" +#include "WeakSet.h" + +namespace JSC { + +// WebKit has a good malloc that already knows what to do for large allocations. The GC shouldn't +// have to think about such things. That's where LargeAllocation comes in. We will allocate large +// objects directly using malloc, and put the LargeAllocation header just before them. We can detect +// when a HeapCell* is a LargeAllocation because it will have the MarkedBlock::atomSize / 2 bit set. + +class LargeAllocation { +public: + static LargeAllocation* tryCreate(Heap&, size_t, const AllocatorAttributes&); + + static LargeAllocation* fromCell(const void* cell) + { + return bitwise_cast(bitwise_cast(cell) - headerSize()); + } + + HeapCell* cell() const + { + return bitwise_cast(bitwise_cast(this) + headerSize()); + } + + static bool isLargeAllocation(HeapCell* cell) + { + return bitwise_cast(cell) & halfAlignment; + } + + void lastChanceToFinalize(); + + Heap* heap() const { return m_weakSet.heap(); } + VM* vm() const { return m_weakSet.vm(); } + WeakSet& weakSet() { return m_weakSet; } + + void shrink(); + + void visitWeakSet(HeapRootVisitor&); + void reapWeakSet(); + + void clearNewlyAllocated() { m_isNewlyAllocated = false; } + void flip(); + + bool isNewlyAllocated() const { return m_isNewlyAllocated; } + ALWAYS_INLINE bool isMarked() { return m_isMarked.load(std::memory_order_relaxed); } + bool isMarkedOrNewlyAllocated() { return isMarked() || isNewlyAllocated(); } + bool isLive() { return isMarkedOrNewlyAllocated(); } + + bool hasValidCell() const { return m_hasValidCell; } + + bool isEmpty(); + + size_t cellSize() const { return m_cellSize; } + + bool aboveLowerBound(const void* rawPtr) + { + char* ptr = bitwise_cast(rawPtr); + char* begin = bitwise_cast(cell()); + return ptr >= begin; + } + + bool belowUpperBound(const void* rawPtr) + { + char* ptr = bitwise_cast(rawPtr); + char* begin = bitwise_cast(cell()); + char* end = begin + cellSize(); + // We cannot #include IndexingHeader.h because reasons. The fact that IndexingHeader is 8 + // bytes is wired deep into our engine, so this isn't so bad. + size_t sizeOfIndexingHeader = 8; + return ptr <= end + sizeOfIndexingHeader; + } + + bool contains(const void* rawPtr) + { + return aboveLowerBound(rawPtr) && belowUpperBound(rawPtr); + } + + const AllocatorAttributes& attributes() const { return m_attributes; } + + void flipIfNecessary(uint64_t) { } + void flipIfNecessaryConcurrently(uint64_t) { } + + ALWAYS_INLINE bool testAndSetMarked() + { + // This method is usually called when the object is already marked. This avoids us + // having to CAS in that case. It's profitable to reduce the total amount of CAS + // traffic. + if (isMarked()) + return true; + return !m_isMarked.compareExchangeStrong(false, true); + } + ALWAYS_INLINE bool testAndSetMarked(HeapCell*) { return testAndSetMarked(); } + void setMarked() { m_isMarked.store(true); } + void clearMarked() { m_isMarked.store(false); } + + void noteMarked() { } + + void sweep(); + + void destroy(); + + void dump(PrintStream&) const; + +private: + LargeAllocation(Heap&, size_t, const AllocatorAttributes&); + + static const unsigned alignment = MarkedBlock::atomSize; + static const unsigned halfAlignment = alignment / 2; + + static unsigned headerSize(); + + size_t m_cellSize; + bool m_isNewlyAllocated; + bool m_hasValidCell; + Atomic m_isMarked; + AllocatorAttributes m_attributes; + WeakSet m_weakSet; +}; + +inline unsigned LargeAllocation::headerSize() +{ + return ((sizeof(LargeAllocation) + halfAlignment - 1) & ~(halfAlignment - 1)) | halfAlignment; +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MachineStackMarker.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MachineStackMarker.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MachineStackMarker.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MachineStackMarker.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -144,7 +144,7 @@ m_set.add(machineThreads); } - void remove(MachineThreads* machineThreads) + void THREAD_SPECIFIC_CALL remove(MachineThreads* machineThreads) { LockHolder managerLock(m_lock); auto recordedMachineThreads = m_set.take(machineThreads); @@ -192,14 +192,12 @@ MachineThreads::MachineThreads(Heap* heap) : m_registeredThreads(0) , m_threadSpecificForMachineThreads(0) - , m_threadSpecificForThread(0) #if !ASSERT_DISABLED , m_heap(heap) #endif { UNUSED_PARAM(heap); threadSpecificKeyCreate(&m_threadSpecificForMachineThreads, removeThread); - threadSpecificKeyCreate(&m_threadSpecificForThread, nullptr); activeMachineThreadsManager().add(this); } @@ -207,7 +205,6 @@ { activeMachineThreadsManager().remove(this); threadSpecificKeyDelete(m_threadSpecificForMachineThreads); - threadSpecificKeyDelete(m_threadSpecificForThread); LockHolder registeredThreadsLock(m_registeredThreadsMutex); for (Thread* t = m_registeredThreads; t;) { @@ -234,18 +231,6 @@ #endif } -#ifndef NDEBUG -static bool isThreadInList(Thread* listHead, Thread* target) -{ - for (Thread* thread = listHead; thread; thread = thread->next) { - if (thread == target) - return true; - } - - return false; -} -#endif - void MachineThreads::addCurrentThread() { ASSERT(!m_heap->vm()->hasExclusiveThread() || m_heap->vm()->exclusiveThread() == std::this_thread::get_id()); @@ -254,15 +239,12 @@ #ifndef NDEBUG LockHolder lock(m_registeredThreadsMutex); ASSERT(threadSpecificGet(m_threadSpecificForMachineThreads) == this); - ASSERT(threadSpecificGet(m_threadSpecificForThread)); - ASSERT(isThreadInList(m_registeredThreads, static_cast(threadSpecificGet(m_threadSpecificForThread)))); #endif return; } Thread* thread = Thread::createForCurrentThread(); threadSpecificSet(m_threadSpecificForMachineThreads, this); - threadSpecificSet(m_threadSpecificForThread, thread); LockHolder lock(m_registeredThreadsMutex); @@ -272,17 +254,18 @@ Thread* MachineThreads::machineThreadForCurrentThread() { - Thread* result = static_cast(threadSpecificGet(m_threadSpecificForThread)); - RELEASE_ASSERT(result); -#ifndef NDEBUG LockHolder lock(m_registeredThreadsMutex); - ASSERT(isThreadInList(m_registeredThreads, result)); -#endif + PlatformThread platformThread = getCurrentPlatformThread(); + for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { + if (*thread == platformThread) + return thread; + } - return result; + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; } -void MachineThreads::removeThread(void* p) +void THREAD_SPECIFIC_CALL MachineThreads::removeThread(void* p) { auto& manager = activeMachineThreadsManager(); ActiveMachineThreadsManager::Locker lock(manager); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MachineStackMarker.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MachineStackMarker.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MachineStackMarker.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MachineStackMarker.h 2016-11-03 07:04:20.000000000 +0000 @@ -151,7 +151,7 @@ void tryCopyOtherThreadStack(Thread*, void*, size_t capacity, size_t*); bool tryCopyOtherThreadStacks(LockHolder&, void*, size_t capacity, size_t*); - static void removeThread(void*); + static void THREAD_SPECIFIC_CALL removeThread(void*); template void removeThreadIfFound(PlatformThread); @@ -159,7 +159,6 @@ Lock m_registeredThreadsMutex; Thread* m_registeredThreads; WTF::ThreadSpecificKey m_threadSpecificForMachineThreads; - WTF::ThreadSpecificKey m_threadSpecificForThread; #if !ASSERT_DISABLED Heap* m_heap; #endif diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedAllocator.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedAllocator.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedAllocator.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedAllocator.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,17 +30,31 @@ #include "Heap.h" #include "IncrementalSweeper.h" #include "JSCInlines.h" +#include "SuperSampler.h" #include "VM.h" #include namespace JSC { -static bool isListPagedOut(double deadline, DoublyLinkedList& list) +MarkedAllocator::MarkedAllocator(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, const AllocatorAttributes& attributes) + : m_currentBlock(0) + , m_lastActiveBlock(0) + , m_nextBlockToSweep(nullptr) + , m_cellSize(static_cast(cellSize)) + , m_attributes(attributes) + , m_heap(heap) + , m_markedSpace(markedSpace) +{ +} + +bool MarkedAllocator::isPagedOut(double deadline) { unsigned itersSinceLastTimeCheck = 0; - MarkedBlock* block = list.head(); + MarkedBlock::Handle* block = m_blockList.begin(); while (block) { - block = block->next(); + block = filterNextBlock(block->next()); + if (block) + block->flipIfNecessary(); // Forces us to touch the memory of the block, but has no semantic effect. ++itersSinceLastTimeCheck; if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) { double currentTime = WTF::monotonicallyIncreasingTime(); @@ -52,74 +66,104 @@ return false; } -bool MarkedAllocator::isPagedOut(double deadline) +void MarkedAllocator::retire(MarkedBlock::Handle* block) { - if (isListPagedOut(deadline, m_blockList)) - return true; - return false; + LockHolder locker(m_lock); // This will be called in parallel during GC. + if (block == m_currentBlock) { + // This happens when the mutator is running. We finished a full GC and marked too few things + // to retire. Then we started allocating in this block. Then a barrier ran, which marked an + // object in this block, which put it over the retirement threshold. It's OK to simply do + // nothing in that case. + return; + } + if (block == m_lastActiveBlock) { + // This can easily happen during marking. It would be easy to handle this case, but it's + // just as easy to ignore it. + return; + } + RELEASE_ASSERT(block->isOnList()); + if (block == m_nextBlockToSweep) + m_nextBlockToSweep = filterNextBlock(block->next()); + block->remove(); + m_retiredBlocks.push(block); +} + +MarkedBlock::Handle* MarkedAllocator::filterNextBlock(MarkedBlock::Handle* block) +{ + if (block == m_blockList.end()) + return nullptr; + return block; +} + +void MarkedAllocator::setNextBlockToSweep(MarkedBlock::Handle* block) +{ + m_nextBlockToSweep = filterNextBlock(block); } -inline void* MarkedAllocator::tryAllocateHelper(size_t bytes) +void* MarkedAllocator::tryAllocateWithoutCollectingImpl() { + SuperSamplerScope superSamplerScope(false); + if (m_currentBlock) { ASSERT(m_currentBlock == m_nextBlockToSweep); m_currentBlock->didConsumeFreeList(); - m_nextBlockToSweep = m_currentBlock->next(); + setNextBlockToSweep(m_currentBlock->next()); } + + setFreeList(FreeList()); - MarkedBlock* next; - for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) { - next = block->next(); + RELEASE_ASSERT(m_nextBlockToSweep != m_blockList.end()); - MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList); - - double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize; - if (utilization >= Options::minMarkedBlockUtilization()) { - ASSERT(freeList.bytes || !freeList.head); - m_blockList.remove(block); - m_retiredBlocks.push(block); - block->didRetireBlock(freeList); - continue; - } + MarkedBlock::Handle* next; + for (MarkedBlock::Handle*& block = m_nextBlockToSweep; block; block = next) { + next = filterNextBlock(block->next()); - if (bytes > block->cellSize()) { - block->stopAllocating(freeList); + // It would be super weird if the blocks we are sweeping have anything allocated during this + // cycle. + ASSERT(!block->hasAnyNewlyAllocated()); + + FreeList freeList = block->sweep(MarkedBlock::Handle::SweepToFreeList); + + // It's possible to stumble on a complete-full block. Marking tries to retire these, but + // that algorithm is racy and may forget to do it sometimes. + if (freeList.allocationWillFail()) { + ASSERT(block->isFreeListed()); + block->unsweepWithNoNewlyAllocated(); + ASSERT(block->isMarked()); + retire(block); continue; } m_currentBlock = block; - m_freeList = freeList; + setFreeList(freeList); break; } - if (!m_freeList.head) { + if (!m_freeList) { m_currentBlock = 0; return 0; } - ASSERT(m_freeList.head); - void* head = tryPopFreeList(bytes); - ASSERT(head); + void* result; + if (m_freeList.remaining) { + unsigned cellSize = m_cellSize; + m_freeList.remaining -= cellSize; + result = m_freeList.payloadEnd - m_freeList.remaining - cellSize; + } else { + FreeCell* head = m_freeList.head; + m_freeList.head = head->next; + result = head; + } + RELEASE_ASSERT(result); m_markedSpace->didAllocateInBlock(m_currentBlock); - return head; -} - -inline void* MarkedAllocator::tryPopFreeList(size_t bytes) -{ - ASSERT(m_currentBlock); - if (bytes > m_currentBlock->cellSize()) - return 0; - - MarkedBlock::FreeCell* head = m_freeList.head; - m_freeList.head = head->next; - return head; + return result; } -inline void* MarkedAllocator::tryAllocate(size_t bytes) +inline void* MarkedAllocator::tryAllocateWithoutCollecting() { ASSERT(!m_heap->isBusy()); m_heap->m_operationInProgress = Allocation; - void* result = tryAllocateHelper(bytes); + void* result = tryAllocateWithoutCollectingImpl(); m_heap->m_operationInProgress = NoOperation; ASSERT(result || !m_currentBlock); @@ -141,92 +185,145 @@ allocationCount = 0; } -void* MarkedAllocator::allocateSlowCase(size_t bytes) +void* MarkedAllocator::allocateSlowCase() { + bool crashOnFailure = true; + return allocateSlowCaseImpl(crashOnFailure); +} + +void* MarkedAllocator::tryAllocateSlowCase() +{ + bool crashOnFailure = false; + return allocateSlowCaseImpl(crashOnFailure); +} + +void* MarkedAllocator::allocateSlowCaseImpl(bool crashOnFailure) +{ + SuperSamplerScope superSamplerScope(false); ASSERT(m_heap->vm()->currentThreadIsHoldingAPILock()); doTestCollectionsIfNeeded(); ASSERT(!m_markedSpace->isIterating()); - ASSERT(!m_freeList.head); - m_heap->didAllocate(m_freeList.bytes); + m_heap->didAllocate(m_freeList.originalSize); - void* result = tryAllocate(bytes); + void* result = tryAllocateWithoutCollecting(); if (LIKELY(result != 0)) return result; if (m_heap->collectIfNecessaryOrDefer()) { - result = tryAllocate(bytes); + result = tryAllocateWithoutCollecting(); if (result) return result; } ASSERT(!m_heap->shouldCollect()); - MarkedBlock* block = allocateBlock(bytes); - ASSERT(block); + MarkedBlock::Handle* block = tryAllocateBlock(); + if (!block) { + if (crashOnFailure) + RELEASE_ASSERT_NOT_REACHED(); + else + return nullptr; + } addBlock(block); - result = tryAllocate(bytes); + result = tryAllocateWithoutCollecting(); ASSERT(result); return result; } -MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes) +static size_t blockHeaderSize() +{ + return WTF::roundUpToMultipleOf(sizeof(MarkedBlock)); +} + +size_t MarkedAllocator::blockSizeForBytes(size_t bytes) { size_t minBlockSize = MarkedBlock::blockSize; - size_t minAllocationSize = WTF::roundUpToMultipleOf(sizeof(MarkedBlock)) + WTF::roundUpToMultipleOf(bytes); + size_t minAllocationSize = blockHeaderSize() + WTF::roundUpToMultipleOf(bytes); minAllocationSize = WTF::roundUpToMultipleOf(WTF::pageSize(), minAllocationSize); - size_t blockSize = std::max(minBlockSize, minAllocationSize); - - size_t cellSize = m_cellSize ? m_cellSize : WTF::roundUpToMultipleOf(bytes); + return std::max(minBlockSize, minAllocationSize); +} - return MarkedBlock::create(*m_heap, this, blockSize, cellSize, m_needsDestruction); +MarkedBlock::Handle* MarkedAllocator::tryAllocateBlock() +{ + SuperSamplerScope superSamplerScope(false); + return MarkedBlock::tryCreate(*m_heap, this, m_cellSize, m_attributes); } -void MarkedAllocator::addBlock(MarkedBlock* block) +void MarkedAllocator::addBlock(MarkedBlock::Handle* block) { ASSERT(!m_currentBlock); - ASSERT(!m_freeList.head); + ASSERT(!m_freeList); m_blockList.append(block); - m_nextBlockToSweep = block; + setNextBlockToSweep(block); m_markedSpace->didAddBlock(block); } -void MarkedAllocator::removeBlock(MarkedBlock* block) +void MarkedAllocator::removeBlock(MarkedBlock::Handle* block) { if (m_currentBlock == block) { - m_currentBlock = m_currentBlock->next(); - m_freeList = MarkedBlock::FreeList(); + m_currentBlock = filterNextBlock(m_currentBlock->next()); + setFreeList(FreeList()); } if (m_nextBlockToSweep == block) - m_nextBlockToSweep = m_nextBlockToSweep->next(); + setNextBlockToSweep(m_nextBlockToSweep->next()); block->willRemoveBlock(); m_blockList.remove(block); } +void MarkedAllocator::stopAllocating() +{ + if (m_heap->operationInProgress() == FullCollection) + m_blockList.takeFrom(m_retiredBlocks); + + ASSERT(!m_lastActiveBlock); + if (!m_currentBlock) { + ASSERT(!m_freeList); + return; + } + + m_currentBlock->stopAllocating(m_freeList); + m_lastActiveBlock = m_currentBlock; + m_currentBlock = 0; + m_freeList = FreeList(); +} + void MarkedAllocator::reset() { m_lastActiveBlock = 0; m_currentBlock = 0; - m_freeList = MarkedBlock::FreeList(); - if (m_heap->operationInProgress() == FullCollection) - m_blockList.append(m_retiredBlocks); + setFreeList(FreeList()); - m_nextBlockToSweep = m_blockList.head(); -} + setNextBlockToSweep(m_blockList.begin()); -struct LastChanceToFinalize : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) { block->lastChanceToFinalize(); } -}; + if (UNLIKELY(Options::useImmortalObjects())) { + MarkedBlock::Handle* next; + for (MarkedBlock::Handle*& block = m_nextBlockToSweep; block; block = next) { + next = filterNextBlock(block->next()); + + FreeList freeList = block->sweep(MarkedBlock::Handle::SweepToFreeList); + block->zap(freeList); + retire(block); + } + } +} void MarkedAllocator::lastChanceToFinalize() { - m_blockList.append(m_retiredBlocks); - LastChanceToFinalize functor; - forEachBlock(functor); + m_blockList.takeFrom(m_retiredBlocks); + forEachBlock( + [&] (MarkedBlock::Handle* block) { + block->lastChanceToFinalize(); + }); +} + +void MarkedAllocator::setFreeList(const FreeList& freeList) +{ + m_freeList = freeList; } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedAllocator.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedAllocator.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedAllocator.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedAllocator.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,8 +26,10 @@ #ifndef MarkedAllocator_h #define MarkedAllocator_h +#include "AllocatorAttributes.h" +#include "FreeList.h" #include "MarkedBlock.h" -#include +#include namespace JSC { @@ -39,105 +41,112 @@ friend class LLIntOffsetsExtractor; public: - static ptrdiff_t offsetOfFreeListHead(); + static ptrdiff_t offsetOfFreeList(); + static ptrdiff_t offsetOfCellSize(); - MarkedAllocator(); + MarkedAllocator(Heap*, MarkedSpace*, size_t cellSize, const AllocatorAttributes&); void lastChanceToFinalize(); void reset(); void stopAllocating(); void resumeAllocating(); - size_t cellSize() { return m_cellSize; } - bool needsDestruction() { return m_needsDestruction; } - void* allocate(size_t); + size_t cellSize() const { return m_cellSize; } + const AllocatorAttributes& attributes() const { return m_attributes; } + bool needsDestruction() const { return m_attributes.destruction == NeedsDestruction; } + DestructionMode destruction() const { return m_attributes.destruction; } + HeapCell::Kind cellKind() const { return m_attributes.cellKind; } + void* allocate(); + void* tryAllocate(); Heap* heap() { return m_heap; } - MarkedBlock* takeLastActiveBlock() + MarkedBlock::Handle* takeLastActiveBlock() { - MarkedBlock* block = m_lastActiveBlock; + MarkedBlock::Handle* block = m_lastActiveBlock; m_lastActiveBlock = 0; return block; } - template void forEachBlock(Functor&); + template void forEachBlock(const Functor&); - void addBlock(MarkedBlock*); - void removeBlock(MarkedBlock*); - void init(Heap*, MarkedSpace*, size_t cellSize, bool needsDestruction); + void addBlock(MarkedBlock::Handle*); + void removeBlock(MarkedBlock::Handle*); bool isPagedOut(double deadline); + + static size_t blockSizeForBytes(size_t); private: - JS_EXPORT_PRIVATE void* allocateSlowCase(size_t); - void* tryAllocate(size_t); - void* tryAllocateHelper(size_t); - void* tryPopFreeList(size_t); - MarkedBlock* allocateBlock(size_t); + friend class MarkedBlock; + + JS_EXPORT_PRIVATE void* allocateSlowCase(); + JS_EXPORT_PRIVATE void* tryAllocateSlowCase(); + void* allocateSlowCaseImpl(bool crashOnFailure); + void* tryAllocateWithoutCollecting(); + void* tryAllocateWithoutCollectingImpl(); + MarkedBlock::Handle* tryAllocateBlock(); ALWAYS_INLINE void doTestCollectionsIfNeeded(); + void retire(MarkedBlock::Handle*); + + void setFreeList(const FreeList&); + + MarkedBlock::Handle* filterNextBlock(MarkedBlock::Handle*); + void setNextBlockToSweep(MarkedBlock::Handle*); - MarkedBlock::FreeList m_freeList; - MarkedBlock* m_currentBlock; - MarkedBlock* m_lastActiveBlock; - MarkedBlock* m_nextBlockToSweep; - DoublyLinkedList m_blockList; - DoublyLinkedList m_retiredBlocks; - size_t m_cellSize; - bool m_needsDestruction { false }; + FreeList m_freeList; + MarkedBlock::Handle* m_currentBlock; + MarkedBlock::Handle* m_lastActiveBlock; + MarkedBlock::Handle* m_nextBlockToSweep; + SentinelLinkedList> m_blockList; + SentinelLinkedList> m_retiredBlocks; + Lock m_lock; + unsigned m_cellSize; + AllocatorAttributes m_attributes; Heap* m_heap; MarkedSpace* m_markedSpace; }; -inline ptrdiff_t MarkedAllocator::offsetOfFreeListHead() +inline ptrdiff_t MarkedAllocator::offsetOfFreeList() { - return OBJECT_OFFSETOF(MarkedAllocator, m_freeList) + OBJECT_OFFSETOF(MarkedBlock::FreeList, head); + return OBJECT_OFFSETOF(MarkedAllocator, m_freeList); } -inline MarkedAllocator::MarkedAllocator() - : m_currentBlock(0) - , m_lastActiveBlock(0) - , m_nextBlockToSweep(0) - , m_cellSize(0) - , m_heap(0) - , m_markedSpace(0) +inline ptrdiff_t MarkedAllocator::offsetOfCellSize() { + return OBJECT_OFFSETOF(MarkedAllocator, m_cellSize); } -inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, bool needsDestruction) +ALWAYS_INLINE void* MarkedAllocator::tryAllocate() { - m_heap = heap; - m_markedSpace = markedSpace; - m_cellSize = cellSize; - m_needsDestruction = needsDestruction; -} - -inline void* MarkedAllocator::allocate(size_t bytes) -{ - MarkedBlock::FreeCell* head = m_freeList.head; - if (UNLIKELY(!head)) { - void* result = allocateSlowCase(bytes); -#ifndef NDEBUG - memset(result, 0xCD, bytes); -#endif - return result; + unsigned remaining = m_freeList.remaining; + if (remaining) { + unsigned cellSize = m_cellSize; + remaining -= cellSize; + m_freeList.remaining = remaining; + return m_freeList.payloadEnd - remaining - cellSize; } + FreeCell* head = m_freeList.head; + if (UNLIKELY(!head)) + return tryAllocateSlowCase(); + m_freeList.head = head->next; -#ifndef NDEBUG - memset(head, 0xCD, bytes); -#endif return head; } -inline void MarkedAllocator::stopAllocating() +ALWAYS_INLINE void* MarkedAllocator::allocate() { - ASSERT(!m_lastActiveBlock); - if (!m_currentBlock) { - ASSERT(!m_freeList.head); - return; + unsigned remaining = m_freeList.remaining; + if (remaining) { + unsigned cellSize = m_cellSize; + remaining -= cellSize; + m_freeList.remaining = remaining; + return m_freeList.payloadEnd - remaining - cellSize; } - m_currentBlock->stopAllocating(m_freeList); - m_lastActiveBlock = m_currentBlock; - m_currentBlock = 0; - m_freeList = MarkedBlock::FreeList(); + FreeCell* head = m_freeList.head; + if (UNLIKELY(!head)) + return allocateSlowCase(); + + m_freeList.head = head->next; + return head; } inline void MarkedAllocator::resumeAllocating() @@ -150,18 +159,10 @@ m_lastActiveBlock = 0; } -template inline void MarkedAllocator::forEachBlock(Functor& functor) +template inline void MarkedAllocator::forEachBlock(const Functor& functor) { - MarkedBlock* next; - for (MarkedBlock* block = m_blockList.head(); block; block = next) { - next = block->next(); - functor(block); - } - - for (MarkedBlock* block = m_retiredBlocks.head(); block; block = next) { - next = block->next(); - functor(block); - } + m_blockList.forEach(functor); + m_retiredBlocks.forEach(functor); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedBlock.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedBlock.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedBlock.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedBlock.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,89 +29,128 @@ #include "JSCell.h" #include "JSDestructibleObject.h" #include "JSCInlines.h" +#include "SuperSampler.h" namespace JSC { static const bool computeBalance = false; static size_t balance; -MarkedBlock* MarkedBlock::create(Heap& heap, MarkedAllocator* allocator, size_t capacity, size_t cellSize, bool needsDestruction) +MarkedBlock::Handle* MarkedBlock::tryCreate(Heap& heap, MarkedAllocator* allocator, size_t cellSize, const AllocatorAttributes& attributes) { if (computeBalance) { balance++; if (!(balance % 10)) dataLog("MarkedBlock Balance: ", balance, "\n"); } - MarkedBlock* block = new (NotNull, fastAlignedMalloc(blockSize, capacity)) MarkedBlock(allocator, capacity, cellSize, needsDestruction); - heap.didAllocateBlock(capacity); - return block; + void* blockSpace = tryFastAlignedMalloc(blockSize, blockSize); + if (!blockSpace) + return nullptr; + if (scribbleFreeCells()) + scribble(blockSpace, blockSize); + return new Handle(heap, allocator, cellSize, attributes, blockSpace); } -void MarkedBlock::destroy(Heap& heap, MarkedBlock* block) +MarkedBlock::Handle::Handle(Heap& heap, MarkedAllocator* allocator, size_t cellSize, const AllocatorAttributes& attributes, void* blockSpace) + : m_atomsPerCell((cellSize + atomSize - 1) / atomSize) + , m_endAtom(atomsPerBlock - m_atomsPerCell + 1) + , m_attributes(attributes) + , m_state(New) // All cells start out unmarked. + , m_allocator(allocator) + , m_weakSet(allocator->heap()->vm(), CellContainer()) { + m_block = new (NotNull, blockSpace) MarkedBlock(*heap.vm(), *this); + + m_weakSet.setContainer(*m_block); + + heap.didAllocateBlock(blockSize); + HEAP_LOG_BLOCK_STATE_TRANSITION(this); + ASSERT(allocator); + if (m_attributes.cellKind != HeapCell::JSCell) + RELEASE_ASSERT(m_attributes.destruction == DoesNotNeedDestruction); +} + +MarkedBlock::Handle::~Handle() +{ + Heap& heap = *this->heap(); if (computeBalance) { balance--; if (!(balance % 10)) dataLog("MarkedBlock Balance: ", balance, "\n"); } - size_t capacity = block->capacity(); - block->~MarkedBlock(); - fastAlignedFree(block); - heap.didFreeBlock(capacity); + m_block->~MarkedBlock(); + fastAlignedFree(m_block); + heap.didFreeBlock(blockSize); } -MarkedBlock::MarkedBlock(MarkedAllocator* allocator, size_t capacity, size_t cellSize, bool needsDestruction) - : DoublyLinkedListNode() - , m_atomsPerCell((cellSize + atomSize - 1) / atomSize) - , m_endAtom((allocator->cellSize() ? atomsPerBlock - m_atomsPerCell : firstAtom()) + 1) - , m_capacity(capacity) - , m_needsDestruction(needsDestruction) - , m_allocator(allocator) - , m_state(New) // All cells start out unmarked. - , m_weakSet(allocator->heap()->vm(), *this) +MarkedBlock::MarkedBlock(VM& vm, Handle& handle) + : m_needsDestruction(handle.needsDestruction()) + , m_version(vm.heap.objectSpace().version()) + , m_handle(handle) + , m_vm(&vm) { - ASSERT(allocator); - HEAP_LOG_BLOCK_STATE_TRANSITION(this); -} - -inline void MarkedBlock::callDestructor(JSCell* cell) -{ - // A previous eager sweep may already have run cell's destructor. - if (cell->isZapped()) - return; - - ASSERT(cell->structureID()); - if (cell->inlineTypeFlags() & StructureIsImmortal) - cell->structure(*vm())->classInfo()->methodTable.destroy(cell); - else - jsCast(cell)->classInfo()->methodTable.destroy(cell); - cell->zap(); + unsigned cellsPerBlock = MarkedSpace::blockPayload / handle.cellSize(); + double markCountBias = -(Options::minMarkedBlockUtilization() * cellsPerBlock); + + // The mark count bias should be comfortably within this range. + RELEASE_ASSERT(markCountBias > static_cast(std::numeric_limits::min())); + RELEASE_ASSERT(markCountBias < 0); + + m_markCountBias = static_cast(markCountBias); + + m_biasedMarkCount = m_markCountBias; // This means we haven't marked anything yet. } -template -MarkedBlock::FreeList MarkedBlock::specializedSweep() +template +FreeList MarkedBlock::Handle::specializedSweep() { - ASSERT(blockState != Allocated && blockState != FreeListed); - ASSERT(!(!callDestructors && sweepMode == SweepOnly)); - - SamplingRegion samplingRegion((!callDestructors && blockState != New) ? "Calling destructors" : "sweeping"); + SuperSamplerScope superSamplerScope(false); + ASSERT(blockState == New || blockState == Marked); + ASSERT(!(destructionMode == DoesNotNeedDestruction && sweepMode == SweepOnly)); + assertFlipped(); + MarkedBlock& block = this->block(); + + bool isNewBlock = blockState == New; + bool isEmptyBlock = !block.hasAnyMarked() + && newlyAllocatedMode == DoesNotHaveNewlyAllocated + && destructionMode == DoesNotNeedDestruction; + if (Options::useBumpAllocator() && (isNewBlock || isEmptyBlock)) { + ASSERT(block.m_marks.isEmpty()); + + char* startOfLastCell = static_cast(cellAlign(block.atoms() + m_endAtom - 1)); + char* payloadEnd = startOfLastCell + cellSize(); + RELEASE_ASSERT(payloadEnd - MarkedBlock::blockSize <= bitwise_cast(&block)); + char* payloadBegin = bitwise_cast(block.atoms() + firstAtom()); + if (scribbleMode == Scribble) + scribble(payloadBegin, payloadEnd - payloadBegin); + m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Marked); + FreeList result = FreeList::bump(payloadEnd, payloadEnd - payloadBegin); + if (false) + dataLog("Quickly swept block ", RawPointer(this), " with cell size ", cellSize(), " and attributes ", m_attributes, ": ", result, "\n"); + return result; + } + // This produces a free list that is ordered in reverse through the block. // This is fine, since the allocation code makes no assumptions about the // order of the free list. FreeCell* head = 0; size_t count = 0; for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { - if (blockState == Marked && (m_marks.get(i) || (m_newlyAllocated && m_newlyAllocated->get(i)))) + if (blockState == Marked + && (block.m_marks.get(i) + || (newlyAllocatedMode == HasNewlyAllocated && m_newlyAllocated->get(i)))) continue; - JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); + HeapCell* cell = reinterpret_cast_ptr(&block.atoms()[i]); - if (callDestructors && blockState != New) - callDestructor(cell); + if (destructionMode == NeedsDestruction && blockState != New) + static_cast(cell)->callDestructor(*vm()); if (sweepMode == SweepToFreeList) { - FreeCell* freeCell = reinterpret_cast(cell); + FreeCell* freeCell = reinterpret_cast_ptr(cell); + if (scribbleMode == Scribble) + scribble(freeCell, cellSize()); freeCell->next = head; head = freeCell; ++count; @@ -120,86 +159,117 @@ // We only want to discard the newlyAllocated bits if we're creating a FreeList, // otherwise we would lose information on what's currently alive. - if (sweepMode == SweepToFreeList && m_newlyAllocated) + if (sweepMode == SweepToFreeList && newlyAllocatedMode == HasNewlyAllocated) m_newlyAllocated = nullptr; - m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Marked); - return FreeList(head, count * cellSize()); + FreeList result = FreeList::list(head, count * cellSize()); + m_state = (sweepMode == SweepToFreeList ? FreeListed : Marked); + if (false) + dataLog("Slowly swept block ", RawPointer(&block), " with cell size ", cellSize(), " and attributes ", m_attributes, ": ", result, "\n"); + return result; } -MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode) +FreeList MarkedBlock::Handle::sweep(SweepMode sweepMode) { + flipIfNecessary(); + HEAP_LOG_BLOCK_STATE_TRANSITION(this); m_weakSet.sweep(); - if (sweepMode == SweepOnly && !m_needsDestruction) + if (sweepMode == SweepOnly && m_attributes.destruction == DoesNotNeedDestruction) return FreeList(); - if (m_needsDestruction) - return sweepHelper(sweepMode); - return sweepHelper(sweepMode); + if (m_attributes.destruction == NeedsDestruction) + return sweepHelperSelectScribbleMode(sweepMode); + return sweepHelperSelectScribbleMode(sweepMode); +} + +template +FreeList MarkedBlock::Handle::sweepHelperSelectScribbleMode(SweepMode sweepMode) +{ + if (scribbleFreeCells()) + return sweepHelperSelectStateAndSweepMode(sweepMode); + return sweepHelperSelectStateAndSweepMode(sweepMode); } -template -MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode) +template +FreeList MarkedBlock::Handle::sweepHelperSelectStateAndSweepMode(SweepMode sweepMode) { switch (m_state) { case New: ASSERT(sweepMode == SweepToFreeList); - return specializedSweep(); + return specializedSweep(); case FreeListed: // Happens when a block transitions to fully allocated. ASSERT(sweepMode == SweepToFreeList); return FreeList(); - case Retired: case Allocated: RELEASE_ASSERT_NOT_REACHED(); return FreeList(); case Marked: - return sweepMode == SweepToFreeList - ? specializedSweep() - : specializedSweep(); + if (m_newlyAllocated) { + return sweepMode == SweepToFreeList + ? specializedSweep() + : specializedSweep(); + } else { + return sweepMode == SweepToFreeList + ? specializedSweep() + : specializedSweep(); + } } - RELEASE_ASSERT_NOT_REACHED(); return FreeList(); } +void MarkedBlock::Handle::unsweepWithNoNewlyAllocated() +{ + flipIfNecessary(); + + HEAP_LOG_BLOCK_STATE_TRANSITION(this); + + RELEASE_ASSERT(m_state == FreeListed); + m_state = Marked; +} + class SetNewlyAllocatedFunctor : public MarkedBlock::VoidFunctor { public: - SetNewlyAllocatedFunctor(MarkedBlock* block) + SetNewlyAllocatedFunctor(MarkedBlock::Handle* block) : m_block(block) { } - IterationStatus operator()(JSCell* cell) + IterationStatus operator()(HeapCell* cell, HeapCell::Kind) const { - ASSERT(MarkedBlock::blockFor(cell) == m_block); + ASSERT(MarkedBlock::blockFor(cell) == &m_block->block()); m_block->setNewlyAllocated(cell); return IterationStatus::Continue; } private: - MarkedBlock* m_block; + MarkedBlock::Handle* m_block; }; -void MarkedBlock::stopAllocating(const FreeList& freeList) +void MarkedBlock::Handle::stopAllocating(const FreeList& freeList) { + flipIfNecessary(); HEAP_LOG_BLOCK_STATE_TRANSITION(this); - FreeCell* head = freeList.head; if (m_state == Marked) { - // If the block is in the Marked state then we know that: - // 1) It was not used for allocation during the previous allocation cycle. - // 2) It may have dead objects, and we only know them to be dead by the - // fact that their mark bits are unset. + // If the block is in the Marked state then we know that one of these + // conditions holds: + // + // - It was not used for allocation during the previous allocation cycle. + // It may have dead objects, and we only know them to be dead by the + // fact that their mark bits are unset. + // + // - Someone had already done stopAllocating(), for example because of + // heap iteration, and they had already // Hence if the block is Marked we need to leave it Marked. - - ASSERT(!head); + ASSERT(freeList.allocationWillFail()); return; } - + ASSERT(m_state == FreeListed); // Roll back to a coherent state for Heap introspection. Cells newly @@ -212,56 +282,29 @@ SetNewlyAllocatedFunctor functor(this); forEachCell(functor); - FreeCell* next; - for (FreeCell* current = head; current; current = next) { - next = current->next; - reinterpret_cast(current)->zap(); - clearNewlyAllocated(current); - } + forEachFreeCell( + freeList, + [&] (HeapCell* cell) { + if (m_attributes.destruction == NeedsDestruction) + cell->zap(); + clearNewlyAllocated(cell); + }); m_state = Marked; } -void MarkedBlock::clearMarks() -{ - if (heap()->operationInProgress() == JSC::EdenCollection) - this->clearMarksWithCollectionType(); - else - this->clearMarksWithCollectionType(); -} - -template -void MarkedBlock::clearMarksWithCollectionType() -{ - ASSERT(collectionType == FullCollection || collectionType == EdenCollection); - HEAP_LOG_BLOCK_STATE_TRANSITION(this); - - ASSERT(m_state != New && m_state != FreeListed); - if (collectionType == FullCollection) { - m_marks.clearAll(); - // This will become true at the end of the mark phase. We set it now to - // avoid an extra pass to do so later. - m_state = Marked; - return; - } - - ASSERT(collectionType == EdenCollection); - // If a block was retired then there's no way an EdenCollection can un-retire it. - if (m_state != Retired) - m_state = Marked; -} - -void MarkedBlock::lastChanceToFinalize() +void MarkedBlock::Handle::lastChanceToFinalize() { + m_block->clearMarks(); m_weakSet.lastChanceToFinalize(); clearNewlyAllocated(); - clearMarksWithCollectionType(); sweep(); } -MarkedBlock::FreeList MarkedBlock::resumeAllocating() +FreeList MarkedBlock::Handle::resumeAllocating() { + flipIfNecessary(); HEAP_LOG_BLOCK_STATE_TRANSITION(this); ASSERT(m_state == Marked); @@ -272,31 +315,148 @@ return FreeList(); } - // Re-create our free list from before stopping allocation. + // Re-create our free list from before stopping allocation. Note that this may return an empty + // freelist, in which case the block will still be Marked! return sweep(SweepToFreeList); } -void MarkedBlock::didRetireBlock(const FreeList& freeList) +void MarkedBlock::Handle::zap(const FreeList& freeList) { - HEAP_LOG_BLOCK_STATE_TRANSITION(this); - FreeCell* head = freeList.head; - - // Currently we don't notify the Heap that we're giving up on this block. - // The Heap might be able to make a better decision about how many bytes should - // be allocated before the next collection if it knew about this retired block. - // On the other hand we'll waste at most 10% of our Heap space between FullCollections - // and only under heavy fragmentation. - - // We need to zap the free list when retiring a block so that we don't try to destroy - // previously destroyed objects when we re-sweep the block in the future. - FreeCell* next; - for (FreeCell* current = head; current; current = next) { - next = current->next; - reinterpret_cast(current)->zap(); + forEachFreeCell( + freeList, + [&] (HeapCell* cell) { + if (m_attributes.destruction == NeedsDestruction) + cell->zap(); + }); +} + +template +void MarkedBlock::Handle::forEachFreeCell(const FreeList& freeList, const Func& func) +{ + if (freeList.remaining) { + for (unsigned remaining = freeList.remaining; remaining; remaining -= cellSize()) + func(bitwise_cast(freeList.payloadEnd - remaining)); + } else { + for (FreeCell* current = freeList.head; current;) { + FreeCell* next = current->next; + func(bitwise_cast(current)); + current = next; + } } +} +void MarkedBlock::flipIfNecessary() +{ + flipIfNecessary(vm()->heap.objectSpace().version()); +} + +void MarkedBlock::Handle::flipIfNecessary() +{ + block().flipIfNecessary(); +} + +void MarkedBlock::flipIfNecessarySlow() +{ + ASSERT(needsFlip()); + clearMarks(); +} + +void MarkedBlock::flipIfNecessaryConcurrentlySlow() +{ + LockHolder locker(m_lock); + if (needsFlip()) + clearMarks(); +} + +void MarkedBlock::clearMarks() +{ + m_marks.clearAll(); + clearHasAnyMarked(); + // This will become true at the end of the mark phase. We set it now to + // avoid an extra pass to do so later. + handle().m_state = Marked; + WTF::storeStoreFence(); + m_version = vm()->heap.objectSpace().version(); +} + +#if !ASSERT_DISABLED +void MarkedBlock::assertFlipped() +{ + ASSERT(m_version == vm()->heap.objectSpace().version()); +} +#endif // !ASSERT_DISABLED + +bool MarkedBlock::needsFlip() +{ + return needsFlip(vm()->heap.objectSpace().version()); +} + +bool MarkedBlock::Handle::needsFlip() +{ + return m_block->needsFlip(); +} + +void MarkedBlock::Handle::willRemoveBlock() +{ + flipIfNecessary(); +} + +void MarkedBlock::Handle::didConsumeFreeList() +{ + flipIfNecessary(); + HEAP_LOG_BLOCK_STATE_TRANSITION(this); + ASSERT(m_state == FreeListed); - m_state = Retired; + + m_state = Allocated; +} + +size_t MarkedBlock::markCount() +{ + flipIfNecessary(); + return m_marks.count(); +} + +bool MarkedBlock::Handle::isEmpty() +{ + flipIfNecessary(); + return m_state == Marked && !block().hasAnyMarked() && m_weakSet.isEmpty() && (!m_newlyAllocated || m_newlyAllocated->isEmpty()); +} + +void MarkedBlock::clearHasAnyMarked() +{ + m_biasedMarkCount = m_markCountBias; +} + +void MarkedBlock::noteMarkedSlow() +{ + handle().m_allocator->retire(&handle()); } } // namespace JSC + +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, MarkedBlock::BlockState blockState) +{ + switch (blockState) { + case MarkedBlock::New: + out.print("New"); + return; + case MarkedBlock::FreeListed: + out.print("FreeListed"); + return; + case MarkedBlock::Allocated: + out.print("Allocated"); + return; + case MarkedBlock::Marked: + out.print("Marked"); + return; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedBlock.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2003-2009, 2011, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +22,10 @@ #ifndef MarkedBlock_h #define MarkedBlock_h +#include "AllocatorAttributes.h" +#include "DestructionMode.h" +#include "FreeList.h" +#include "HeapCell.h" #include "HeapOperation.h" #include "IterationStatus.h" #include "WeakSet.h" @@ -31,453 +35,675 @@ #include #include +namespace JSC { + +class Heap; +class JSCell; +class MarkedAllocator; + +typedef uintptr_t Bits; +typedef uint32_t HeapVersion; + // Set to log state transitions of blocks. #define HEAP_LOG_BLOCK_STATE_TRANSITIONS 0 #if HEAP_LOG_BLOCK_STATE_TRANSITIONS -#define HEAP_LOG_BLOCK_STATE_TRANSITION(block) do { \ - dataLogF( \ - "%s:%d %s: block %s = %p, %d\n", \ - __FILE__, __LINE__, __FUNCTION__, \ - #block, (block), (block)->m_state); \ +#define HEAP_LOG_BLOCK_STATE_TRANSITION(handle) do { \ + dataLogF( \ + "%s:%d %s: block %s = %p, %d\n", \ + __FILE__, __LINE__, __FUNCTION__, \ + #handle, &(handle)->block(), (handle)->m_state); \ } while (false) #else -#define HEAP_LOG_BLOCK_STATE_TRANSITION(block) ((void)0) +#define HEAP_LOG_BLOCK_STATE_TRANSITION(handle) ((void)0) #endif -namespace JSC { - - class Heap; - class JSCell; - class MarkedAllocator; +// A marked block is a page-aligned container for heap-allocated objects. +// Objects are allocated within cells of the marked block. For a given +// marked block, all cells have the same size. Objects smaller than the +// cell size may be allocated in the marked block, in which case the +// allocation suffers from internal fragmentation: wasted space whose +// size is equal to the difference between the cell size and the object +// size. + +class MarkedBlock { + WTF_MAKE_NONCOPYABLE(MarkedBlock); + friend class LLIntOffsetsExtractor; + friend struct VerifyMarked; + +public: + class Handle; +private: + friend class Handle; +public: + enum BlockState : uint8_t { New, FreeListed, Allocated, Marked }; + + static const size_t atomSize = 16; // bytes + static const size_t blockSize = 16 * KB; + static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. + + static const size_t atomsPerBlock = blockSize / atomSize; + + static_assert(!(MarkedBlock::atomSize & (MarkedBlock::atomSize - 1)), "MarkedBlock::atomSize must be a power of two."); + static_assert(!(MarkedBlock::blockSize & (MarkedBlock::blockSize - 1)), "MarkedBlock::blockSize must be a power of two."); + + struct VoidFunctor { + typedef void ReturnType; + void returnValue() { } + }; - typedef uintptr_t Bits; + class CountFunctor { + public: + typedef size_t ReturnType; - bool isZapped(const JSCell*); - - // A marked block is a page-aligned container for heap-allocated objects. - // Objects are allocated within cells of the marked block. For a given - // marked block, all cells have the same size. Objects smaller than the - // cell size may be allocated in the marked block, in which case the - // allocation suffers from internal fragmentation: wasted space whose - // size is equal to the difference between the cell size and the object - // size. + CountFunctor() : m_count(0) { } + void count(size_t count) const { m_count += count; } + ReturnType returnValue() const { return m_count; } - class MarkedBlock : public DoublyLinkedListNode { - friend class WTF::DoublyLinkedListNode; + private: + // FIXME: This is mutable because we're using a functor rather than C++ lambdas. + // https://bugs.webkit.org/show_bug.cgi?id=159644 + mutable ReturnType m_count; + }; + + class Handle : public BasicRawSentinelNode { + WTF_MAKE_NONCOPYABLE(Handle); + WTF_MAKE_FAST_ALLOCATED; + friend class DoublyLinkedListNode; friend class LLIntOffsetsExtractor; - friend struct VerifyMarkedOrRetired; + friend class MarkedBlock; + friend struct VerifyMarked; public: - static const size_t atomSize = 16; // bytes - static const size_t blockSize = 16 * KB; - static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. - - static const size_t atomsPerBlock = blockSize / atomSize; - - static_assert(!(MarkedBlock::atomSize & (MarkedBlock::atomSize - 1)), "MarkedBlock::atomSize must be a power of two."); - static_assert(!(MarkedBlock::blockSize & (MarkedBlock::blockSize - 1)), "MarkedBlock::blockSize must be a power of two."); - - struct FreeCell { - FreeCell* next; - }; - - struct FreeList { - FreeCell* head; - size_t bytes; - - FreeList(); - FreeList(FreeCell*, size_t); - }; - - struct VoidFunctor { - typedef void ReturnType; - void returnValue() { } - }; - - class CountFunctor { - public: - typedef size_t ReturnType; - - CountFunctor() : m_count(0) { } - void count(size_t count) { m_count += count; } - ReturnType returnValue() { return m_count; } - - private: - ReturnType m_count; - }; - - static MarkedBlock* create(Heap&, MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction); - static void destroy(Heap&, MarkedBlock*); - - static bool isAtomAligned(const void*); - static MarkedBlock* blockFor(const void*); - static size_t firstAtom(); - + + ~Handle(); + + MarkedBlock& block(); + + void* cellAlign(void*); + + bool isEmpty(); + void lastChanceToFinalize(); MarkedAllocator* allocator() const; Heap* heap() const; VM* vm() const; WeakSet& weakSet(); - + enum SweepMode { SweepOnly, SweepToFreeList }; FreeList sweep(SweepMode = SweepOnly); - + + void unsweepWithNoNewlyAllocated(); + + void zap(const FreeList&); + void shrink(); - - void visitWeakSet(HeapRootVisitor&); + + unsigned visitWeakSet(HeapRootVisitor&); void reapWeakSet(); - + // While allocating from a free list, MarkedBlock temporarily has bogus // cell liveness data. To restore accurate cell liveness data, call one // of these functions: void didConsumeFreeList(); // Call this once you've allocated all the items in the free list. void stopAllocating(const FreeList&); FreeList resumeAllocating(); // Call this if you canonicalized a block for some non-collection related purpose. - + // Returns true if the "newly allocated" bitmap was non-null // and was successfully cleared and false otherwise. bool clearNewlyAllocated(); - void clearMarks(); - template - void clearMarksWithCollectionType(); - - size_t markCount(); - bool isEmpty(); - + + void flipForEdenCollection(); + size_t cellSize(); + const AllocatorAttributes& attributes() const; + DestructionMode destruction() const; bool needsDestruction() const; - + HeapCell::Kind cellKind() const; + + size_t markCount(); size_t size(); - size_t capacity(); - - bool isMarked(const void*); - bool testAndSetMarked(const void*); - bool isLive(const JSCell*); + + bool isLive(const HeapCell*); bool isLiveCell(const void*); - bool isAtom(const void*); - bool isMarkedOrNewlyAllocated(const JSCell*); - void setMarked(const void*); - void clearMarked(const void*); - + bool isMarkedOrNewlyAllocated(const HeapCell*); + bool isNewlyAllocated(const void*); void setNewlyAllocated(const void*); void clearNewlyAllocated(const void*); - + + bool hasAnyNewlyAllocated() const { return !!m_newlyAllocated; } + bool isAllocated() const; - bool isMarkedOrRetired() const; + bool isMarked() const; + bool isFreeListed() const; bool needsSweeping() const; - void didRetireBlock(const FreeList&); void willRemoveBlock(); - template IterationStatus forEachCell(Functor&); - template IterationStatus forEachLiveCell(Functor&); - template IterationStatus forEachDeadCell(Functor&); - - private: - static const size_t atomAlignmentMask = atomSize - 1; - - enum BlockState { New, FreeListed, Allocated, Marked, Retired }; - template FreeList sweepHelper(SweepMode = SweepOnly); - - typedef char Atom[atomSize]; - - MarkedBlock(MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction); - Atom* atoms(); - size_t atomNumber(const void*); - void callDestructor(JSCell*); - template FreeList specializedSweep(); + template IterationStatus forEachCell(const Functor&); + template IterationStatus forEachLiveCell(const Functor&); + template IterationStatus forEachDeadCell(const Functor&); + + bool needsFlip(); + + void flipIfNecessaryConcurrently(HeapVersion); + void flipIfNecessary(HeapVersion); + void flipIfNecessary(); + + void assertFlipped(); + + bool isOnBlocksToSweep() const { return m_isOnBlocksToSweep; } + void setIsOnBlocksToSweep(bool value) { m_isOnBlocksToSweep = value; } - MarkedBlock* m_prev; - MarkedBlock* m_next; - + BlockState state() const { return m_state; } + + private: + Handle(Heap&, MarkedAllocator*, size_t cellSize, const AllocatorAttributes&, void*); + + template + FreeList sweepHelperSelectScribbleMode(SweepMode = SweepOnly); + + enum ScribbleMode { DontScribble, Scribble }; + + template + FreeList sweepHelperSelectStateAndSweepMode(SweepMode = SweepOnly); + + enum NewlyAllocatedMode { HasNewlyAllocated, DoesNotHaveNewlyAllocated }; + + template + FreeList specializedSweep(); + + template + void forEachFreeCell(const FreeList&, const Func&); + + MarkedBlock::Handle* m_prev; + MarkedBlock::Handle* m_next; + size_t m_atomsPerCell; size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom. - WTF::Bitmap m_marks; + std::unique_ptr> m_newlyAllocated; - - size_t m_capacity; - bool m_needsDestruction; - MarkedAllocator* m_allocator; + + AllocatorAttributes m_attributes; BlockState m_state; + bool m_isOnBlocksToSweep { false }; + + MarkedAllocator* m_allocator; WeakSet m_weakSet; + + MarkedBlock* m_block; }; + + static MarkedBlock::Handle* tryCreate(Heap&, MarkedAllocator*, size_t cellSize, const AllocatorAttributes&); + + Handle& handle(); + + VM* vm() const; - inline MarkedBlock::FreeList::FreeList() - : head(0) - , bytes(0) - { - } - - inline MarkedBlock::FreeList::FreeList(FreeCell* head, size_t bytes) - : head(head) - , bytes(bytes) - { - } - - inline size_t MarkedBlock::firstAtom() - { - return WTF::roundUpToMultipleOf(sizeof(MarkedBlock)) / atomSize; - } - - inline MarkedBlock::Atom* MarkedBlock::atoms() - { - return reinterpret_cast(this); - } - - inline bool MarkedBlock::isAtomAligned(const void* p) - { - return !(reinterpret_cast(p) & atomAlignmentMask); - } - - inline MarkedBlock* MarkedBlock::blockFor(const void* p) - { - return reinterpret_cast(reinterpret_cast(p) & blockMask); - } - - inline MarkedAllocator* MarkedBlock::allocator() const - { - return m_allocator; - } - - inline Heap* MarkedBlock::heap() const - { - return m_weakSet.heap(); - } - - inline VM* MarkedBlock::vm() const - { - return m_weakSet.vm(); - } - - inline WeakSet& MarkedBlock::weakSet() - { - return m_weakSet; - } - - inline void MarkedBlock::shrink() - { - m_weakSet.shrink(); - } - - inline void MarkedBlock::visitWeakSet(HeapRootVisitor& heapRootVisitor) - { - m_weakSet.visit(heapRootVisitor); - } - - inline void MarkedBlock::reapWeakSet() - { - m_weakSet.reap(); - } - - inline void MarkedBlock::willRemoveBlock() - { - ASSERT(m_state != Retired); - } - - inline void MarkedBlock::didConsumeFreeList() - { - HEAP_LOG_BLOCK_STATE_TRANSITION(this); - - ASSERT(m_state == FreeListed); - m_state = Allocated; - } - - inline size_t MarkedBlock::markCount() - { - return m_marks.count(); - } - - inline bool MarkedBlock::isEmpty() - { - return m_marks.isEmpty() && m_weakSet.isEmpty() && (!m_newlyAllocated || m_newlyAllocated->isEmpty()); - } - - inline size_t MarkedBlock::cellSize() - { - return m_atomsPerCell * atomSize; - } - - inline bool MarkedBlock::needsDestruction() const - { - return m_needsDestruction; - } - - inline size_t MarkedBlock::size() - { - return markCount() * cellSize(); - } - - inline size_t MarkedBlock::capacity() - { - return m_capacity; - } + static bool isAtomAligned(const void*); + static MarkedBlock* blockFor(const void*); + static size_t firstAtom(); + size_t atomNumber(const void*); + + size_t markCount(); - inline size_t MarkedBlock::atomNumber(const void* p) - { - return (reinterpret_cast(p) - reinterpret_cast(this)) / atomSize; - } + bool isMarked(const void*); + bool testAndSetMarked(const void*); + + bool isMarkedOrNewlyAllocated(const HeapCell*); - inline bool MarkedBlock::isMarked(const void* p) - { - return m_marks.get(atomNumber(p)); - } + bool isAtom(const void*); + void setMarked(const void*); + void clearMarked(const void*); + + size_t cellSize(); + const AllocatorAttributes& attributes() const; - inline bool MarkedBlock::testAndSetMarked(const void* p) - { - return m_marks.concurrentTestAndSet(atomNumber(p)); - } + bool hasAnyMarked() const; + void noteMarked(); + + WeakSet& weakSet(); - inline void MarkedBlock::setMarked(const void* p) - { - m_marks.set(atomNumber(p)); - } + bool needsFlip(HeapVersion); + bool needsFlip(); + + void flipIfNecessaryConcurrently(HeapVersion); + void flipIfNecessary(HeapVersion); + void flipIfNecessary(); + + void assertFlipped(); + + bool needsDestruction() const { return m_needsDestruction; } + +private: + static const size_t atomAlignmentMask = atomSize - 1; - inline void MarkedBlock::clearMarked(const void* p) - { - ASSERT(m_marks.get(atomNumber(p))); - m_marks.clear(atomNumber(p)); - } + typedef char Atom[atomSize]; - inline bool MarkedBlock::isNewlyAllocated(const void* p) - { - return m_newlyAllocated->get(atomNumber(p)); - } + MarkedBlock(VM&, Handle&); + Atom* atoms(); + + void flipIfNecessaryConcurrentlySlow(); + void flipIfNecessarySlow(); + void clearMarks(); + void clearHasAnyMarked(); + + void noteMarkedSlow(); + + WTF::Bitmap m_marks; - inline void MarkedBlock::setNewlyAllocated(const void* p) - { - m_newlyAllocated->set(atomNumber(p)); - } + bool m_needsDestruction; + Lock m_lock; + + // The actual mark count can be computed by doing: m_biasedMarkCount - m_markCountBias. Note + // that this count is racy. It will accurately detect whether or not exactly zero things were + // marked, but if N things got marked, then this may report anything in the range [1, N] (or + // before unbiased, it would be [1 + m_markCountBias, N + m_markCountBias].) + int16_t m_biasedMarkCount; + + // We bias the mark count so that if m_biasedMarkCount >= 0 then the block should be retired. + // We go to all this trouble to make marking a bit faster: this way, marking knows when to + // retire a block using a js/jns on m_biasedMarkCount. + // + // For example, if a block has room for 100 objects and retirement happens whenever 90% are + // live, then m_markCountBias will be -90. This way, when marking begins, this will cause us to + // set m_biasedMarkCount to -90 as well, since: + // + // m_biasedMarkCount = actualMarkCount + m_markCountBias. + // + // Marking an object will increment m_biasedMarkCount. Once 90 objects get marked, we will have + // m_biasedMarkCount = 0, which will trigger retirement. In other words, we want to set + // m_markCountBias like so: + // + // m_markCountBias = -(minMarkedBlockUtilization * cellsPerBlock) + // + // All of this also means that you can detect if any objects are marked by doing: + // + // m_biasedMarkCount != m_markCountBias + int16_t m_markCountBias; - inline void MarkedBlock::clearNewlyAllocated(const void* p) - { - m_newlyAllocated->clear(atomNumber(p)); - } + HeapVersion m_version; + + Handle& m_handle; + VM* m_vm; +}; + +inline MarkedBlock::Handle& MarkedBlock::handle() +{ + return m_handle; +} + +inline MarkedBlock& MarkedBlock::Handle::block() +{ + return *m_block; +} + +inline size_t MarkedBlock::firstAtom() +{ + return WTF::roundUpToMultipleOf(sizeof(MarkedBlock)) / atomSize; +} + +inline MarkedBlock::Atom* MarkedBlock::atoms() +{ + return reinterpret_cast(this); +} + +inline bool MarkedBlock::isAtomAligned(const void* p) +{ + return !(reinterpret_cast(p) & atomAlignmentMask); +} + +inline void* MarkedBlock::Handle::cellAlign(void* p) +{ + Bits base = reinterpret_cast(block().atoms() + firstAtom()); + Bits bits = reinterpret_cast(p); + bits -= base; + bits -= bits % cellSize(); + bits += base; + return reinterpret_cast(bits); +} + +inline MarkedBlock* MarkedBlock::blockFor(const void* p) +{ + return reinterpret_cast(reinterpret_cast(p) & blockMask); +} + +inline MarkedAllocator* MarkedBlock::Handle::allocator() const +{ + return m_allocator; +} + +inline Heap* MarkedBlock::Handle::heap() const +{ + return m_weakSet.heap(); +} + +inline VM* MarkedBlock::Handle::vm() const +{ + return m_weakSet.vm(); +} + +inline VM* MarkedBlock::vm() const +{ + return m_vm; +} + +inline WeakSet& MarkedBlock::Handle::weakSet() +{ + return m_weakSet; +} + +inline WeakSet& MarkedBlock::weakSet() +{ + return m_handle.weakSet(); +} + +inline void MarkedBlock::Handle::shrink() +{ + m_weakSet.shrink(); +} + +inline unsigned MarkedBlock::Handle::visitWeakSet(HeapRootVisitor& heapRootVisitor) +{ + return m_weakSet.visit(heapRootVisitor); +} + +inline void MarkedBlock::Handle::reapWeakSet() +{ + m_weakSet.reap(); +} + +inline size_t MarkedBlock::Handle::cellSize() +{ + return m_atomsPerCell * atomSize; +} + +inline size_t MarkedBlock::cellSize() +{ + return m_handle.cellSize(); +} + +inline const AllocatorAttributes& MarkedBlock::Handle::attributes() const +{ + return m_attributes; +} + +inline const AllocatorAttributes& MarkedBlock::attributes() const +{ + return m_handle.attributes(); +} + +inline bool MarkedBlock::Handle::needsDestruction() const +{ + return m_attributes.destruction == NeedsDestruction; +} + +inline DestructionMode MarkedBlock::Handle::destruction() const +{ + return m_attributes.destruction; +} + +inline HeapCell::Kind MarkedBlock::Handle::cellKind() const +{ + return m_attributes.cellKind; +} + +inline size_t MarkedBlock::Handle::markCount() +{ + return m_block->markCount(); +} + +inline size_t MarkedBlock::Handle::size() +{ + return markCount() * cellSize(); +} + +inline size_t MarkedBlock::atomNumber(const void* p) +{ + return (reinterpret_cast(p) - reinterpret_cast(this)) / atomSize; +} + +inline bool MarkedBlock::needsFlip(HeapVersion heapVersion) +{ + return heapVersion != m_version; +} + +inline void MarkedBlock::flipIfNecessary(HeapVersion heapVersion) +{ + if (UNLIKELY(needsFlip(heapVersion))) + flipIfNecessarySlow(); +} + +inline void MarkedBlock::flipIfNecessaryConcurrently(HeapVersion heapVersion) +{ + if (UNLIKELY(needsFlip(heapVersion))) + flipIfNecessaryConcurrentlySlow(); + WTF::loadLoadFence(); +} + +inline void MarkedBlock::Handle::flipIfNecessary(HeapVersion heapVersion) +{ + block().flipIfNecessary(heapVersion); +} + +inline void MarkedBlock::Handle::flipIfNecessaryConcurrently(HeapVersion heapVersion) +{ + block().flipIfNecessaryConcurrently(heapVersion); +} + +inline void MarkedBlock::Handle::flipForEdenCollection() +{ + assertFlipped(); + + HEAP_LOG_BLOCK_STATE_TRANSITION(this); + + ASSERT(m_state != New && m_state != FreeListed); + + m_state = Marked; +} - inline bool MarkedBlock::clearNewlyAllocated() - { - if (m_newlyAllocated) { - m_newlyAllocated = nullptr; - return true; - } - return false; +#if ASSERT_DISABLED +inline void MarkedBlock::assertFlipped() +{ +} +#endif // ASSERT_DISABLED + +inline void MarkedBlock::Handle::assertFlipped() +{ + block().assertFlipped(); +} + +inline bool MarkedBlock::isMarked(const void* p) +{ + assertFlipped(); + return m_marks.get(atomNumber(p)); +} + +inline bool MarkedBlock::testAndSetMarked(const void* p) +{ + assertFlipped(); + return m_marks.concurrentTestAndSet(atomNumber(p)); +} + +inline bool MarkedBlock::Handle::isNewlyAllocated(const void* p) +{ + return m_newlyAllocated->get(m_block->atomNumber(p)); +} + +inline void MarkedBlock::Handle::setNewlyAllocated(const void* p) +{ + m_newlyAllocated->set(m_block->atomNumber(p)); +} + +inline void MarkedBlock::Handle::clearNewlyAllocated(const void* p) +{ + m_newlyAllocated->clear(m_block->atomNumber(p)); +} + +inline bool MarkedBlock::Handle::clearNewlyAllocated() +{ + if (m_newlyAllocated) { + m_newlyAllocated = nullptr; + return true; } + return false; +} - inline bool MarkedBlock::isMarkedOrNewlyAllocated(const JSCell* cell) - { - ASSERT(m_state == Retired || m_state == Marked); - return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell)); - } +inline bool MarkedBlock::Handle::isMarkedOrNewlyAllocated(const HeapCell* cell) +{ + ASSERT(m_state == Marked); + return m_block->isMarked(cell) || (m_newlyAllocated && isNewlyAllocated(cell)); +} + +inline bool MarkedBlock::isMarkedOrNewlyAllocated(const HeapCell* cell) +{ + ASSERT(m_handle.m_state == Marked); + return isMarked(cell) || (m_handle.m_newlyAllocated && m_handle.isNewlyAllocated(cell)); +} + +inline bool MarkedBlock::Handle::isLive(const HeapCell* cell) +{ + assertFlipped(); + switch (m_state) { + case Allocated: + return true; - inline bool MarkedBlock::isLive(const JSCell* cell) - { - switch (m_state) { - case Allocated: - return true; - - case Retired: - case Marked: - return isMarkedOrNewlyAllocated(cell); - - case New: - case FreeListed: - RELEASE_ASSERT_NOT_REACHED(); - return false; - } + case Marked: + return isMarkedOrNewlyAllocated(cell); + case New: + case FreeListed: RELEASE_ASSERT_NOT_REACHED(); return false; } - inline bool MarkedBlock::isAtom(const void* p) - { - ASSERT(MarkedBlock::isAtomAligned(p)); - size_t atomNumber = this->atomNumber(p); - size_t firstAtom = this->firstAtom(); - if (atomNumber < firstAtom) // Filters pointers into MarkedBlock metadata. - return false; - if ((atomNumber - firstAtom) % m_atomsPerCell) // Filters pointers into cell middles. - return false; - if (atomNumber >= m_endAtom) // Filters pointers into invalid cells out of the range. - return false; - return true; - } - - inline bool MarkedBlock::isLiveCell(const void* p) - { - if (!isAtom(p)) - return false; - return isLive(static_cast(p)); - } - - template inline IterationStatus MarkedBlock::forEachCell(Functor& functor) - { - for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { - JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); - if (functor(cell) == IterationStatus::Done) - return IterationStatus::Done; - } - return IterationStatus::Continue; - } + RELEASE_ASSERT_NOT_REACHED(); + return false; +} + +inline bool MarkedBlock::isAtom(const void* p) +{ + ASSERT(MarkedBlock::isAtomAligned(p)); + size_t atomNumber = this->atomNumber(p); + size_t firstAtom = MarkedBlock::firstAtom(); + if (atomNumber < firstAtom) // Filters pointers into MarkedBlock metadata. + return false; + if ((atomNumber - firstAtom) % m_handle.m_atomsPerCell) // Filters pointers into cell middles. + return false; + if (atomNumber >= m_handle.m_endAtom) // Filters pointers into invalid cells out of the range. + return false; + return true; +} - template inline IterationStatus MarkedBlock::forEachLiveCell(Functor& functor) - { - for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { - JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); - if (!isLive(cell)) - continue; - - if (functor(cell) == IterationStatus::Done) - return IterationStatus::Done; - } - return IterationStatus::Continue; - } +inline bool MarkedBlock::Handle::isLiveCell(const void* p) +{ + if (!m_block->isAtom(p)) + return false; + return isLive(static_cast(p)); +} - template inline IterationStatus MarkedBlock::forEachDeadCell(Functor& functor) - { - for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { - JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); - if (isLive(cell)) - continue; - - if (functor(cell) == IterationStatus::Done) - return IterationStatus::Done; - } - return IterationStatus::Continue; - } +template +inline IterationStatus MarkedBlock::Handle::forEachCell(const Functor& functor) +{ + HeapCell::Kind kind = m_attributes.cellKind; + for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { + HeapCell* cell = reinterpret_cast_ptr(&m_block->atoms()[i]); + if (functor(cell, kind) == IterationStatus::Done) + return IterationStatus::Done; + } + return IterationStatus::Continue; +} + +template +inline IterationStatus MarkedBlock::Handle::forEachLiveCell(const Functor& functor) +{ + flipIfNecessary(); + HeapCell::Kind kind = m_attributes.cellKind; + for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { + HeapCell* cell = reinterpret_cast_ptr(&m_block->atoms()[i]); + if (!isLive(cell)) + continue; + + if (functor(cell, kind) == IterationStatus::Done) + return IterationStatus::Done; + } + return IterationStatus::Continue; +} + +template +inline IterationStatus MarkedBlock::Handle::forEachDeadCell(const Functor& functor) +{ + flipIfNecessary(); + HeapCell::Kind kind = m_attributes.cellKind; + for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { + HeapCell* cell = reinterpret_cast_ptr(&m_block->atoms()[i]); + if (isLive(cell)) + continue; + + if (functor(cell, kind) == IterationStatus::Done) + return IterationStatus::Done; + } + return IterationStatus::Continue; +} + +inline bool MarkedBlock::Handle::needsSweeping() const +{ + const_cast(this)->flipIfNecessary(); + return m_state == Marked; +} + +inline bool MarkedBlock::Handle::isAllocated() const +{ + const_cast(this)->flipIfNecessary(); + return m_state == Allocated; +} + +inline bool MarkedBlock::Handle::isMarked() const +{ + const_cast(this)->flipIfNecessary(); + return m_state == Marked; +} + +inline bool MarkedBlock::Handle::isFreeListed() const +{ + const_cast(this)->flipIfNecessary(); + return m_state == FreeListed; +} + +inline bool MarkedBlock::hasAnyMarked() const +{ + return m_biasedMarkCount != m_markCountBias; +} + +inline void MarkedBlock::noteMarked() +{ + // This is racy by design. We don't want to pay the price of an atomic increment! + int16_t biasedMarkCount = m_biasedMarkCount; + ++biasedMarkCount; + m_biasedMarkCount = biasedMarkCount; + if (UNLIKELY(!biasedMarkCount)) + noteMarkedSlow(); +} - inline bool MarkedBlock::needsSweeping() const - { - return m_state == Marked; - } +} // namespace JSC - inline bool MarkedBlock::isAllocated() const - { - return m_state == Allocated; - } +namespace WTF { - inline bool MarkedBlock::isMarkedOrRetired() const +struct MarkedBlockHash : PtrHash { + static unsigned hash(JSC::MarkedBlock* const& key) { - return m_state == Marked || m_state == Retired; + // Aligned VM regions tend to be monotonically increasing integers, + // which is a great hash function, but we have to remove the low bits, + // since they're always zero, which is a terrible hash function! + return reinterpret_cast(key) / JSC::MarkedBlock::blockSize; } +}; -} // namespace JSC +template<> struct DefaultHash { + typedef MarkedBlockHash Hash; +}; -namespace WTF { - - struct MarkedBlockHash : PtrHash { - static unsigned hash(JSC::MarkedBlock* const& key) - { - // Aligned VM regions tend to be monotonically increasing integers, - // which is a great hash function, but we have to remove the low bits, - // since they're always zero, which is a terrible hash function! - return reinterpret_cast(key) / JSC::MarkedBlock::blockSize; - } - }; - - template<> struct DefaultHash { - typedef MarkedBlockHash Hash; - }; +void printInternal(PrintStream& out, JSC::MarkedBlock::BlockState); } // namespace WTF diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedSpace.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedSpace.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedSpace.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedSpace.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * This library is free software; you can redistribute it and/or @@ -24,74 +24,264 @@ #include "IncrementalSweeper.h" #include "JSObject.h" #include "JSCInlines.h" +#include "SuperSampler.h" +#include namespace JSC { -struct Free : MarkedBlock::VoidFunctor { - Free(MarkedSpace& space) : m_markedSpace(space) { } - void operator()(MarkedBlock* block) { m_markedSpace.freeBlock(block); } -private: - MarkedSpace& m_markedSpace; -}; - -struct FreeOrShrink : MarkedBlock::VoidFunctor { - FreeOrShrink(MarkedSpace& space) : m_markedSpace(space) { } - void operator()(MarkedBlock* block) { m_markedSpace.freeOrShrinkBlock(block); } -private: - MarkedSpace& m_markedSpace; -}; - -struct VisitWeakSet : MarkedBlock::VoidFunctor { - VisitWeakSet(HeapRootVisitor& heapRootVisitor) : m_heapRootVisitor(heapRootVisitor) { } - void operator()(MarkedBlock* block) { block->visitWeakSet(m_heapRootVisitor); } -private: - HeapRootVisitor& m_heapRootVisitor; -}; - -struct ReapWeakSet : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) { block->reapWeakSet(); } -}; +std::array MarkedSpace::s_sizeClassForSizeStep; + +namespace { + +const Vector& sizeClasses() +{ + static Vector* result; + static std::once_flag once; + std::call_once( + once, + [] { + result = new Vector(); + + auto add = [&] (size_t sizeClass) { + if (Options::dumpSizeClasses()) + dataLog("Adding JSC MarkedSpace size class: ", sizeClass, "\n"); + // Perform some validation as we go. + RELEASE_ASSERT(!(sizeClass % MarkedSpace::sizeStep)); + if (result->isEmpty()) + RELEASE_ASSERT(sizeClass == MarkedSpace::sizeStep); + else + RELEASE_ASSERT(sizeClass > result->last()); + result->append(sizeClass); + }; + + // This is a definition of the size classes in our GC. It must define all of the + // size classes from sizeStep up to largeCutoff. + + // Have very precise size classes for the small stuff. This is a loop to make it easy to reduce + // atomSize. + for (size_t size = MarkedSpace::sizeStep; size < MarkedSpace::preciseCutoff; size += MarkedSpace::sizeStep) + add(size); + + // We want to make sure that the remaining size classes minimize internal fragmentation (i.e. + // the wasted space at the tail end of a MarkedBlock) while proceeding roughly in an exponential + // way starting at just above the precise size classes to four cells per block. + + if (Options::dumpSizeClasses()) + dataLog(" Marked block payload size: ", static_cast(MarkedSpace::blockPayload), "\n"); + + for (unsigned i = 0; ; ++i) { + double approximateSize = MarkedSpace::preciseCutoff * pow(Options::sizeClassProgression(), i); + + if (Options::dumpSizeClasses()) + dataLog(" Next size class as a double: ", approximateSize, "\n"); + + size_t approximateSizeInBytes = static_cast(approximateSize); + + if (Options::dumpSizeClasses()) + dataLog(" Next size class as bytes: ", approximateSizeInBytes, "\n"); + + // Make sure that the computer did the math correctly. + RELEASE_ASSERT(approximateSizeInBytes >= MarkedSpace::preciseCutoff); + + if (approximateSizeInBytes > MarkedSpace::largeCutoff) + break; + + size_t sizeClass = + WTF::roundUpToMultipleOf(approximateSizeInBytes); + + if (Options::dumpSizeClasses()) + dataLog(" Size class: ", sizeClass, "\n"); + + // Optimize the size class so that there isn't any slop at the end of the block's + // payload. + unsigned cellsPerBlock = MarkedSpace::blockPayload / sizeClass; + size_t possiblyBetterSizeClass = (MarkedSpace::blockPayload / cellsPerBlock) & ~(MarkedSpace::sizeStep - 1); + + if (Options::dumpSizeClasses()) + dataLog(" Possibly better size class: ", possiblyBetterSizeClass, "\n"); + + // The size class we just came up with is better than the other one if it reduces + // total wastage assuming we only allocate cells of that size. + size_t originalWastage = MarkedSpace::blockPayload - cellsPerBlock * sizeClass; + size_t newWastage = (possiblyBetterSizeClass - sizeClass) * cellsPerBlock; + + if (Options::dumpSizeClasses()) + dataLog(" Original wastage: ", originalWastage, ", new wastage: ", newWastage, "\n"); + + size_t betterSizeClass; + if (newWastage > originalWastage) + betterSizeClass = sizeClass; + else + betterSizeClass = possiblyBetterSizeClass; + + if (Options::dumpSizeClasses()) + dataLog(" Choosing size class: ", betterSizeClass, "\n"); + + if (betterSizeClass == result->last()) { + // Defense for when expStep is small. + continue; + } + + // This is usually how we get out of the loop. + if (betterSizeClass > MarkedSpace::largeCutoff + || betterSizeClass > Options::largeAllocationCutoff()) + break; + + add(betterSizeClass); + } + + if (Options::dumpSizeClasses()) + dataLog("JSC Heap MarkedSpace size class dump: ", listDump(*result), "\n"); + + // We have an optimiation in MarkedSpace::optimalSizeFor() that assumes things about + // the size class table. This checks our results against that function's assumptions. + for (size_t size = MarkedSpace::sizeStep, i = 0; size <= MarkedSpace::preciseCutoff; size += MarkedSpace::sizeStep, i++) + RELEASE_ASSERT(result->at(i) == size); + }); + return *result; +} + +template +void buildSizeClassTable(TableType& table, const SizeClassCons& cons, const DefaultCons& defaultCons) +{ + size_t nextIndex = 0; + for (size_t sizeClass : sizeClasses()) { + auto entry = cons(sizeClass); + size_t index = MarkedSpace::sizeClassToIndex(sizeClass); + for (size_t i = nextIndex; i <= index; ++i) + table[i] = entry; + nextIndex = index + 1; + } + for (size_t i = nextIndex; i < MarkedSpace::numSizeClasses; ++i) + table[i] = defaultCons(MarkedSpace::indexToSizeClass(i)); +} + +} // anonymous namespace + +void MarkedSpace::initializeSizeClassForStepSize() +{ + // We call this multiple times and we may call it simultaneously from multiple threads. That's + // OK, since it always stores the same values into the table. + + buildSizeClassTable( + s_sizeClassForSizeStep, + [&] (size_t sizeClass) -> size_t { + return sizeClass; + }, + [&] (size_t sizeClass) -> size_t { + return sizeClass; + }); +} MarkedSpace::MarkedSpace(Heap* heap) : m_heap(heap) , m_capacity(0) , m_isIterating(false) { - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { - allocatorFor(cellSize).init(heap, this, cellSize, false); - destructorAllocatorFor(cellSize).init(heap, this, cellSize, true); - } - - for (size_t cellSize = impreciseStart; cellSize <= impreciseCutoff; cellSize += impreciseStep) { - allocatorFor(cellSize).init(heap, this, cellSize, false); - destructorAllocatorFor(cellSize).init(heap, this, cellSize, true); - } - - m_normalSpace.largeAllocator.init(heap, this, 0, false); - m_destructorSpace.largeAllocator.init(heap, this, 0, true); + initializeSizeClassForStepSize(); + + forEachSubspace( + [&] (Subspace& subspace, AllocatorAttributes attributes) -> IterationStatus { + subspace.attributes = attributes; + + buildSizeClassTable( + subspace.allocatorForSizeStep, + [&] (size_t sizeClass) -> MarkedAllocator* { + return subspace.bagOfAllocators.add(heap, this, sizeClass, attributes); + }, + [&] (size_t) -> MarkedAllocator* { + return nullptr; + }); + + return IterationStatus::Continue; + }); } MarkedSpace::~MarkedSpace() { - Free free(*this); - forEachBlock(free); + forEachBlock( + [&] (MarkedBlock::Handle* block) { + freeBlock(block); + }); + for (LargeAllocation* allocation : m_largeAllocations) + allocation->destroy(); ASSERT(!m_blocks.set().size()); } -struct LastChanceToFinalize { - void operator()(MarkedAllocator& allocator) { allocator.lastChanceToFinalize(); } -}; - void MarkedSpace::lastChanceToFinalize() { stopAllocating(); - forEachAllocator(); + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + allocator.lastChanceToFinalize(); + return IterationStatus::Continue; + }); + for (LargeAllocation* allocation : m_largeAllocations) + allocation->lastChanceToFinalize(); +} + +void* MarkedSpace::allocate(Subspace& subspace, size_t bytes) +{ + if (MarkedAllocator* allocator = allocatorFor(subspace, bytes)) + return allocator->allocate(); + return allocateLarge(subspace, bytes); +} + +void* MarkedSpace::tryAllocate(Subspace& subspace, size_t bytes) +{ + if (MarkedAllocator* allocator = allocatorFor(subspace, bytes)) + return allocator->tryAllocate(); + return tryAllocateLarge(subspace, bytes); +} + +void* MarkedSpace::allocateLarge(Subspace& subspace, size_t size) +{ + void* result = tryAllocateLarge(subspace, size); + RELEASE_ASSERT(result); + return result; +} + +void* MarkedSpace::tryAllocateLarge(Subspace& subspace, size_t size) +{ + m_heap->collectIfNecessaryOrDefer(); + + size = WTF::roundUpToMultipleOf(size); + LargeAllocation* allocation = LargeAllocation::tryCreate(*m_heap, size, subspace.attributes); + if (!allocation) + return nullptr; + + m_largeAllocations.append(allocation); + m_heap->didAllocate(size); + m_capacity += size; + return allocation->cell(); } void MarkedSpace::sweep() { m_heap->sweeper()->willFinishSweeping(); - forEachBlock(); + forEachBlock( + [&] (MarkedBlock::Handle* block) { + block->sweep(); + }); +} + +void MarkedSpace::sweepLargeAllocations() +{ + RELEASE_ASSERT(m_largeAllocationsNurseryOffset == m_largeAllocations.size()); + unsigned srcIndex = m_largeAllocationsNurseryOffsetForSweep; + unsigned dstIndex = srcIndex; + while (srcIndex < m_largeAllocations.size()) { + LargeAllocation* allocation = m_largeAllocations[srcIndex++]; + allocation->sweep(); + if (allocation->isEmpty()) { + m_capacity -= allocation->cellSize(); + allocation->destroy(); + continue; + } + m_largeAllocations[dstIndex++] = allocation; + } + m_largeAllocations.resize(dstIndex); + m_largeAllocationsNurseryOffset = m_largeAllocations.size(); } void MarkedSpace::zombifySweep() @@ -99,120 +289,116 @@ if (Options::logGC()) dataLog("Zombifying sweep..."); m_heap->sweeper()->willFinishSweeping(); - forEachBlock(); + forEachBlock( + [&] (MarkedBlock::Handle* block) { + if (block->needsSweeping()) + block->sweep(); + }); } void MarkedSpace::resetAllocators() { - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { - allocatorFor(cellSize).reset(); - destructorAllocatorFor(cellSize).reset(); - } - - for (size_t cellSize = impreciseStart; cellSize <= impreciseCutoff; cellSize += impreciseStep) { - allocatorFor(cellSize).reset(); - destructorAllocatorFor(cellSize).reset(); - } - - m_normalSpace.largeAllocator.reset(); - m_destructorSpace.largeAllocator.reset(); + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + allocator.reset(); + return IterationStatus::Continue; + }); m_blocksWithNewObjects.clear(); + m_activeWeakSets.takeFrom(m_newActiveWeakSets); + if (m_heap->operationInProgress() == EdenCollection) + m_largeAllocationsNurseryOffsetForSweep = m_largeAllocationsNurseryOffset; + else + m_largeAllocationsNurseryOffsetForSweep = 0; + m_largeAllocationsNurseryOffset = m_largeAllocations.size(); } void MarkedSpace::visitWeakSets(HeapRootVisitor& heapRootVisitor) { - VisitWeakSet visitWeakSet(heapRootVisitor); - if (m_heap->operationInProgress() == EdenCollection) { - for (unsigned i = 0; i < m_blocksWithNewObjects.size(); ++i) - visitWeakSet(m_blocksWithNewObjects[i]); - } else - forEachBlock(visitWeakSet); + auto visit = [&] (WeakSet* weakSet) { + weakSet->visit(heapRootVisitor); + }; + + m_newActiveWeakSets.forEach(visit); + + if (m_heap->operationInProgress() == FullCollection) + m_activeWeakSets.forEach(visit); } void MarkedSpace::reapWeakSets() { - if (m_heap->operationInProgress() == EdenCollection) { - for (unsigned i = 0; i < m_blocksWithNewObjects.size(); ++i) - m_blocksWithNewObjects[i]->reapWeakSet(); - } else - forEachBlock(); -} - -template -void MarkedSpace::forEachAllocator() -{ - Functor functor; - forEachAllocator(functor); + auto visit = [&] (WeakSet* weakSet) { + weakSet->reap(); + }; + + m_newActiveWeakSets.forEach(visit); + + if (m_heap->operationInProgress() == FullCollection) + m_activeWeakSets.forEach(visit); } -template -void MarkedSpace::forEachAllocator(Functor& functor) -{ - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { - functor(allocatorFor(cellSize)); - functor(destructorAllocatorFor(cellSize)); - } - - for (size_t cellSize = impreciseStart; cellSize <= impreciseCutoff; cellSize += impreciseStep) { - functor(allocatorFor(cellSize)); - functor(destructorAllocatorFor(cellSize)); - } - - functor(m_normalSpace.largeAllocator); - functor(m_destructorSpace.largeAllocator); -} - -struct StopAllocatingFunctor { - void operator()(MarkedAllocator& allocator) { allocator.stopAllocating(); } -}; - void MarkedSpace::stopAllocating() { ASSERT(!isIterating()); - forEachAllocator(); + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + allocator.stopAllocating(); + return IterationStatus::Continue; + }); +} + +void MarkedSpace::prepareForMarking() +{ + if (m_heap->operationInProgress() == EdenCollection) + m_largeAllocationsOffsetForThisCollection = m_largeAllocationsNurseryOffset; + else + m_largeAllocationsOffsetForThisCollection = 0; + m_largeAllocationsForThisCollectionBegin = m_largeAllocations.begin() + m_largeAllocationsOffsetForThisCollection; + m_largeAllocationsForThisCollectionSize = m_largeAllocations.size() - m_largeAllocationsOffsetForThisCollection; + m_largeAllocationsForThisCollectionEnd = m_largeAllocations.end(); + RELEASE_ASSERT(m_largeAllocationsForThisCollectionEnd == m_largeAllocationsForThisCollectionBegin + m_largeAllocationsForThisCollectionSize); + std::sort( + m_largeAllocationsForThisCollectionBegin, m_largeAllocationsForThisCollectionEnd, + [&] (LargeAllocation* a, LargeAllocation* b) { + return a < b; + }); } -struct ResumeAllocatingFunctor { - void operator()(MarkedAllocator& allocator) { allocator.resumeAllocating(); } -}; - void MarkedSpace::resumeAllocating() { ASSERT(isIterating()); - forEachAllocator(); + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + allocator.resumeAllocating(); + return IterationStatus::Continue; + }); + // Nothing to do for LargeAllocations. } bool MarkedSpace::isPagedOut(double deadline) { - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { - if (allocatorFor(cellSize).isPagedOut(deadline) - || destructorAllocatorFor(cellSize).isPagedOut(deadline)) - return true; - } - - for (size_t cellSize = impreciseStart; cellSize <= impreciseCutoff; cellSize += impreciseStep) { - if (allocatorFor(cellSize).isPagedOut(deadline) - || destructorAllocatorFor(cellSize).isPagedOut(deadline)) - return true; - } - - if (m_normalSpace.largeAllocator.isPagedOut(deadline) - || m_destructorSpace.largeAllocator.isPagedOut(deadline)) - return true; - - return false; + bool result = false; + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + if (allocator.isPagedOut(deadline)) { + result = true; + return IterationStatus::Done; + } + return IterationStatus::Continue; + }); + // FIXME: Consider taking LargeAllocations into account here. + return result; } -void MarkedSpace::freeBlock(MarkedBlock* block) +void MarkedSpace::freeBlock(MarkedBlock::Handle* block) { block->allocator()->removeBlock(block); - m_capacity -= block->capacity(); - m_blocks.remove(block); - MarkedBlock::destroy(*m_heap, block); + m_capacity -= MarkedBlock::blockSize; + m_blocks.remove(&block->block()); + delete block; } -void MarkedSpace::freeOrShrinkBlock(MarkedBlock* block) +void MarkedSpace::freeOrShrinkBlock(MarkedBlock::Handle* block) { if (!block->isEmpty()) { block->shrink(); @@ -224,59 +410,44 @@ void MarkedSpace::shrink() { - FreeOrShrink freeOrShrink(*this); - forEachBlock(freeOrShrink); + forEachBlock( + [&] (MarkedBlock::Handle* block) { + freeOrShrinkBlock(block); + }); + // For LargeAllocations, we do the moral equivalent in sweepLargeAllocations(). } -static void clearNewlyAllocatedInBlock(MarkedBlock* block) -{ - if (!block) - return; - block->clearNewlyAllocated(); -} - -struct ClearNewlyAllocated : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) { block->clearNewlyAllocated(); } -}; - -#ifndef NDEBUG -struct VerifyNewlyAllocated : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) { ASSERT(!block->clearNewlyAllocated()); } -}; -#endif - void MarkedSpace::clearNewlyAllocated() { - for (size_t i = 0; i < preciseCount; ++i) { - clearNewlyAllocatedInBlock(m_normalSpace.preciseAllocators[i].takeLastActiveBlock()); - clearNewlyAllocatedInBlock(m_destructorSpace.preciseAllocators[i].takeLastActiveBlock()); - } - - for (size_t i = 0; i < impreciseCount; ++i) { - clearNewlyAllocatedInBlock(m_normalSpace.impreciseAllocators[i].takeLastActiveBlock()); - clearNewlyAllocatedInBlock(m_destructorSpace.impreciseAllocators[i].takeLastActiveBlock()); - } - - // We have to iterate all of the blocks in the large allocators because they are - // canonicalized as they are used up (see MarkedAllocator::tryAllocateHelper) - // which creates the m_newlyAllocated bitmap. - ClearNewlyAllocated functor; - m_normalSpace.largeAllocator.forEachBlock(functor); - m_destructorSpace.largeAllocator.forEachBlock(functor); - -#ifndef NDEBUG - VerifyNewlyAllocated verifyFunctor; - forEachBlock(verifyFunctor); -#endif + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + if (MarkedBlock::Handle* block = allocator.takeLastActiveBlock()) + block->clearNewlyAllocated(); + return IterationStatus::Continue; + }); + + for (unsigned i = m_largeAllocationsOffsetForThisCollection; i < m_largeAllocations.size(); ++i) + m_largeAllocations[i]->clearNewlyAllocated(); + +#if !ASSERT_DISABLED + forEachBlock( + [&] (MarkedBlock::Handle* block) { + ASSERT(!block->clearNewlyAllocated()); + }); + + for (LargeAllocation* allocation : m_largeAllocations) + ASSERT(!allocation->isNewlyAllocated()); +#endif // !ASSERT_DISABLED } #ifndef NDEBUG -struct VerifyMarkedOrRetired : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) +struct VerifyMarked : MarkedBlock::VoidFunctor { + void operator()(MarkedBlock::Handle* block) const { + if (block->needsFlip()) + return; switch (block->m_state) { case MarkedBlock::Marked: - case MarkedBlock::Retired: return; default: RELEASE_ASSERT_NOT_REACHED(); @@ -285,16 +456,28 @@ }; #endif -void MarkedSpace::clearMarks() +void MarkedSpace::flip() { if (m_heap->operationInProgress() == EdenCollection) { for (unsigned i = 0; i < m_blocksWithNewObjects.size(); ++i) - m_blocksWithNewObjects[i]->clearMarks(); - } else - forEachBlock(); + m_blocksWithNewObjects[i]->flipForEdenCollection(); + } else { + HeapVersion nextVersion = m_version + 1; + if (UNLIKELY(nextVersion == initialVersion)) { + // Oh no! Version wrap-around! We handle this by flipping all blocks. This happens + // super rarely, probably never for most users. + forEachBlock( + [&] (MarkedBlock::Handle* handle) { + handle->flipIfNecessary(); + }); + } + m_version = nextVersion; // Henceforth, flipIfNecessary() will trigger on all blocks. + for (LargeAllocation* allocation : m_largeAllocations) + allocation->flip(); + } #ifndef NDEBUG - VerifyMarkedOrRetired verifyFunctor; + VerifyMarked verifyFunctor; forEachBlock(verifyFunctor); #endif } @@ -313,4 +496,63 @@ m_isIterating = false; } +size_t MarkedSpace::objectCount() +{ + size_t result = 0; + forEachBlock( + [&] (MarkedBlock::Handle* block) { + result += block->markCount(); + }); + for (LargeAllocation* allocation : m_largeAllocations) { + if (allocation->isMarked()) + result++; + } + return result; +} + +size_t MarkedSpace::size() +{ + size_t result = 0; + forEachBlock( + [&] (MarkedBlock::Handle* block) { + result += block->markCount() * block->cellSize(); + }); + for (LargeAllocation* allocation : m_largeAllocations) { + if (allocation->isMarked()) + result += allocation->cellSize(); + } + return result; +} + +size_t MarkedSpace::capacity() +{ + return m_capacity; +} + +void MarkedSpace::addActiveWeakSet(WeakSet* weakSet) +{ + // We conservatively assume that the WeakSet should belong in the new set. In fact, some weak + // sets might contain new weak handles even though they are tied to old objects. This slightly + // increases the amount of scanning that an eden collection would have to do, but the effect + // ought to be small. + m_newActiveWeakSets.append(weakSet); +} + +void MarkedSpace::didAddBlock(MarkedBlock::Handle* block) +{ + m_capacity += MarkedBlock::blockSize; + m_blocks.add(&block->block()); +} + +void MarkedSpace::didAllocateInBlock(MarkedBlock::Handle* block) +{ + block->assertFlipped(); + m_blocksWithNewObjects.append(block); + + if (block->weakSet().isOnList()) { + block->weakSet().remove(); + m_newActiveWeakSets.append(&block->weakSet()); + } +} + } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedSpace.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedSpace.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/MarkedSpace.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/MarkedSpace.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,13 +22,17 @@ #ifndef MarkedSpace_h #define MarkedSpace_h +#include "IterationStatus.h" +#include "LargeAllocation.h" #include "MarkedAllocator.h" #include "MarkedBlock.h" #include "MarkedBlockSet.h" #include +#include #include #include #include +#include #include namespace JSC { @@ -36,66 +40,80 @@ class Heap; class HeapIterationScope; class LLIntOffsetsExtractor; +class WeakSet; -struct ClearMarks : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) - { - block->clearMarks(); - } -}; - -struct Sweep : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) { block->sweep(); } -}; - -struct ZombifySweep : MarkedBlock::VoidFunctor { - void operator()(MarkedBlock* block) - { - if (block->needsSweeping()) - block->sweep(); - } -}; - -struct MarkCount : MarkedBlock::CountFunctor { - void operator()(MarkedBlock* block) { count(block->markCount()); } -}; - -struct Size : MarkedBlock::CountFunctor { - void operator()(MarkedBlock* block) { count(block->markCount() * block->cellSize()); } -}; +typedef uint32_t HeapVersion; class MarkedSpace { WTF_MAKE_NONCOPYABLE(MarkedSpace); public: - // [ 16 ... 768 ] - static const size_t preciseStep = MarkedBlock::atomSize; - static const size_t preciseCutoff = 768; - static const size_t preciseCount = preciseCutoff / preciseStep; - - // [ 1024 ... blockSize/2 ] - static const size_t impreciseStart = 1024; - static const size_t impreciseStep = 256; - static const size_t impreciseCutoff = MarkedBlock::blockSize / 2; - static const size_t impreciseCount = impreciseCutoff / impreciseStep; - + // sizeStep is really a synonym for atomSize; it's no accident that they are the same. + static const size_t sizeStep = MarkedBlock::atomSize; + + // Sizes up to this amount get a size class for each size step. + static const size_t preciseCutoff = 80; + + // The amount of available payload in a block is the block's size minus the header. But the + // header size might not be atom size aligned, so we round down the result accordingly. + static const size_t blockPayload = (MarkedBlock::blockSize - sizeof(MarkedBlock)) & ~(MarkedBlock::atomSize - 1); + + // The largest cell we're willing to allocate in a MarkedBlock the "normal way" (i.e. using size + // classes, rather than a large allocation) is half the size of the payload, rounded down. This + // ensures that we only use the size class approach if it means being able to pack two things + // into one block. + static const size_t largeCutoff = (blockPayload / 2) & ~(sizeStep - 1); + + static const size_t numSizeClasses = largeCutoff / sizeStep; + + static const HeapVersion initialVersion = 42; // This can be any value, including random garbage, so long as it's consistent for the lifetime of the process. + + static size_t sizeClassToIndex(size_t size) + { + ASSERT(size); + return (size + sizeStep - 1) / sizeStep - 1; + } + + static size_t indexToSizeClass(size_t index) + { + return (index + 1) * sizeStep; + } + + // Each Subspace corresponds to all of the blocks for all of the sizes for some "class" of + // objects. There are three classes: non-destructor JSCells, destructor JSCells, and auxiliary. + // MarkedSpace is set up to make it relatively easy to add new Subspaces. struct Subspace { - std::array preciseAllocators; - std::array impreciseAllocators; - MarkedAllocator largeAllocator; + std::array allocatorForSizeStep; + + // Each MarkedAllocator is a size class. + Bag bagOfAllocators; + + AllocatorAttributes attributes; }; - + MarkedSpace(Heap*); ~MarkedSpace(); void lastChanceToFinalize(); - MarkedAllocator& allocatorFor(size_t); - MarkedAllocator& destructorAllocatorFor(size_t); + static size_t optimalSizeFor(size_t); + + static MarkedAllocator* allocatorFor(Subspace&, size_t); + + MarkedAllocator* allocatorFor(size_t); + MarkedAllocator* destructorAllocatorFor(size_t); + MarkedAllocator* auxiliaryAllocatorFor(size_t); + + JS_EXPORT_PRIVATE void* allocate(Subspace&, size_t); + JS_EXPORT_PRIVATE void* tryAllocate(Subspace&, size_t); + void* allocateWithDestructor(size_t); void* allocateWithoutDestructor(size_t); - + void* allocateAuxiliary(size_t); + void* tryAllocateAuxiliary(size_t); + Subspace& subspaceForObjectsWithDestructor() { return m_destructorSpace; } Subspace& subspaceForObjectsWithoutDestructor() { return m_normalSpace; } - + Subspace& subspaceForAuxiliaryData() { return m_auxiliarySpace; } + void resetAllocators(); void visitWeakSets(HeapRootVisitor&); @@ -109,164 +127,214 @@ void stopAllocating(); void resumeAllocating(); // If we just stopped allocation but we didn't do a collection, we need to resume allocation. + + void prepareForMarking(); typedef HashSet::iterator BlockIterator; - template typename Functor::ReturnType forEachLiveCell(HeapIterationScope&, Functor&); - template typename Functor::ReturnType forEachLiveCell(HeapIterationScope&); - template typename Functor::ReturnType forEachDeadCell(HeapIterationScope&, Functor&); - template typename Functor::ReturnType forEachDeadCell(HeapIterationScope&); - template typename Functor::ReturnType forEachBlock(Functor&); - template typename Functor::ReturnType forEachBlock(); + template void forEachLiveCell(HeapIterationScope&, const Functor&); + template void forEachDeadCell(HeapIterationScope&, const Functor&); + template void forEachBlock(const Functor&); void shrink(); - void freeBlock(MarkedBlock*); - void freeOrShrinkBlock(MarkedBlock*); + void freeBlock(MarkedBlock::Handle*); + void freeOrShrinkBlock(MarkedBlock::Handle*); - void didAddBlock(MarkedBlock*); - void didConsumeFreeList(MarkedBlock*); - void didAllocateInBlock(MarkedBlock*); + void didAddBlock(MarkedBlock::Handle*); + void didConsumeFreeList(MarkedBlock::Handle*); + void didAllocateInBlock(MarkedBlock::Handle*); - void clearMarks(); + void flip(); void clearNewlyAllocated(); void sweep(); + void sweepLargeAllocations(); void zombifySweep(); size_t objectCount(); size_t size(); size_t capacity(); bool isPagedOut(double deadline); + + HeapVersion version() const { return m_version; } - const Vector& blocksWithNewObjects() const { return m_blocksWithNewObjects; } + const Vector& blocksWithNewObjects() const { return m_blocksWithNewObjects; } + + const Vector& largeAllocations() const { return m_largeAllocations; } + unsigned largeAllocationsNurseryOffset() const { return m_largeAllocationsNurseryOffset; } + unsigned largeAllocationsOffsetForThisCollection() const { return m_largeAllocationsOffsetForThisCollection; } + + // These are cached pointers and offsets for quickly searching the large allocations that are + // relevant to this collection. + LargeAllocation** largeAllocationsForThisCollectionBegin() const { return m_largeAllocationsForThisCollectionBegin; } + LargeAllocation** largeAllocationsForThisCollectionEnd() const { return m_largeAllocationsForThisCollectionEnd; } + unsigned largeAllocationsForThisCollectionSize() const { return m_largeAllocationsForThisCollectionSize; } private: friend class LLIntOffsetsExtractor; friend class JIT; - - template void forEachAllocator(Functor&); - template void forEachAllocator(); + friend class WeakSet; + + JS_EXPORT_PRIVATE static std::array s_sizeClassForSizeStep; + + JS_EXPORT_PRIVATE void* allocateLarge(Subspace&, size_t); + JS_EXPORT_PRIVATE void* tryAllocateLarge(Subspace&, size_t); + + static void initializeSizeClassForStepSize(); + + void initializeSubspace(Subspace&); + + template void forEachAllocator(const Functor&); + template void forEachSubspace(const Functor&); + + void addActiveWeakSet(WeakSet*); Subspace m_destructorSpace; Subspace m_normalSpace; + Subspace m_auxiliarySpace; Heap* m_heap; + HeapVersion m_version { initialVersion }; size_t m_capacity; bool m_isIterating; MarkedBlockSet m_blocks; - Vector m_blocksWithNewObjects; + Vector m_blocksWithNewObjects; + Vector m_largeAllocations; + unsigned m_largeAllocationsNurseryOffset { 0 }; + unsigned m_largeAllocationsOffsetForThisCollection { 0 }; + unsigned m_largeAllocationsNurseryOffsetForSweep { 0 }; + LargeAllocation** m_largeAllocationsForThisCollectionBegin { nullptr }; + LargeAllocation** m_largeAllocationsForThisCollectionEnd { nullptr }; + unsigned m_largeAllocationsForThisCollectionSize { 0 }; + SentinelLinkedList> m_activeWeakSets; + SentinelLinkedList> m_newActiveWeakSets; }; -template inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope&, Functor& functor) +template inline void MarkedSpace::forEachLiveCell(HeapIterationScope&, const Functor& functor) { ASSERT(isIterating()); BlockIterator end = m_blocks.set().end(); for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) { - if ((*it)->forEachLiveCell(functor) == IterationStatus::Done) - break; + if ((*it)->handle().forEachLiveCell(functor) == IterationStatus::Done) + return; + } + for (LargeAllocation* allocation : m_largeAllocations) { + if (allocation->isLive()) { + if (functor(allocation->cell(), allocation->attributes().cellKind) == IterationStatus::Done) + return; + } } - return functor.returnValue(); -} - -template inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope& scope) -{ - Functor functor; - return forEachLiveCell(scope, functor); } -template inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(HeapIterationScope&, Functor& functor) +template inline void MarkedSpace::forEachDeadCell(HeapIterationScope&, const Functor& functor) { ASSERT(isIterating()); BlockIterator end = m_blocks.set().end(); for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) { - if ((*it)->forEachDeadCell(functor) == IterationStatus::Done) - break; + if ((*it)->handle().forEachDeadCell(functor) == IterationStatus::Done) + return; + } + for (LargeAllocation* allocation : m_largeAllocations) { + if (!allocation->isLive()) { + if (functor(allocation->cell(), allocation->attributes().cellKind) == IterationStatus::Done) + return; + } } - return functor.returnValue(); } -template inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(HeapIterationScope& scope) +inline MarkedAllocator* MarkedSpace::allocatorFor(Subspace& space, size_t bytes) { - Functor functor; - return forEachDeadCell(scope, functor); + ASSERT(bytes); + if (bytes <= largeCutoff) + return space.allocatorForSizeStep[sizeClassToIndex(bytes)]; + return nullptr; } -inline MarkedAllocator& MarkedSpace::allocatorFor(size_t bytes) +inline MarkedAllocator* MarkedSpace::allocatorFor(size_t bytes) { - ASSERT(bytes); - if (bytes <= preciseCutoff) - return m_normalSpace.preciseAllocators[(bytes - 1) / preciseStep]; - if (bytes <= impreciseCutoff) - return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep]; - return m_normalSpace.largeAllocator; + return allocatorFor(m_normalSpace, bytes); } -inline MarkedAllocator& MarkedSpace::destructorAllocatorFor(size_t bytes) +inline MarkedAllocator* MarkedSpace::destructorAllocatorFor(size_t bytes) { - ASSERT(bytes); - if (bytes <= preciseCutoff) - return m_destructorSpace.preciseAllocators[(bytes - 1) / preciseStep]; - if (bytes <= impreciseCutoff) - return m_destructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep]; - return m_destructorSpace.largeAllocator; + return allocatorFor(m_destructorSpace, bytes); } -inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes) +inline MarkedAllocator* MarkedSpace::auxiliaryAllocatorFor(size_t bytes) { - return allocatorFor(bytes).allocate(bytes); + return allocatorFor(m_auxiliarySpace, bytes); } -inline void* MarkedSpace::allocateWithDestructor(size_t bytes) +inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes) { - return destructorAllocatorFor(bytes).allocate(bytes); + return allocate(m_normalSpace, bytes); } -template inline typename Functor::ReturnType MarkedSpace::forEachBlock(Functor& functor) +inline void* MarkedSpace::allocateWithDestructor(size_t bytes) { - for (size_t i = 0; i < preciseCount; ++i) - m_normalSpace.preciseAllocators[i].forEachBlock(functor); - for (size_t i = 0; i < impreciseCount; ++i) - m_normalSpace.impreciseAllocators[i].forEachBlock(functor); - m_normalSpace.largeAllocator.forEachBlock(functor); - - for (size_t i = 0; i < preciseCount; ++i) - m_destructorSpace.preciseAllocators[i].forEachBlock(functor); - for (size_t i = 0; i < impreciseCount; ++i) - m_destructorSpace.impreciseAllocators[i].forEachBlock(functor); - m_destructorSpace.largeAllocator.forEachBlock(functor); - - return functor.returnValue(); + return allocate(m_destructorSpace, bytes); } -template inline typename Functor::ReturnType MarkedSpace::forEachBlock() +inline void* MarkedSpace::allocateAuxiliary(size_t bytes) { - Functor functor; - return forEachBlock(functor); + return allocate(m_auxiliarySpace, bytes); } -inline void MarkedSpace::didAddBlock(MarkedBlock* block) +inline void* MarkedSpace::tryAllocateAuxiliary(size_t bytes) { - m_capacity += block->capacity(); - m_blocks.add(block); + return tryAllocate(m_auxiliarySpace, bytes); } -inline void MarkedSpace::didAllocateInBlock(MarkedBlock* block) +template inline void MarkedSpace::forEachBlock(const Functor& functor) { - m_blocksWithNewObjects.append(block); + forEachAllocator( + [&] (MarkedAllocator& allocator) -> IterationStatus { + allocator.forEachBlock(functor); + return IterationStatus::Continue; + }); } -inline size_t MarkedSpace::objectCount() +template +void MarkedSpace::forEachAllocator(const Functor& functor) { - return forEachBlock(); + forEachSubspace( + [&] (Subspace& subspace, AllocatorAttributes) -> IterationStatus { + for (MarkedAllocator* allocator : subspace.bagOfAllocators) { + if (functor(*allocator) == IterationStatus::Done) + return IterationStatus::Done; + } + + return IterationStatus::Continue; + }); } -inline size_t MarkedSpace::size() +template +inline void MarkedSpace::forEachSubspace(const Functor& func) { - return forEachBlock(); + AllocatorAttributes attributes; + + attributes.destruction = NeedsDestruction; + attributes.cellKind = HeapCell::JSCell; + if (func(m_destructorSpace, attributes) == IterationStatus::Done) + return; + + attributes.destruction = DoesNotNeedDestruction; + attributes.cellKind = HeapCell::JSCell; + if (func(m_normalSpace, attributes) == IterationStatus::Done) + return; + + attributes.destruction = DoesNotNeedDestruction; + attributes.cellKind = HeapCell::Auxiliary; + func(m_auxiliarySpace, attributes); } -inline size_t MarkedSpace::capacity() +ALWAYS_INLINE size_t MarkedSpace::optimalSizeFor(size_t bytes) { - return m_capacity; + ASSERT(bytes); + if (bytes <= preciseCutoff) + return WTF::roundUpToMultipleOf(bytes); + if (bytes <= largeCutoff) + return s_sizeClassForSizeStep[sizeClassToIndex(bytes)]; + return bytes; } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/SlotVisitor.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/SlotVisitor.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/SlotVisitor.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/SlotVisitor.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,12 +31,16 @@ #include "CopiedBlockInlines.h" #include "CopiedSpace.h" #include "CopiedSpaceInlines.h" +#include "HeapCellInlines.h" +#include "HeapProfiler.h" +#include "HeapSnapshotBuilder.h" #include "JSArray.h" #include "JSDestructibleObject.h" -#include "VM.h" #include "JSObject.h" #include "JSString.h" #include "JSCInlines.h" +#include "SuperSampler.h" +#include "VM.h" #include namespace JSC { @@ -77,6 +81,7 @@ , m_bytesCopied(0) , m_visitCount(0) , m_isInParallelMode(false) + , m_version(MarkedSpace::initialVersion) , m_heap(heap) #if !ASSERT_DISABLED , m_isCheckingForDefaultMarkViolation(false) @@ -94,6 +99,13 @@ { if (heap()->operationInProgress() == FullCollection) ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now. + else + reset(); + + if (HeapProfiler* heapProfiler = vm().heapProfiler()) + m_heapSnapshotBuilder = heapProfiler->activeSnapshotBuilder(); + + m_version = heap()->objectSpace().version(); } void SlotVisitor::reset() @@ -101,7 +113,8 @@ m_bytesVisited = 0; m_bytesCopied = 0; m_visitCount = 0; - ASSERT(m_stack.isEmpty()); + m_heapSnapshotBuilder = nullptr; + ASSERT(!m_currentCell); } void SlotVisitor::clearMarkStack() @@ -111,21 +124,66 @@ void SlotVisitor::append(ConservativeRoots& conservativeRoots) { - JSCell** roots = conservativeRoots.roots(); + HeapCell** roots = conservativeRoots.roots(); size_t size = conservativeRoots.size(); for (size_t i = 0; i < size; ++i) - append(roots[i]); + appendJSCellOrAuxiliary(roots[i]); +} + +void SlotVisitor::appendJSCellOrAuxiliary(HeapCell* heapCell) +{ + if (!heapCell) + return; + + ASSERT(!m_isCheckingForDefaultMarkViolation); + + if (Heap::testAndSetMarked(m_version, heapCell)) + return; + + switch (heapCell->cellKind()) { + case HeapCell::JSCell: { + JSCell* jsCell = static_cast(heapCell); + + if (!jsCell->structure()) { + ASSERT_NOT_REACHED(); + return; + } + + jsCell->setCellState(CellState::NewGrey); + + appendToMarkStack(jsCell); + return; + } + + case HeapCell::Auxiliary: { + noteLiveAuxiliaryCell(heapCell); + return; + } } } void SlotVisitor::append(JSValue value) { if (!value || !value.isCell()) return; + + if (UNLIKELY(m_heapSnapshotBuilder)) + m_heapSnapshotBuilder->appendEdge(m_currentCell, value.asCell()); + + setMarkedAndAppendToMarkStack(value.asCell()); +} + +void SlotVisitor::appendHidden(JSValue value) +{ + if (!value || !value.isCell()) + return; + setMarkedAndAppendToMarkStack(value.asCell()); } void SlotVisitor::setMarkedAndAppendToMarkStack(JSCell* cell) { + SuperSamplerScope superSamplerScope(false); + ASSERT(!m_isCheckingForDefaultMarkViolation); if (!cell) return; @@ -133,34 +191,112 @@ #if ENABLE(GC_VALIDATION) validate(cell); #endif + + if (cell->isLargeAllocation()) + setMarkedAndAppendToMarkStack(cell->largeAllocation(), cell); + else + setMarkedAndAppendToMarkStack(cell->markedBlock(), cell); +} - if (Heap::testAndSetMarked(cell) || !cell->structure()) { - ASSERT(cell->structure()); +template +ALWAYS_INLINE void SlotVisitor::setMarkedAndAppendToMarkStack(ContainerType& container, JSCell* cell) +{ + container.flipIfNecessaryConcurrently(m_version); + + if (container.testAndSetMarked(cell)) return; - } - + + ASSERT(cell->structure()); + // Indicate that the object is grey and that: // In case of concurrent GC: it's the first time it is grey in this GC cycle. // In case of eden collection: it's a new object that became grey rather than an old remembered object. cell->setCellState(CellState::NewGrey); - - appendToMarkStack(cell); + + appendToMarkStack(container, cell); } void SlotVisitor::appendToMarkStack(JSCell* cell) { - ASSERT(Heap::isMarked(cell)); - ASSERT(!cell->isZapped()); + if (cell->isLargeAllocation()) + appendToMarkStack(cell->largeAllocation(), cell); + else + appendToMarkStack(cell->markedBlock(), cell); +} +template +ALWAYS_INLINE void SlotVisitor::appendToMarkStack(ContainerType& container, JSCell* cell) +{ + ASSERT(Heap::isMarkedConcurrently(cell)); + ASSERT(!cell->isZapped()); + + container.noteMarked(); + + // FIXME: These "just work" because the GC resets these fields before doing anything else. But + // that won't be the case when we do concurrent GC. m_visitCount++; - m_bytesVisited += MarkedBlock::blockFor(cell)->cellSize(); + m_bytesVisited += container.cellSize(); + m_stack.append(cell); + + if (UNLIKELY(m_heapSnapshotBuilder)) + m_heapSnapshotBuilder->appendNode(cell); } -ALWAYS_INLINE void SlotVisitor::visitChildren(const JSCell* cell) +void SlotVisitor::markAuxiliary(const void* base) +{ + HeapCell* cell = bitwise_cast(base); + + if (Heap::testAndSetMarked(m_version, cell)) { + RELEASE_ASSERT(Heap::isMarkedConcurrently(cell)); + return; + } + + noteLiveAuxiliaryCell(cell); +} + +void SlotVisitor::noteLiveAuxiliaryCell(HeapCell* cell) { - ASSERT(Heap::isMarked(cell)); + // We get here once per GC under these circumstances: + // + // Eden collection: if the cell was allocated since the last collection and is live somehow. + // + // Full collection: if the cell is live somehow. + + CellContainer container = cell->cellContainer(); + + container.noteMarked(); + + m_visitCount++; + m_bytesVisited += container.cellSize(); +} + +class SetCurrentCellScope { +public: + SetCurrentCellScope(SlotVisitor& visitor, const JSCell* cell) + : m_visitor(visitor) + { + ASSERT(!m_visitor.m_currentCell); + m_visitor.m_currentCell = const_cast(cell); + } + ~SetCurrentCellScope() + { + ASSERT(m_visitor.m_currentCell); + m_visitor.m_currentCell = nullptr; + } + +private: + SlotVisitor& m_visitor; +}; + + +ALWAYS_INLINE void SlotVisitor::visitChildren(const JSCell* cell) +{ + ASSERT(Heap::isMarkedConcurrently(cell)); + + SetCurrentCellScope currentCellScope(*this, cell); + m_currentObjectCellStateBeforeVisiting = cell->cellState(); cell->setCellState(CellState::OldBlack); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/SlotVisitor.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/SlotVisitor.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/SlotVisitor.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/SlotVisitor.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2011-2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,16 +37,22 @@ class ConservativeRoots; class GCThreadSharedData; class Heap; +class HeapCell; +class HeapSnapshotBuilder; template class JITWriteBarrier; +class MarkedBlock; class UnconditionalFinalizer; template class Weak; class WeakReferenceHarvester; template class WriteBarrierBase; +typedef uint32_t HeapVersion; + class SlotVisitor { WTF_MAKE_NONCOPYABLE(SlotVisitor); WTF_MAKE_FAST_ALLOCATED; + friend class SetCurrentCellScope; friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly. friend class Heap; @@ -63,10 +69,11 @@ void append(ConservativeRoots&); - template void append(JITWriteBarrier*); template void append(WriteBarrierBase*); + template void appendHidden(WriteBarrierBase*); template void append(Iterator begin , Iterator end); void appendValues(WriteBarrierBase*, size_t count); + void appendValuesHidden(WriteBarrierBase*, size_t count); template void appendUnbarrieredPointer(T**); @@ -101,24 +108,44 @@ void harvestWeakReferences(); void finalizeUnconditionalFinalizers(); + + // This informs the GC about auxiliary of some size that we are keeping alive. If you don't do + // this then the space will be freed at end of GC. + void markAuxiliary(const void* base); void copyLater(JSCell*, CopyToken, void*, size_t); void reportExtraMemoryVisited(size_t); +#if ENABLE(RESOURCE_USAGE) + void reportExternalMemoryVisited(size_t); +#endif void addWeakReferenceHarvester(WeakReferenceHarvester*); void addUnconditionalFinalizer(UnconditionalFinalizer*); void dump(PrintStream&) const; + bool isBuildingHeapSnapshot() const { return !!m_heapSnapshotBuilder; } + private: friend class ParallelModeEnabler; JS_EXPORT_PRIVATE void append(JSValue); // This is private to encourage clients to use WriteBarrier. + void appendJSCellOrAuxiliary(HeapCell*); + void appendHidden(JSValue); JS_EXPORT_PRIVATE void setMarkedAndAppendToMarkStack(JSCell*); + + template + void setMarkedAndAppendToMarkStack(ContainerType&, JSCell*); + void appendToMarkStack(JSCell*); + template + void appendToMarkStack(ContainerType&, JSCell*); + + void noteLiveAuxiliaryCell(HeapCell*); + JS_EXPORT_PRIVATE void mergeOpaqueRoots(); void mergeOpaqueRootsIfNecessary(); void mergeOpaqueRootsIfProfitable(); @@ -135,8 +162,13 @@ size_t m_visitCount; bool m_isInParallelMode; + HeapVersion m_version; + Heap& m_heap; + HeapSnapshotBuilder* m_heapSnapshotBuilder { nullptr }; + JSCell* m_currentCell { nullptr }; + CellState m_currentObjectCellStateBeforeVisiting { CellState::NewWhite }; public: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/SlotVisitorInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/SlotVisitorInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/SlotVisitorInlines.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/SlotVisitorInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -69,6 +69,12 @@ append(slot->get()); } +template +inline void SlotVisitor::appendHidden(WriteBarrierBase* slot) +{ + appendHidden(slot->get()); +} + template inline void SlotVisitor::append(Iterator begin, Iterator end) { @@ -82,6 +88,12 @@ append(&barriers[i]); } +inline void SlotVisitor::appendValuesHidden(WriteBarrierBase* barriers, size_t count) +{ + for (size_t i = 0; i < count; ++i) + appendHidden(&barriers[i]); +} + inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester) { m_heap.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester); @@ -97,6 +109,13 @@ heap()->reportExtraMemoryVisited(m_currentObjectCellStateBeforeVisiting, size); } +#if ENABLE(RESOURCE_USAGE) +inline void SlotVisitor::reportExternalMemoryVisited(size_t size) +{ + heap()->reportExternalMemoryVisited(m_currentObjectCellStateBeforeVisiting, size); +} +#endif + inline Heap* SlotVisitor::heap() const { return &m_heap; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakBlock.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakBlock.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakBlock.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakBlock.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +26,7 @@ #include "config.h" #include "WeakBlock.h" +#include "CellContainerInlines.h" #include "Heap.h" #include "HeapRootVisitor.h" #include "JSCInlines.h" @@ -34,10 +35,10 @@ namespace JSC { -WeakBlock* WeakBlock::create(Heap& heap, MarkedBlock& markedBlock) +WeakBlock* WeakBlock::create(Heap& heap, CellContainer container) { heap.didAllocateBlock(WeakBlock::blockSize); - return new (NotNull, fastMalloc(blockSize)) WeakBlock(markedBlock); + return new (NotNull, fastMalloc(blockSize)) WeakBlock(container); } void WeakBlock::destroy(Heap& heap, WeakBlock* block) @@ -47,9 +48,9 @@ heap.didFreeBlock(WeakBlock::blockSize); } -WeakBlock::WeakBlock(MarkedBlock& markedBlock) +WeakBlock::WeakBlock(CellContainer container) : DoublyLinkedListNode() - , m_markedBlock(&markedBlock) + , m_container(container) { for (size_t i = 0; i < weakImplCount(); ++i) { WeakImpl* weakImpl = &weakImpls()[i]; @@ -101,11 +102,13 @@ if (isEmpty()) return; - // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here. - ASSERT(m_markedBlock); + // If this WeakBlock doesn't belong to a CellContainer, we won't even be here. + ASSERT(m_container); + + m_container.flipIfNecessary(); // We only visit after marking. - ASSERT(m_markedBlock->isMarkedOrRetired()); + ASSERT(m_container.isMarked()); SlotVisitor& visitor = heapRootVisitor.visitor(); @@ -119,9 +122,9 @@ continue; const JSValue& jsValue = weakImpl->jsValue(); - if (m_markedBlock->isMarkedOrNewlyAllocated(jsValue.asCell())) + if (m_container.isMarkedOrNewlyAllocated(jsValue.asCell())) continue; - + if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle::wrapSlot(&const_cast(jsValue)), weakImpl->context(), visitor)) continue; @@ -135,18 +138,20 @@ if (isEmpty()) return; - // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here. - ASSERT(m_markedBlock); + // If this WeakBlock doesn't belong to a CellContainer, we won't even be here. + ASSERT(m_container); + + m_container.flipIfNecessary(); // We only reap after marking. - ASSERT(m_markedBlock->isMarkedOrRetired()); + ASSERT(m_container.isMarked()); for (size_t i = 0; i < weakImplCount(); ++i) { WeakImpl* weakImpl = &weakImpls()[i]; if (weakImpl->state() > WeakImpl::Dead) continue; - if (m_markedBlock->isMarkedOrNewlyAllocated(weakImpl->jsValue().asCell())) { + if (m_container.isMarkedOrNewlyAllocated(weakImpl->jsValue().asCell())) { ASSERT(weakImpl->state() == WeakImpl::Live); continue; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakBlock.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakBlock.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakBlock.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakBlock.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +26,7 @@ #ifndef WeakBlock_h #define WeakBlock_h +#include "CellContainer.h" #include "WeakImpl.h" #include #include @@ -34,12 +35,11 @@ class Heap; class HeapRootVisitor; -class MarkedBlock; class WeakBlock : public DoublyLinkedListNode { public: friend class WTF::DoublyLinkedListNode; - static const size_t blockSize = 1 * KB; // 1/16 of MarkedBlock size + static const size_t blockSize = 256; // 1/16 of MarkedBlock size struct FreeCell { FreeCell* next; @@ -53,7 +53,7 @@ FreeCell* freeList { nullptr }; }; - static WeakBlock* create(Heap&, MarkedBlock&); + static WeakBlock* create(Heap&, CellContainer); static void destroy(Heap&, WeakBlock*); static WeakImpl* asWeakImpl(FreeCell*); @@ -68,18 +68,18 @@ void reap(); void lastChanceToFinalize(); - void disconnectMarkedBlock() { m_markedBlock = nullptr; } + void disconnectContainer() { m_container = CellContainer(); } private: static FreeCell* asFreeCell(WeakImpl*); - explicit WeakBlock(MarkedBlock&); + explicit WeakBlock(CellContainer); void finalize(WeakImpl*); WeakImpl* weakImpls(); size_t weakImplCount(); void addToFreeList(FreeCell**, WeakImpl*); - MarkedBlock* m_markedBlock; + CellContainer m_container; WeakBlock* m_prev; WeakBlock* m_next; SweepResult m_sweepResult; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakSet.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakSet.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakSet.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakSet.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +34,9 @@ WeakSet::~WeakSet() { + if (isOnList()) + remove(); + Heap& heap = *this->heap(); WeakBlock* next = 0; for (WeakBlock* block = m_blocks.head(); block; block = next) { @@ -46,15 +49,17 @@ void WeakSet::sweep() { for (WeakBlock* block = m_blocks.head(); block;) { + heap()->sweepNextLogicallyEmptyWeakBlock(); + WeakBlock* nextBlock = block->next(); block->sweep(); if (block->isLogicallyEmptyButNotFree()) { // If this WeakBlock is logically empty, but still has Weaks pointing into it, // we can't destroy it just yet. Detach it from the WeakSet and hand ownership - // to the Heap so we don't pin down the entire 64kB MarkedBlock. + // to the Heap so we don't pin down the entire MarkedBlock or LargeAllocation. m_blocks.remove(block); heap()->addLogicallyEmptyWeakBlock(block); - block->disconnectMarkedBlock(); + block->disconnectContainer(); } block = nextBlock; } @@ -62,6 +67,22 @@ resetAllocator(); } +void WeakSet::shrink() +{ + WeakBlock* next; + for (WeakBlock* block = m_blocks.head(); block; block = next) { + next = block->next(); + + if (block->isEmpty()) + removeAllocator(block); + } + + resetAllocator(); + + if (m_blocks.isEmpty() && isOnList()) + remove(); +} + WeakBlock::FreeCell* WeakSet::findAllocator() { if (WeakBlock::FreeCell* allocator = tryFindAllocator()) @@ -86,7 +107,10 @@ WeakBlock::FreeCell* WeakSet::addAllocator() { - WeakBlock* block = WeakBlock::create(*heap(), m_markedBlock); + if (m_blocks.isEmpty() && !isOnList()) + heap()->objectSpace().addActiveWeakSet(this); + + WeakBlock* block = WeakBlock::create(*heap(), m_container); heap()->didAllocate(WeakBlock::blockSize); m_blocks.append(block); WeakBlock::SweepResult sweepResult = block->takeSweepResult(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakSet.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakSet.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakSet.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakSet.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,31 +26,35 @@ #ifndef WeakSet_h #define WeakSet_h +#include "CellContainer.h" #include "WeakBlock.h" +#include namespace JSC { class Heap; -class MarkedBlock; class WeakImpl; -class WeakSet { +class WeakSet : public BasicRawSentinelNode { friend class LLIntOffsetsExtractor; public: static WeakImpl* allocate(JSValue, WeakHandleOwner* = 0, void* context = 0); static void deallocate(WeakImpl*); - WeakSet(VM*, MarkedBlock&); + WeakSet(VM*, CellContainer); ~WeakSet(); void lastChanceToFinalize(); + + CellContainer container() const { return m_container; } + void setContainer(CellContainer container) { m_container = container; } Heap* heap() const; VM* vm() const; bool isEmpty() const; - void visit(HeapRootVisitor&); + unsigned visit(HeapRootVisitor&); void reap(); void sweep(); void shrink(); @@ -66,14 +70,14 @@ WeakBlock* m_nextAllocator; DoublyLinkedList m_blocks; VM* m_vm; - MarkedBlock& m_markedBlock; + CellContainer m_container; }; -inline WeakSet::WeakSet(VM* vm, MarkedBlock& markedBlock) +inline WeakSet::WeakSet(VM* vm, CellContainer container) : m_allocator(0) , m_nextAllocator(0) , m_vm(vm) - , m_markedBlock(markedBlock) + , m_container(container) { } @@ -103,10 +107,14 @@ block->lastChanceToFinalize(); } -inline void WeakSet::visit(HeapRootVisitor& visitor) +inline unsigned WeakSet::visit(HeapRootVisitor& visitor) { - for (WeakBlock* block = m_blocks.head(); block; block = block->next()) + unsigned count = 0; + for (WeakBlock* block = m_blocks.head(); block; block = block->next()) { + count++; block->visit(visitor); + } + return count; } inline void WeakSet::reap() @@ -115,19 +123,6 @@ block->reap(); } -inline void WeakSet::shrink() -{ - WeakBlock* next; - for (WeakBlock* block = m_blocks.head(); block; block = next) { - next = block->next(); - - if (block->isEmpty()) - removeAllocator(block); - } - - resetAllocator(); -} - inline void WeakSet::resetAllocator() { m_allocator = 0; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakSetInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakSetInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/heap/WeakSetInlines.h 2015-09-24 06:18:42.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/heap/WeakSetInlines.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,13 +26,14 @@ #ifndef WeakSetInlines_h #define WeakSetInlines_h +#include "CellContainerInlines.h" #include "MarkedBlock.h" namespace JSC { inline WeakImpl* WeakSet::allocate(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context) { - WeakSet& weakSet = MarkedBlock::blockFor(jsValue.asCell())->weakSet(); + WeakSet& weakSet = jsValue.asCell()->cellContainer().weakSet(); WeakBlock::FreeCell* allocator = weakSet.m_allocator; if (UNLIKELY(!allocator)) allocator = weakSet.findAllocator(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/icu/unicode/ucurr.h webkit2gtk-2.14.2/Source/JavaScriptCore/icu/unicode/ucurr.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/icu/unicode/ucurr.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/icu/unicode/ucurr.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,360 @@ +/* +********************************************************************** +* Copyright (c) 2002-2013, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +#ifndef _UCURR_H_ +#define _UCURR_H_ + +#include "unicode/utypes.h" +#include "unicode/uenum.h" + +/** + * \file + * \brief C API: Encapsulates information about a currency. + */ + +#if !UCONFIG_NO_FORMATTING + +/** + * The ucurr API encapsulates information about a currency, as defined by + * ISO 4217. A currency is represented by a 3-character string + * containing its ISO 4217 code. This API can return various data + * necessary the proper display of a currency: + * + *
    • A display symbol, for a specific locale + *
    • The number of fraction digits to display + *
    • A rounding increment + *
    + * + * The DecimalFormat class uses these data to display + * currencies. + * @author Alan Liu + * @since ICU 2.2 + */ + +/** + * Finds a currency code for the given locale. + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. If 0, + * currency couldn't be found or the input values are + * invalid. + * @stable ICU 2.8 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocale(const char* locale, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Selector constants for ucurr_getName(). + * + * @see ucurr_getName + * @stable ICU 2.6 + */ +typedef enum UCurrNameStyle { + /** + * Selector for ucurr_getName indicating a symbolic name for a + * currency, such as "$" for USD. + * @stable ICU 2.6 + */ + UCURR_SYMBOL_NAME, + + /** + * Selector for ucurr_getName indicating the long name for a + * currency, such as "US Dollar" for USD. + * @stable ICU 2.6 + */ + UCURR_LONG_NAME +} UCurrNameStyle; + +#if !UCONFIG_NO_SERVICE +/** + * @stable ICU 2.6 + */ +typedef const void* UCurrRegistryKey; + +/** + * Register an (existing) ISO 4217 currency code for the given locale. + * Only the country code and the two variants EURO and PRE_EURO are + * recognized. + * @param isoCode the three-letter ISO 4217 currency code + * @param locale the locale for which to register this currency code + * @param status the in/out status code + * @return a registry key that can be used to unregister this currency code, or NULL + * if there was an error. + * @stable ICU 2.6 + */ +U_STABLE UCurrRegistryKey U_EXPORT2 +ucurr_register(const UChar* isoCode, + const char* locale, + UErrorCode* status); +/** + * Unregister the previously-registered currency definitions using the + * URegistryKey returned from ucurr_register. Key becomes invalid after + * a successful call and should not be used again. Any currency + * that might have been hidden by the original ucurr_register call is + * restored. + * @param key the registry key returned by a previous call to ucurr_register + * @param status the in/out status code, no special meanings are assigned + * @return TRUE if the currency for this key was successfully unregistered + * @stable ICU 2.6 + */ +U_STABLE UBool U_EXPORT2 +ucurr_unregister(UCurrRegistryKey key, UErrorCode* status); +#endif /* UCONFIG_NO_SERVICE */ + +/** + * Returns the display name for the given currency in the + * given locale. For example, the display name for the USD + * currency object in the en_US locale is "$". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param nameStyle selector for which kind of name to return + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. If *isChoiceFormat is TRUE, then the result is a + * ChoiceFormat pattern. Otherwise it is a static string. + * @stable ICU 2.6 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getName(const UChar* currency, + const char* locale, + UCurrNameStyle nameStyle, + UBool* isChoiceFormat, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the plural name for the given currency in the + * given locale. For example, the plural name for the USD + * currency object in the en_US locale is "US dollar" or "US dollars". + * @param currency null-terminated 3-letter ISO 4217 code + * @param locale locale in which to display currency + * @param isChoiceFormat fill-in set to TRUE if the returned value + * is a ChoiceFormat pattern; otherwise it is a static string + * @param pluralCount plural count + * @param len fill-in parameter to receive length of result + * @param ec error code + * @return pointer to display string of 'len' UChars. If the resource + * data contains no entry for 'currency', then 'currency' itself is + * returned. + * @stable ICU 4.2 + */ +U_STABLE const UChar* U_EXPORT2 +ucurr_getPluralName(const UChar* currency, + const char* locale, + UBool* isChoiceFormat, + const char* pluralCount, + int32_t* len, + UErrorCode* ec); + +/** + * Returns the number of the number of fraction digits that should + * be displayed for the given currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return a non-negative number of fraction digits to be + * displayed, or 0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getDefaultFractionDigits(const UChar* currency, + UErrorCode* ec); + +/** + * Returns the rounding increment for the given currency, or 0.0 if no + * rounding is done by the currency. + * @param currency null-terminated 3-letter ISO 4217 code + * @param ec input-output error code + * @return the non-negative rounding increment, or 0.0 if none, + * or 0.0 if there is an error + * @stable ICU 3.0 + */ +U_STABLE double U_EXPORT2 +ucurr_getRoundingIncrement(const UChar* currency, + UErrorCode* ec); + +/** + * Selector constants for ucurr_openCurrencies(). + * + * @see ucurr_openCurrencies + * @stable ICU 3.2 + */ +typedef enum UCurrCurrencyType { + /** + * Select all ISO-4217 currency codes. + * @stable ICU 3.2 + */ + UCURR_ALL = INT32_MAX, + /** + * Select only ISO-4217 commonly used currency codes. + * These currencies can be found in common use, and they usually have + * bank notes or coins associated with the currency code. + * This does not include fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * @stable ICU 3.2 + */ + UCURR_COMMON = 1, + /** + * Select ISO-4217 uncommon currency codes. + * These codes respresent fund codes, precious metals and other + * various ISO-4217 codes limited to special financial products. + * A fund code is a monetary resource associated with a currency. + * @stable ICU 3.2 + */ + UCURR_UNCOMMON = 2, + /** + * Select only deprecated ISO-4217 codes. + * These codes are no longer in general public use. + * @stable ICU 3.2 + */ + UCURR_DEPRECATED = 4, + /** + * Select only non-deprecated ISO-4217 codes. + * These codes are in general public use. + * @stable ICU 3.2 + */ + UCURR_NON_DEPRECATED = 8 +} UCurrCurrencyType; + +/** + * Provides a UEnumeration object for listing ISO-4217 codes. + * @param currType You can use one of several UCurrCurrencyType values for this + * variable. You can also | (or) them together to get a specific list of + * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to + * get a list of current currencies. + * @param pErrorCode Error code + * @stable ICU 3.2 + */ +U_STABLE UEnumeration * U_EXPORT2 +ucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode); + +/** + * Queries if the given ISO 4217 3-letter code is available on the specified date range. + * + * Note: For checking availability of a currency on a specific date, specify the date on both 'from' and 'to' + * + * When 'from' is U_DATE_MIN and 'to' is U_DATE_MAX, this method checks if the specified currency is available any time. + * If 'from' and 'to' are same UDate value, this method checks if the specified currency is available on that date. + * + * @param isoCode + * The ISO 4217 3-letter code. + * + * @param from + * The lower bound of the date range, inclusive. When 'from' is U_DATE_MIN, check the availability + * of the currency any date before 'to' + * + * @param to + * The upper bound of the date range, inclusive. When 'to' is U_DATE_MAX, check the availability of + * the currency any date after 'from' + * + * @param errorCode + * ICU error code + * + * @return TRUE if the given ISO 4217 3-letter code is supported on the specified date range. + * + * @stable ICU 4.8 + */ +U_STABLE UBool U_EXPORT2 +ucurr_isAvailable(const UChar* isoCode, + UDate from, + UDate to, + UErrorCode* errorCode); + +/** + * Finds the number of valid currency codes for the + * given locale and date. + * @param locale the locale for which to retrieve the + * currency count. + * @param date the date for which to retrieve the + * currency count for the given locale. + * @param ec error code + * @return the number of currency codes for the + * given locale and date. If 0, currency + * codes couldn't be found for the input + * values are invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_countCurrencies(const char* locale, + UDate date, + UErrorCode* ec); + +/** + * Finds a currency code for the given locale and date + * @param locale the locale for which to retrieve a currency code. + * Currency can be specified by the "currency" keyword + * in which case it overrides the default currency code + * @param date the date for which to retrieve a currency code for + * the given locale. + * @param index the index within the available list of currency codes + * for the given locale on the given date. + * @param buff fill in buffer. Can be NULL for preflighting. + * @param buffCapacity capacity of the fill in buffer. Can be 0 for + * preflighting. If it is non-zero, the buff parameter + * must not be NULL. + * @param ec error code + * @return length of the currency string. It should always be 3. + * If 0, currency couldn't be found or the input values are + * invalid. + * @stable ICU 4.0 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_forLocaleAndDate(const char* locale, + UDate date, + int32_t index, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec); + +/** + * Given a key and a locale, returns an array of string values in a preferred + * order that would make a difference. These are all and only those values where + * the open (creation) of the service with the locale formed from the input locale + * plus input keyword and that value has different behavior than creation with the + * input locale alone. + * @param key one of the keys supported by this service. For now, only + * "currency" is supported. + * @param locale the locale + * @param commonlyUsed if set to true it will return only commonly used values + * with the given locale in preferred order. Otherwise, + * it will return all the available values for the locale. + * @param status error status + * @return a string enumeration over keyword values for the given key and the locale. + * @stable ICU 4.2 + */ +U_STABLE UEnumeration* U_EXPORT2 +ucurr_getKeywordValuesForLocale(const char* key, + const char* locale, + UBool commonlyUsed, + UErrorCode* status); + +/** + * Returns the ISO 4217 numeric code for the currency. + *

    Note: If the ISO 4217 numeric code is not assigned for the currency or + * the currency is unknown, this function returns 0. + * + * @param currency null-terminated 3-letter ISO 4217 code + * @return The ISO 4217 numeric code of the currency + * @stable ICU 49 + */ +U_STABLE int32_t U_EXPORT2 +ucurr_getNumericCode(const UChar* currency); + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorAgent.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorAgent.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -121,7 +121,7 @@ return; } - Ref> domainNames = Inspector::Protocol::Array::create(); + auto domainNames = Inspector::Protocol::Array::create(); domainNames->addItem(domainName); m_frontendDispatcher->activateExtraDomains(WTFMove(domainNames)); } @@ -131,14 +131,14 @@ if (extraDomains.isEmpty()) return; - RefPtr> domainNames = Inspector::Protocol::Array::create(); + auto domainNames = Inspector::Protocol::Array::create(); for (auto domainName : extraDomains) domainNames->addItem(domainName); if (!m_enabled) - m_pendingExtraDomainsData = domainNames.release(); + m_pendingExtraDomainsData = WTFMove(domainNames); else - m_frontendDispatcher->activateExtraDomains(domainNames.release()); + m_frontendDispatcher->activateExtraDomains(WTFMove(domainNames)); } #endif diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorAgent_h -#define InspectorAgent_h +#pragma once #include "InspectorBackendDispatchers.h" #include "InspectorFrontendDispatchers.h" @@ -51,12 +50,12 @@ InspectorAgent(AgentContext&); virtual ~InspectorAgent(); - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; - virtual void willDestroyFrontendAndBackend(DisconnectReason) override; + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; + void willDestroyFrontendAndBackend(DisconnectReason) override; - virtual void enable(ErrorString&) override; - virtual void disable(ErrorString&) override; - virtual void initialized(ErrorString&) override; + void enable(ErrorString&) override; + void disable(ErrorString&) override; + void initialized(ErrorString&) override; void inspect(RefPtr&& objectToInspect, RefPtr&& hints); void evaluateForTestInFrontend(const String& script); @@ -80,5 +79,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorAgent_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -29,13 +29,13 @@ #include "ConsoleMessage.h" #include "InjectedScriptManager.h" #include "InspectorFrontendRouter.h" +#include "InspectorHeapAgent.h" #include "ScriptArguments.h" #include "ScriptCallFrame.h" #include "ScriptCallStack.h" #include "ScriptCallStackFactory.h" #include "ScriptObject.h" #include -#include #include namespace Inspector { @@ -43,11 +43,12 @@ static const unsigned maximumConsoleMessages = 100; static const int expireConsoleMessagesStep = 10; -InspectorConsoleAgent::InspectorConsoleAgent(AgentContext& context) +InspectorConsoleAgent::InspectorConsoleAgent(AgentContext& context, InspectorHeapAgent* heapAgent) : InspectorAgentBase(ASCIILiteral("Console")) , m_injectedScriptManager(context.injectedScriptManager) , m_frontendDispatcher(std::make_unique(context.frontendRouter)) , m_backendDispatcher(ConsoleBackendDispatcher::create(context.backendDispatcher, this)) + , m_heapAgent(heapAgent) { } @@ -126,24 +127,32 @@ void InspectorConsoleAgent::startTiming(const String& title) { - // Follow Firebug's behavior of requiring a title that is not null or - // undefined for timing functions + ASSERT(!title.isNull()); if (title.isNull()) return; - m_times.add(title, monotonicallyIncreasingTime()); + auto result = m_times.add(title, monotonicallyIncreasingTime()); + + if (!result.isNewEntry) { + // FIXME: Send an enum to the frontend for localization? + String warning = makeString("Timer \"", title, "\" already exists"); + addMessageToConsole(std::make_unique(MessageSource::ConsoleAPI, MessageType::Timing, MessageLevel::Warning, warning)); + } } void InspectorConsoleAgent::stopTiming(const String& title, PassRefPtr callStack) { - // Follow Firebug's behavior of requiring a title that is not null or - // undefined for timing functions + ASSERT(!title.isNull()); if (title.isNull()) return; - HashMap::iterator it = m_times.find(title); - if (it == m_times.end()) + auto it = m_times.find(title); + if (it == m_times.end()) { + // FIXME: Send an enum to the frontend for localization? + String warning = makeString("Timer \"", title, "\" does not exist"); + addMessageToConsole(std::make_unique(MessageSource::ConsoleAPI, MessageType::Timing, MessageLevel::Warning, warning)); return; + } double startTime = it->value; m_times.remove(it); @@ -153,33 +162,42 @@ addMessageToConsole(std::make_unique(MessageSource::ConsoleAPI, MessageType::Timing, MessageLevel::Debug, message, callStack)); } +void InspectorConsoleAgent::takeHeapSnapshot(const String& title) +{ + if (!m_injectedScriptManager.inspectorEnvironment().developerExtrasEnabled()) + return; + + ErrorString ignored; + double timestamp; + String snapshotData; + m_heapAgent->snapshot(ignored, ×tamp, &snapshotData); + + m_frontendDispatcher->heapSnapshot(timestamp, snapshotData, title.isEmpty() ? nullptr : &title); +} + void InspectorConsoleAgent::count(JSC::ExecState* state, PassRefPtr arguments) { RefPtr callStack(createScriptCallStackForConsole(state, ScriptCallStack::maxCallStackSizeToCapture)); - const ScriptCallFrame& lastCaller = callStack->at(0); - // Follow Firebug's behavior of counting with null and undefined title in - // the same bucket as no argument - String title; - arguments->getFirstArgumentAsString(title); - String identifier = title + '@' + lastCaller.sourceURL() + ':' + String::number(lastCaller.lineNumber()); - HashMap::iterator it = m_counts.find(identifier); - int count; - if (it == m_counts.end()) - count = 1; - else { - count = it->value + 1; - m_counts.remove(it); + String title; + String identifier; + if (!arguments->argumentCount()) { + // '@' prefix for engine generated labels. + title = ASCIILiteral("Global"); + identifier = makeString('@', title); + } else { + // '#' prefix for user labels. + arguments->getFirstArgumentAsString(title); + identifier = makeString('#', title); } - m_counts.add(identifier, count); + auto result = m_counts.add(identifier, 1); + if (!result.isNewEntry) + result.iterator->value += 1; - String message; - if (title.isEmpty()) - message = ": " + String::number(count); - else - message = title + ": " + String::number(count); + // FIXME: Web Inspector should have a better UI for counters, but for now we just log an updated counter value. + String message = makeString(title, ": ", String::number(result.iterator->value)); addMessageToConsole(std::make_unique(MessageSource::ConsoleAPI, MessageType::Log, MessageLevel::Debug, message, callStack)); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorConsoleAgent.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,8 +23,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorConsoleAgent_h -#define InspectorConsoleAgent_h +#pragma once #include "InspectorBackendDispatchers.h" #include "InspectorFrontendDispatchers.h" @@ -44,6 +43,7 @@ class ConsoleMessage; class InjectedScriptManager; +class InspectorHeapAgent; class ScriptArguments; class ScriptCallStack; typedef String ErrorString; @@ -52,17 +52,17 @@ WTF_MAKE_NONCOPYABLE(InspectorConsoleAgent); WTF_MAKE_FAST_ALLOCATED; public: - InspectorConsoleAgent(AgentContext&); + InspectorConsoleAgent(AgentContext&, InspectorHeapAgent*); virtual ~InspectorConsoleAgent(); - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; - virtual void willDestroyFrontendAndBackend(DisconnectReason) override; + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; + void willDestroyFrontendAndBackend(DisconnectReason) override; - virtual void enable(ErrorString&) override; - virtual void disable(ErrorString&) override; - virtual void clearMessages(ErrorString&) override; - virtual void setMonitoringXHREnabled(ErrorString&, bool enabled) override = 0; - virtual void addInspectedNode(ErrorString&, int nodeId) override = 0; + void enable(ErrorString&) override; + void disable(ErrorString&) override; + void clearMessages(ErrorString&) override; + void setMonitoringXHREnabled(ErrorString&, bool enabled) override = 0; + void addInspectedNode(ErrorString&, int nodeId) override = 0; bool enabled() const { return m_enabled; } void reset(); @@ -71,6 +71,7 @@ void startTiming(const String& title); void stopTiming(const String& title, PassRefPtr); + void takeHeapSnapshot(const String& title); void count(JSC::ExecState*, PassRefPtr); protected: @@ -79,6 +80,7 @@ InjectedScriptManager& m_injectedScriptManager; std::unique_ptr m_frontendDispatcher; RefPtr m_backendDispatcher; + InspectorHeapAgent* m_heapAgent; ConsoleMessage* m_previousMessage { nullptr }; Vector> m_consoleMessages; @@ -89,5 +91,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorConsoleAgent_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -35,6 +35,7 @@ #include "InjectedScriptManager.h" #include "InspectorFrontendRouter.h" #include "InspectorValues.h" +#include "JSCInlines.h" #include "RegularExpression.h" #include "ScriptDebugServer.h" #include "ScriptObject.h" @@ -88,7 +89,6 @@ if (m_enabled) return; - m_scriptDebugServer.setBreakpointsActivated(true); m_scriptDebugServer.addListener(this); if (m_listener) @@ -105,6 +105,9 @@ m_scriptDebugServer.removeListener(this, isBeingDestroyed); clearInspectorBreakpointState(); + if (!isBeingDestroyed) + m_scriptDebugServer.deactivateBreakpoints(); + ASSERT(m_javaScriptBreakpoints.isEmpty()); if (m_listener) @@ -123,6 +126,11 @@ disable(false); } +bool InspectorDebuggerAgent::breakpointsActive() const +{ + return m_scriptDebugServer.breakpointsActive(); +} + void InspectorDebuggerAgent::setBreakpointsActive(ErrorString&, bool active) { if (active) @@ -131,7 +139,7 @@ m_scriptDebugServer.deactivateBreakpoints(); } -bool InspectorDebuggerAgent::isPaused() +bool InspectorDebuggerAgent::isPaused() const { return m_scriptDebugServer.isPaused(); } @@ -170,10 +178,10 @@ return reason->openAccessors(); } -RefPtr InspectorDebuggerAgent::buildExceptionPauseReason(const Deprecated::ScriptValue& exception, const InjectedScript& injectedScript) +RefPtr InspectorDebuggerAgent::buildExceptionPauseReason(JSC::JSValue exception, const InjectedScript& injectedScript) { - ASSERT(!exception.hasNoValue()); - if (exception.hasNoValue()) + ASSERT(exception); + if (!exception) return nullptr; ASSERT(!injectedScript.hasNoValue()); @@ -217,19 +225,19 @@ static bool breakpointActionTypeForString(const String& typeString, ScriptBreakpointActionType* output) { - if (typeString == Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Log)) { + if (typeString == Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Log)) { *output = ScriptBreakpointActionTypeLog; return true; } - if (typeString == Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Evaluate)) { + if (typeString == Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Evaluate)) { *output = ScriptBreakpointActionTypeEvaluate; return true; } - if (typeString == Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Sound)) { + if (typeString == Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Sound)) { *output = ScriptBreakpointActionTypeSound; return true; } - if (typeString == Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Probe)) { + if (typeString == Inspector::Protocol::InspectorHelpers::getEnumConstantValue(Inspector::Protocol::Debugger::BreakpointAction::Type::Probe)) { *output = ScriptBreakpointActionTypeProbe; return true; } @@ -318,8 +326,8 @@ ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, breakpointActions, autoContinue, ignoreCount); for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) { - String scriptURL = !it->value.sourceURL.isEmpty() ? it->value.sourceURL : it->value.url; - if (!matches(scriptURL, url, isRegex)) + String scriptURLForBreakpoints = !it->value.sourceURL.isEmpty() ? it->value.sourceURL : it->value.url; + if (!matches(scriptURLForBreakpoints, url, isRegex)) continue; RefPtr location = resolveBreakpoint(breakpointIdentifier, it->key, breakpoint); @@ -563,9 +571,14 @@ void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) { + if (m_currentCallStack.hasNoValue()) { + errorString = ASCIILiteral("Not paused"); + return; + } + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(callFrameId); if (injectedScript.hasNoValue()) { - errorString = ASCIILiteral("Inspected frame has gone"); + errorString = ASCIILiteral("Could not find InjectedScript for callFrameId"); return; } @@ -611,18 +624,21 @@ void InspectorDebuggerAgent::didParseSource(JSC::SourceID sourceID, const Script& script) { + String scriptIDStr = String::number(sourceID); bool hasSourceURL = !script.sourceURL.isEmpty(); - String scriptURL = hasSourceURL ? script.sourceURL : script.url; - bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; + String sourceURL = script.sourceURL; String sourceMappingURL = sourceMapURLForScript(script); - String* sourceMapURLParam = sourceMappingURL.isNull() ? nullptr : &sourceMappingURL; + const bool* isContentScript = script.isContentScript ? &script.isContentScript : nullptr; - String scriptIDStr = String::number(sourceID); - m_frontendDispatcher->scriptParsed(scriptIDStr, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam); + String* sourceURLParam = hasSourceURL ? &sourceURL : nullptr; + String* sourceMapURLParam = sourceMappingURL.isEmpty() ? nullptr : &sourceMappingURL; + + m_frontendDispatcher->scriptParsed(scriptIDStr, script.url, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceURLParam, sourceMapURLParam); m_scripts.set(sourceID, script); - if (scriptURL.isEmpty()) + String scriptURLForBreakpoints = hasSourceURL ? script.sourceURL : script.url; + if (scriptURLForBreakpoints.isEmpty()) return; for (auto it = m_javaScriptBreakpoints.begin(), end = m_javaScriptBreakpoints.end(); it != end; ++it) { @@ -631,10 +647,10 @@ return; bool isRegex; - breakpointObject->getBoolean(ASCIILiteral("isRegex"), isRegex); String url; + breakpointObject->getBoolean(ASCIILiteral("isRegex"), isRegex); breakpointObject->getString(ASCIILiteral("url"), url); - if (!matches(scriptURL, url, isRegex)) + if (!matches(scriptURLForBreakpoints, url, isRegex)) continue; ScriptBreakpoint breakpoint; @@ -662,13 +678,13 @@ m_frontendDispatcher->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage); } -void InspectorDebuggerAgent::didPause(JSC::ExecState* scriptState, const Deprecated::ScriptValue& callFrames, const Deprecated::ScriptValue& exceptionOrCaughtValue) +void InspectorDebuggerAgent::didPause(JSC::ExecState& scriptState, JSC::JSValue callFrames, JSC::JSValue exceptionOrCaughtValue) { - ASSERT(scriptState && !m_pausedScriptState); - m_pausedScriptState = scriptState; - m_currentCallStack = callFrames; + ASSERT(!m_pausedScriptState); + m_pausedScriptState = &scriptState; + m_currentCallStack = { scriptState.vm(), callFrames }; - InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(scriptState); + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(&scriptState); // If a high level pause pause reason is not already set, try to infer a reason from the debugger. if (m_breakReason == DebuggerFrontendDispatcher::Reason::Other) { @@ -703,7 +719,7 @@ } // Set $exception to the exception or caught value. - if (!exceptionOrCaughtValue.hasNoValue() && !injectedScript.hasNoValue()) { + if (exceptionOrCaughtValue && !injectedScript.hasNoValue()) { injectedScript.setExceptionValue(exceptionOrCaughtValue); m_hasExceptionValue = true; } @@ -731,18 +747,17 @@ m_frontendDispatcher->playBreakpointActionSound(breakpointActionIdentifier); } -void InspectorDebuggerAgent::breakpointActionProbe(JSC::ExecState* scriptState, const ScriptBreakpointAction& action, unsigned batchId, unsigned sampleId, const Deprecated::ScriptValue& sample) +void InspectorDebuggerAgent::breakpointActionProbe(JSC::ExecState& scriptState, const ScriptBreakpointAction& action, unsigned batchId, unsigned sampleId, JSC::JSValue sample) { - InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(scriptState); - RefPtr payload = injectedScript.wrapObject(sample, objectGroupForBreakpointAction(action), true); + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(&scriptState); + auto payload = injectedScript.wrapObject(sample, objectGroupForBreakpointAction(action), true); auto result = Protocol::Debugger::ProbeSample::create() .setProbeId(action.identifier) .setBatchId(batchId) .setSampleId(sampleId) .setTimestamp(m_injectedScriptManager.inspectorEnvironment().executionStopwatch()->elapsedTime()) - .setPayload(payload.release()) + .setPayload(WTFMove(payload)) .release(); - m_frontendDispatcher->didSampleProbe(WTFMove(result)); } @@ -754,7 +769,7 @@ } m_pausedScriptState = nullptr; - m_currentCallStack = Deprecated::ScriptValue(); + m_currentCallStack = { }; m_injectedScriptManager.releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup); clearBreakDetails(); clearExceptionValue(); @@ -787,7 +802,7 @@ m_scriptDebugServer.clearBreakpoints(); m_pausedScriptState = nullptr; - m_currentCallStack = Deprecated::ScriptValue(); + m_currentCallStack = { }; m_scripts.clear(); m_breakpointIdentifierToDebugServerBreakpointIDs.clear(); m_debuggerBreakpointIdentifierToInspectorBreakpointIdentifier.clear(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.h 2016-11-03 07:04:20.000000000 +0000 @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorDebuggerAgent_h -#define InspectorDebuggerAgent_h +#pragma once #include "InspectorBackendDispatchers.h" #include "InspectorFrontendDispatchers.h" @@ -41,7 +40,6 @@ #include #include #include -#include namespace Inspector { @@ -61,29 +59,30 @@ virtual ~InspectorDebuggerAgent(); - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; - virtual void willDestroyFrontendAndBackend(DisconnectReason) override; + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) final; + void willDestroyFrontendAndBackend(DisconnectReason) final; - virtual void enable(ErrorString&) override; - virtual void disable(ErrorString&) override; - virtual void setBreakpointsActive(ErrorString&, bool active) override; - virtual void setBreakpointByUrl(ErrorString&, int lineNumber, const String* optionalURL, const String* optionalURLRegex, const int* optionalColumnNumber, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr>& locations) override; - virtual void setBreakpoint(ErrorString&, const Inspector::InspectorObject& location, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr& actualLocation) override; - virtual void removeBreakpoint(ErrorString&, const String& breakpointIdentifier) override; - virtual void continueToLocation(ErrorString&, const InspectorObject& location) override; - virtual void searchInContent(ErrorString&, const String& scriptID, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr>&) override; - virtual void getScriptSource(ErrorString&, const String& scriptID, String* scriptSource) override; - virtual void getFunctionDetails(ErrorString&, const String& functionId, RefPtr&) override; - virtual void pause(ErrorString&) override; - virtual void resume(ErrorString&) override; - virtual void stepOver(ErrorString&) override; - virtual void stepInto(ErrorString&) override; - virtual void stepOut(ErrorString&) override; - virtual void setPauseOnExceptions(ErrorString&, const String& pauseState) override; - virtual void evaluateOnCallFrame(ErrorString&, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) override; - virtual void setOverlayMessage(ErrorString&, const String*) override; + void enable(ErrorString&) final; + void disable(ErrorString&) final; + void setBreakpointsActive(ErrorString&, bool active) final; + void setBreakpointByUrl(ErrorString&, int lineNumber, const String* optionalURL, const String* optionalURLRegex, const int* optionalColumnNumber, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr>& locations) final; + void setBreakpoint(ErrorString&, const Inspector::InspectorObject& location, const Inspector::InspectorObject* options, Inspector::Protocol::Debugger::BreakpointId*, RefPtr& actualLocation) final; + void removeBreakpoint(ErrorString&, const String& breakpointIdentifier) final; + void continueToLocation(ErrorString&, const InspectorObject& location) final; + void searchInContent(ErrorString&, const String& scriptID, const String& query, const bool* optionalCaseSensitive, const bool* optionalIsRegex, RefPtr>&) final; + void getScriptSource(ErrorString&, const String& scriptID, String* scriptSource) final; + void getFunctionDetails(ErrorString&, const String& functionId, RefPtr&) final; + void pause(ErrorString&) final; + void resume(ErrorString&) final; + void stepOver(ErrorString&) final; + void stepInto(ErrorString&) final; + void stepOut(ErrorString&) final; + void setPauseOnExceptions(ErrorString&, const String& pauseState) final; + void evaluateOnCallFrame(ErrorString&, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) final; + void setOverlayMessage(ErrorString&, const String*) override; - bool isPaused(); + bool isPaused() const; + bool breakpointsActive() const; void setSuppressAllPauses(bool); @@ -117,8 +116,8 @@ virtual void enable(); virtual void disable(bool skipRecompile); - virtual void didPause(JSC::ExecState*, const Deprecated::ScriptValue& callFrames, const Deprecated::ScriptValue& exceptionOrCaughtValue) override; - virtual void didContinue() override; + void didPause(JSC::ExecState&, JSC::JSValue callFrames, JSC::JSValue exceptionOrCaughtValue) final; + void didContinue() final; virtual String sourceMapURLForScript(const Script&); @@ -127,11 +126,11 @@ private: Ref> currentCallFrames(const InjectedScript&); - virtual void didParseSource(JSC::SourceID, const Script&) override final; - virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) override final; + void didParseSource(JSC::SourceID, const Script&) final; + void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) final; - virtual void breakpointActionSound(int breakpointActionIdentifier) override; - virtual void breakpointActionProbe(JSC::ExecState*, const ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, const Deprecated::ScriptValue& sample) override final; + void breakpointActionSound(int breakpointActionIdentifier) final; + void breakpointActionProbe(JSC::ExecState&, const ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, JSC::JSValue sample) final; RefPtr resolveBreakpoint(const String& breakpointIdentifier, JSC::SourceID, const ScriptBreakpoint&); bool assertPaused(ErrorString&); @@ -141,7 +140,7 @@ void clearExceptionValue(); RefPtr buildBreakpointPauseReason(JSC::BreakpointID); - RefPtr buildExceptionPauseReason(const Deprecated::ScriptValue& exception, const InjectedScript&); + RefPtr buildExceptionPauseReason(JSC::JSValue exception, const InjectedScript&); bool breakpointActionsFromProtocol(ErrorString&, RefPtr& actions, BreakpointActions* result); @@ -171,5 +170,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorDebuggerAgent_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,11 @@ #include "config.h" #include "InspectorHeapAgent.h" +#include "HeapProfiler.h" +#include "InjectedScript.h" +#include "InjectedScriptManager.h" #include "InspectorEnvironment.h" +#include "JSCInlines.h" #include "VM.h" #include #include @@ -35,16 +39,86 @@ namespace Inspector { +struct GarbageCollectionData { + Inspector::Protocol::Heap::GarbageCollection::Type type; + double startTime; + double endTime; +}; + +class SendGarbageCollectionEventsTask { +public: + SendGarbageCollectionEventsTask(HeapFrontendDispatcher&); + void addGarbageCollection(GarbageCollectionData&); + void reset(); +private: + void timerFired(); + + HeapFrontendDispatcher& m_frontendDispatcher; + Vector m_collections; + RunLoop::Timer m_timer; + Lock m_mutex; +}; + +SendGarbageCollectionEventsTask::SendGarbageCollectionEventsTask(HeapFrontendDispatcher& frontendDispatcher) + : m_frontendDispatcher(frontendDispatcher) + , m_timer(RunLoop::current(), this, &SendGarbageCollectionEventsTask::timerFired) +{ +} + +void SendGarbageCollectionEventsTask::addGarbageCollection(GarbageCollectionData& collection) +{ + { + std::lock_guard lock(m_mutex); + m_collections.append(collection); + } + + if (!m_timer.isActive()) + m_timer.startOneShot(0); +} + +void SendGarbageCollectionEventsTask::reset() +{ + { + std::lock_guard lock(m_mutex); + m_collections.clear(); + } + + m_timer.stop(); +} + +void SendGarbageCollectionEventsTask::timerFired() +{ + Vector collectionsToSend; + + { + std::lock_guard lock(m_mutex); + m_collections.swap(collectionsToSend); + } + + // The timer is stopped on agent destruction, so this method will never be called after agent has been destroyed. + for (auto& collection : collectionsToSend) { + auto protocolObject = Inspector::Protocol::Heap::GarbageCollection::create() + .setType(collection.type) + .setStartTime(collection.startTime) + .setEndTime(collection.endTime) + .release(); + m_frontendDispatcher.garbageCollected(WTFMove(protocolObject)); + } +} + InspectorHeapAgent::InspectorHeapAgent(AgentContext& context) : InspectorAgentBase(ASCIILiteral("Heap")) + , m_injectedScriptManager(context.injectedScriptManager) , m_frontendDispatcher(std::make_unique(context.frontendRouter)) , m_backendDispatcher(HeapBackendDispatcher::create(context.backendDispatcher, this)) , m_environment(context.environment) + , m_sendGarbageCollectionEventsTask(std::make_unique(*m_frontendDispatcher)) { } InspectorHeapAgent::~InspectorHeapAgent() { + m_sendGarbageCollectionEventsTask->reset(); } void InspectorHeapAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) @@ -53,6 +127,9 @@ void InspectorHeapAgent::willDestroyFrontendAndBackend(DisconnectReason) { + // Stop tracking without taking a snapshot. + m_tracking = false; + ErrorString ignored; disable(ignored); } @@ -75,6 +152,9 @@ m_enabled = false; m_environment.vm().heap.removeObserver(this); + m_sendGarbageCollectionEventsTask->reset(); + + clearHeapSnapshots(); } void InspectorHeapAgent::gc(ErrorString&) @@ -85,6 +165,161 @@ vm.heap.collectAllGarbage(); } +void InspectorHeapAgent::snapshot(ErrorString&, double* timestamp, String* snapshotData) +{ + VM& vm = m_environment.vm(); + JSLockHolder lock(vm); + + HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler()); + snapshotBuilder.buildSnapshot(); + + *timestamp = m_environment.executionStopwatch()->elapsedTime(); + *snapshotData = snapshotBuilder.json([&] (const HeapSnapshotNode& node) { + if (Structure* structure = node.cell->structure(vm)) { + if (JSGlobalObject* globalObject = structure->globalObject()) { + if (!m_environment.canAccessInspectedScriptState(globalObject->globalExec())) + return false; + } + } + return true; + }); +} + +void InspectorHeapAgent::startTracking(ErrorString& errorString) +{ + if (m_tracking) + return; + + m_tracking = true; + + double timestamp; + String snapshotData; + snapshot(errorString, ×tamp, &snapshotData); + + m_frontendDispatcher->trackingStart(timestamp, snapshotData); +} + +void InspectorHeapAgent::stopTracking(ErrorString& errorString) +{ + if (!m_tracking) + return; + + m_tracking = false; + + double timestamp; + String snapshotData; + snapshot(errorString, ×tamp, &snapshotData); + + m_frontendDispatcher->trackingComplete(timestamp, snapshotData); +} + +Optional InspectorHeapAgent::nodeForHeapObjectIdentifier(ErrorString& errorString, unsigned heapObjectIdentifier) +{ + HeapProfiler* heapProfiler = m_environment.vm().heapProfiler(); + if (!heapProfiler) { + errorString = ASCIILiteral("No heap snapshot"); + return Nullopt; + } + + HeapSnapshot* snapshot = heapProfiler->mostRecentSnapshot(); + if (!snapshot) { + errorString = ASCIILiteral("No heap snapshot"); + return Nullopt; + } + + const Optional optionalNode = snapshot->nodeForObjectIdentifier(heapObjectIdentifier); + if (!optionalNode) { + errorString = ASCIILiteral("No object for identifier, it may have been collected"); + return Nullopt; + } + + return optionalNode; +} + +void InspectorHeapAgent::getPreview(ErrorString& errorString, int heapObjectId, Inspector::Protocol::OptOutput* resultString, RefPtr& functionDetails, RefPtr& objectPreview) +{ + // Prevent the cell from getting collected as we look it up. + VM& vm = m_environment.vm(); + JSLockHolder lock(vm); + DeferGC deferGC(vm.heap); + + unsigned heapObjectIdentifier = static_cast(heapObjectId); + const Optional optionalNode = nodeForHeapObjectIdentifier(errorString, heapObjectIdentifier); + if (!optionalNode) + return; + + // String preview. + JSCell* cell = optionalNode->cell; + if (cell->isString()) { + *resultString = cell->getString(nullptr); + return; + } + + // FIXME: Provide preview information for Internal Objects? CodeBlock, Executable, etc. + + Structure* structure = cell->structure(vm); + if (!structure) { + errorString = ASCIILiteral("Unable to get object details - Structure"); + return; + } + + JSGlobalObject* globalObject = structure->globalObject(); + if (!globalObject) { + errorString = ASCIILiteral("Unable to get object details - GlobalObject"); + return; + } + + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(globalObject->globalExec()); + if (injectedScript.hasNoValue()) { + errorString = ASCIILiteral("Unable to get object details - InjectedScript"); + return; + } + + // Function preview. + if (cell->inherits(JSFunction::info())) { + injectedScript.functionDetails(errorString, cell, &functionDetails); + return; + } + + // Object preview. + objectPreview = injectedScript.previewValue(cell); +} + +void InspectorHeapAgent::getRemoteObject(ErrorString& errorString, int heapObjectId, const String* optionalObjectGroup, RefPtr& result) +{ + // Prevent the cell from getting collected as we look it up. + VM& vm = m_environment.vm(); + JSLockHolder lock(vm); + DeferGC deferGC(vm.heap); + + unsigned heapObjectIdentifier = static_cast(heapObjectId); + const Optional optionalNode = nodeForHeapObjectIdentifier(errorString, heapObjectIdentifier); + if (!optionalNode) + return; + + JSCell* cell = optionalNode->cell; + Structure* structure = cell->structure(vm); + if (!structure) { + errorString = ASCIILiteral("Unable to get object details"); + return; + } + + JSGlobalObject* globalObject = structure->globalObject(); + if (!globalObject) { + errorString = ASCIILiteral("Unable to get object details"); + return; + } + + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(globalObject->globalExec()); + if (injectedScript.hasNoValue()) { + errorString = ASCIILiteral("Unable to get object details - InjectedScript"); + return; + } + + String objectGroup = optionalObjectGroup ? *optionalObjectGroup : String(); + result = injectedScript.wrapObject(cell, objectGroup, true); +} + static Inspector::Protocol::Heap::GarbageCollection::Type protocolTypeForHeapOperation(HeapOperation operation) { switch (operation) { @@ -113,9 +348,6 @@ // FIXME: Include number of bytes freed by collection. - double startTime = m_gcStartTime; - double endTime = m_environment.executionStopwatch()->elapsedTime(); - // Dispatch the event asynchronously because this method may be // called between collection and sweeping and we don't want to // create unexpected JavaScript allocations that the Sweeper does @@ -123,17 +355,25 @@ // with WebKitLegacy's in process inspector which shares the same // VM as the inspected page. - RunLoop::current().dispatch([this, startTime, endTime, operation]() { - auto collection = Inspector::Protocol::Heap::GarbageCollection::create() - .setType(protocolTypeForHeapOperation(operation)) - .setStartTime(startTime) - .setEndTime(endTime) - .release(); + GarbageCollectionData data; + data.type = protocolTypeForHeapOperation(operation); + data.startTime = m_gcStartTime; + data.endTime = m_environment.executionStopwatch()->elapsedTime(); - m_frontendDispatcher->garbageCollected(WTFMove(collection)); - }); + m_sendGarbageCollectionEventsTask->addGarbageCollection(data); m_gcStartTime = NAN; } +void InspectorHeapAgent::clearHeapSnapshots() +{ + VM& vm = m_environment.vm(); + JSLockHolder lock(vm); + + if (HeapProfiler* heapProfiler = vm.heapProfiler()) { + heapProfiler->clearSnapshots(); + HeapSnapshotBuilder::resetNextAvailableObjectIdentifier(); + } +} + } // namespace Inspector diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,9 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorHeapAgent_h -#define InspectorHeapAgent_h +#pragma once +#include "HeapSnapshot.h" #include "InspectorBackendDispatchers.h" #include "InspectorFrontendDispatchers.h" #include "heap/HeapObserver.h" @@ -35,34 +35,49 @@ namespace Inspector { +class InjectedScriptManager; +class SendGarbageCollectionEventsTask; typedef String ErrorString; -class JS_EXPORT_PRIVATE InspectorHeapAgent final : public InspectorAgentBase, public HeapBackendDispatcherHandler, public JSC::HeapObserver { +class JS_EXPORT_PRIVATE InspectorHeapAgent : public InspectorAgentBase, public HeapBackendDispatcherHandler, public JSC::HeapObserver { WTF_MAKE_NONCOPYABLE(InspectorHeapAgent); public: InspectorHeapAgent(AgentContext&); virtual ~InspectorHeapAgent(); - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; - virtual void willDestroyFrontendAndBackend(DisconnectReason) override; + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; + void willDestroyFrontendAndBackend(DisconnectReason) override; // HeapBackendDispatcherHandler - virtual void enable(ErrorString&) override; - virtual void disable(ErrorString&) override; - virtual void gc(ErrorString&) override; + void enable(ErrorString&) override; + void disable(ErrorString&) override; + void gc(ErrorString&) final; + void snapshot(ErrorString&, double* timestamp, String* snapshotData) final; + void startTracking(ErrorString&) final; + void stopTracking(ErrorString&) final; + void getPreview(ErrorString&, int heapObjectId, Inspector::Protocol::OptOutput* resultString, RefPtr& functionDetails, RefPtr& objectPreview) final; + void getRemoteObject(ErrorString&, int heapObjectId, const String* optionalObjectGroup, RefPtr& result) final; // HeapObserver - virtual void willGarbageCollect() override; - virtual void didGarbageCollect(JSC::HeapOperation) override; + void willGarbageCollect() override; + void didGarbageCollect(JSC::HeapOperation) override; + +protected: + void clearHeapSnapshots(); private: + Optional nodeForHeapObjectIdentifier(ErrorString&, unsigned heapObjectIdentifier); + + InjectedScriptManager& m_injectedScriptManager; std::unique_ptr m_frontendDispatcher; RefPtr m_backendDispatcher; InspectorEnvironment& m_environment; + + std::unique_ptr m_sendGarbageCollectionEventsTask; + bool m_enabled { false }; + bool m_tracking { false }; double m_gcStartTime { NAN }; }; } // namespace Inspector - -#endif // InspectorHeapAgent_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -137,7 +137,7 @@ { InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); if (injectedScript.hasNoValue()) { - errorString = ASCIILiteral("Inspected frame has gone"); + errorString = ASCIILiteral("Could not find InjectedScript for objectId"); return; } @@ -163,7 +163,7 @@ { InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); if (injectedScript.hasNoValue()) { - errorString = ASCIILiteral("Inspected frame has gone"); + errorString = ASCIILiteral("Could not find InjectedScript for objectId"); return; } @@ -181,7 +181,7 @@ { InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); if (injectedScript.hasNoValue()) { - errorString = ASCIILiteral("Inspected frame has gone"); + errorString = ASCIILiteral("Could not find InjectedScript for objectId"); return; } @@ -199,7 +199,7 @@ { InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); if (injectedScript.hasNoValue()) { - errorString = ASCIILiteral("Inspected frame has gone"); + errorString = ASCIILiteral("Could not find InjectedScript for objectId"); return; } @@ -217,7 +217,7 @@ if (callArgument.getString(ASCIILiteral("objectId"), objectId)) { injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); if (injectedScript.hasNoValue()) { - errorString = ASCIILiteral("Inspected frame has gone"); + errorString = ASCIILiteral("Could not find InjectedScript for objectId"); return; } } else { @@ -317,6 +317,16 @@ setTypeProfilerEnabledState(false); } +void InspectorRuntimeAgent::enableControlFlowProfiler(ErrorString&) +{ + setControlFlowProfilerEnabledState(true); +} + +void InspectorRuntimeAgent::disableControlFlowProfiler(ErrorString&) +{ + setControlFlowProfilerEnabledState(false); +} + void InspectorRuntimeAgent::setTypeProfilerEnabledState(bool isTypeProfilingEnabled) { if (m_isTypeProfilingEnabled == isTypeProfilingEnabled) @@ -326,10 +336,22 @@ VM& vm = m_vm; vm.whenIdle([&vm, isTypeProfilingEnabled] () { bool shouldRecompileFromTypeProfiler = (isTypeProfilingEnabled ? vm.enableTypeProfiler() : vm.disableTypeProfiler()); - bool shouldRecompileFromControlFlowProfiler = (isTypeProfilingEnabled ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler()); - bool needsToRecompile = shouldRecompileFromTypeProfiler || shouldRecompileFromControlFlowProfiler; + if (shouldRecompileFromTypeProfiler) + vm.deleteAllCode(); + }); +} + +void InspectorRuntimeAgent::setControlFlowProfilerEnabledState(bool isControlFlowProfilingEnabled) +{ + if (m_isControlFlowProfilingEnabled == isControlFlowProfilingEnabled) + return; + m_isControlFlowProfilingEnabled = isControlFlowProfilingEnabled; + + VM& vm = m_vm; + vm.whenIdle([&vm, isControlFlowProfilingEnabled] () { + bool shouldRecompileFromControlFlowProfiler = (isControlFlowProfilingEnabled ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler()); - if (needsToRecompile) + if (shouldRecompileFromControlFlowProfiler) vm.deleteAllCode(); }); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorRuntimeAgent_h -#define InspectorRuntimeAgent_h +#pragma once #include "InspectorBackendDispatchers.h" #include "InspectorFrontendDispatchers.h" @@ -55,23 +54,25 @@ public: virtual ~InspectorRuntimeAgent(); - virtual void willDestroyFrontendAndBackend(DisconnectReason) override; + void willDestroyFrontendAndBackend(DisconnectReason) override; - virtual void enable(ErrorString&) override { m_enabled = true; } - virtual void disable(ErrorString&) override { m_enabled = false; } - virtual void parse(ErrorString&, const String& expression, Inspector::Protocol::Runtime::SyntaxErrorType* result, Inspector::Protocol::OptOutput* message, RefPtr&) override final; - virtual void evaluate(ErrorString&, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) override final; - virtual void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const Inspector::InspectorArray* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown) override final; - virtual void releaseObject(ErrorString&, const ErrorString& objectId) override final; - virtual void getProperties(ErrorString&, const String& objectId, const bool* ownProperties, const bool* generatePreview, RefPtr>& result, RefPtr>& internalProperties) override final; - virtual void getDisplayableProperties(ErrorString&, const String& objectId, const bool* generatePreview, RefPtr>& result, RefPtr>& internalProperties) override final; - virtual void getCollectionEntries(ErrorString&, const String& objectId, const String* objectGroup, const int* startIndex, const int* numberToFetch, RefPtr>& entries) override final; - virtual void saveResult(ErrorString&, const Inspector::InspectorObject& callArgument, const int* executionContextId, Inspector::Protocol::OptOutput* savedResultIndex) override final; - virtual void releaseObjectGroup(ErrorString&, const String& objectGroup) override final; - virtual void getRuntimeTypesForVariablesAtOffsets(ErrorString&, const Inspector::InspectorArray& locations, RefPtr>&) override; - virtual void enableTypeProfiler(ErrorString&) override; - virtual void disableTypeProfiler(ErrorString&) override; - virtual void getBasicBlocks(ErrorString&, const String& in_sourceID, RefPtr>& out_basicBlocks) override; + void enable(ErrorString&) override { m_enabled = true; } + void disable(ErrorString&) override { m_enabled = false; } + void parse(ErrorString&, const String& expression, Inspector::Protocol::Runtime::SyntaxErrorType* result, Inspector::Protocol::OptOutput* message, RefPtr&) final; + void evaluate(ErrorString&, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) final; + void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const Inspector::InspectorArray* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, RefPtr& result, Inspector::Protocol::OptOutput* wasThrown) final; + void releaseObject(ErrorString&, const ErrorString& objectId) final; + void getProperties(ErrorString&, const String& objectId, const bool* ownProperties, const bool* generatePreview, RefPtr>& result, RefPtr>& internalProperties) final; + void getDisplayableProperties(ErrorString&, const String& objectId, const bool* generatePreview, RefPtr>& result, RefPtr>& internalProperties) final; + void getCollectionEntries(ErrorString&, const String& objectId, const String* objectGroup, const int* startIndex, const int* numberToFetch, RefPtr>& entries) final; + void saveResult(ErrorString&, const Inspector::InspectorObject& callArgument, const int* executionContextId, Inspector::Protocol::OptOutput* savedResultIndex) final; + void releaseObjectGroup(ErrorString&, const String& objectGroup) final; + void getRuntimeTypesForVariablesAtOffsets(ErrorString&, const Inspector::InspectorArray& locations, RefPtr>&) override; + void enableTypeProfiler(ErrorString&) override; + void disableTypeProfiler(ErrorString&) override; + void enableControlFlowProfiler(ErrorString&) override; + void disableControlFlowProfiler(ErrorString&) override; + void getBasicBlocks(ErrorString&, const String& in_sourceID, RefPtr>& out_basicBlocks) override; bool enabled() const { return m_enabled; } @@ -87,14 +88,14 @@ private: void setTypeProfilerEnabledState(bool); + void setControlFlowProfilerEnabledState(bool); InjectedScriptManager& m_injectedScriptManager; ScriptDebugServer& m_scriptDebugServer; JSC::VM& m_vm; bool m_enabled {false}; bool m_isTypeProfilingEnabled {false}; + bool m_isControlFlowProfilingEnabled {false}; }; } // namespace Inspector - -#endif // InspectorRuntimeAgent_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -53,8 +53,15 @@ void InspectorScriptProfilerAgent::willDestroyFrontendAndBackend(DisconnectReason) { - ErrorString ignored; - stopTracking(ignored); + // Stop tracking without sending results. + if (m_tracking) { + m_tracking = false; + m_activeEvaluateScript = false; + m_environment.scriptDebugServer().setProfilingClient(nullptr); + + // Stop sampling without processing the samples. + stopSamplingWhenDisconnecting(); + } } void InspectorScriptProfilerAgent::startTracking(ErrorString&, const bool* includeSamples) @@ -67,11 +74,9 @@ #if ENABLE(SAMPLING_PROFILER) if (includeSamples && *includeSamples) { VM& vm = m_environment.scriptDebugServer().vm(); - vm.ensureSamplingProfiler(m_environment.executionStopwatch()); + SamplingProfiler& samplingProfiler = vm.ensureSamplingProfiler(m_environment.executionStopwatch()); - SamplingProfiler& samplingProfiler = *vm.samplingProfiler(); LockHolder locker(samplingProfiler.getLock()); - samplingProfiler.setStopWatch(locker, m_environment.executionStopwatch()); samplingProfiler.noticeCurrentThreadAsJSCExecutionThread(locker); samplingProfiler.start(locker); @@ -157,7 +162,7 @@ } #if ENABLE(SAMPLING_PROFILER) -static Ref buildSamples(VM& vm, Vector&& samplingProfilerStackTraces, double totalTime) +static Ref buildSamples(VM& vm, Vector&& samplingProfilerStackTraces) { Ref> stackTraces = Protocol::Array::create(); for (SamplingProfiler::StackTrace& stackTrace : samplingProfilerStackTraces) { @@ -190,7 +195,6 @@ return Protocol::ScriptProfiler::Samples::create() .setStackTraces(WTFMove(stackTraces)) - .setTotalTime(totalTime) .release(); } #endif // ENABLE(SAMPLING_PROFILER) @@ -203,9 +207,9 @@ SamplingProfiler* samplingProfiler = m_environment.scriptDebugServer().vm().samplingProfiler(); RELEASE_ASSERT(samplingProfiler); LockHolder locker(samplingProfiler->getLock()); - samplingProfiler->stop(locker); + samplingProfiler->pause(locker); Vector stackTraces = samplingProfiler->releaseStackTraces(locker); - Ref samples = buildSamples(m_environment.scriptDebugServer().vm(), WTFMove(stackTraces), samplingProfiler->totalTime(locker)); + Ref samples = buildSamples(m_environment.scriptDebugServer().vm(), WTFMove(stackTraces)); locker.unlockEarly(); @@ -219,4 +223,31 @@ #endif // ENABLE(SAMPLING_PROFILER) } +void InspectorScriptProfilerAgent::stopSamplingWhenDisconnecting() +{ +#if ENABLE(SAMPLING_PROFILER) + if (!m_enabledSamplingProfiler) + return; + + JSLockHolder lock(m_environment.scriptDebugServer().vm()); + SamplingProfiler* samplingProfiler = m_environment.scriptDebugServer().vm().samplingProfiler(); + RELEASE_ASSERT(samplingProfiler); + LockHolder locker(samplingProfiler->getLock()); + samplingProfiler->pause(locker); + samplingProfiler->clearData(locker); + + m_enabledSamplingProfiler = false; +#endif +} + +void InspectorScriptProfilerAgent::programmaticCaptureStarted() +{ + m_frontendDispatcher->programmaticCaptureStarted(); +} + +void InspectorScriptProfilerAgent::programmaticCaptureStopped() +{ + m_frontendDispatcher->programmaticCaptureStopped(); +} + } // namespace Inspector diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/InspectorScriptProfilerAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorScriptProfilerAgent_h -#define InspectorScriptProfilerAgent_h +#pragma once #include "InspectorBackendDispatchers.h" #include "InspectorFrontendDispatchers.h" @@ -46,17 +45,20 @@ InspectorScriptProfilerAgent(AgentContext&); virtual ~InspectorScriptProfilerAgent(); - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; - virtual void willDestroyFrontendAndBackend(DisconnectReason) override; + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; + void willDestroyFrontendAndBackend(DisconnectReason) override; // ScriptProfilerBackendDispatcherHandler - virtual void startTracking(ErrorString&, const bool* includeSamples) override; - virtual void stopTracking(ErrorString&) override; + void startTracking(ErrorString&, const bool* includeSamples) override; + void stopTracking(ErrorString&) override; + + void programmaticCaptureStarted(); + void programmaticCaptureStopped(); // Debugger::ProfilingClient - virtual bool isAlreadyProfiling() const override; - virtual double willEvaluateScript() override; - virtual void didEvaluateScript(double, JSC::ProfilingReason) override; + bool isAlreadyProfiling() const override; + double willEvaluateScript() override; + void didEvaluateScript(double, JSC::ProfilingReason) override; private: struct Event { @@ -67,6 +69,7 @@ void addEvent(double startTime, double endTime, JSC::ProfilingReason); void trackingComplete(); + void stopSamplingWhenDisconnecting(); std::unique_ptr m_frontendDispatcher; RefPtr m_backendDispatcher; @@ -79,5 +82,3 @@ }; } // namespace Inspector - -#endif // InspectorScriptProfilerAgent_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -28,8 +28,8 @@ namespace Inspector { -JSGlobalObjectConsoleAgent::JSGlobalObjectConsoleAgent(AgentContext& context) - : InspectorConsoleAgent(context) +JSGlobalObjectConsoleAgent::JSGlobalObjectConsoleAgent(AgentContext& context, InspectorHeapAgent* heapAgent) + : InspectorConsoleAgent(context, heapAgent) { } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectConsoleAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSGlobalObjectConsoleAgent_h -#define JSGlobalObjectConsoleAgent_h +#pragma once #include "InspectorConsoleAgent.h" #include "JSGlobalObjectScriptDebugServer.h" @@ -35,14 +34,12 @@ WTF_MAKE_NONCOPYABLE(JSGlobalObjectConsoleAgent); WTF_MAKE_FAST_ALLOCATED; public: - JSGlobalObjectConsoleAgent(AgentContext&); + JSGlobalObjectConsoleAgent(AgentContext&, InspectorHeapAgent*); virtual ~JSGlobalObjectConsoleAgent() { } // FIXME: XHRs and Nodes only makes sense debugging a Web context. Can this be moved to a different agent? - virtual void setMonitoringXHREnabled(ErrorString&, bool enabled) override; - virtual void addInspectedNode(ErrorString&, int nodeId) override; + void setMonitoringXHREnabled(ErrorString&, bool enabled) override; + void addInspectedNode(ErrorString&, int nodeId) override; }; } // namespace Inspector - -#endif // !defined(JSGlobalObjectConsoleAgent_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -55,9 +55,9 @@ return injectedScriptManager().injectedScriptFor(exec); } -void JSGlobalObjectDebuggerAgent::breakpointActionLog(JSC::ExecState* exec, const String& message) +void JSGlobalObjectDebuggerAgent::breakpointActionLog(JSC::ExecState& state, const String& message) { - m_consoleAgent->addMessageToConsole(std::make_unique(MessageSource::JS, MessageType::Log, MessageLevel::Log, message, createScriptCallStack(exec, ScriptCallStack::maxCallStackSizeToCapture), 0)); + m_consoleAgent->addMessageToConsole(std::make_unique(MessageSource::JS, MessageType::Log, MessageLevel::Log, message, createScriptCallStack(&state, ScriptCallStack::maxCallStackSizeToCapture), 0)); } } // namespace Inspector diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectDebuggerAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSGlobalObjectDebuggerAgent_h -#define JSGlobalObjectDebuggerAgent_h +#pragma once #include "InspectorDebuggerAgent.h" #include "JSGlobalObjectScriptDebugServer.h" @@ -40,19 +39,17 @@ JSGlobalObjectDebuggerAgent(JSAgentContext&, InspectorConsoleAgent*); virtual ~JSGlobalObjectDebuggerAgent() { } - virtual InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override; + InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override; - virtual void breakpointActionLog(JSC::ExecState*, const String&) override; + void breakpointActionLog(JSC::ExecState&, const String&) final; // NOTE: JavaScript inspector does not yet need to mute a console because no messages // are sent to the console outside of the API boundary or console object. - virtual void muteConsole() override { } - virtual void unmuteConsole() override { } + void muteConsole() final { } + void unmuteConsole() final { } private: InspectorConsoleAgent* m_consoleAgent { nullptr }; }; } // namespace Inspector - -#endif // !defined(JSGlobalObjectDebuggerAgent_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectRuntimeAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectRuntimeAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/agents/JSGlobalObjectRuntimeAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/agents/JSGlobalObjectRuntimeAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSGlobalObjectRuntimeAgent_h -#define JSGlobalObjectRuntimeAgent_h +#pragma once #include "InspectorRuntimeAgent.h" @@ -38,14 +37,14 @@ public: JSGlobalObjectRuntimeAgent(JSAgentContext&); - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override; - virtual InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override; + InjectedScript injectedScriptForEval(ErrorString&, const int* executionContextId) override; // NOTE: JavaScript inspector does not yet need to mute a console because no messages // are sent to the console outside of the API boundary or console object. - virtual void muteConsole() override { } - virtual void unmuteConsole() override { } + void muteConsole() override { } + void unmuteConsole() override { } private: std::unique_ptr m_frontendDispatcher; @@ -54,5 +53,3 @@ }; } // namespace Inspector - -#endif // !defined(JSGlobalObjectRuntimeAgent_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/augmentable/AlternateDispatchableAgent.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/augmentable/AlternateDispatchableAgent.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/augmentable/AlternateDispatchableAgent.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/augmentable/AlternateDispatchableAgent.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AlternateDispatchableAgent_h -#define AlternateDispatchableAgent_h +#pragma once #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) @@ -53,11 +52,11 @@ m_alternateDispatcher->setBackendDispatcher(nullptr); } - virtual void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override + void didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) override { } - virtual void willDestroyFrontendAndBackend(DisconnectReason) override + void willDestroyFrontendAndBackend(DisconnectReason) override { } @@ -69,5 +68,3 @@ } // namespace Inspector #endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // AlternateDispatchableAgent_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorControllerClient.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorControllerClient.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorControllerClient.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorControllerClient.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AugmentableInspectorControllerClient_h -#define AugmentableInspectorControllerClient_h +#pragma once #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) @@ -33,6 +32,7 @@ class AugmentableInspectorControllerClient { public: virtual ~AugmentableInspectorControllerClient() { } + virtual void inspectorControllerDestroyed() = 0; virtual void inspectorConnected() = 0; virtual void inspectorDisconnected() = 0; }; @@ -40,5 +40,3 @@ } // namespace Inspector #endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(AugmentableInspectorControllerClient_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorController.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorController.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorController.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/augmentable/AugmentableInspectorController.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AugmentableInspectorController_h -#define AugmentableInspectorController_h +#pragma once #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) @@ -53,5 +52,3 @@ } // namespace Inspector #endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(AugmentableInspectorController_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ConsoleMessage.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ConsoleMessage.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ConsoleMessage.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ConsoleMessage.h 2016-09-19 12:18:06.000000000 +0000 @@ -28,8 +28,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ConsoleMessage_h -#define ConsoleMessage_h +#pragma once #include "ConsoleTypes.h" #include "InspectorFrontendDispatchers.h" @@ -93,5 +92,3 @@ }; } // namespace Inspector - -#endif // ConsoleMessage_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -32,6 +32,7 @@ #include "InspectorValues.h" #include "RegularExpression.h" #include "Yarr.h" +#include "YarrInterpreter.h" #include #include #include @@ -103,12 +104,13 @@ size_t start = 0; while (start < text.length()) { - size_t nextStart = text.findNextLineStart(start); - if (nextStart == notFound) { + size_t nextStart = text.find('\n', start); + if (nextStart == notFound || nextStart == (text.length() - 1)) { result->append(text.length()); break; } + nextStart += 1; result->append(nextStart); start = nextStart; } @@ -176,7 +178,7 @@ { ASSERT(!content.isNull()); const char* error = nullptr; - JSC::Yarr::YarrPattern pattern(patternString, false, true, &error); + JSC::Yarr::YarrPattern pattern(patternString, JSC::RegExpFlags::FlagMultiline, &error); ASSERT(!error); BumpPointerAllocator regexAllocator; auto bytecodePattern = JSC::Yarr::byteCompile(pattern, ®exAllocator); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ContentSearchUtilities.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ContentSearchUtilities.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ContentSearchUtilities.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ContentSearchUtilities.h 2016-09-19 12:18:06.000000000 +0000 @@ -26,8 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ContentSearchUtilities_h -#define ContentSearchUtilities_h +#pragma once #include "InspectorProtocolObjects.h" #include @@ -53,5 +52,3 @@ } // namespace ContentSearchUtilities } // namespace Inspector - -#endif // !defined(ContentSearchUtilities_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/EventLoop.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/EventLoop.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/EventLoop.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/EventLoop.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -53,6 +53,12 @@ } TranslateMessage(&msg); DispatchMessage(&msg); +#elif PLATFORM(WATCHOS) + // FIXME: . In order for auto-attach to work, we need to + // run in the default run loop mode otherwise we do not receive the XPC messages + // necessary to setup the relay connection and negotiate an auto-attach debugger. + CFTimeInterval timeInterval = 0.05; + CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeInterval, true); #elif USE(CF) // Run the RunLoop in a custom run loop mode to prevent default observers // to run and potentially evaluate JavaScript in this context while we are diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/EventLoop.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/EventLoop.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/EventLoop.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/EventLoop.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EventLoop_h -#define EventLoop_h +#pragma once #include @@ -54,5 +53,3 @@ }; } // namespace Inspector - -#endif // EventLoop_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/IdentifiersFactory.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/IdentifiersFactory.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/IdentifiersFactory.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/IdentifiersFactory.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IdentifiersFactory_h -#define IdentifiersFactory_h +#pragma once #include @@ -43,5 +42,3 @@ }; } // namespace Inspector - -#endif // !defined(IdentifiersFactory_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -36,7 +36,6 @@ #include "InspectorValues.h" #include "JSCInlines.h" #include "JSGlobalObject.h" -#include "LegacyProfiler.h" #include "ScriptFunctionCall.h" #include @@ -69,20 +68,11 @@ return m_injectedScriptObject; } -Deprecated::ScriptValue InjectedScriptBase::callFunctionWithEvalEnabled(Deprecated::ScriptFunctionCall& function, bool& hadException) const +JSC::JSValue InjectedScriptBase::callFunctionWithEvalEnabled(Deprecated::ScriptFunctionCall& function, bool& hadException) const { JSC::ExecState* scriptState = m_injectedScriptObject.scriptState(); - JSC::LegacyProfiler::profiler()->suspendProfiling(scriptState); - - Deprecated::ScriptValue resultValue; - { - JSC::DebuggerEvalEnabler evalEnabler(scriptState); - resultValue = function.call(hadException); - } - - JSC::LegacyProfiler::profiler()->unsuspendProfiling(scriptState); - - return resultValue; + JSC::DebuggerEvalEnabler evalEnabler(scriptState); + return function.call(hadException); } void InjectedScriptBase::makeCall(Deprecated::ScriptFunctionCall& function, RefPtr* result) @@ -93,15 +83,15 @@ } bool hadException = false; - Deprecated::ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); + auto resultValue = callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); if (!hadException) { - *result = resultValue.toInspectorValue(m_injectedScriptObject.scriptState()); + *result = toInspectorValue(*m_injectedScriptObject.scriptState(), resultValue); if (!*result) - *result = InspectorString::create(String::format("Object has too long reference chain (must not be longer than %d)", InspectorValue::maxDepth)); + *result = InspectorValue::create(String::format("Object has too long reference chain (must not be longer than %d)", InspectorValue::maxDepth)); } else - *result = InspectorString::create("Exception while making a call."); + *result = InspectorValue::create("Exception while making a call."); } void InjectedScriptBase::makeEvalCall(ErrorString& errorString, Deprecated::ScriptFunctionCall& function, RefPtr* objectResult, Protocol::OptOutput* wasThrown, Protocol::OptOutput* savedResultIndex) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptBase.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptBase.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptBase.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptBase.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InjectedScriptBase_h -#define InjectedScriptBase_h +#pragma once #include "InspectorEnvironment.h" #include "InspectorProtocolObjects.h" @@ -63,7 +62,7 @@ bool hasAccessToInspectedScriptState() const; const Deprecated::ScriptObject& injectedScriptObject() const; - Deprecated::ScriptValue callFunctionWithEvalEnabled(Deprecated::ScriptFunctionCall&, bool& hadException) const; + JSC::JSValue callFunctionWithEvalEnabled(Deprecated::ScriptFunctionCall&, bool& hadException) const; void makeCall(Deprecated::ScriptFunctionCall&, RefPtr* result); void makeEvalCall(ErrorString&, Deprecated::ScriptFunctionCall&, RefPtr* result, Protocol::OptOutput* wasThrown, Protocol::OptOutput* savedResult = nullptr); @@ -74,5 +73,3 @@ }; } // namespace Inspector - -#endif // InjectedScriptBase_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScript.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScript.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScript.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScript.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -79,7 +79,7 @@ makeEvalCall(errorString, function, result, wasThrown); } -void InjectedScript::evaluateOnCallFrame(ErrorString& errorString, const Deprecated::ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr* result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) +void InjectedScript::evaluateOnCallFrame(ErrorString& errorString, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr* result, Inspector::Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex) { Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("evaluateOnCallFrame"), inspectorEnvironment()->functionCallHandler()); function.appendArgument(callFrames); @@ -109,6 +109,23 @@ *result = BindingTraits::runtimeCast(WTFMove(resultValue)); } +void InjectedScript::functionDetails(ErrorString& errorString, JSC::JSValue value, RefPtr* result) +{ + Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("functionDetails"), inspectorEnvironment()->functionCallHandler()); + function.appendArgument(value); + function.appendArgument(true); // Preview only. + + RefPtr resultValue; + makeCall(function, &resultValue); + if (!resultValue || resultValue->type() != InspectorValue::Type::Object) { + if (!resultValue->asString(errorString)) + errorString = ASCIILiteral("Internal error"); + return; + } + + *result = BindingTraits::runtimeCast(WTFMove(resultValue)); +} + void InjectedScript::getProperties(ErrorString& errorString, const String& objectId, bool ownProperties, bool generatePreview, RefPtr>* properties) { Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getProperties"), inspectorEnvironment()->functionCallHandler()); @@ -194,23 +211,23 @@ *savedResultIndex = savedResultIndexInt; } -Ref> InjectedScript::wrapCallFrames(const Deprecated::ScriptValue& callFrames) const +Ref> InjectedScript::wrapCallFrames(JSC::JSValue callFrames) const { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("wrapCallFrames"), inspectorEnvironment()->functionCallHandler()); function.appendArgument(callFrames); bool hadException = false; - Deprecated::ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException); + auto callFramesValue = callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); - RefPtr result = callFramesValue.toInspectorValue(scriptState()); + RefPtr result = toInspectorValue(*scriptState(), callFramesValue); if (result->type() == InspectorValue::Type::Array) return BindingTraits>::runtimeCast(WTFMove(result)).releaseNonNull(); return Array::create(); } -RefPtr InjectedScript::wrapObject(const Deprecated::ScriptValue& value, const String& groupName, bool generatePreview) const +RefPtr InjectedScript::wrapObject(JSC::JSValue value, const String& groupName, bool generatePreview) const { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("wrapObject"), inspectorEnvironment()->functionCallHandler()); @@ -220,41 +237,59 @@ wrapFunction.appendArgument(generatePreview); bool hadException = false; - Deprecated::ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); + auto r = callFunctionWithEvalEnabled(wrapFunction, hadException); if (hadException) return nullptr; RefPtr resultObject; - bool castSucceeded = r.toInspectorValue(scriptState())->asObject(resultObject); + bool castSucceeded = toInspectorValue(*scriptState(), r)->asObject(resultObject); ASSERT_UNUSED(castSucceeded, castSucceeded); return BindingTraits::runtimeCast(resultObject); } -RefPtr InjectedScript::wrapTable(const Deprecated::ScriptValue& table, const Deprecated::ScriptValue& columns) const +RefPtr InjectedScript::wrapTable(JSC::JSValue table, JSC::JSValue columns) const { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("wrapTable"), inspectorEnvironment()->functionCallHandler()); wrapFunction.appendArgument(hasAccessToInspectedScriptState()); wrapFunction.appendArgument(table); - if (columns.hasNoValue()) + if (!columns) wrapFunction.appendArgument(false); else wrapFunction.appendArgument(columns); bool hadException = false; - Deprecated::ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); + auto r = callFunctionWithEvalEnabled(wrapFunction, hadException); if (hadException) return nullptr; RefPtr resultObject; - bool castSucceeded = r.toInspectorValue(scriptState())->asObject(resultObject); + bool castSucceeded = toInspectorValue(*scriptState(), r)->asObject(resultObject); ASSERT_UNUSED(castSucceeded, castSucceeded); return BindingTraits::runtimeCast(resultObject); } -void InjectedScript::setExceptionValue(const Deprecated::ScriptValue& value) +RefPtr InjectedScript::previewValue(JSC::JSValue value) const +{ + ASSERT(!hasNoValue()); + Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("previewValue"), inspectorEnvironment()->functionCallHandler()); + wrapFunction.appendArgument(value); + + bool hadException = false; + auto r = callFunctionWithEvalEnabled(wrapFunction, hadException); + if (hadException) + return nullptr; + + RefPtr resultObject; + bool castSucceeded = toInspectorValue(*scriptState(), r)->asObject(resultObject); + ASSERT_UNUSED(castSucceeded, castSucceeded); + + return BindingTraits::runtimeCast(resultObject); +} + +void InjectedScript::setExceptionValue(JSC::JSValue value) { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("setExceptionValue"), inspectorEnvironment()->functionCallHandler()); @@ -271,20 +306,20 @@ makeCall(function, &result); } -Deprecated::ScriptValue InjectedScript::findObjectById(const String& objectId) const +JSC::JSValue InjectedScript::findObjectById(const String& objectId) const { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("findObjectById"), inspectorEnvironment()->functionCallHandler()); function.appendArgument(objectId); bool hadException = false; - Deprecated::ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); + auto resultValue = callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); return resultValue; } -void InjectedScript::inspectObject(Deprecated::ScriptValue value) +void InjectedScript::inspectObject(JSC::JSValue value) { ASSERT(!hasNoValue()); Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("inspectObject"), inspectorEnvironment()->functionCallHandler()); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScript.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScript.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScript.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScript.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InjectedScript_h -#define InjectedScript_h +#pragma once #include "InjectedScriptBase.h" #include @@ -54,23 +53,25 @@ void evaluate(ErrorString&, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr* result, Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex); void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr* result, Protocol::OptOutput* wasThrown); - void evaluateOnCallFrame(ErrorString&, const Deprecated::ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr* result, Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex); + void evaluateOnCallFrame(ErrorString&, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr* result, Protocol::OptOutput* wasThrown, Inspector::Protocol::OptOutput* savedResultIndex); void getFunctionDetails(ErrorString&, const String& functionId, RefPtr* result); + void functionDetails(ErrorString&, JSC::JSValue, RefPtr* result); void getProperties(ErrorString&, const String& objectId, bool ownProperties, bool generatePreview, RefPtr>* result); void getDisplayableProperties(ErrorString&, const String& objectId, bool generatePreview, RefPtr>* result); void getInternalProperties(ErrorString&, const String& objectId, bool generatePreview, RefPtr>* result); void getCollectionEntries(ErrorString&, const String& objectId, const String& objectGroup, int startIndex, int numberToFetch, RefPtr>* entries); void saveResult(ErrorString&, const String& callArgumentJSON, Inspector::Protocol::OptOutput* savedResultIndex); - Ref> wrapCallFrames(const Deprecated::ScriptValue&) const; - RefPtr wrapObject(const Deprecated::ScriptValue&, const String& groupName, bool generatePreview = false) const; - RefPtr wrapTable(const Deprecated::ScriptValue& table, const Deprecated::ScriptValue& columns) const; + Ref> wrapCallFrames(JSC::JSValue) const; + RefPtr wrapObject(JSC::JSValue, const String& groupName, bool generatePreview = false) const; + RefPtr wrapTable(JSC::JSValue table, JSC::JSValue columns) const; + RefPtr previewValue(JSC::JSValue) const; - void setExceptionValue(const Deprecated::ScriptValue&); + void setExceptionValue(JSC::JSValue); void clearExceptionValue(); - Deprecated::ScriptValue findObjectById(const String& objectId) const; - void inspectObject(Deprecated::ScriptValue); + JSC::JSValue findObjectById(const String& objectId) const; + void inspectObject(JSC::JSValue); void releaseObject(const String& objectId); void releaseObjectGroup(const String& objectGroup); @@ -79,5 +80,3 @@ }; } // namespace Inspector - -#endif // InjectedScript_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptHost.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptHost.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptHost.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptHost.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -45,7 +45,7 @@ JSObject* prototype = JSInjectedScriptHost::createPrototype(exec->vm(), globalObject); Structure* structure = JSInjectedScriptHost::createStructure(exec->vm(), globalObject, prototype); - JSInjectedScriptHost* injectedScriptHost = JSInjectedScriptHost::create(exec->vm(), structure, Ref(*this)); + JSInjectedScriptHost* injectedScriptHost = JSInjectedScriptHost::create(exec->vm(), structure, makeRef(*this)); m_wrappers.addWrapper(globalObject, injectedScriptHost); return injectedScriptHost; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptHost.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptHost.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptHost.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptHost.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InjectedScriptHost_h -#define InjectedScriptHost_h +#pragma once #include "JSCJSValueInlines.h" #include "inspector/PerGlobalObjectWrapperWorld.h" @@ -49,5 +48,3 @@ }; } // namespace Inspector - -#endif // !defined(InjectedScriptHost_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptManager.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptManager.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptManager.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptManager.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -35,6 +35,7 @@ #include "InjectedScriptHost.h" #include "InjectedScriptSource.h" #include "InspectorValues.h" +#include "JSCInlines.h" #include "JSInjectedScriptHost.h" #include "JSLock.h" #include "ScriptObject.h" @@ -131,7 +132,7 @@ return StringImpl::createWithoutCopying(InjectedScriptSource_js, sizeof(InjectedScriptSource_js)); } -Deprecated::ScriptObject InjectedScriptManager::createInjectedScript(const String& source, ExecState* scriptState, int id) +JSC::JSObject* InjectedScriptManager::createInjectedScript(const String& source, ExecState* scriptState, int id) { JSLockHolder lock(scriptState); @@ -143,12 +144,12 @@ InspectorEvaluateHandler evaluateHandler = m_environment.evaluateHandler(); JSValue functionValue = evaluateHandler(scriptState, sourceCode, globalThisValue, evaluationException); if (evaluationException) - return Deprecated::ScriptObject(); + return nullptr; CallData callData; CallType callType = getCallData(functionValue, callData); - if (callType == CallTypeNone) - return Deprecated::ScriptObject(); + if (callType == CallType::None) + return nullptr; MarkedArgumentBuffer args; args.append(m_injectedScriptHost->wrapper(scriptState, globalObject)); @@ -157,10 +158,7 @@ JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); scriptState->clearException(); - if (result.isObject()) - return Deprecated::ScriptObject(scriptState, result.getObject()); - - return Deprecated::ScriptObject(); + return result.getObject(); } InjectedScript InjectedScriptManager::injectedScriptFor(ExecState* inspectedExecState) @@ -176,14 +174,14 @@ return InjectedScript(); int id = injectedScriptIdFor(inspectedExecState); - Deprecated::ScriptObject injectedScriptObject = createInjectedScript(injectedScriptSource(), inspectedExecState, id); - if (injectedScriptObject.scriptState() != inspectedExecState) { + auto injectedScriptObject = createInjectedScript(injectedScriptSource(), inspectedExecState, id); + if (!injectedScriptObject) { WTFLogAlways("Failed to parse/execute InjectedScriptSource.js!"); WTFLogAlways("%s\n", injectedScriptSource().ascii().data()); RELEASE_ASSERT_NOT_REACHED(); } - InjectedScript result(injectedScriptObject, &m_environment); + InjectedScript result({ inspectedExecState, injectedScriptObject }, &m_environment); m_idToInjectedScript.set(id, result); didCreateInjectedScript(result); return result; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptManager.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptManager.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptManager.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptManager.h 2016-09-19 12:18:06.000000000 +0000 @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InjectedScriptManager_h -#define InjectedScriptManager_h +#pragma once #include "InjectedScript.h" #include "InjectedScriptHost.h" @@ -74,7 +73,7 @@ private: String injectedScriptSource(); - Deprecated::ScriptObject createInjectedScript(const String& source, JSC::ExecState*, int id); + JSC::JSObject* createInjectedScript(const String& source, JSC::ExecState*, int id); InspectorEnvironment& m_environment; RefPtr m_injectedScriptHost; @@ -82,5 +81,3 @@ }; } // namespace Inspector - -#endif // !defined(InjectedScriptManager_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptModule.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptModule.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptModule.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptModule.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -65,9 +65,9 @@ Deprecated::ScriptFunctionCall function(injectedScript.injectedScriptObject(), ASCIILiteral("module"), injectedScriptManager->inspectorEnvironment().functionCallHandler()); function.appendArgument(name()); bool hadException = false; - Deprecated::ScriptValue resultValue = injectedScript.callFunctionWithEvalEnabled(function, hadException); + auto resultValue = injectedScript.callFunctionWithEvalEnabled(function, hadException); ASSERT(!hadException); - if (hadException || resultValue.hasNoValue() || !resultValue.isObject()) { + if (hadException || !resultValue || !resultValue.isObject()) { Deprecated::ScriptFunctionCall function(injectedScript.injectedScriptObject(), ASCIILiteral("injectModule"), injectedScriptManager->inspectorEnvironment().functionCallHandler()); function.appendArgument(name()); function.appendArgument(source()); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptModule.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptModule.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptModule.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptModule.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InjectedScriptModule_h -#define InjectedScriptModule_h +#pragma once #include "InjectedScriptBase.h" #include @@ -60,5 +59,3 @@ }; } // namespace Inspector - -#endif // InjectedScriptModule_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptSource.js webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptSource.js --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InjectedScriptSource.js 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InjectedScriptSource.js 2016-11-03 07:04:20.000000000 +0000 @@ -27,11 +27,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -//# sourceURL=__WebInspectorInjectedScript__ +//# sourceURL=__InjectedScript_InjectedScriptSource.js (function (InjectedScriptHost, inspectedGlobalObject, injectedScriptId) { -// Protect against Object overwritten by the user code. +// FIXME: Web Inspector: Parse InjectedScriptSource as a built-in to get guaranteed non-user-overriden built-ins + var Object = {}.constructor; function toString(obj) @@ -98,6 +99,36 @@ return InjectedScript.primitiveTypes[typeof object] && !this._isHTMLAllCollection(object); }, + previewValue: function(value) + { + return InjectedScript.RemoteObject.createObjectPreviewForValue(value, true); + }, + + functionDetails: function(func, previewOnly) + { + var details = InjectedScriptHost.functionDetails(func); + if (!details) + return "Cannot resolve function details."; + + // FIXME: provide function scope data in "scopesRaw" property when JSC supports it. + // [JSC] expose function (closure) inner context to debugger + if ("rawScopes" in details) { + if (previewOnly) + delete details.rawScopes; + else { + var objectGroupName = this._idToObjectGroupName[parsedFunctionId.id]; + var rawScopes = details.rawScopes; + var scopes = []; + delete details.rawScopes; + for (var i = 0; i < rawScopes.length; i++) + scopes.push(InjectedScript.CallFrameProxy._createScopeJson(rawScopes[i].type, rawScopes[i].object, objectGroupName)); + details.scopeChain = scopes; + } + } + + return details; + }, + wrapObject: function(object, groupName, canAccessInspectedGlobalObject, generatePreview) { if (canAccessInspectedGlobalObject) @@ -220,7 +251,7 @@ return result; }, - _getProperties: function(objectId, collectionMode, generatePreview) + _getProperties: function(objectId, collectionMode, generatePreview, nativeGettersAsValues) { var parsedObjectId = this._parseObjectId(objectId); var object = this._objectForId(parsedObjectId); @@ -232,7 +263,7 @@ if (isSymbol(object)) return false; - var descriptors = this._propertyDescriptors(object, collectionMode); + var descriptors = this._propertyDescriptors(object, collectionMode, nativeGettersAsValues); // Go over properties, wrap object values. for (var i = 0; i < descriptors.length; ++i) { @@ -256,14 +287,16 @@ getProperties: function(objectId, ownProperties, generatePreview) { + var nativeGettersAsValues = false; var collectionMode = ownProperties ? InjectedScript.CollectionMode.OwnProperties : InjectedScript.CollectionMode.AllProperties; - return this._getProperties(objectId, collectionMode, generatePreview); + return this._getProperties(objectId, collectionMode, generatePreview, nativeGettersAsValues); }, getDisplayableProperties: function(objectId, generatePreview) { + var nativeGettersAsValues = true; var collectionMode = InjectedScript.CollectionMode.OwnProperties | InjectedScript.CollectionMode.NativeGetterProperties; - return this._getProperties(objectId, collectionMode, generatePreview); + return this._getProperties(objectId, collectionMode, generatePreview, nativeGettersAsValues); }, getInternalProperties: function(objectId, generatePreview) @@ -332,19 +365,7 @@ var func = this._objectForId(parsedFunctionId); if (typeof func !== "function") return "Cannot resolve function by id."; - var details = InjectedScriptHost.functionDetails(func); - if (!details) - return "Cannot resolve function details."; - if ("rawScopes" in details) { - var objectGroupName = this._idToObjectGroupName[parsedFunctionId.id]; - var rawScopes = details.rawScopes; - var scopes = []; - delete details.rawScopes; - for (var i = 0; i < rawScopes.length; i++) - scopes.push(InjectedScript.CallFrameProxy._createScopeJson(rawScopes[i].type, rawScopes[i].object, objectGroupName)); - details.scopeChain = scopes; - } - return details; + return injectedScript.functionDetails(func); }, releaseObject: function(objectId) @@ -361,7 +382,7 @@ evaluate: function(expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview, saveResult) { - return this._evaluateAndWrap(InjectedScriptHost.evaluate, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI, returnByValue, generatePreview, saveResult); + return this._evaluateAndWrap(InjectedScriptHost.evaluateWithScopeExtension, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI, returnByValue, generatePreview, saveResult); }, callFunctionOn: function(objectId, expression, args, returnByValue, generatePreview) @@ -457,76 +478,13 @@ if (this.CommandLineAPI) commandLineAPI = new this.CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null); else - commandLineAPI = new BasicCommandLineAPI; - } - - if (isEvalOnCallFrame) { - // We can only use this approach if the evaluate function is the true 'eval'. That allows us to use it with - // the 'eval' identifier when calling it. Using 'eval' grants access to the local scope of the closure we - // create that provides the command line APIs. - - var parameters = [InjectedScriptHost.evaluate, expression]; - var expressionFunctionBody = "" + - "var global = Function('return this')() || (1, eval)('this');" + - "var __originalEval = global.eval; global.eval = __eval;" + - "try { return eval(__currentExpression); }" + - "finally { global.eval = __originalEval; }"; - - if (commandLineAPI) { - // To avoid using a 'with' statement (which fails in strict mode and requires injecting the API object) - // we instead create a closure where we evaluate the expression. The command line APIs are passed as - // parameters to the closure so they are in scope but not injected. This allows the code evaluated in - // the console to stay in strict mode (if is was already set), or to get strict mode by prefixing - // expressions with 'use strict';. - - var parameterNames = Object.getOwnPropertyNames(commandLineAPI); - for (var i = 0; i < parameterNames.length; ++i) - parameters.push(commandLineAPI[parameterNames[i]]); - - var expressionFunctionString = "(function(__eval, __currentExpression, " + parameterNames.join(", ") + ") { " + expressionFunctionBody + " })"; - } else { - // Use a closure in this case too to keep the same behavior of 'var' being captured by the closure instead - // of leaking out into the calling scope. - var expressionFunctionString = "(function(__eval, __currentExpression) { " + expressionFunctionBody + " })"; - } - - // Bind 'this' to the function expression using another closure instead of Function.prototype.bind. This ensures things will work if the page replaces bind. - var boundExpressionFunctionString = "(function(__function, __thisObject) { return function() { return __function.apply(__thisObject, arguments) }; })(" + expressionFunctionString + ", this)"; - var expressionFunction = evalFunction.call(object, boundExpressionFunctionString); - var result = expressionFunction.apply(null, parameters); - - if (saveResult) - this._saveResult(result); - - return result; + commandLineAPI = new BasicCommandLineAPI(isEvalOnCallFrame ? object : null); } - // When not evaluating on a call frame we use a 'with' statement to allow var and function statements to leak - // into the global scope. This allow them to stick around between evaluations. - - try { - if (commandLineAPI) { - if (inspectedGlobalObject.console) - inspectedGlobalObject.console.__commandLineAPI = commandLineAPI; - else - inspectedGlobalObject.__commandLineAPI = commandLineAPI; - expression = "with ((this && (this.console ? this.console.__commandLineAPI : this.__commandLineAPI)) || {}) { " + expression + "\n}"; - } - - var result = evalFunction.call(inspectedGlobalObject, expression); - - if (saveResult) - this._saveResult(result); - - return result; - } finally { - if (commandLineAPI) { - if (inspectedGlobalObject.console) - delete inspectedGlobalObject.console.__commandLineAPI; - else - delete inspectedGlobalObject.__commandLineAPI; - } - } + var result = evalFunction.call(object, expression, commandLineAPI); + if (saveResult) + this._saveResult(result); + return result; }, wrapCallFrames: function(callFrame) @@ -548,7 +506,7 @@ var callFrame = this._callFrameForId(topCallFrame, callFrameId); if (!callFrame) return "Could not find call frame with given id"; - return this._evaluateAndWrap(callFrame.evaluate, callFrame, expression, objectGroup, true, injectCommandLineAPI, returnByValue, generatePreview, saveResult); + return this._evaluateAndWrap(callFrame.evaluateWithScopeExtension, callFrame, expression, objectGroup, true, injectCommandLineAPI, returnByValue, generatePreview, saveResult); }, _callFrameForId: function(topCallFrame, callFrameId) @@ -614,7 +572,7 @@ return descriptors; }, - _propertyDescriptors: function(object, collectionMode) + _propertyDescriptors: function(object, collectionMode, nativeGettersAsValues) { var descriptors = []; var nameProcessed = new Set; @@ -656,11 +614,7 @@ // Native Getter properties. if (collectionMode & InjectedScript.CollectionMode.NativeGetterProperties) { - // FIXME: Web Inspector: Native Bindings Descriptors are Incomplete - // if (descriptor.hasOwnProperty("get") && descriptor.get && isNativeFunction(descriptor.get)) { ... } - if (possibleNativeBindingGetter) { - // Possible getter property in the prototype chain. descriptors.push(descriptor); return; } @@ -688,15 +642,14 @@ continue; } - if (endsWith(String(descriptor.get), "[native code]\n}") || - (!descriptor.get && descriptor.hasOwnProperty("get") && !descriptor.set && descriptor.hasOwnProperty("set"))) { - // FIXME: Some Native Bindings Descriptors are Incomplete - // Some IDL attributes appear on the instances instead of on prototypes - // Developers may create such a descriptors, so we should be resilient: - // var x = {}; Object.defineProperty(x, "p", {get:undefined}); Object.getOwnPropertyDescriptor(x, "p") - var fakeDescriptor = createFakeValueDescriptor(name, symbol, descriptor, isOwnProperty, true); - processDescriptor(fakeDescriptor, isOwnProperty, true); - continue; + if (nativeGettersAsValues) { + if (endsWith(String(descriptor.get), "[native code]\n}") || (!descriptor.get && descriptor.hasOwnProperty("get") && !descriptor.set && descriptor.hasOwnProperty("set"))) { + // Developers may create such a descriptor, so we should be resilient: + // var x = {}; Object.defineProperty(x, "p", {get:undefined}); Object.getOwnPropertyDescriptor(x, "p") + var fakeDescriptor = createFakeValueDescriptor(name, symbol, descriptor, isOwnProperty, true); + processDescriptor(fakeDescriptor, isOwnProperty, true); + continue; + } } descriptor.name = name; @@ -710,7 +663,7 @@ function arrayIndexPropertyNames(o, length) { - var array = new Array(length); + var array = []; for (var i = 0; i < length; ++i) { if (i in o) array.push("" + i); @@ -720,16 +673,16 @@ // FIXME: Web Inspector: Better handling for large collections in Object Trees // For array types with a large length we attempt to skip getOwnPropertyNames and instead just sublist of indexes. - var isArrayTypeWithLargeLength = false; + var isArrayLike = false; try { - isArrayTypeWithLargeLength = injectedScript._subtype(object) === "array" && isFinite(object.length) && object.length > 100; + isArrayLike = injectedScript._subtype(object) === "array" && isFinite(object.length) && object.length > 0; } catch(e) {} for (var o = object; this._isDefined(o); o = o.__proto__) { var isOwnProperty = o === object; - if (isArrayTypeWithLargeLength && isOwnProperty) - processProperties(o, arrayIndexPropertyNames(o, 100), isOwnProperty); + if (isArrayLike && isOwnProperty) + processProperties(o, arrayIndexPropertyNames(o, Math.min(object.length, 100)), isOwnProperty); else { processProperties(o, Object.getOwnPropertyNames(o), isOwnProperty); if (Object.getOwnPropertySymbols) @@ -785,27 +738,6 @@ return null; }, - _nodeDescription: function(node) - { - var isXMLDocument = node.ownerDocument && !!node.ownerDocument.xmlVersion; - var description = isXMLDocument ? node.nodeName : node.nodeName.toLowerCase(); - - switch (node.nodeType) { - case 1: // Node.ELEMENT_NODE - if (node.id) - description += "#" + node.id; - if (node.hasAttribute("class")) { - // Using .getAttribute() is a workaround for SVG*Element.className returning SVGAnimatedString, - // which doesn't have any useful String methods. See . - description += "." + node.getAttribute("class").trim().replace(/\s+/g, "."); - } - return description; - - default: - return description; - } - }, - _classPreview: function(classConstructorValue) { return "class " + classConstructorValue.name; @@ -860,12 +792,15 @@ return toString(obj); if (subtype === "node") - return this._nodeDescription(obj); + return this._nodePreview(obj); var className = InjectedScriptHost.internalConstructorName(obj); if (subtype === "array") return className; + if (subtype === "iterator" && Symbol.toStringTag in obj) + return obj[Symbol.toStringTag]; + // NodeList in JSC is a function, check for array prior to this. if (typeof obj === "function") return toString(obj); @@ -1025,7 +960,17 @@ if (generatePreview && this.type === "object") this.preview = this._generatePreview(object, undefined, columnNames); -} +}; + +InjectedScript.RemoteObject.createObjectPreviewForValue = function(value, generatePreview) +{ + var remoteObject = new InjectedScript.RemoteObject(value, undefined, false, generatePreview, undefined); + if (remoteObject.objectId) + injectedScript.releaseObject(remoteObject.objectId); + if (remoteObject.classPrototype && remoteObject.classPrototype.objectId) + injectedScript.releaseObject(remoteObject.classPrototype.objectId); + return remoteObject.preview || remoteObject._emptyPreview(); +}; InjectedScript.RemoteObject.prototype = { _initialPreview: function() @@ -1065,17 +1010,6 @@ return preview; }, - _createObjectPreviewForValue: function(value, generatePreview) - { - var remoteObject = new InjectedScript.RemoteObject(value, undefined, false, generatePreview, undefined); - if (remoteObject.objectId) - injectedScript.releaseObject(remoteObject.objectId); - if (remoteObject.classPrototype && remoteObject.classPrototype.objectId) - injectedScript.releaseObject(remoteObject.classPrototype.objectId); - - return remoteObject.preview || remoteObject._emptyPreview(); - }, - _generatePreview: function(object, firstLevelKeys, secondLevelKeys) { var preview = this._initialPreview(); @@ -1106,7 +1040,8 @@ return preview; // Properties. - var descriptors = injectedScript._propertyDescriptors(object, InjectedScript.CollectionMode.AllProperties); + var nativeGettersAsValues = true; + var descriptors = injectedScript._propertyDescriptors(object, InjectedScript.CollectionMode.AllProperties, nativeGettersAsValues); this._appendPropertyPreviews(object, preview, descriptors, false, propertiesThreshold, firstLevelKeys, secondLevelKeys); if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0) return preview; @@ -1132,15 +1067,24 @@ // Do not show "__proto__" in preview. var name = descriptor.name; - if (name === "__proto__") + if (name === "__proto__") { + // Non basic __proto__ objects may have interesting, non-enumerable, methods to show. + if (descriptor.value && descriptor.value.constructor + && descriptor.value.constructor !== Object + && descriptor.value.constructor !== Array + && descriptor.value.constructor !== RegExp) + preview.lossless = false; continue; + } // For arrays, only allow indexes. if (this.subtype === "array" && !isUInt32(name)) continue; - // Do not show non-enumerable non-own properties. Special case to allow array indexes that may be on the prototype. - if (!descriptor.enumerable && !descriptor.isOwn && this.subtype !== "array") + // Do not show non-enumerable non-own properties. + // Special case to allow array indexes that may be on the prototype. + // Special case to allow native getters on non-RegExp objects. + if (!descriptor.enumerable && !descriptor.isOwn && !(this.subtype === "array" || (this.subtype !== "regexp" && descriptor.nativeGetter))) continue; // If we have a filter, only show properties in the filter. @@ -1202,7 +1146,7 @@ // Second level. if ((secondLevelKeys === null || secondLevelKeys) || this._isPreviewableObject(value, object)) { // FIXME: If we want secondLevelKeys filter to continue we would need some refactoring. - var subPreview = this._createObjectPreviewForValue(value, value !== object); + var subPreview = InjectedScript.RemoteObject.createObjectPreviewForValue(value, value !== object); property.valuePreview = subPreview; if (!subPreview.lossless) preview.lossless = false; @@ -1266,10 +1210,10 @@ } preview.entries = entries.map(function(entry) { - entry.value = this._createObjectPreviewForValue(entry.value, entry.value !== object); + entry.value = InjectedScript.RemoteObject.createObjectPreviewForValue(entry.value, entry.value !== object); updateMainPreview(entry.value); if ("key" in entry) { - entry.key = this._createObjectPreviewForValue(entry.key, entry.key !== object); + entry.key = InjectedScript.RemoteObject.createObjectPreviewForValue(entry.key, entry.key !== object); updateMainPreview(entry.key); } return entry; @@ -1352,16 +1296,19 @@ this.functionName = callFrame.functionName; this.location = {scriptId: String(callFrame.sourceID), lineNumber: callFrame.line, columnNumber: callFrame.column}; this.scopeChain = this._wrapScopeChain(callFrame); - this.this = injectedScript._wrapObject(callFrame.thisObject, "backtrace"); + this.this = injectedScript._wrapObject(callFrame.thisObject, "backtrace", false, true); + this.isTailDeleted = callFrame.isTailDeleted; } InjectedScript.CallFrameProxy.prototype = { _wrapScopeChain: function(callFrame) { var scopeChain = callFrame.scopeChain; + var scopeDescriptions = callFrame.scopeDescriptions(); + var scopeChainProxy = []; for (var i = 0; i < scopeChain.length; i++) - scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson(callFrame.scopeType(i), scopeChain[i], "backtrace"); + scopeChainProxy[i] = InjectedScript.CallFrameProxy._createScopeJson(scopeChain[i], scopeDescriptions[i], "backtrace"); return scopeChainProxy; } } @@ -1374,46 +1321,63 @@ 4: "functionName", // FUNCTION_NAME_SCOPE 5: "globalLexicalEnvironment", // GLOBAL_LEXICAL_ENVIRONMENT_SCOPE 6: "nestedLexical", // NESTED_LEXICAL_SCOPE -} +}; -InjectedScript.CallFrameProxy._createScopeJson = function(scopeTypeCode, scopeObject, groupId) +InjectedScript.CallFrameProxy._createScopeJson = function(object, {name, type, location}, groupId) { - return { - object: injectedScript._wrapObject(scopeObject, groupId), - type: InjectedScript.CallFrameProxy._scopeTypeNames[scopeTypeCode] + var scope = { + object: injectedScript._wrapObject(object, groupId), + type: InjectedScript.CallFrameProxy._scopeTypeNames[type], }; -} + if (name) + scope.name = name; + if (location) + scope.location = location; -function slice(array, index) -{ - var result = []; - for (var i = index || 0; i < array.length; ++i) - result.push(array[i]); - return result; + return scope; } -function bind(func, thisObject, var_args) + +function bind(func, thisObject, ...outerArgs) { - var args = slice(arguments, 2); - return function(var_args) { - return func.apply(thisObject, args.concat(slice(arguments))); - } + return function(...innerArgs) { + return func.apply(thisObject, outerArgs.concat(innerArgs)); + }; } -function BasicCommandLineAPI() +function BasicCommandLineAPI(callFrame) { this.$_ = injectedScript._lastResult; this.$exception = injectedScript._exceptionValue; // $1-$99 - for (var i = 1; i <= injectedScript._savedResults.length; ++i) { - var member = "$" + i; - if (member in inspectedGlobalObject) - continue; + for (let i = 1; i <= injectedScript._savedResults.length; ++i) this.__defineGetter__("$" + i, bind(injectedScript._savedResult, injectedScript, i)); - } + + // Command Line API methods. + for (let method of BasicCommandLineAPI.methods) + this[method.name] = method; } +BasicCommandLineAPI.methods = [ + function dir() { return inspectedGlobalObject.console.dir(...arguments); }, + function clear() { return inspectedGlobalObject.console.clear(...arguments); }, + function table() { return inspectedGlobalObject.console.table(...arguments); }, + function profile() { return inspectedGlobalObject.console.profile(...arguments); }, + function profileEnd() { return inspectedGlobalObject.console.profileEnd(...arguments); }, + + function keys(object) { return Object.keys(object); }, + function values(object) { + let result = []; + for (let key in object) + result.push(object[key]); + return result; + }, +]; + +for (let method of BasicCommandLineAPI.methods) + method.toString = function() { return "function " + method.name + "() { [Command Line API] }"; }; + return injectedScript; }) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorAgentBase.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorAgentBase.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorAgentBase.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorAgentBase.h 2016-11-03 07:04:20.000000000 +0000 @@ -24,8 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorAgentBase_h -#define InspectorAgentBase_h +#pragma once #include @@ -83,5 +82,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorAgentBase_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorAgentRegistry.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorAgentRegistry.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorAgentRegistry.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorAgentRegistry.h 2016-11-03 07:04:20.000000000 +0000 @@ -24,8 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorAgentRegistry_h -#define InspectorAgentRegistry_h +#pragma once #include #include @@ -66,5 +65,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorAgentRegistry_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -192,7 +192,7 @@ // The JSON-RPC 2.0 specification requires that the "error" member have the value 'null' // if no error occurred during an invocation, but we do not include it at all. Ref responseMessage = InspectorObject::create(); - responseMessage->setObject(ASCIILiteral("result"), result); + responseMessage->setObject(ASCIILiteral("result"), WTFMove(result)); responseMessage->setInteger(ASCIILiteral("id"), requestId); m_frontendRouter->sendResponse(responseMessage->toJSONString()); } @@ -212,7 +212,7 @@ // To construct the error object, only use the last error's code and message. // Per JSON-RPC 2.0, Section 5.1, the 'data' member may contain nested errors, // but only one top-level Error object should be sent per request. - CommonErrorCode errorCode; + CommonErrorCode errorCode = InternalError; String errorMessage; Ref payload = InspectorArray::create(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h 2016-09-19 12:18:06.000000000 +0000 @@ -24,8 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorBackendDispatcher_h -#define InspectorBackendDispatcher_h +#pragma once #include "InspectorFrontendRouter.h" #include "InspectorProtocolTypes.h" @@ -39,7 +38,7 @@ typedef String ErrorString; -class SupplementalBackendDispatcher : public RefCounted { +class JS_EXPORT_PRIVATE SupplementalBackendDispatcher : public RefCounted { public: SupplementalBackendDispatcher(BackendDispatcher&); virtual ~SupplementalBackendDispatcher(); @@ -48,9 +47,9 @@ Ref m_backendDispatcher; }; -class BackendDispatcher : public RefCounted { +class JS_EXPORT_PRIVATE BackendDispatcher : public RefCounted { public: - JS_EXPORT_PRIVATE static Ref create(Ref&&); + static Ref create(Ref&&); class JS_EXPORT_PRIVATE CallbackBase : public RefCounted { public: @@ -82,15 +81,16 @@ }; void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*); - JS_EXPORT_PRIVATE void dispatch(const String& message); + void dispatch(const String& message); - JS_EXPORT_PRIVATE void sendResponse(long requestId, RefPtr&& result); - JS_EXPORT_PRIVATE void sendPendingErrors(); + void sendResponse(long requestId, RefPtr&& result); + void sendPendingErrors(); void reportProtocolError(CommonErrorCode, const String& errorMessage); - JS_EXPORT_PRIVATE void reportProtocolError(Optional relatedRequestId, CommonErrorCode, const String& errorMessage); + void reportProtocolError(Optional relatedRequestId, CommonErrorCode, const String& errorMessage); template + WTF_HIDDEN_DECLARATION T getPropertyValue(InspectorObject*, const String& name, bool* out_optionalValueFound, T defaultValue, std::function, const char* typeName); int getInteger(InspectorObject*, const String& name, bool* valueFound); @@ -118,5 +118,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorBackendDispatcher_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorEnvironment.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorEnvironment.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorEnvironment.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorEnvironment.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorEnvironment_h -#define InspectorEnvironment_h +#pragma once #include "CallData.h" @@ -58,5 +57,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorEnvironment_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorFrontendChannel.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorFrontendChannel.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorFrontendChannel.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorFrontendChannel.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorFrontendChannel_h -#define InspectorFrontendChannel_h +#pragma once #include @@ -47,5 +46,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorFrontendChannel_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorFrontendRouter.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorFrontendRouter.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorFrontendRouter.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorFrontendRouter.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorFrontendRouter_h -#define InspectorFrontendRouter_h +#pragma once #include #include @@ -55,5 +54,3 @@ }; } // namespace Inspector - -#endif // !defined(InspectorFrontendRouter_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorProtocolTypes.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorProtocolTypes.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorProtocolTypes.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorProtocolTypes.h 2016-09-19 12:18:06.000000000 +0000 @@ -24,8 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorProtocolTypes_h -#define InspectorProtocolTypes_h +#pragma once #include "InspectorValues.h" #include @@ -179,5 +178,3 @@ using Protocol::BindingTraits; } // namespace Inspector - -#endif // !defined(InspectorProtocolTypes_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorValues.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorValues.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorValues.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorValues.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -363,17 +363,17 @@ result = InspectorValue::null(); break; case BOOL_TRUE: - result = InspectorBasicValue::create(true); + result = InspectorValue::create(true); break; case BOOL_FALSE: - result = InspectorBasicValue::create(false); + result = InspectorValue::create(false); break; case NUMBER: { bool ok; double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok); if (!ok) return nullptr; - result = InspectorBasicValue::create(value); + result = InspectorValue::create(value); break; } case STRING: { @@ -381,7 +381,7 @@ bool ok = decodeString(tokenStart + 1, tokenEnd - 1, value); if (!ok) return nullptr; - result = InspectorString::create(value); + result = InspectorValue::create(value); break; } case ARRAY_BEGIN: { @@ -459,7 +459,7 @@ return nullptr; } *valueTokenEnd = tokenEnd; - return result.release(); + return result; } inline bool escapeChar(UChar c, StringBuilder& dst) @@ -498,59 +498,39 @@ } // anonymous namespace -bool InspectorValue::asBoolean(bool&) const -{ - return false; -} - -bool InspectorValue::asDouble(double&) const -{ - return false; -} - -bool InspectorValue::asDouble(float&) const -{ - return false; -} - -bool InspectorValue::asInteger(int&) const -{ - return false; -} - -bool InspectorValue::asInteger(unsigned&) const +Ref InspectorValue::null() { - return false; + return adoptRef(*new InspectorValue); } -bool InspectorValue::asInteger(long&) const +Ref InspectorValue::create(bool value) { - return false; + return adoptRef(*new InspectorValue(value)); } -bool InspectorValue::asInteger(long long&) const +Ref InspectorValue::create(int value) { - return false; + return adoptRef(*new InspectorValue(value)); } -bool InspectorValue::asInteger(unsigned long&) const +Ref InspectorValue::create(double value) { - return false; + return adoptRef(*new InspectorValue(value)); } -bool InspectorValue::asInteger(unsigned long long&) const +Ref InspectorValue::create(const String& value) { - return false; + return adoptRef(*new InspectorValue(value)); } -bool InspectorValue::asString(String&) const +Ref InspectorValue::create(const char* value) { - return false; + return adoptRef(*new InspectorValue(value)); } -bool InspectorValue::asValue(RefPtr& output) +bool InspectorValue::asValue(RefPtr & value) { - output = this; + value = this; return true; } @@ -571,11 +551,11 @@ const UChar* start = characters; const UChar* end = start + jsonInput.length(); const UChar* tokenEnd; - RefPtr result = buildValue(start, end, &tokenEnd, 0); + auto result = buildValue(start, end, &tokenEnd, 0); if (!result || tokenEnd != end) return false; - output = result.release(); + output = WTFMove(result); return true; } @@ -587,110 +567,119 @@ return result.toString(); } -void InspectorValue::writeJSON(StringBuilder& output) const -{ - ASSERT(m_type == Type::Null); - - output.appendLiteral("null"); -} - -bool InspectorBasicValue::asBoolean(bool& output) const +bool InspectorValue::asBoolean(bool& output) const { if (type() != Type::Boolean) return false; - output = m_booleanValue; + output = m_value.boolean; return true; } -bool InspectorBasicValue::asDouble(double& output) const +bool InspectorValue::asDouble(double& output) const { if (type() != Type::Double) return false; - output = m_doubleValue; + output = m_value.number; return true; } -bool InspectorBasicValue::asDouble(float& output) const +bool InspectorValue::asDouble(float& output) const { if (type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -bool InspectorBasicValue::asInteger(int& output) const +bool InspectorValue::asInteger(int& output) const { if (type() != Type::Integer && type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -bool InspectorBasicValue::asInteger(unsigned& output) const +bool InspectorValue::asInteger(unsigned& output) const { if (type() != Type::Integer && type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -bool InspectorBasicValue::asInteger(long& output) const +bool InspectorValue::asInteger(long& output) const { if (type() != Type::Integer && type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -bool InspectorBasicValue::asInteger(long long& output) const +bool InspectorValue::asInteger(long long& output) const { if (type() != Type::Integer && type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -bool InspectorBasicValue::asInteger(unsigned long& output) const +bool InspectorValue::asInteger(unsigned long& output) const { if (type() != Type::Integer && type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -bool InspectorBasicValue::asInteger(unsigned long long& output) const +bool InspectorValue::asInteger(unsigned long long& output) const { if (type() != Type::Integer && type() != Type::Double) return false; - output = static_cast(m_doubleValue); + output = static_cast(m_value.number); return true; } -void InspectorBasicValue::writeJSON(StringBuilder& output) const +bool InspectorValue::asString(String& output) const { - ASSERT(type() == Type::Boolean || type() == Type::Double || type() == Type::Integer); + if (type() != Type::String) + return false; - if (type() == Type::Boolean) { - if (m_booleanValue) + output = m_value.string; + return true; +} + +void InspectorValue::writeJSON(StringBuilder& output) const +{ + switch (m_type) { + case Type::Null: + output.appendLiteral("null"); + break; + case Type::Boolean: + if (m_value.boolean) output.appendLiteral("true"); else output.appendLiteral("false"); - } else if (type() == Type::Double || type() == Type::Integer) { + break; + case Type::String: + doubleQuoteString(m_value.string, output); + break; + case Type::Double: + case Type::Integer: { NumberToLStringBuffer buffer; - if (!std::isfinite(m_doubleValue)) { + if (!std::isfinite(m_value.number)) { output.appendLiteral("null"); return; } - DecimalNumber decimal = m_doubleValue; + DecimalNumber decimal = m_value.number; unsigned length = 0; if (decimal.bufferLengthForStringDecimal() > WTF::NumberToStringBufferLength) { // Not enough room for decimal. Use exponential format. @@ -703,19 +692,11 @@ } else length = decimal.toStringDecimal(buffer, WTF::NumberToStringBufferLength); output.append(buffer, length); + break; + } + default: + ASSERT_NOT_REACHED(); } -} - -bool InspectorString::asString(String& output) const -{ - output = m_stringValue; - return true; -} - -void InspectorString::writeJSON(StringBuilder& output) const -{ - ASSERT(type() == Type::String); - doubleQuoteString(m_stringValue, output); } InspectorObjectBase::~InspectorObjectBase() @@ -775,8 +756,8 @@ bool InspectorObjectBase::getValue(const String& name, RefPtr& output) const { - Dictionary::const_iterator findResult = m_data.find(name); - if (findResult == m_data.end()) + Dictionary::const_iterator findResult = m_map.find(name); + if (findResult == m_map.end()) return false; output = findResult->value; @@ -785,7 +766,7 @@ void InspectorObjectBase::remove(const String& name) { - m_data.remove(name); + m_map.remove(name); m_order.removeFirst(name); } @@ -793,8 +774,8 @@ { output.append('{'); for (size_t i = 0; i < m_order.size(); ++i) { - auto findResult = m_data.find(m_order[i]); - ASSERT(findResult != m_data.end()); + auto findResult = m_map.find(m_order[i]); + ASSERT(findResult != m_map.end()); if (i) output.append(','); doubleQuoteString(findResult->key, output); @@ -805,8 +786,8 @@ } InspectorObjectBase::InspectorObjectBase() - : InspectorValue(Type::Object) - , m_data() + : Inspector::InspectorValue(Type::Object) + , m_map() , m_order() { } @@ -825,8 +806,8 @@ void InspectorArrayBase::writeJSON(StringBuilder& output) const { output.append('['); - for (Vector>::const_iterator it = m_data.begin(); it != m_data.end(); ++it) { - if (it != m_data.begin()) + for (Vector>::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (it != m_map.begin()) output.append(','); (*it)->writeJSON(output); } @@ -835,14 +816,14 @@ InspectorArrayBase::InspectorArrayBase() : InspectorValue(Type::Array) - , m_data() + , m_map() { } RefPtr InspectorArrayBase::get(size_t index) const { - ASSERT_WITH_SECURITY_IMPLICATION(index < m_data.size()); - return m_data[index]; + ASSERT_WITH_SECURITY_IMPLICATION(index < m_map.size()); + return m_map[index]; } Ref InspectorObject::create() @@ -855,34 +836,4 @@ return adoptRef(*new InspectorArray); } -Ref InspectorValue::null() -{ - return adoptRef(*new InspectorValue); -} - -Ref InspectorString::create(const String& value) -{ - return adoptRef(*new InspectorString(value)); -} - -Ref InspectorString::create(const char* value) -{ - return adoptRef(*new InspectorString(value)); -} - -Ref InspectorBasicValue::create(bool value) -{ - return adoptRef(*new InspectorBasicValue(value)); -} - -Ref InspectorBasicValue::create(int value) -{ - return adoptRef(*new InspectorBasicValue(value)); -} - -Ref InspectorBasicValue::create(double value) -{ - return adoptRef(*new InspectorBasicValue(value)); -} - } // namespace Inspector diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorValues.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorValues.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/InspectorValues.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/InspectorValues.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InspectorValues_h -#define InspectorValues_h +#pragma once #include "JSExportMacros.h" #include @@ -51,11 +50,30 @@ public: static const int maxDepth = 1000; - InspectorValue() - : m_type(Type::Null) { } - virtual ~InspectorValue() { } + virtual ~InspectorValue() + { + switch (m_type) { + case Type::Null: + case Type::Boolean: + case Type::Double: + case Type::Integer: + break; + case Type::String: + if (m_value.string) + m_value.string->deref(); + break; + case Type::Object: + case Type::Array: + break; + } + } static Ref null(); + static Ref create(bool); + static Ref create(int); + static Ref create(double); + static Ref create(const String&); + static Ref create(const char*); enum class Type { Null = 0, @@ -64,24 +82,24 @@ Integer, String, Object, - Array + Array, }; Type type() const { return m_type; } - bool isNull() const { return m_type == Type::Null; } - virtual bool asBoolean(bool&) const; - virtual bool asInteger(int&) const; - virtual bool asInteger(unsigned&) const; - virtual bool asInteger(long&) const; - virtual bool asInteger(long long&) const; - virtual bool asInteger(unsigned long&) const; - virtual bool asInteger(unsigned long long&) const; - virtual bool asDouble(double&) const; - virtual bool asDouble(float&) const; - virtual bool asString(String&) const; - virtual bool asValue(RefPtr&); + bool asBoolean(bool&) const; + bool asInteger(int&) const; + bool asInteger(unsigned&) const; + bool asInteger(long&) const; + bool asInteger(long long&) const; + bool asInteger(unsigned long&) const; + bool asInteger(unsigned long long&) const; + bool asDouble(double&) const; + bool asDouble(float&) const; + bool asString(String&) const; + bool asValue(RefPtr&); + virtual bool asObject(RefPtr&); virtual bool asArray(RefPtr&); @@ -91,71 +109,54 @@ virtual void writeJSON(StringBuilder& output) const; protected: - explicit InspectorValue(Type type) : m_type(type) { } - -private: - Type m_type; -}; - -class JS_EXPORT_PRIVATE InspectorBasicValue : public InspectorValue { -public: - - static Ref create(bool); - static Ref create(int); - static Ref create(double); - - virtual bool asBoolean(bool&) const override; - // Numbers from the frontend are always parsed as doubles, so we allow - // clients to convert to integral values with this function. - virtual bool asInteger(int&) const override; - virtual bool asInteger(unsigned&) const override; - virtual bool asInteger(long&) const override; - virtual bool asInteger(long long&) const override; - virtual bool asInteger(unsigned long&) const override; - virtual bool asInteger(unsigned long long&) const override; - virtual bool asDouble(double&) const override; - virtual bool asDouble(float&) const override; + InspectorValue() + : m_type(Type::Null) { } - virtual void writeJSON(StringBuilder& output) const override; + explicit InspectorValue(Type type) + : m_type(type) { } -private: - explicit InspectorBasicValue(bool value) - : InspectorValue(Type::Boolean) - , m_booleanValue(value) { } - - explicit InspectorBasicValue(int value) - : InspectorValue(Type::Integer) - , m_doubleValue(static_cast(value)) { } - - explicit InspectorBasicValue(double value) - : InspectorValue(Type::Double) - , m_doubleValue(value) { } + explicit InspectorValue(bool value) + : m_type(Type::Boolean) + { + m_value.boolean = value; + } - union { - bool m_booleanValue; - double m_doubleValue; - }; -}; + explicit InspectorValue(int value) + : m_type(Type::Integer) + { + m_value.number = static_cast(value); + } -class JS_EXPORT_PRIVATE InspectorString : public InspectorValue { -public: - static Ref create(const String&); - static Ref create(const char*); + explicit InspectorValue(double value) + : m_type(Type::Double) + { + m_value.number = value; + } - virtual bool asString(String& output) const override; + explicit InspectorValue(const String& value) + : m_type(Type::String) + { + m_value.string = value.impl(); + if (m_value.string) + m_value.string->ref(); + } - virtual void writeJSON(StringBuilder& output) const override; + explicit InspectorValue(const char* value) + : m_type(Type::String) + { + String wrapper(value); + m_value.string = wrapper.impl(); + if (m_value.string) + m_value.string->ref(); + } private: - explicit InspectorString(const String& value) - : InspectorValue(Type::String) - , m_stringValue(value) { } - - explicit InspectorString(const char* value) - : InspectorValue(Type::String) - , m_stringValue(value) { } - - String m_stringValue; + Type m_type { Type::Null }; + union { + bool boolean; + double number; + StringImpl* string; + } m_value; }; class JS_EXPORT_PRIVATE InspectorObjectBase : public InspectorValue { @@ -171,7 +172,7 @@ protected: virtual ~InspectorObjectBase(); - virtual bool asObject(RefPtr& output) override; + bool asObject(RefPtr& output) override; // FIXME: use templates to reduce the amount of duplicated set*() methods. void setBoolean(const String& name, bool); @@ -211,20 +212,20 @@ void remove(const String& name); - virtual void writeJSON(StringBuilder& output) const override; + void writeJSON(StringBuilder& output) const override; - iterator begin() { return m_data.begin(); } - iterator end() { return m_data.end(); } - const_iterator begin() const { return m_data.begin(); } - const_iterator end() const { return m_data.end(); } + iterator begin() { return m_map.begin(); } + iterator end() { return m_map.end(); } + const_iterator begin() const { return m_map.begin(); } + const_iterator end() const { return m_map.end(); } - int size() const { return m_data.size(); } + int size() const { return m_map.size(); } protected: InspectorObjectBase(); private: - Dictionary m_data; + Dictionary m_map; Vector m_order; }; @@ -265,12 +266,12 @@ typedef Vector>::iterator iterator; typedef Vector>::const_iterator const_iterator; - unsigned length() const { return static_cast(m_data.size()); } + unsigned length() const { return static_cast(m_map.size()); } protected: virtual ~InspectorArrayBase(); - virtual bool asArray(RefPtr&) override; + bool asArray(RefPtr&) override; void pushBoolean(bool); void pushInteger(int); @@ -282,18 +283,18 @@ RefPtr get(size_t index) const; - virtual void writeJSON(StringBuilder& output) const override; + void writeJSON(StringBuilder& output) const override; - iterator begin() { return m_data.begin(); } - iterator end() { return m_data.end(); } - const_iterator begin() const { return m_data.begin(); } - const_iterator end() const { return m_data.end(); } + iterator begin() { return m_map.begin(); } + iterator end() { return m_map.end(); } + const_iterator begin() const { return m_map.begin(); } + const_iterator end() const { return m_map.end(); } protected: InspectorArrayBase(); private: - Vector> m_data; + Vector> m_map; }; class InspectorArray : public InspectorArrayBase { @@ -319,93 +320,91 @@ inline InspectorObjectBase::iterator InspectorObjectBase::find(const String& name) { - return m_data.find(name); + return m_map.find(name); } inline InspectorObjectBase::const_iterator InspectorObjectBase::find(const String& name) const { - return m_data.find(name); + return m_map.find(name); } inline void InspectorObjectBase::setBoolean(const String& name, bool value) { - setValue(name, InspectorBasicValue::create(value)); + setValue(name, InspectorValue::create(value)); } inline void InspectorObjectBase::setInteger(const String& name, int value) { - setValue(name, InspectorBasicValue::create(value)); + setValue(name, InspectorValue::create(value)); } inline void InspectorObjectBase::setDouble(const String& name, double value) { - setValue(name, InspectorBasicValue::create(value)); + setValue(name, InspectorValue::create(value)); } inline void InspectorObjectBase::setString(const String& name, const String& value) { - setValue(name, InspectorString::create(value)); + setValue(name, InspectorValue::create(value)); } inline void InspectorObjectBase::setValue(const String& name, RefPtr&& value) { ASSERT(value); - if (m_data.set(name, WTFMove(value)).isNewEntry) + if (m_map.set(name, WTFMove(value)).isNewEntry) m_order.append(name); } inline void InspectorObjectBase::setObject(const String& name, RefPtr&& value) { ASSERT(value); - if (m_data.set(name, WTFMove(value)).isNewEntry) + if (m_map.set(name, WTFMove(value)).isNewEntry) m_order.append(name); } inline void InspectorObjectBase::setArray(const String& name, RefPtr&& value) { ASSERT(value); - if (m_data.set(name, WTFMove(value)).isNewEntry) + if (m_map.set(name, WTFMove(value)).isNewEntry) m_order.append(name); } inline void InspectorArrayBase::pushBoolean(bool value) { - m_data.append(InspectorBasicValue::create(value)); + m_map.append(InspectorValue::create(value)); } inline void InspectorArrayBase::pushInteger(int value) { - m_data.append(InspectorBasicValue::create(value)); + m_map.append(InspectorValue::create(value)); } inline void InspectorArrayBase::pushDouble(double value) { - m_data.append(InspectorBasicValue::create(value)); + m_map.append(InspectorValue::create(value)); } inline void InspectorArrayBase::pushString(const String& value) { - m_data.append(InspectorString::create(value)); + m_map.append(InspectorValue::create(value)); } inline void InspectorArrayBase::pushValue(RefPtr&& value) { ASSERT(value); - m_data.append(WTFMove(value)); + m_map.append(WTFMove(value)); } inline void InspectorArrayBase::pushObject(RefPtr&& value) { ASSERT(value); - m_data.append(WTFMove(value)); + m_map.append(WTFMove(value)); } inline void InspectorArrayBase::pushArray(RefPtr&& value) { ASSERT(value); - m_data.append(WTFMove(value)); + m_map.append(WTFMove(value)); } } // namespace Inspector - -#endif // !defined(InspectorValues_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JavaScriptCallFrame_h -#define JavaScriptCallFrame_h +#pragma once #include "JSCJSValueInlines.h" #include "debugger/DebuggerCallFrame.h" @@ -53,9 +52,10 @@ JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); } JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame->scope(); } JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); } + bool isTailDeleted() const { return m_debuggerCallFrame->isTailDeleted(); } JSC::JSValue thisValue() const { return m_debuggerCallFrame->thisValue(); } - JSC::JSValue evaluate(const String& script, NakedPtr& exception) const { return m_debuggerCallFrame->evaluate(script, exception); } + JSC::JSValue evaluateWithScopeExtension(const String& script, JSC::JSObject* scopeExtension, NakedPtr& exception) const { return m_debuggerCallFrame->evaluateWithScopeExtension(script, scopeExtension, exception); } private: JavaScriptCallFrame(PassRefPtr); @@ -65,5 +65,3 @@ }; } // namespace Inspector - -#endif // JavaScriptCallFrame_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -28,6 +28,8 @@ #include "ConsoleMessage.h" #include "InspectorConsoleAgent.h" +#include "InspectorDebuggerAgent.h" +#include "InspectorScriptProfilerAgent.h" #include "ScriptArguments.h" #include "ScriptCallStack.h" #include "ScriptCallStackFactory.h" @@ -52,9 +54,11 @@ sLogToSystemConsole = shouldLog; } -JSGlobalObjectConsoleClient::JSGlobalObjectConsoleClient(InspectorConsoleAgent* consoleAgent) +JSGlobalObjectConsoleClient::JSGlobalObjectConsoleClient(InspectorConsoleAgent* consoleAgent, InspectorDebuggerAgent* debuggerAgent, InspectorScriptProfilerAgent* scriptProfilerAgent) : ConsoleClient() , m_consoleAgent(consoleAgent) + , m_debuggerAgent(debuggerAgent) + , m_scriptProfilerAgent(scriptProfilerAgent) { } @@ -73,14 +77,76 @@ m_consoleAgent->count(exec, arguments); } -void JSGlobalObjectConsoleClient::profile(JSC::ExecState*, const String&) +void JSGlobalObjectConsoleClient::profile(JSC::ExecState*, const String& title) { - // FIXME: support |console.profile| for JSContexts. + if (!m_consoleAgent->enabled()) + return; + + // Allow duplicate unnamed profiles. Disallow duplicate named profiles. + if (!title.isEmpty()) { + for (auto& existingTitle : m_profiles) { + if (existingTitle == title) { + // FIXME: Send an enum to the frontend for localization? + String warning = title.isEmpty() ? ASCIILiteral("Unnamed Profile already exists") : makeString("Profile \"", title, "\" already exists"); + m_consoleAgent->addMessageToConsole(std::make_unique(MessageSource::ConsoleAPI, MessageType::Profile, MessageLevel::Warning, warning)); + return; + } + } + } + + m_profiles.append(title); + startConsoleProfile(); +} + +void JSGlobalObjectConsoleClient::profileEnd(JSC::ExecState*, const String& title) +{ + if (!m_consoleAgent->enabled()) + return; + + // Stop profiles in reverse order. If the title is empty, then stop the last profile. + // Otherwise, match the title of the profile to stop. + for (ptrdiff_t i = m_profiles.size() - 1; i >= 0; --i) { + if (title.isEmpty() || m_profiles[i] == title) { + m_profiles.remove(i); + if (m_profiles.isEmpty()) + stopConsoleProfile(); + return; + } + } + + // FIXME: Send an enum to the frontend for localization? + String warning = title.isEmpty() ? ASCIILiteral("No profiles exist") : makeString("Profile \"", title, "\" does not exist"); + m_consoleAgent->addMessageToConsole(std::make_unique(MessageSource::ConsoleAPI, MessageType::ProfileEnd, MessageLevel::Warning, warning)); +} + +void JSGlobalObjectConsoleClient::startConsoleProfile() +{ + // FIXME: Generalize the concept of Instruments on the backend to work equally for JSContext and Web inspection + m_scriptProfilerAgent->programmaticCaptureStarted(); + + m_profileRestoreBreakpointActiveValue = m_debuggerAgent->breakpointsActive(); + + ErrorString unused; + m_debuggerAgent->setBreakpointsActive(unused, false); + + const bool includeSamples = true; + m_scriptProfilerAgent->startTracking(unused, &includeSamples); +} + +void JSGlobalObjectConsoleClient::stopConsoleProfile() +{ + ErrorString unused; + m_scriptProfilerAgent->stopTracking(unused); + + m_debuggerAgent->setBreakpointsActive(unused, m_profileRestoreBreakpointActiveValue); + + // FIXME: Generalize the concept of Instruments on the backend to work equally for JSContext and Web inspection + m_scriptProfilerAgent->programmaticCaptureStopped(); } -void JSGlobalObjectConsoleClient::profileEnd(JSC::ExecState*, const String&) +void JSGlobalObjectConsoleClient::takeHeapSnapshot(JSC::ExecState*, const String& title) { - // FIXME: support |console.profile| for JSContexts. + m_consoleAgent->takeHeapSnapshot(title); } void JSGlobalObjectConsoleClient::time(ExecState*, const String& title) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h 2016-09-16 09:56:47.000000000 +0000 @@ -23,40 +23,49 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSGlobalObjectConsoleClient_h -#define JSGlobalObjectConsoleClient_h +#pragma once #include "ConsoleClient.h" +#include +#include namespace Inspector { class InspectorConsoleAgent; +class InspectorDebuggerAgent; +class InspectorScriptProfilerAgent; class JSGlobalObjectConsoleClient final : public JSC::ConsoleClient { WTF_MAKE_FAST_ALLOCATED; public: - explicit JSGlobalObjectConsoleClient(InspectorConsoleAgent*); + explicit JSGlobalObjectConsoleClient(InspectorConsoleAgent*, InspectorDebuggerAgent*, InspectorScriptProfilerAgent*); virtual ~JSGlobalObjectConsoleClient() { } static bool logToSystemConsole(); static void setLogToSystemConsole(bool); protected: - virtual void messageWithTypeAndLevel(MessageType, MessageLevel, JSC::ExecState*, RefPtr&&) override; - virtual void count(JSC::ExecState*, RefPtr&&) override; - virtual void profile(JSC::ExecState*, const String& title) override; - virtual void profileEnd(JSC::ExecState*, const String& title) override; - virtual void time(JSC::ExecState*, const String& title) override; - virtual void timeEnd(JSC::ExecState*, const String& title) override; - virtual void timeStamp(JSC::ExecState*, RefPtr&&) override; + void messageWithTypeAndLevel(MessageType, MessageLevel, JSC::ExecState*, RefPtr&&) override; + void count(JSC::ExecState*, RefPtr&&) override; + void profile(JSC::ExecState*, const String& title) override; + void profileEnd(JSC::ExecState*, const String& title) override; + void takeHeapSnapshot(JSC::ExecState*, const String& title) override; + void time(JSC::ExecState*, const String& title) override; + void timeEnd(JSC::ExecState*, const String& title) override; + void timeStamp(JSC::ExecState*, RefPtr&&) override; private: void warnUnimplemented(const String& method); void internalAddMessage(MessageType, MessageLevel, JSC::ExecState*, RefPtr&&); + void startConsoleProfile(); + void stopConsoleProfile(); + InspectorConsoleAgent* m_consoleAgent; + InspectorDebuggerAgent* m_debuggerAgent; + InspectorScriptProfilerAgent* m_scriptProfilerAgent; + Vector m_profiles; + bool m_profileRestoreBreakpointActiveValue { false }; }; } - -#endif // !defined(JSGlobalObjectConsoleClient_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -38,6 +38,7 @@ #include "InspectorFrontendRouter.h" #include "InspectorHeapAgent.h" #include "InspectorScriptProfilerAgent.h" +#include "JSCInlines.h" #include "JSGlobalObject.h" #include "JSGlobalObjectConsoleAgent.h" #include "JSGlobalObjectConsoleClient.h" @@ -48,8 +49,8 @@ #include "ScriptCallStackFactory.h" #include -#include #if OS(DARWIN) || (OS(LINUX) && !PLATFORM(GTK)) +#include #include #include #endif @@ -85,31 +86,37 @@ auto inspectorAgent = std::make_unique(context); auto runtimeAgent = std::make_unique(context); - auto consoleAgent = std::make_unique(context); + auto heapAgent = std::make_unique(context); + auto consoleAgent = std::make_unique(context, heapAgent.get()); auto debuggerAgent = std::make_unique(context, consoleAgent.get()); + auto scriptProfilerAgent = std::make_unique(context); m_inspectorAgent = inspectorAgent.get(); m_debuggerAgent = debuggerAgent.get(); m_consoleAgent = consoleAgent.get(); - m_consoleClient = std::make_unique(m_consoleAgent); + m_consoleClient = std::make_unique(m_consoleAgent, m_debuggerAgent, scriptProfilerAgent.get()); m_agents.append(WTFMove(inspectorAgent)); m_agents.append(WTFMove(runtimeAgent)); m_agents.append(WTFMove(consoleAgent)); m_agents.append(WTFMove(debuggerAgent)); - m_agents.append(std::make_unique(context)); - m_agents.append(std::make_unique(context)); + m_agents.append(WTFMove(heapAgent)); + m_agents.append(WTFMove(scriptProfilerAgent)); m_executionStopwatch->start(); } JSGlobalObjectInspectorController::~JSGlobalObjectInspectorController() { +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + if (m_augmentingClient) + m_augmentingClient->inspectorControllerDestroyed(); +#endif } void JSGlobalObjectInspectorController::globalObjectDestroyed() { - disconnectAllFrontends(); + ASSERT(!m_frontendRouter->hasFrontends()); m_injectedScriptManager->disconnect(); } @@ -126,6 +133,10 @@ if (!connectedFirstFrontend) return; + // Keep the JSGlobalObject and VM alive while we are debugging it. + m_strongVM = &m_globalObject.vm(); + m_strongGlobalObject.set(m_globalObject.vm(), &m_globalObject); + // FIXME: change this to notify agents which frontend has connected (by id). m_agents.didCreateFrontendAndBackend(nullptr, nullptr); @@ -156,21 +167,10 @@ if (m_augmentingClient) m_augmentingClient->inspectorDisconnected(); #endif -} - -void JSGlobalObjectInspectorController::disconnectAllFrontends() -{ - // FIXME: change this to notify agents which frontend has disconnected (by id). - m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectedTargetDestroyed); - - m_frontendRouter->disconnectAllFrontends(); - m_isAutomaticInspection = false; - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - if (m_augmentingClient) - m_augmentingClient->inspectorDisconnected(); -#endif + // Remove our JSGlobalObject and VM references, we are done debugging it. + m_strongGlobalObject.clear(); + m_strongVM = nullptr; } void JSGlobalObjectInspectorController::dispatchMessageFromFrontend(const String& message) @@ -206,9 +206,9 @@ if (mangledName) cxaDemangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, nullptr); if (mangledName || cxaDemangled) - callStack->append(ScriptCallFrame(cxaDemangled ? cxaDemangled : mangledName, ASCIILiteral("[native code]"), 0, 0)); + callStack->append(ScriptCallFrame(cxaDemangled ? cxaDemangled : mangledName, ASCIILiteral("[native code]"), noSourceID, 0, 0)); else - callStack->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), 0, 0)); + callStack->append(ScriptCallFrame(ASCIILiteral("?"), ASCIILiteral("[native code]"), noSourceID, 0, 0)); free(cxaDemangled); } #else @@ -309,4 +309,3 @@ #endif } // namespace Inspector - diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectInspectorController.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSGlobalObjectInspectorController_h -#define JSGlobalObjectInspectorController_h +#pragma once #include "InspectorAgentRegistry.h" #include "InspectorEnvironment.h" @@ -43,7 +42,6 @@ class Exception; class ExecState; class JSGlobalObject; -class JSValue; } namespace Inspector { @@ -54,7 +52,6 @@ class InspectorAgent; class InspectorConsoleAgent; class InspectorDebuggerAgent; -class InspectorHeapAgent; class InspectorScriptProfilerAgent; class JSGlobalObjectConsoleClient; class ScriptCallStack; @@ -73,7 +70,6 @@ void connectFrontend(FrontendChannel*, bool isAutomaticInspection); void disconnectFrontend(FrontendChannel*); - void disconnectAllFrontends(); void dispatchMessageFromFrontend(const String&); @@ -87,22 +83,22 @@ JSC::ConsoleClient* consoleClient() const; - virtual bool developerExtrasEnabled() const override; - virtual bool canAccessInspectedScriptState(JSC::ExecState*) const override { return true; } - virtual InspectorFunctionCallHandler functionCallHandler() const override; - virtual InspectorEvaluateHandler evaluateHandler() const override; - virtual void frontendInitialized() override; - virtual Ref executionStopwatch() override; - virtual JSGlobalObjectScriptDebugServer& scriptDebugServer() override; - virtual JSC::VM& vm() override; + bool developerExtrasEnabled() const override; + bool canAccessInspectedScriptState(JSC::ExecState*) const override { return true; } + InspectorFunctionCallHandler functionCallHandler() const override; + InspectorEvaluateHandler evaluateHandler() const override; + void frontendInitialized() override; + Ref executionStopwatch() override; + JSGlobalObjectScriptDebugServer& scriptDebugServer() override; + JSC::VM& vm() override; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - virtual AugmentableInspectorControllerClient* augmentableInspectorControllerClient() const override { return m_augmentingClient; } - virtual void setAugmentableInspectorControllerClient(AugmentableInspectorControllerClient* client) override { m_augmentingClient = client; } + AugmentableInspectorControllerClient* augmentableInspectorControllerClient() const override { return m_augmentingClient; } + void setAugmentableInspectorControllerClient(AugmentableInspectorControllerClient* client) override { m_augmentingClient = client; } - virtual const FrontendRouter& frontendRouter() const override { return m_frontendRouter.get(); } - virtual BackendDispatcher& backendDispatcher() override { return m_backendDispatcher.get(); } - virtual void appendExtraAgent(std::unique_ptr) override; + const FrontendRouter& frontendRouter() const override { return m_frontendRouter.get(); } + BackendDispatcher& backendDispatcher() override { return m_backendDispatcher.get(); } + void appendExtraAgent(std::unique_ptr) override; #endif private: @@ -122,6 +118,10 @@ Ref m_frontendRouter; Ref m_backendDispatcher; + // Used to keep the JSGlobalObject and VM alive while we are debugging it. + JSC::Strong m_strongGlobalObject; + RefPtr m_strongVM; + bool m_includeNativeCallStackWithExceptions { true }; bool m_isAutomaticInspection { false }; @@ -131,5 +131,3 @@ }; } // namespace Inspector - -#endif // !defined(JSGlobalObjectInspectorController_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -43,7 +43,6 @@ void JSGlobalObjectScriptDebugServer::attachDebugger() { attach(&m_globalObject); - recompileAllJSFunctions(); } void JSGlobalObjectScriptDebugServer::detachDebugger(bool isBeingDestroyed) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSGlobalObjectScriptDebugServer.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSGlobalObjectScriptDebugServer_h -#define JSGlobalObjectScriptDebugServer_h +#pragma once #include "ScriptDebugServer.h" @@ -39,22 +38,20 @@ JSC::JSGlobalObject& globalObject() const { return m_globalObject; } private: - virtual void attachDebugger() override; - virtual void detachDebugger(bool isBeingDestroyed) override; + void attachDebugger() override; + void detachDebugger(bool isBeingDestroyed) override; - virtual void didPause(JSC::JSGlobalObject*) override { } - virtual void didContinue(JSC::JSGlobalObject*) override { } - virtual void runEventLoopWhilePaused() override; - virtual bool isContentScript(JSC::ExecState*) const override { return false; } + void didPause(JSC::JSGlobalObject*) override { } + void didContinue(JSC::JSGlobalObject*) override { } + void runEventLoopWhilePaused() override; + bool isContentScript(JSC::ExecState*) const override { return false; } // NOTE: Currently all exceptions are reported at the API boundary through reportAPIException. // Until a time comes where an exception can be caused outside of the API (e.g. setTimeout // or some other async operation in a pure JSContext) we can ignore exceptions reported here. - virtual void reportException(JSC::ExecState*, JSC::Exception*) const override { } + void reportException(JSC::ExecState*, JSC::Exception*) const override { } JSC::JSGlobalObject& m_globalObject; }; } // namespace Inspector - -#endif // JSGlobalObjectScriptDebugServer_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,16 +26,18 @@ #include "config.h" #include "JSInjectedScriptHost.h" +#include "BuiltinNames.h" +#include "Completion.h" #include "DateInstance.h" #include "DirectArguments.h" #include "Error.h" #include "InjectedScriptHost.h" #include "IteratorOperations.h" #include "JSArray.h" -#include "JSArrayIterator.h" #include "JSBoundFunction.h" #include "JSCInlines.h" #include "JSFunction.h" +#include "JSGlobalObjectFunctions.h" #include "JSInjectedScriptHostPrototype.h" #include "JSMap.h" #include "JSMapIterator.h" @@ -47,7 +49,9 @@ #include "JSTypedArrays.h" #include "JSWeakMap.h" #include "JSWeakSet.h" +#include "JSWithScope.h" #include "ObjectConstructor.h" +#include "ProxyObject.h" #include "RegExpObject.h" #include "ScopedArguments.h" #include "SourceCode.h" @@ -89,6 +93,28 @@ return globalObject->evalFunction(); } +JSValue JSInjectedScriptHost::evaluateWithScopeExtension(ExecState* exec) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue scriptValue = exec->argument(0); + if (!scriptValue.isString()) + return throwTypeError(exec, scope, ASCIILiteral("InjectedScriptHost.evaluateWithScopeExtension first argument must be a string.")); + + String program = scriptValue.toString(exec)->value(exec); + if (exec->hadException()) + return jsUndefined(); + + NakedPtr exception; + JSObject* scopeExtension = exec->argument(1).getObject(); + JSValue result = JSC::evaluateWithScopeExtension(exec, makeSource(program), scopeExtension, exception); + if (exception) + throwException(exec, scope, exception); + + return result; +} + JSValue JSInjectedScriptHost::internalConstructorName(ExecState* exec) { if (exec->argumentCount() < 1) @@ -152,13 +178,15 @@ if (value.inherits(JSWeakSet::info())) return jsNontrivialString(exec, ASCIILiteral("weakset")); - if (value.inherits(JSArrayIterator::info()) - || value.inherits(JSMapIterator::info()) + if (value.inherits(JSMapIterator::info()) || value.inherits(JSSetIterator::info()) || value.inherits(JSStringIterator::info()) || value.inherits(JSPropertyNameIterator::info())) return jsNontrivialString(exec, ASCIILiteral("iterator")); + if (object && object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) + return jsNontrivialString(exec, ASCIILiteral("iterator")); + if (value.inherits(JSInt8Array::info()) || value.inherits(JSInt16Array::info()) || value.inherits(JSInt32Array::info())) return jsNontrivialString(exec, ASCIILiteral("array")); if (value.inherits(JSUint8Array::info()) || value.inherits(JSUint16Array::info()) || value.inherits(JSUint32Array::info())) @@ -193,22 +221,23 @@ if (columnNumber) columnNumber -= 1; + VM& vm = exec->vm(); String scriptID = String::number(sourceCode->provider()->asID()); JSObject* location = constructEmptyObject(exec); - location->putDirect(exec->vm(), Identifier::fromString(exec, "scriptId"), jsString(exec, scriptID)); - location->putDirect(exec->vm(), Identifier::fromString(exec, "lineNumber"), jsNumber(lineNumber)); - location->putDirect(exec->vm(), Identifier::fromString(exec, "columnNumber"), jsNumber(columnNumber)); + location->putDirect(vm, Identifier::fromString(exec, "scriptId"), jsString(exec, scriptID)); + location->putDirect(vm, Identifier::fromString(exec, "lineNumber"), jsNumber(lineNumber)); + location->putDirect(vm, Identifier::fromString(exec, "columnNumber"), jsNumber(columnNumber)); JSObject* result = constructEmptyObject(exec); - result->putDirect(exec->vm(), Identifier::fromString(exec, "location"), location); + result->putDirect(vm, Identifier::fromString(exec, "location"), location); - String name = function->name(exec); + String name = function->name(vm); if (!name.isEmpty()) - result->putDirect(exec->vm(), Identifier::fromString(exec, "name"), jsString(exec, name)); + result->putDirect(vm, Identifier::fromString(exec, "name"), jsString(exec, name)); - String displayName = function->displayName(exec); + String displayName = function->displayName(vm); if (!displayName.isEmpty()) - result->putDirect(exec->vm(), Identifier::fromString(exec, "displayName"), jsString(exec, displayName)); + result->putDirect(vm, Identifier::fromString(exec, "displayName"), jsString(exec, displayName)); // FIXME: provide function scope data in "scopesRaw" property when JSC supports it. // [JSC] expose function (closure) inner context to debugger @@ -229,11 +258,14 @@ if (exec->argumentCount() < 1) return jsUndefined(); + VM& vm = exec->vm(); JSValue value = exec->uncheckedArgument(0); if (JSPromise* promise = jsDynamicCast(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr); + if (UNLIKELY(vm.exception())) + return jsUndefined(); switch (promise->status(exec->vm())) { case JSPromise::Status::Pending: array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("status"), jsNontrivialString(exec, ASCIILiteral("pending")))); @@ -253,48 +285,58 @@ if (JSBoundFunction* boundFunction = jsDynamicCast(value)) { unsigned index = 0; - JSArray* array = constructEmptyArray(exec, nullptr, 3); + JSArray* array = constructEmptyArray(exec, nullptr); + if (UNLIKELY(vm.exception())) + return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "targetFunction", boundFunction->targetFunction())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundThis", boundFunction->boundThis())); - array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundArgs", boundFunction->boundArgs())); + if (boundFunction->boundArgs()) + array->putDirectIndex(exec, index++, constructInternalProperty(exec, "boundArgs", boundFunction->boundArgs())); return array; } - if (JSArrayIterator* arrayIterator = jsDynamicCast(value)) { - String kind; - switch (arrayIterator->kind(exec)) { - case ArrayIterateKey: - kind = ASCIILiteral("key"); - break; - case ArrayIterateValue: - kind = ASCIILiteral("value"); - break; - case ArrayIterateKeyValue: - kind = ASCIILiteral("key+value"); - break; - } + if (ProxyObject* proxy = jsDynamicCast(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); - array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", arrayIterator->iteratedValue(exec))); - array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); + if (UNLIKELY(vm.exception())) + return jsUndefined(); + array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("target"), proxy->target())); + array->putDirectIndex(exec, index++, constructInternalProperty(exec, ASCIILiteral("handler"), proxy->handler())); return array; } + if (JSObject* iteratorObject = jsDynamicCast(value)) { + if (iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) { + JSValue iteratedValue = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().iteratedObjectPrivateName()); + JSValue kind = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorKindPrivateName()); + + unsigned index = 0; + JSArray* array = constructEmptyArray(exec, nullptr, 2); + if (UNLIKELY(vm.exception())) + return jsUndefined(); + array->putDirectIndex(exec, index++, constructInternalProperty(exec, "array", iteratedValue)); + array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", kind)); + return array; + } + } + if (JSMapIterator* mapIterator = jsDynamicCast(value)) { String kind; switch (mapIterator->kind()) { - case MapIterateKey: + case IterateKey: kind = ASCIILiteral("key"); break; - case MapIterateValue: + case IterateValue: kind = ASCIILiteral("value"); break; - case MapIterateKeyValue: + case IterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); + if (UNLIKELY(vm.exception())) + return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; @@ -303,18 +345,20 @@ if (JSSetIterator* setIterator = jsDynamicCast(value)) { String kind; switch (setIterator->kind()) { - case SetIterateKey: + case IterateKey: kind = ASCIILiteral("key"); break; - case SetIterateValue: + case IterateValue: kind = ASCIILiteral("value"); break; - case SetIterateKeyValue: + case IterateKeyValue: kind = ASCIILiteral("key+value"); break; } unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 2); + if (UNLIKELY(vm.exception())) + return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue())); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind))); return array; @@ -323,6 +367,8 @@ if (JSStringIterator* stringIterator = jsDynamicCast(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 1); + if (UNLIKELY(vm.exception())) + return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "string", stringIterator->iteratedValue(exec))); return array; } @@ -330,6 +376,8 @@ if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast(value)) { unsigned index = 0; JSArray* array = constructEmptyArray(exec, nullptr, 1); + if (UNLIKELY(vm.exception())) + return jsUndefined(); array->putDirectIndex(exec, index++, constructInternalProperty(exec, "object", propertyNameIterator->iteratedValue())); return array; } @@ -355,6 +403,7 @@ if (exec->argumentCount() < 1) return jsUndefined(); + VM& vm = exec->vm(); JSValue value = exec->uncheckedArgument(0); JSWeakMap* weakMap = jsDynamicCast(value); if (!weakMap) @@ -369,6 +418,8 @@ numberToFetch = static_cast(fetchDouble); JSArray* array = constructEmptyArray(exec, nullptr); + if (UNLIKELY(vm.exception())) + return jsUndefined(); for (auto it = weakMap->weakMapData()->begin(); it != weakMap->weakMapData()->end(); ++it) { JSObject* entry = constructEmptyObject(exec); entry->putDirect(exec->vm(), Identifier::fromString(exec, "key"), it->key); @@ -399,6 +450,7 @@ if (exec->argumentCount() < 1) return jsUndefined(); + VM& vm = exec->vm(); JSValue value = exec->uncheckedArgument(0); JSWeakSet* weakSet = jsDynamicCast(value); if (!weakSet) @@ -413,6 +465,8 @@ numberToFetch = static_cast(fetchDouble); JSArray* array = constructEmptyArray(exec, nullptr); + if (UNLIKELY(vm.exception())) + return jsUndefined(); for (auto it = weakSet->weakMapData()->begin(); it != weakSet->weakMapData()->end(); ++it) { JSObject* entry = constructEmptyObject(exec); entry->putDirect(exec->vm(), Identifier::fromString(exec, "value"), it->key); @@ -424,24 +478,44 @@ return array; } +static JSObject* cloneArrayIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSValue nextIndex) +{ + ASSERT(iteratorObject->type() == FinalObjectType); + JSObject* clone = constructEmptyObject(exec, iteratorObject->structure()); + clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName(), nextIndex); + clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName())); + clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorIsDonePrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorIsDonePrivateName())); + clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName())); + return clone; +} + JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec) { if (exec->argumentCount() < 1) return jsUndefined(); + VM& vm = exec->vm(); JSValue iterator; JSValue value = exec->uncheckedArgument(0); - if (JSArrayIterator* arrayIterator = jsDynamicCast(value)) - iterator = arrayIterator->clone(exec); - else if (JSMapIterator* mapIterator = jsDynamicCast(value)) + if (JSMapIterator* mapIterator = jsDynamicCast(value)) iterator = mapIterator->clone(exec); else if (JSSetIterator* setIterator = jsDynamicCast(value)) iterator = setIterator->clone(exec); else if (JSStringIterator* stringIterator = jsDynamicCast(value)) iterator = stringIterator->clone(exec); - else if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast(value)) + else if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast(value)) { iterator = propertyNameIterator->clone(exec); - else + if (UNLIKELY(vm.exception())) + return JSValue(); + } else { + if (JSObject* iteratorObject = jsDynamicCast(value)) { + // Array Iterators are created in JS for performance reasons. Thus the only way to know we have one is to + // look for a property that is unique to them. + if (JSValue nextIndex = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) + iterator = cloneArrayIteratorObject(exec, vm, iteratorObject, nextIndex); + } + } + if (!iterator) return jsUndefined(); unsigned numberToFetch = 5; @@ -451,16 +525,18 @@ numberToFetch = static_cast(fetchDouble); JSArray* array = constructEmptyArray(exec, nullptr); + if (UNLIKELY(vm.exception())) + return jsUndefined(); for (unsigned i = 0; i < numberToFetch; ++i) { JSValue next = iteratorStep(exec, iterator); - if (exec->hadException()) + if (UNLIKELY(vm.exception())) break; if (next.isFalse()) break; JSValue nextValue = iteratorValue(exec, next); - if (exec->hadException()) + if (UNLIKELY(vm.exception())) break; JSObject* entry = constructEmptyObject(exec); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSInjectedScriptHost_h -#define JSInjectedScriptHost_h +#pragma once #include "JSDestructibleObject.h" @@ -60,6 +59,7 @@ JSC::JSValue evaluate(JSC::ExecState*) const; // Functions. + JSC::JSValue evaluateWithScopeExtension(JSC::ExecState*); JSC::JSValue internalConstructorName(JSC::ExecState*); JSC::JSValue isHTMLAllCollection(JSC::ExecState*); JSC::JSValue subtype(JSC::ExecState*); @@ -81,5 +81,3 @@ }; } // namespace Inspector - -#endif // !defined(JSInjectedScriptHost_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,6 +48,7 @@ static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakSetSize(ExecState*); static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakSetEntries(ExecState*); static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIteratorEntries(ExecState*); +static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionEvaluateWithScopeExtension(ExecState*); static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeEvaluate(ExecState*); @@ -69,132 +70,164 @@ JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("weakSetSize", jsInjectedScriptHostPrototypeFunctionWeakSetSize, DontEnum, 1); JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("weakSetEntries", jsInjectedScriptHostPrototypeFunctionWeakSetEntries, DontEnum, 1); JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("iteratorEntries", jsInjectedScriptHostPrototypeFunctionIteratorEntries, DontEnum, 1); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluateWithScopeExtension", jsInjectedScriptHostPrototypeFunctionEvaluateWithScopeExtension, DontEnum, 1); - Identifier evaluateIdentifier = Identifier::fromString(&vm, "evaluate"); - GetterSetter* accessor = GetterSetter::create(vm, globalObject); - JSFunction* function = JSFunction::create(vm, globalObject, 0, evaluateIdentifier.string(), jsInjectedScriptHostPrototypeAttributeEvaluate); - accessor->setGetter(vm, globalObject, function); - putDirectNonIndexAccessor(vm, evaluateIdentifier, accessor, DontEnum | Accessor); + JSC_NATIVE_GETTER("evaluate", jsInjectedScriptHostPrototypeAttributeEvaluate, DontEnum | Accessor); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeEvaluate(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->evaluate(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionInternalConstructorName(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->internalConstructorName(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->isHTMLAllCollection(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMapSize(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->weakMapSize(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMapEntries(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->weakMapEntries(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakSetSize(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->weakSetSize(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakSetEntries(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->weakSetEntries(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIteratorEntries(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->iteratorEntries(exec)); } +EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionEvaluateWithScopeExtension(ExecState* exec) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue thisValue = exec->thisValue(); + JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); + if (!castedThis) + return throwVMTypeError(exec, scope); + + return JSValue::encode(castedThis->evaluateWithScopeExtension(exec)); +} + EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionSubtype(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->subtype(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionFunctionDetails(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->functionDetails(exec)); } EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionGetInternalProperties(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSInjectedScriptHost* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSInjectedScriptHost::info()); return JSValue::encode(castedThis->getInternalProperties(exec)); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSInjectedScriptHostPrototype_h -#define JSInjectedScriptHostPrototype_h +#pragma once #include "JSObject.h" @@ -58,5 +57,3 @@ }; } // namespace Inspector - -#endif // !defined(JSInjectedScriptHostPrototype_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,10 +28,10 @@ #include "DebuggerScope.h" #include "Error.h" -#include "JSCJSValue.h" -#include "JSCellInlines.h" +#include "IdentifierInlines.h" +#include "JSCInlines.h" #include "JSJavaScriptCallFramePrototype.h" -#include "StructureInlines.h" +#include "ObjectConstructor.h" using namespace JSC; @@ -73,55 +73,80 @@ releaseImpl(); } -JSValue JSJavaScriptCallFrame::evaluate(ExecState* exec) +JSValue JSJavaScriptCallFrame::evaluateWithScopeExtension(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue scriptValue = exec->argument(0); + if (!scriptValue.isString()) + return throwTypeError(exec, scope, ASCIILiteral("JSJavaScriptCallFrame.evaluateWithScopeExtension first argument must be a string.")); + + String script = scriptValue.toString(exec)->value(exec); + if (exec->hadException()) + return jsUndefined(); + NakedPtr exception; - JSValue result = impl().evaluate(exec->argument(0).toString(exec)->value(exec), exception); + JSObject* scopeExtension = exec->argument(1).getObject(); + JSValue result = impl().evaluateWithScopeExtension(script, scopeExtension, exception); if (exception) - exec->vm().throwException(exec, exception); + throwException(exec, scope, exception); return result; } -JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec) +static JSValue valueForScopeType(DebuggerScope* scope) { - if (!impl().scopeChain()) - return jsUndefined(); + if (scope->isCatchScope()) + return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE); + if (scope->isFunctionNameScope()) + return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE); + if (scope->isWithScope()) + return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); + if (scope->isNestedLexicalScope()) + return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE); + if (scope->isGlobalLexicalEnvironment()) + return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE); + if (scope->isGlobalScope()) + return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); - if (!exec->argument(0).isInt32()) - return jsUndefined(); - int index = exec->argument(0).asInt32(); + ASSERT(scope->isClosureScope()); + return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); +} + +static JSValue valueForScopeLocation(ExecState* exec, const DebuggerLocation& location) +{ + if (location.sourceID == noSourceID) + return jsNull(); + + // Debugger.Location protocol object. + JSObject* result = constructEmptyObject(exec); + result->putDirect(exec->vm(), Identifier::fromString(exec, "scriptId"), jsString(exec, String::number(location.sourceID))); + result->putDirect(exec->vm(), Identifier::fromString(exec, "lineNumber"), jsNumber(location.line)); + result->putDirect(exec->vm(), Identifier::fromString(exec, "columnNumber"), jsNumber(location.column)); + return result; +} +JSValue JSJavaScriptCallFrame::scopeDescriptions(ExecState* exec) +{ DebuggerScope* scopeChain = impl().scopeChain(); - DebuggerScope::iterator end = scopeChain->end(); + if (!scopeChain) + return jsUndefined(); + + int index = 0; + JSArray* array = constructEmptyArray(exec, nullptr); + DebuggerScope::iterator end = scopeChain->end(); for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) { DebuggerScope* scope = iter.get(); - - if (!index) { - if (scope->isCatchScope()) - return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE); - if (scope->isFunctionNameScope()) - return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE); - if (scope->isWithScope()) - return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); - if (scope->isNestedLexicalScope()) - return jsNumber(JSJavaScriptCallFrame::NESTED_LEXICAL_SCOPE); - if (scope->isGlobalLexicalEnvironment()) - return jsNumber(JSJavaScriptCallFrame::GLOBAL_LEXICAL_ENVIRONMENT_SCOPE); - if (scope->isGlobalScope()) { - ASSERT(++iter == end); - return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); - } - ASSERT(scope->isClosureScope()); - return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); - } - - --index; + JSObject* description = constructEmptyObject(exec); + description->putDirect(exec->vm(), Identifier::fromString(exec, "type"), valueForScopeType(scope)); + description->putDirect(exec->vm(), Identifier::fromString(exec, "name"), jsString(exec, scope->name())); + description->putDirect(exec->vm(), Identifier::fromString(exec, "location"), valueForScopeLocation(exec, scope->location())); + array->putDirectIndex(exec, index++, description); } - ASSERT_NOT_REACHED(); - return jsUndefined(); + return array; } JSValue JSJavaScriptCallFrame::caller(ExecState* exec) const @@ -175,6 +200,11 @@ return impl().thisValue(); } +JSValue JSJavaScriptCallFrame::isTailDeleted(JSC::ExecState*) const +{ + return jsBoolean(impl().isTailDeleted()); +} + JSValue JSJavaScriptCallFrame::type(ExecState* exec) const { switch (impl().type()) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSJavaScriptCallFrame_h -#define JSJavaScriptCallFrame_h +#pragma once #include "JSDestructibleObject.h" #include "JavaScriptCallFrame.h" @@ -57,8 +56,8 @@ void releaseImpl(); // Functions. - JSC::JSValue evaluate(JSC::ExecState*); - JSC::JSValue scopeType(JSC::ExecState*); + JSC::JSValue evaluateWithScopeExtension(JSC::ExecState*); + JSC::JSValue scopeDescriptions(JSC::ExecState*); // Attributes. JSC::JSValue caller(JSC::ExecState*) const; @@ -69,6 +68,7 @@ JSC::JSValue scopeChain(JSC::ExecState*) const; JSC::JSValue thisObject(JSC::ExecState*) const; JSC::JSValue type(JSC::ExecState*) const; + JSC::JSValue isTailDeleted(JSC::ExecState*) const; // Constants. static const unsigned short GLOBAL_SCOPE = 0; @@ -93,5 +93,3 @@ JSJavaScriptCallFrame* toJSJavaScriptCallFrame(JSC::JSValue); } // namespace Inspector - -#endif // !defined(JSJavaScriptCallFrame_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,8 +38,8 @@ namespace Inspector { // Functions. -static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluate(ExecState*); -static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeType(ExecState*); +static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension(ExecState*); +static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeDescriptions(ExecState*); // Attributes. static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeCaller(ExecState*); @@ -50,145 +50,171 @@ static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeScopeChain(ExecState*); static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeThisObject(ExecState*); static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeType(ExecState*); +static EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameIsTailDeleted(ExecState*); const ClassInfo JSJavaScriptCallFramePrototype::s_info = { "JavaScriptCallFrame", &Base::s_info, 0, CREATE_METHOD_TABLE(JSJavaScriptCallFramePrototype) }; -#define JSC_NATIVE_NON_INDEX_ACCESSOR(jsName, cppName, attributes) \ - { \ - Identifier identifier = Identifier::fromString(&vm, jsName); \ - GetterSetter* accessor = GetterSetter::create(vm, globalObject); \ - JSFunction* function = JSFunction::create(vm, globalObject, 0, identifier.string(), cppName); \ - accessor->setGetter(vm, globalObject, function); \ - putDirectNonIndexAccessor(vm, identifier, accessor, (attributes)); \ - } - void JSJavaScriptCallFramePrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) { Base::finishCreation(vm); ASSERT(inherits(info())); vm.prototypeMap.addPrototype(this); - JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluate", jsJavaScriptCallFramePrototypeFunctionEvaluate, DontEnum, 1); - JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scopeType", jsJavaScriptCallFramePrototypeFunctionScopeType, DontEnum, 1); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluateWithScopeExtension", jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension, DontEnum, 1); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("scopeDescriptions", jsJavaScriptCallFramePrototypeFunctionScopeDescriptions, DontEnum, 0); - JSC_NATIVE_NON_INDEX_ACCESSOR("caller", jsJavaScriptCallFrameAttributeCaller, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("sourceID", jsJavaScriptCallFrameAttributeSourceID, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("line", jsJavaScriptCallFrameAttributeLine, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("column", jsJavaScriptCallFrameAttributeColumn, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("functionName", jsJavaScriptCallFrameAttributeFunctionName, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("scopeChain", jsJavaScriptCallFrameAttributeScopeChain, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("thisObject", jsJavaScriptCallFrameAttributeThisObject, DontEnum | Accessor); - JSC_NATIVE_NON_INDEX_ACCESSOR("type", jsJavaScriptCallFrameAttributeType, DontEnum | Accessor); + JSC_NATIVE_GETTER("caller", jsJavaScriptCallFrameAttributeCaller, DontEnum | Accessor); + JSC_NATIVE_GETTER("sourceID", jsJavaScriptCallFrameAttributeSourceID, DontEnum | Accessor); + JSC_NATIVE_GETTER("line", jsJavaScriptCallFrameAttributeLine, DontEnum | Accessor); + JSC_NATIVE_GETTER("column", jsJavaScriptCallFrameAttributeColumn, DontEnum | Accessor); + JSC_NATIVE_GETTER("functionName", jsJavaScriptCallFrameAttributeFunctionName, DontEnum | Accessor); + JSC_NATIVE_GETTER("scopeChain", jsJavaScriptCallFrameAttributeScopeChain, DontEnum | Accessor); + JSC_NATIVE_GETTER("thisObject", jsJavaScriptCallFrameAttributeThisObject, DontEnum | Accessor); + JSC_NATIVE_GETTER("type", jsJavaScriptCallFrameAttributeType, DontEnum | Accessor); + JSC_NATIVE_GETTER("isTailDeleted", jsJavaScriptCallFrameIsTailDeleted, DontEnum | Accessor); } -EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluate(ExecState* exec) +EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionEvaluateWithScopeExtension(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); - return JSValue::encode(castedThis->evaluate(exec)); + return JSValue::encode(castedThis->evaluateWithScopeExtension(exec)); } -EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeType(ExecState* exec) +EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFramePrototypeFunctionScopeDescriptions(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); - return JSValue::encode(castedThis->scopeType(exec)); + return JSValue::encode(castedThis->scopeDescriptions(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeCaller(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->caller(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeSourceID(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->sourceID(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeLine(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->line(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeColumn(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->column(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeFunctionName(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->functionName(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeScopeChain(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->scopeChain(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeThisObject(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->thisObject(exec)); } EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameAttributeType(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue thisValue = exec->thisValue(); JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); if (!castedThis) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); - ASSERT_GC_OBJECT_INHERITS(castedThis, JSJavaScriptCallFrame::info()); return JSValue::encode(castedThis->type(exec)); } +EncodedJSValue JSC_HOST_CALL jsJavaScriptCallFrameIsTailDeleted(ExecState* exec) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue thisValue = exec->thisValue(); + JSJavaScriptCallFrame* castedThis = jsDynamicCast(thisValue); + if (!castedThis) + return throwVMTypeError(exec, scope); + + return JSValue::encode(castedThis->isTailDeleted(exec)); +} + } // namespace Inspector diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/JSJavaScriptCallFramePrototype.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSJavaScriptCallFramePrototype_h -#define JSJavaScriptCallFramePrototype_h +#pragma once #include "JSObject.h" @@ -58,5 +57,3 @@ }; } // namespace Inspector - -#endif // !defined(JSJavaScriptCallFramePrototype_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/PerGlobalObjectWrapperWorld.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/PerGlobalObjectWrapperWorld.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/PerGlobalObjectWrapperWorld.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/PerGlobalObjectWrapperWorld.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PerGlobalObjectWrapperWorld_h -#define PerGlobalObjectWrapperWorld_h +#pragma once #include "JSCJSValueInlines.h" #include "Strong.h" @@ -44,5 +43,3 @@ }; } // namespace Inspector - -#endif // !defined(PerGlobalObjectWrapperWorld_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Console.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Console.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Console.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Console.json 2016-09-16 09:56:47.000000000 +0000 @@ -27,6 +27,7 @@ "properties": [ { "name": "functionName", "type": "string", "description": "JavaScript function name." }, { "name": "url", "type": "string", "description": "JavaScript script name or url." }, + { "name": "scriptId", "$ref": "Debugger.ScriptId", "description": "Script identifier." }, { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." }, { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." } ] @@ -84,6 +85,15 @@ { "name": "messagesCleared", "description": "Issued when console is cleared. This happens either upon clearMessages command or after page navigation." + }, + { + "name": "heapSnapshot", + "description": "Issued from console.takeHeapSnapshot.", + "parameters": [ + { "name": "timestamp", "type": "number" }, + { "name": "snapshotData", "$ref": "Heap.HeapSnapshotData", "description": "Snapshot at the end of tracking." }, + { "name": "title", "type": "string", "optional": true, "description": "Optional title provided to console.takeHeapSnapshot." } + ] } ] } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Debugger.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Debugger.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Debugger.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Debugger.json 2016-11-03 07:04:20.000000000 +0000 @@ -60,7 +60,6 @@ { "name": "location", "$ref": "Location", "description": "Location of the function." }, { "name": "name", "type": "string", "optional": true, "description": "Name of the function. Not present for anonymous functions." }, { "name": "displayName", "type": "string", "optional": true, "description": "Display name of the function(specified in 'displayName' property on the function object)." }, - { "name": "inferredName", "type": "string", "optional": true, "description": "Name of the function inferred from its initial assignment." }, { "name": "scopeChain", "type": "array", "optional": true, "items": { "$ref": "Scope" }, "description": "Scope chain for this closure." } ], "description": "Information about the function." @@ -73,7 +72,8 @@ { "name": "functionName", "type": "string", "description": "Name of the JavaScript function called on this call frame." }, { "name": "location", "$ref": "Location", "description": "Location in the source code." }, { "name": "scopeChain", "type": "array", "items": { "$ref": "Scope" }, "description": "Scope chain for this call frame." }, - { "name": "this", "$ref": "Runtime.RemoteObject", "description": "this object for this call frame." } + { "name": "this", "$ref": "Runtime.RemoteObject", "description": "this object for this call frame." }, + { "name": "isTailDeleted", "type": "boolean", "description": "Is the current frame tail deleted from a tail call." } ], "description": "JavaScript call frame. Array of call frames form the call stack." }, @@ -81,8 +81,10 @@ "id": "Scope", "type": "object", "properties": [ + { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For global and with scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." }, { "name": "type", "type": "string", "enum": ["global", "with", "closure", "catch", "functionName", "globalLexicalEnvironment", "nestedLexical"], "description": "Scope type." }, - { "name": "object", "$ref": "Runtime.RemoteObject", "description": "Object representing the scope. For global and with scopes it represents the actual object; for the rest of the scopes, it is artificial transient object enumerating scope variables as its properties." } + { "name": "name", "type": "string", "optional": true, "description": "Name associated with the scope." }, + { "name": "location", "$ref": "Location", "optional": true, "description": "Location if available of the scope definition." } ], "description": "Scope description." }, @@ -276,14 +278,14 @@ "name": "scriptParsed", "parameters": [ { "name": "scriptId", "$ref": "ScriptId", "description": "Identifier of the script parsed." }, - { "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." }, + { "name": "url", "type": "string", "description": "URL of the script parsed (if any)." }, { "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." }, { "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." }, { "name": "endLine", "type": "integer", "description": "Last line of the script." }, { "name": "endColumn", "type": "integer", "description": "Length of the last line of the script." }, { "name": "isContentScript", "type": "boolean", "optional": true, "description": "Determines whether this script is a user extension script." }, - { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." }, - { "name": "hasSourceURL", "type": "boolean", "optional": true, "description": "True, if this script has sourceURL." } + { "name": "sourceURL", "type": "string", "optional": true, "description": "sourceURL name of the script (if any)." }, + { "name": "sourceMapURL", "type": "string", "optional": true, "description": "URL of source map associated with script (if any)." } ], "description": "Fired when virtual machine parses script. This event is also fired for all known and uncollected scripts upon enabling debugger." }, diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/DOM.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/DOM.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/DOM.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/DOM.json 2016-11-03 07:04:20.000000000 +0000 @@ -20,6 +20,12 @@ "description": "Pseudo element type." }, { + "id": "ShadowRootType", + "type": "string", + "enum": ["user-agent", "open", "closed"], + "description": "Shadow root type." + }, + { "id": "LiveRegionRelevant", "type": "string", "enum": ["additions", "removals", "text"], @@ -41,17 +47,18 @@ { "name": "baseURL", "type": "string", "optional": true, "description": "Base URL that Document or FrameOwner node uses for URL completion." }, { "name": "publicId", "type": "string", "optional": true, "description": "DocumentType's publicId." }, { "name": "systemId", "type": "string", "optional": true, "description": "DocumentType's systemId." }, - { "name": "internalSubset", "type": "string", "optional": true, "description": "DocumentType's internalSubset." }, { "name": "xmlVersion", "type": "string", "optional": true, "description": "Document's XML version in case of XML documents." }, { "name": "name", "type": "string", "optional": true, "description": "Attr's name." }, { "name": "value", "type": "string", "optional": true, "description": "Attr's value." }, { "name": "pseudoType", "$ref": "PseudoType", "optional": true, "description": "Pseudo element type for this node." }, + { "name": "shadowRootType", "$ref": "ShadowRootType", "optional": true, "description": "Shadow root type." }, { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Frame ID for frame owner elements." }, { "name": "contentDocument", "$ref": "Node", "optional": true, "description": "Content document for frame owner elements." }, { "name": "shadowRoots", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Shadow root list for given element host." }, { "name": "templateContent", "$ref": "Node", "optional": true, "description": "Content document fragment for template elements" }, { "name": "pseudoElements", "type": "array", "items": { "$ref": "Node" }, "optional": true, "description": "Pseudo elements associated with this node." }, - { "name": "role", "type": "string", "optional": true, "description": "Computed value for first recognized role token, default role per element, or overridden role." } + { "name": "role", "type": "string", "optional": true, "description": "Computed value for first recognized role token, default role per element, or overridden role." }, + { "name": "contentSecurityPolicyHash", "type": "string", "optional": true, "description": "Computed SHA-256 Content Security Policy hash source for given element." } ], "description": "DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes. DOMNode is a base node mirror type." }, diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Heap.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Heap.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Heap.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Heap.json 2016-09-16 09:56:47.000000000 +0000 @@ -11,6 +11,11 @@ { "name": "startTime", "type": "number" }, { "name": "endTime", "type": "number" } ] + }, + { + "id": "HeapSnapshotData", + "description": "JavaScriptCore HeapSnapshot JSON data.", + "type": "string" } ], "commands": [ @@ -25,6 +30,45 @@ { "name": "gc", "description": "Trigger a full garbage collection." + }, + { + "name": "snapshot", + "description": "Take a heap snapshot.", + "returns": [ + { "name": "timestamp", "type": "number" }, + { "name": "snapshotData", "$ref": "HeapSnapshotData" } + ] + }, + { + "name": "startTracking", + "description": "Start tracking heap changes. This will produce a `trackingStart` event." + }, + { + "name": "stopTracking", + "description": "Stop tracking heap changes. This will produce a `trackingComplete` event." + }, + { + "name": "getPreview", + "description": "Returns a preview (string, Debugger.FunctionDetails, or Runtime.ObjectPreview) for a Heap.HeapObjectId.", + "parameters": [ + { "name": "heapObjectId", "type": "integer", "description": "Identifier of the heap object within the snapshot." } + ], + "returns": [ + { "name": "string", "type": "string", "optional": true, "description": "String value." }, + { "name": "functionDetails", "$ref": "Debugger.FunctionDetails", "optional": true, "description": "Function details." }, + { "name": "preview", "$ref": "Runtime.ObjectPreview", "optional": true, "description": "Object preview." } + ] + }, + { + "name": "getRemoteObject", + "description": "Returns the strongly referenced Runtime.RemoteObject for a Heap.HeapObjectId.", + "parameters": [ + { "name": "heapObjectId", "type": "integer", "description": "Identifier of the heap object within the snapshot." }, + { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." } + ], + "returns": [ + { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Resulting object." } + ] } ], "events": [ @@ -32,7 +76,23 @@ "name": "garbageCollected", "description": "Information about the garbage collection.", "parameters": [ - { "name": "collection", "type": "GarbageCollection" } + { "name": "collection", "$ref": "GarbageCollection" } + ] + }, + { + "name": "trackingStart", + "description": "Tracking started.", + "parameters": [ + { "name": "timestamp", "type": "number" }, + { "name": "snapshotData", "$ref": "HeapSnapshotData", "description": "Snapshot at the start of tracking." } + ] + }, + { + "name": "trackingComplete", + "description": "Tracking stopped.", + "parameters": [ + { "name": "timestamp", "type": "number" }, + { "name": "snapshotData", "$ref": "HeapSnapshotData", "description": "Snapshot at the end of tracking." } ] } ] diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/IndexedDB.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/IndexedDB.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/IndexedDB.json 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/IndexedDB.json 2016-09-19 12:18:06.000000000 +0000 @@ -90,17 +90,18 @@ }, { "name": "requestDatabaseNames", + "description": "Requests database names for given security origin.", "async": true, "parameters": [ { "name": "securityOrigin", "type": "string", "description": "Security origin." } ], "returns": [ { "name": "databaseNames", "type": "array", "items": { "type": "string" }, "description": "Database names for origin." } - ], - "description": "Requests database names for given security origin." + ] }, { "name": "requestDatabase", + "description": "Requests database with given name in given frame.", "async": true, "parameters": [ { "name": "securityOrigin", "type": "string", "description": "Security origin." }, @@ -108,11 +109,11 @@ ], "returns": [ { "name": "databaseWithObjectStores", "$ref": "DatabaseWithObjectStores", "description": "Database with an array of object stores." } - ], - "description": "Requests database with given name in given frame." + ] }, { "name": "requestData", + "description": "Requests data from object store or index.", "async": true, "parameters": [ { "name": "securityOrigin", "type": "string", "description": "Security origin." }, @@ -126,20 +127,17 @@ "returns": [ { "name": "objectStoreDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of object store data entries." }, { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." } - ], - "description": "Requests data from object store or index." + ] }, { "name": "clearObjectStore", + "description": "Clears all entries from an object store.", "async": true, "parameters": [ { "name": "securityOrigin", "type": "string", "description": "Security origin." }, { "name": "databaseName", "type": "string", "description": "Database name." }, { "name": "objectStoreName", "type": "string", "description": "Object store name." } - ], - "returns": [ - ], - "description": "Clears all entries from an object store." + ] } ] } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Memory.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Memory.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Memory.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Memory.json 2016-09-16 09:56:47.000000000 +0000 @@ -23,6 +23,14 @@ ], "commands": [ { + "name": "enable", + "description": "Enables Memory domain events." + }, + { + "name": "disable", + "description": "Disables Memory domain events." + }, + { "name": "startTracking", "description": "Start tracking memory. This will produce a `trackingStart` event." }, @@ -33,6 +41,14 @@ ], "events": [ { + "name": "memoryPressure", + "description": "Memory pressure was encountered.", + "parameters": [ + { "name": "timestamp", "type": "number" }, + { "name": "severity", "type": "string", "enum": ["critical", "non-critical"], "description": "The severity of the memory pressure event." } + ] + }, + { "name": "trackingStart", "description": "Tracking started.", "parameters": [ diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Network.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Network.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Network.json 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Network.json 2016-09-19 12:18:06.000000000 +0000 @@ -33,7 +33,7 @@ "type": "object", "description": "Timing information for the request.", "properties": [ - { "name": "navigationStart", "type": "number", "description": "Timing's navigationStart is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this navigationStart." }, + { "name": "startTime", "type": "number", "description": "Timing's startTime is a baseline in seconds, while the other numbers are ticks in milliseconds relatively to this." }, { "name": "domainLookupStart", "type": "number", "description": "Started DNS address resolve." }, { "name": "domainLookupEnd", "type": "number", "description": "Finished DNS address resolve." }, { "name": "connectStart", "type": "number", "description": "Started connecting to the remote host." }, diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/OverlayTypes.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/OverlayTypes.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/OverlayTypes.json 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/OverlayTypes.json 2016-09-19 12:18:06.000000000 +0000 @@ -83,9 +83,10 @@ "properties": [ { "name": "tagName", "type": "string" }, { "name": "idValue", "type": "string", "description": "The value of the element's 'id' attribute." }, - { "name": "className", "type": "string", "optional": true }, + { "name": "classes", "type": "array", "items": { "type": "string" }, "optional": true }, { "name": "size", "$ref": "Size", "optional": true }, { "name": "role", "type": "string", "description": "Computed accessibility role for the element.", "optional": true }, + { "name": "pseudoElement", "type": "string", "optional": true }, { "name": "regionFlowData", "$ref": "RegionFlowData", "optional": true }, { "name": "contentFlowData", "$ref": "ContentFlowData", "optional": true }, { "name": "shapeOutsideData", "$ref": "ShapeOutsideData", "optional": true } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Page.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Page.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Page.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Page.json 2016-09-16 09:56:47.000000000 +0000 @@ -58,7 +58,8 @@ "properties": [ { "name": "url", "type": "string", "description": "Resource URL." }, { "name": "frameId", "$ref": "Network.FrameId", "description": "Resource frame id." }, - { "name": "matchesCount", "type": "number", "description": "Number of matches in the resource content." } + { "name": "matchesCount", "type": "number", "description": "Number of matches in the resource content." }, + { "name": "requestId", "$ref": "Network.RequestId", "optional": true, "description": "Network request id." } ] }, { @@ -164,7 +165,8 @@ { "name": "url", "type": "string", "description": "URL of the resource to search in." }, { "name": "query", "type": "string", "description": "String to search for." }, { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." }, - { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." } + { "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }, + { "name": "requestId", "$ref": "Network.RequestId", "optional": true, "description": "Request id for resource to search in." } ], "returns": [ { "name": "result", "type": "array", "items": { "$ref": "GenericTypes.SearchMatch" }, "description": "List of search matches." } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Runtime.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Runtime.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Runtime.json 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Runtime.json 2016-11-03 07:04:20.000000000 +0000 @@ -331,6 +331,14 @@ "description": "Disables type profiling on the VM." }, { + "name": "enableControlFlowProfiler", + "description": "Enables control flow profiling on the VM." + }, + { + "name": "disableControlFlowProfiler", + "description": "Disables control flow profiling on the VM." + }, + { "name": "getBasicBlocks", "parameters": [ { "name": "sourceID", "type": "string", "description": "Indicates which sourceID information is requested for." } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/ScriptProfiler.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/ScriptProfiler.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/ScriptProfiler.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/ScriptProfiler.json 2016-09-16 09:56:47.000000000 +0000 @@ -20,8 +20,8 @@ "id": "ExpressionLocation", "type": "object", "properties": [ - { "name": "line", "type": "integer" }, - { "name": "column", "type": "integer" } + { "name": "line", "type": "integer", "description": "1-based." }, + { "name": "column", "type": "integer", "description": "1-based." } ] }, { @@ -30,8 +30,8 @@ "properties": [ { "name": "sourceID", "$ref": "Debugger.ScriptId", "description": "Unique script identifier." }, { "name": "name", "type": "string", "description": "A displayable name for the stack frame. i.e function name, (program), etc." }, - { "name": "line", "type": "integer" }, - { "name": "column", "type": "integer" }, + { "name": "line", "type": "integer", "description": "-1 if unavailable. 1-based if available." }, + { "name": "column", "type": "integer", "description": "-1 if unavailable. 1-based if available." }, { "name": "url", "type": "string" }, { "name": "expressionLocation", "$ref": "ExpressionLocation", "optional": true } ] @@ -48,7 +48,6 @@ "id": "Samples", "type": "object", "properties": [ - { "name": "totalTime", "type": "number", "description": "Total execution time of the profiler's data. (Note: not total elapsed time.)" }, { "name": "stackTraces", "type": "array", "items": { "$ref": "StackTrace" } } ] } @@ -87,6 +86,14 @@ "parameters": [ { "name": "samples", "$ref": "Samples", "optional": true, "description": "Stack traces." } ] + }, + { + "name": "programmaticCaptureStarted", + "description": "Fired when programmatic capture starts (console.profile). JSContext inspection only." + }, + { + "name": "programmaticCaptureStopped", + "description": "Fired when programmatic capture stops (console.profileEnd). JSContext inspection only." } ] } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Timeline.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Timeline.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/protocol/Timeline.json 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/protocol/Timeline.json 2016-09-16 09:56:47.000000000 +0000 @@ -6,6 +6,7 @@ { "id": "EventType", "type": "string", + "description": "Timeline record type.", "enum": [ "EventDispatch", "ScheduleStyleRecalculation", @@ -28,88 +29,90 @@ "RequestAnimationFrame", "CancelAnimationFrame", "FireAnimationFrame" - ], - "description": "Timeline record type." - }, - { - "id": "TimelineEvent", - "type": "object", - "properties": [ - { "name": "type", "$ref": "EventType", "description": "Event type." }, - { "name": "data", "type": "object", "description": "Event data." }, - { "name": "children", "type": "array", "optional": true, "items": { "$ref": "TimelineEvent" }, "description": "Nested records." } - ], - "description": "Timeline record contains information about the recorded activity." - }, - { - "id": "CPUProfileNodeAggregateCallInfo", - "type": "object", - "description": "Aggregate CPU Profile call info. Holds time information for all the calls that happened on a node.", - "properties": [ - { "name": "callCount", "type": "number", "description": "Total number of calls." }, - { "name": "startTime", "type": "number", "description": "Start time for the first call." }, - { "name": "endTime", "type": "number", "description": "End time for the last call." }, - { "name": "totalTime", "type": "number", "description": "Total execution time for all calls combined." } ] }, { - "id": "CPUProfileNode", - "type": "object", - "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.", - "properties": [ - { "name": "id", "type": "integer", "description": "Unique identifier for this call site." }, - { "name": "callInfo", "$ref": "CPUProfileNodeAggregateCallInfo", "description": "Aggregate info about all the calls that making up this node." }, - { "name": "functionName", "type": "string", "optional": true, "description": "Function name." }, - { "name": "url", "type": "string", "optional": true, "description": "URL." }, - { "name": "lineNumber", "type": "integer", "optional": true, "description": "Line number." }, - { "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number." }, - { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "optional": true, "description": "Child nodes." } + "id": "Instrument", + "type": "string", + "description": "Instrument types.", + "enum": [ + "ScriptProfiler", + "Timeline", + "Memory", + "Heap" ] }, { - "id": "CPUProfile", + "id": "TimelineEvent", "type": "object", - "description": "Profile.", + "description": "Timeline record contains information about the recorded activity.", "properties": [ - { "name": "rootNodes", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Top level nodes in the stack." }, - { "name": "idleTime", "type": "number", "optional": true } + { "name": "type", "$ref": "EventType", "description": "Event type." }, + { "name": "data", "type": "object", "description": "Event data." }, + { "name": "children", "type": "array", "optional": true, "items": { "$ref": "TimelineEvent" }, "description": "Nested records." } ] } ], "commands": [ { "name": "start", + "description": "Starts capturing instrumentation events.", "parameters": [ { "name": "maxCallStackDepth", "optional": true, "type": "integer", "description": "Samples JavaScript stack traces up to maxCallStackDepth, defaults to 5." } - ], - "description": "Starts capturing instrumentation events." + ] }, { "name": "stop", "description": "Stops capturing instrumentation events." + }, + { + "name": "setAutoCaptureEnabled", + "description": "Toggle auto capture state. If true the backend will disable breakpoints and start capturing on navigation. The backend will fire the autoCaptureStarted event when an auto capture starts. The frontend should stop the auto capture when appropriate and re-enable breakpoints.", + "parameters": [ + { "name": "enabled", "type": "boolean", "description": "New auto capture state." } + ] + }, + { + "name": "setInstruments", + "description": "Instruments to enable when capture starts on the backend (e.g. auto capture or programmatic capture).", + "parameters": [ + { "name": "instruments", "type": "array", "items": { "$ref": "Instrument" }, "description": "Instruments to enable." } + ] } ], "events": [ { "name": "eventRecorded", + "description": "Fired for every instrumentation event while timeline is started.", "parameters": [ { "name": "record", "$ref": "TimelineEvent", "description": "Timeline event record data." } - ], - "description": "Fired for every instrumentation event while timeline is started." + ] }, { "name": "recordingStarted", + "description": "Fired when recording has started.", "parameters": [ { "name": "startTime", "type": "number", "description": "Start time of this new recording." } - ], - "description": "Fired when recording has started." + ] }, { "name": "recordingStopped", + "description": "Fired when recording has stopped.", "parameters": [ { "name": "endTime", "type": "number", "description": "End time of this recording." } - ], - "description": "Fired when recording has stopped." + ] + }, + { + "name": "autoCaptureStarted", + "description": "Fired when auto capture started." + }, + { + "name": "programmaticCaptureStarted", + "description": "Fired when programmatic capture starts (console.profile)." + }, + { + "name": "programmaticCaptureStopped", + "description": "Fired when programmatic capture stops (console.profileEnd)." } ] } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteAutomationTarget.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,10 +23,9 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#if ENABLE(REMOTE_INSPECTOR) +#pragma once -#ifndef RemoteAutomationTarget_h -#define RemoteAutomationTarget_h +#if ENABLE(REMOTE_INSPECTOR) #include "RemoteControllableTarget.h" #include @@ -43,8 +42,8 @@ void setIsPaired(bool); virtual String name() const = 0; - virtual RemoteControllableTarget::Type type() const override { return RemoteControllableTarget::Type::Automation; } - virtual bool remoteControlAllowed() const override { return !m_paired; }; + RemoteControllableTarget::Type type() const override { return RemoteControllableTarget::Type::Automation; } + bool remoteControlAllowed() const override { return !m_paired; }; private: bool m_paired { false }; @@ -54,6 +53,4 @@ SPECIALIZE_TYPE_TRAITS_CONTROLLABLE_TARGET(Inspector::RemoteAutomationTarget, Automation) -#endif // RemoteAutomationTarget_h - #endif // ENABLE(REMOTE_INSPECTOR) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteConnectionToTarget.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,10 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if ENABLE(REMOTE_INSPECTOR) +#pragma once -#ifndef RemoteConnectionToTarget_h -#define RemoteConnectionToTarget_h +#if ENABLE(REMOTE_INSPECTOR) #import "InspectorFrontendChannel.h" #import "RemoteConnectionToTarget.h" @@ -50,9 +49,9 @@ // Main API. bool setup(bool isAutomaticInspection = false, bool automaticallyPause = false); - virtual void sendMessageToTarget(NSString *); - virtual void close(); - virtual void targetClosed(); + void sendMessageToTarget(NSString *); + void close(); + void targetClosed(); Optional targetIdentifier() const; NSString *connectionIdentifier() const; @@ -63,8 +62,8 @@ void clearQueue() { m_queue.clear(); } // FrontendChannel overrides. - virtual ConnectionType connectionType() const override { return ConnectionType::Remote; } - virtual bool sendMessageToFrontend(const String&) override; + ConnectionType connectionType() const override { return ConnectionType::Remote; } + bool sendMessageToFrontend(const String&) override; private: void dispatchAsyncOnTarget(void (^block)()); @@ -93,6 +92,4 @@ } // namespace Inspector -#endif // RemoteConnectionToTarget_h - #endif // ENABLE(REMOTE_INSPECTOR) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteControllableTarget.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,10 +23,9 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#if ENABLE(REMOTE_INSPECTOR) +#pragma once -#ifndef RemoteControllableTarget_h -#define RemoteControllableTarget_h +#if ENABLE(REMOTE_INSPECTOR) #include #include @@ -67,6 +66,4 @@ static bool isType(const Inspector::RemoteControllableTarget& target) { return target.type() == Inspector::RemoteControllableTarget::Type::ToClassType; } \ SPECIALIZE_TYPE_TRAITS_END() -#endif // RemoteControllableTarget_h - #endif // ENABLE(REMOTE_INSPECTOR) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspectionTarget.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,10 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if ENABLE(REMOTE_INSPECTOR) +#pragma once -#ifndef RemoteInspectionTarget_h -#define RemoteInspectionTarget_h +#if ENABLE(REMOTE_INSPECTOR) #include "RemoteControllableTarget.h" #include @@ -57,7 +56,7 @@ virtual void unpauseForInitializedInspector(); // RemoteControllableTarget overrides. - virtual bool remoteControlAllowed() const override; + bool remoteControlAllowed() const override; private: bool m_allowed {false}; RetainPtr m_runLoop; @@ -73,6 +72,4 @@ } SPECIALIZE_TYPE_TRAITS_END() -#endif // RemoteInspectionTarget_h - #endif // ENABLE(REMOTE_INSPECTOR) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspectorConstants.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef RemoteInspectorConstants_h -#define RemoteInspectorConstants_h +#pragma once // WIRConstants are "Web Inspector Relay" constants shared between // the WebInspector framework on the OS X side, webinspectord, and @@ -101,5 +100,3 @@ #define WIRProxyApplicationParentAuditDataKey @"WIRProxyApplicationParentAuditData" #define WIRProxyApplicationSetupMessage @"WIRProxyApplicationSetupMessage" #define WIRProxyApplicationSetupResponseMessage @"WIRProxyApplicationSetupResponseMessage" - -#endif diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspector.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspector.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspector.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspector.h 2016-11-03 07:04:20.000000000 +0000 @@ -23,17 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if ENABLE(REMOTE_INSPECTOR) +#pragma once -#ifndef RemoteInspector_h -#define RemoteInspector_h +#if ENABLE(REMOTE_INSPECTOR) #import "RemoteInspectorXPCConnection.h" #import #import #import #import -#import OBJC_CLASS NSDictionary; OBJC_CLASS NSString; @@ -104,9 +102,9 @@ void sendAutomaticInspectionCandidateMessage(); - virtual void xpcConnectionReceivedMessage(RemoteInspectorXPCConnection*, NSString *messageName, NSDictionary *userInfo) override; - virtual void xpcConnectionFailed(RemoteInspectorXPCConnection*) override; - virtual void xpcConnectionUnhandledMessage(RemoteInspectorXPCConnection*, xpc_object_t) override; + void xpcConnectionReceivedMessage(RemoteInspectorXPCConnection*, NSString *messageName, NSDictionary *userInfo) override; + void xpcConnectionFailed(RemoteInspectorXPCConnection*) override; + void xpcConnectionUnhandledMessage(RemoteInspectorXPCConnection*, xpc_object_t) override; void receivedSetupMessage(NSDictionary *userInfo); void receivedDataMessage(NSDictionary *userInfo); @@ -152,6 +150,4 @@ } // namespace Inspector -#endif // RemoteInspector_h - #endif // ENABLE(REMOTE_INSPECTOR) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspectorXPCConnection.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspectorXPCConnection.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/remote/RemoteInspectorXPCConnection.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/remote/RemoteInspectorXPCConnection.h 2016-09-19 12:18:06.000000000 +0000 @@ -23,10 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if ENABLE(REMOTE_INSPECTOR) +#pragma once -#ifndef RemoteInspectorXPCConnection_h -#define RemoteInspectorXPCConnection_h +#if ENABLE(REMOTE_INSPECTOR) #import #import @@ -68,13 +67,11 @@ dispatch_queue_t m_queue; Client* m_client; bool m_closed { false }; -#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) +#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) bool m_validated { false }; #endif }; } // namespace Inspector -#endif // RemoteInspectorXPCConnection_h - #endif // ENABLE(REMOTE_INSPECTOR) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptArguments.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptArguments.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptArguments.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptArguments.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -42,6 +42,16 @@ return adoptRef(*new ScriptArguments(scriptState, arguments)); } +Ref ScriptArguments::createEmpty(JSC::ExecState* scriptState) +{ + return adoptRef(*new ScriptArguments(scriptState)); +} + +ScriptArguments::ScriptArguments(JSC::ExecState* execState) + : m_globalObject(execState->vm(), execState->lexicalGlobalObject()) +{ +} + ScriptArguments::ScriptArguments(JSC::ExecState* execState, Vector& arguments) : m_globalObject(execState->vm(), execState->lexicalGlobalObject()) { @@ -52,7 +62,7 @@ { } -const Deprecated::ScriptValue &ScriptArguments::argumentAt(size_t index) const +const Deprecated::ScriptValue& ScriptArguments::argumentAt(size_t index) const { ASSERT(m_arguments.size() > index); return m_arguments[index]; @@ -66,21 +76,17 @@ return nullptr; } -bool ScriptArguments::getFirstArgumentAsString(String& result, bool checkForNullOrUndefined) +bool ScriptArguments::getFirstArgumentAsString(String& result) { if (!argumentCount()) return false; - const Deprecated::ScriptValue& value = argumentAt(0); - if (checkForNullOrUndefined && (value.isNull() || value.isUndefined())) - return false; - if (!globalState()) { ASSERT_NOT_REACHED(); return false; } - result = value.toString(globalState()); + result = argumentAt(0).toString(globalState()); return true; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptArguments.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptArguments.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptArguments.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptArguments.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptArguments_h -#define ScriptArguments_h +#pragma once #include #include @@ -52,6 +51,7 @@ class JS_EXPORT_PRIVATE ScriptArguments : public RefCounted { public: static Ref create(JSC::ExecState*, Vector& arguments); + static Ref createEmpty(JSC::ExecState*); ~ScriptArguments(); const Deprecated::ScriptValue& argumentAt(size_t) const; @@ -59,10 +59,11 @@ JSC::ExecState* globalState() const; - bool getFirstArgumentAsString(String& result, bool checkForNullOrUndefined = false); + bool getFirstArgumentAsString(String& result); bool isEqual(ScriptArguments*) const; private: + ScriptArguments(JSC::ExecState*); ScriptArguments(JSC::ExecState*, Vector& arguments); JSC::Strong m_globalObject; @@ -70,5 +71,3 @@ }; } // namespace Inspector - -#endif // ScriptArguments_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptBreakpoint.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptBreakpoint.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptBreakpoint.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptBreakpoint.h 2016-09-19 12:18:06.000000000 +0000 @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptBreakpoint_h -#define ScriptBreakpoint_h +#pragma once #include #include @@ -90,5 +89,3 @@ }; } // namespace Inspector - -#endif // !defined(ScriptBreakpoint_h) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallFrame.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallFrame.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallFrame.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallFrame.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -36,9 +36,10 @@ namespace Inspector { -ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& scriptName, unsigned lineNumber, unsigned column) +ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& scriptName, JSC::SourceID sourceID, unsigned lineNumber, unsigned column) : m_functionName(functionName) , m_scriptName(scriptName) + , m_sourceID(sourceID) , m_lineNumber(lineNumber) , m_column(column) { @@ -50,6 +51,8 @@ bool ScriptCallFrame::isEqual(const ScriptCallFrame& o) const { + // Ignore sourceID in isEqual in case of identical scripts executed multiple times + // that would get different script identifiers, but are otherwise the same. return m_functionName == o.m_functionName && m_scriptName == o.m_scriptName && m_lineNumber == o.m_lineNumber @@ -61,6 +64,7 @@ return Inspector::Protocol::Console::CallFrame::create() .setFunctionName(m_functionName) .setUrl(m_scriptName) + .setScriptId(String::number(m_sourceID)) .setLineNumber(m_lineNumber) .setColumnNumber(m_column) .release(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallFrame.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallFrame.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallFrame.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallFrame.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,24 +29,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptCallFrame_h -#define ScriptCallFrame_h +#pragma once +#include "DebuggerPrimitives.h" +#include "InspectorProtocolObjects.h" #include #include -#include "InspectorProtocolObjects.h" namespace Inspector { class JS_EXPORT_PRIVATE ScriptCallFrame { public: - ScriptCallFrame(const String& functionName, const String& scriptName, unsigned lineNumber, unsigned column); + ScriptCallFrame(const String& functionName, const String& scriptName, JSC::SourceID sourceID, unsigned lineNumber, unsigned column); ~ScriptCallFrame(); const String& functionName() const { return m_functionName; } const String& sourceURL() const { return m_scriptName; } unsigned lineNumber() const { return m_lineNumber; } unsigned columnNumber() const { return m_column; } + JSC::SourceID sourceID() const { return m_sourceID; } bool isEqual(const ScriptCallFrame&) const; @@ -55,10 +56,9 @@ private: String m_functionName; String m_scriptName; + JSC::SourceID m_sourceID; unsigned m_lineNumber; unsigned m_column; }; } // namespace Inspector - -#endif // ScriptCallFrame_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * Copyright (c) 2010 Google Inc. All rights reserved. * Copyright (C) 2012 Research In Motion Limited. All rights reserved. * @@ -43,7 +43,6 @@ #include "ScriptCallStack.h" #include "ScriptValue.h" #include "StackVisitor.h" -#include #include using namespace JSC; @@ -59,7 +58,7 @@ { } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { if (m_needToSkipAFrame) { m_needToSkipAFrame = false; @@ -67,14 +66,10 @@ } if (m_remainingCapacityForFrameCapture) { -#if ENABLE(WEBASSEMBLY) - if (visitor->codeBlock()->ownerExecutable()->isWebAssemblyExecutable()) - return StackVisitor::Continue; -#endif unsigned line; unsigned column; visitor->computeLineAndColumn(line, column); - m_frames.append(ScriptCallFrame(visitor->functionName(), visitor->sourceURL(), line, column)); + m_frames.append(ScriptCallFrame(visitor->functionName(), visitor->sourceURL(), static_cast(visitor->sourceID()), line, column)); m_remainingCapacityForFrameCapture--; return StackVisitor::Continue; @@ -84,9 +79,9 @@ } private: - bool m_needToSkipAFrame; + mutable bool m_needToSkipAFrame; Vector& m_frames; - size_t m_remainingCapacityForFrameCapture; + mutable size_t m_remainingCapacityForFrameCapture; }; Ref createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize) @@ -137,29 +132,31 @@ Ref createScriptCallStackFromException(JSC::ExecState* exec, JSC::Exception* exception, size_t maxStackSize) { Vector frames; - RefCountedArray stackTrace = exception->stack(); + auto& stackTrace = exception->stack(); + VM& vm = exec->vm(); for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) { unsigned line; unsigned column; stackTrace[i].computeLineAndColumn(line, column); - String functionName = stackTrace[i].friendlyFunctionName(exec); - frames.append(ScriptCallFrame(functionName, stackTrace[i].friendlySourceURL(), line, column)); + String functionName = stackTrace[i].functionName(vm); + frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL(), static_cast(stackTrace[i].sourceID()), line, column)); } // Fallback to getting at least the line and sourceURL from the exception object if it has values and the exceptionStack doesn't. if (exception->value().isObject()) { JSObject* exceptionObject = exception->value().toObject(exec); + ASSERT(exceptionObject); int lineNumber; int columnNumber; String exceptionSourceURL; if (!frames.size()) { extractSourceInformationFromException(exec, exceptionObject, &lineNumber, &columnNumber, &exceptionSourceURL); - frames.append(ScriptCallFrame(String(), exceptionSourceURL, lineNumber, columnNumber)); + frames.append(ScriptCallFrame(String(), exceptionSourceURL, noSourceID, lineNumber, columnNumber)); } else { - if (stackTrace[0].sourceURL.isEmpty()) { + if (stackTrace[0].isNative() || stackTrace[0].sourceURL().isEmpty()) { const ScriptCallFrame& firstCallFrame = frames.first(); extractSourceInformationFromException(exec, exceptionObject, &lineNumber, &columnNumber, &exceptionSourceURL); - frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, columnNumber); + frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, stackTrace[0].sourceID(), lineNumber, columnNumber); } } } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallStackFactory.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallStackFactory.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallStackFactory.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallStackFactory.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptCallStackFactory_h -#define ScriptCallStackFactory_h +#pragma once #include @@ -52,5 +51,3 @@ JS_EXPORT_PRIVATE Ref createScriptArguments(JSC::ExecState*, unsigned skipArgumentCount); } // namespace Inspector - -#endif // ScriptCallStackFactory_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallStack.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallStack.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptCallStack.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptCallStack.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptCallStack_h -#define ScriptCallStack_h +#pragma once #include "InspectorProtocolObjects.h" #include "ScriptCallFrame.h" @@ -68,5 +67,3 @@ }; } // namespace Inspector - -#endif // ScriptCallStack_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptDebugListener.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptDebugListener.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptDebugListener.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptDebugListener.h 2016-11-03 07:04:20.000000000 +0000 @@ -27,16 +27,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptDebugListener_h -#define ScriptDebugListener_h +#pragma once #include "debugger/Debugger.h" #include -namespace Deprecated { -class ScriptValue; -} - namespace Inspector { struct ScriptBreakpointAction; @@ -59,14 +54,12 @@ virtual void didParseSource(JSC::SourceID, const Script&) = 0; virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) = 0; - virtual void didPause(JSC::ExecState*, const Deprecated::ScriptValue& callFrames, const Deprecated::ScriptValue& exception) = 0; + virtual void didPause(JSC::ExecState&, JSC::JSValue callFrames, JSC::JSValue exception) = 0; virtual void didContinue() = 0; - virtual void breakpointActionLog(JSC::ExecState*, const String&) = 0; + virtual void breakpointActionLog(JSC::ExecState&, const String&) = 0; virtual void breakpointActionSound(int breakpointActionIdentifier) = 0; - virtual void breakpointActionProbe(JSC::ExecState*, const ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, const Deprecated::ScriptValue& result) = 0; + virtual void breakpointActionProbe(JSC::ExecState&, const ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, JSC::JSValue result) = 0; }; } // namespace Inspector - -#endif // ScriptDebugListener_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -34,6 +34,7 @@ #include "DebuggerCallFrame.h" #include "DebuggerScope.h" #include "Exception.h" +#include "JSCInlines.h" #include "JSJavaScriptCallFrame.h" #include "JSLock.h" #include "JavaScriptCallFrame.h" @@ -89,28 +90,29 @@ switch (breakpointAction.type) { case ScriptBreakpointActionTypeLog: { - dispatchBreakpointActionLog(debuggerCallFrame->exec(), breakpointAction.data); + dispatchBreakpointActionLog(debuggerCallFrame->globalExec(), breakpointAction.data); break; } case ScriptBreakpointActionTypeEvaluate: { NakedPtr exception; - debuggerCallFrame->evaluate(breakpointAction.data, exception); + JSObject* scopeExtensionObject = nullptr; + debuggerCallFrame->evaluateWithScopeExtension(breakpointAction.data, scopeExtensionObject, exception); if (exception) - reportException(debuggerCallFrame->exec(), exception); + reportException(debuggerCallFrame->globalExec(), exception); break; } case ScriptBreakpointActionTypeSound: - dispatchBreakpointActionSound(debuggerCallFrame->exec(), breakpointAction.identifier); + dispatchBreakpointActionSound(debuggerCallFrame->globalExec(), breakpointAction.identifier); break; case ScriptBreakpointActionTypeProbe: { NakedPtr exception; - JSValue result = debuggerCallFrame->evaluate(breakpointAction.data, exception); + JSObject* scopeExtensionObject = nullptr; + JSValue result = debuggerCallFrame->evaluateWithScopeExtension(breakpointAction.data, scopeExtensionObject, exception); + JSC::ExecState* exec = debuggerCallFrame->globalExec(); if (exception) - reportException(debuggerCallFrame->exec(), exception); + reportException(exec, exception); - JSC::ExecState* state = debuggerCallFrame->scope()->globalObject()->globalExec(); - Deprecated::ScriptValue wrappedResult = Deprecated::ScriptValue(state->vm(), exception ? exception->value() : result); - dispatchBreakpointActionProbe(state, breakpointAction, wrappedResult); + dispatchBreakpointActionProbe(exec, breakpointAction, exception ? exception->value() : result); break; } default: @@ -131,11 +133,9 @@ ASSERT(isPaused()); DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame(); JSGlobalObject* globalObject = debuggerCallFrame->scope()->globalObject(); - JSC::ExecState* state = globalObject->globalExec(); - RefPtr javaScriptCallFrame = JavaScriptCallFrame::create(debuggerCallFrame); - JSValue jsCallFrame = toJS(state, globalObject, javaScriptCallFrame.get()); - - listener->didPause(state, Deprecated::ScriptValue(state->vm(), jsCallFrame), exceptionOrCaughtValue(state)); + JSC::ExecState& state = *globalObject->globalExec(); + JSValue jsCallFrame = toJS(&state, globalObject, JavaScriptCallFrame::create(debuggerCallFrame).ptr()); + listener->didPause(state, jsCallFrame, exceptionOrCaughtValue(&state)); } void ScriptDebugServer::dispatchBreakpointActionLog(ExecState* exec, const String& message) @@ -151,7 +151,7 @@ Vector listenersCopy; copyToVector(m_listeners, listenersCopy); for (auto* listener : listenersCopy) - listener->breakpointActionLog(exec, message); + listener->breakpointActionLog(*exec, message); } void ScriptDebugServer::dispatchBreakpointActionSound(ExecState*, int breakpointActionIdentifier) @@ -170,7 +170,7 @@ listener->breakpointActionSound(breakpointActionIdentifier); } -void ScriptDebugServer::dispatchBreakpointActionProbe(ExecState* exec, const ScriptBreakpointAction& action, const Deprecated::ScriptValue& sampleValue) +void ScriptDebugServer::dispatchBreakpointActionProbe(ExecState* exec, const ScriptBreakpointAction& action, JSC::JSValue sampleValue) { if (m_callingListeners) return; @@ -185,7 +185,7 @@ Vector listenersCopy; copyToVector(m_listeners, listenersCopy); for (auto* listener : listenersCopy) - listener->breakpointActionProbe(exec, action, m_currentProbeBatchId, sampleId, sampleValue); + listener->breakpointActionProbe(*exec, action, m_currentProbeBatchId, sampleId, sampleValue); } void ScriptDebugServer::dispatchDidContinue(ScriptDebugListener* listener) @@ -352,20 +352,18 @@ detachDebugger(isBeingDestroyed); } -Deprecated::ScriptValue ScriptDebugServer::exceptionOrCaughtValue(JSC::ExecState* state) +JSC::JSValue ScriptDebugServer::exceptionOrCaughtValue(JSC::ExecState* state) { if (reasonForPause() == PausedForException) - return Deprecated::ScriptValue(state->vm(), currentException()); + return currentException(); - RefPtr debuggerCallFrame = currentDebuggerCallFrame(); - while (debuggerCallFrame) { - DebuggerScope* scope = debuggerCallFrame->scope(); - if (scope->isCatchScope()) - return Deprecated::ScriptValue(state->vm(), scope->caughtValue(state)); - debuggerCallFrame = debuggerCallFrame->callerFrame(); + for (RefPtr frame = currentDebuggerCallFrame(); frame; frame = frame->callerFrame()) { + DebuggerScope& scope = *frame->scope(); + if (scope.isCatchScope()) + return scope.caughtValue(state); } - return Deprecated::ScriptValue(); + return { }; } } // namespace Inspector diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptDebugServer.h webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptDebugServer.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/ScriptDebugServer.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/ScriptDebugServer.h 2016-11-03 07:04:20.000000000 +0000 @@ -27,8 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptDebugServer_h -#define ScriptDebugServer_h +#pragma once #include "ScriptBreakpoint.h" #include "ScriptDebugListener.h" @@ -85,21 +84,20 @@ void dispatchFailedToParseSource(const ListenerSet& listeners, JSC::SourceProvider*, int errorLine, const String& errorMessage); void dispatchBreakpointActionLog(JSC::ExecState*, const String&); void dispatchBreakpointActionSound(JSC::ExecState*, int breakpointActionIdentifier); - void dispatchBreakpointActionProbe(JSC::ExecState*, const ScriptBreakpointAction&, const Deprecated::ScriptValue& sample); + void dispatchBreakpointActionProbe(JSC::ExecState*, const ScriptBreakpointAction&, JSC::JSValue sample); bool m_doneProcessingDebuggerEvents {true}; private: typedef HashMap BreakpointIDToActionsMap; - virtual void sourceParsed(JSC::ExecState*, JSC::SourceProvider*, int errorLine, const String& errorMsg) override final; - virtual bool needPauseHandling(JSC::JSGlobalObject*) override final { return true; } - virtual void handleBreakpointHit(JSC::JSGlobalObject*, const JSC::Breakpoint&) override final; - virtual void handleExceptionInBreakpointCondition(JSC::ExecState*, JSC::Exception*) const override final; - virtual void handlePause(JSC::JSGlobalObject*, JSC::Debugger::ReasonForPause) override final; - virtual void notifyDoneProcessingDebuggerEvents() override final; + void sourceParsed(JSC::ExecState*, JSC::SourceProvider*, int errorLine, const String& errorMsg) final; + void handleBreakpointHit(JSC::JSGlobalObject*, const JSC::Breakpoint&) final; + void handleExceptionInBreakpointCondition(JSC::ExecState*, JSC::Exception*) const final; + void handlePause(JSC::JSGlobalObject*, JSC::Debugger::ReasonForPause) final; + void notifyDoneProcessingDebuggerEvents() final; - Deprecated::ScriptValue exceptionOrCaughtValue(JSC::ExecState*); + JSC::JSValue exceptionOrCaughtValue(JSC::ExecState*); BreakpointIDToActionsMap m_breakpointIDToActions; @@ -111,5 +109,3 @@ }; } // namespace Inspector - -#endif // ScriptDebugServer_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator.py 2016-09-19 12:18:06.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ import os.path import re -from generator import ucfirst +from generator import ucfirst, Generator from models import PrimitiveType, ObjectType, ArrayType, EnumType, AliasedType, Frameworks log = logging.getLogger('global') @@ -43,10 +43,15 @@ 'any': 'Inspector::InspectorValue' } -# This class contains extra static methods used for generation, but does -# not participate in any inheritance hierarchy. File generators should -# extend the generic "Generator" class instead. -class CppGenerator: +class CppGenerator(Generator): + def __init__(self, model, input_filepath): + Generator.__init__(self, model, input_filepath) + + def protocol_name(self): + return self.model().framework.setting('cpp_protocol_group', '') + + def helpers_namespace(self): + return '%sHelpers' % self.protocol_name() # Miscellaneous text manipulation routines. @staticmethod diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator_templates.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator_templates.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator_templates.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/cpp_generator_templates.py 2016-09-16 09:56:47.000000000 +0000 @@ -30,8 +30,7 @@ class CppGeneratorTemplates: HeaderPrelude = ( - """#ifndef ${headerGuardString} -#define ${headerGuardString} + """#pragma once ${includes} @@ -40,9 +39,7 @@ ${typedefs}""") HeaderPostlude = ( - """} // namespace Inspector - -#endif // !defined(${headerGuardString})""") + """} // namespace Inspector""") ImplementationPrelude = ( """#include "config.h" @@ -57,8 +54,7 @@ """) AlternateDispatchersHeaderPrelude = ( - """#ifndef ${headerGuardString} -#define ${headerGuardString} + """#pragma once #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) @@ -78,9 +74,7 @@ AlternateDispatchersHeaderPostlude = ( """} // namespace Inspector -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(${headerGuardString})""") +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)""") AlternateBackendDispatcherHeaderDomainHandlerInterfaceDeclaration = ( """class Alternate${domainName}BackendDispatcher : public AlternateBackendDispatcher { @@ -101,18 +95,20 @@ """${classAndExportMacro} ${domainName}BackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref<${domainName}BackendDispatcher> create(BackendDispatcher&, ${domainName}BackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; ${commandDeclarations} private: ${domainName}BackendDispatcher(BackendDispatcher&, ${domainName}BackendDispatcherHandler*); - ${domainName}BackendDispatcherHandler* m_agent; -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + ${domainName}BackendDispatcherHandler* m_agent { nullptr }; +};""") + + BackendDispatcherHeaderDomainDispatcherAlternatesDeclaration = ( + """#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(Alternate${domainName}BackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - Alternate${domainName}BackendDispatcher* m_alternateDispatcher; -#endif -};""") + Alternate${domainName}BackendDispatcher* m_alternateDispatcher { nullptr }; +#endif""") BackendDispatcherHeaderAsyncCommandDeclaration = ( """ ${classAndExportMacro} ${callbackName} : public BackendDispatcher::CallbackBase { @@ -176,9 +172,6 @@ ${domainName}BackendDispatcher::${domainName}BackendDispatcher(BackendDispatcher& backendDispatcher, ${domainName}BackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("${domainName}"), this); }""") diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_alternate_backend_dispatcher_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,27 +32,25 @@ from cpp_generator import CppGenerator from cpp_generator_templates import CppGeneratorTemplates as CppTemplates -from generator import Generator log = logging.getLogger('global') -class CppAlternateBackendDispatcherHeaderGenerator(Generator): +class CppAlternateBackendDispatcherHeaderGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return 'InspectorAlternateBackendDispatchers.h' + return '%sAlternateBackendDispatchers.h' % self.protocol_name() def generate_output(self): headers = [ - '"InspectorProtocolTypes.h"', + '"%sProtocolTypes.h"' % self.protocol_name(), '', '', ] header_args = { - 'headerGuardString': re.sub('\W+', '_', self.output_filename()), 'includes': '\n'.join(['#include ' + header for header in headers]), } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014, 2015 Apple Inc. All rights reserved. +# Copyright (c) 2014-2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,26 +38,25 @@ log = logging.getLogger('global') -class CppBackendDispatcherHeaderGenerator(Generator): +class CppBackendDispatcherHeaderGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return "InspectorBackendDispatchers.h" + return "%sBackendDispatchers.h" % self.protocol_name() def domains_to_generate(self): return filter(lambda domain: len(domain.commands) > 0, Generator.domains_to_generate(self)) def generate_output(self): headers = [ - '"InspectorProtocolObjects.h"', + '"%sProtocolObjects.h"' % self.protocol_name(), '', ''] typedefs = [('String', 'ErrorString')] header_args = { - 'headerGuardString': re.sub('\W+', '_', self.output_filename()), 'includes': '\n'.join(['#include ' + header for header in headers]), 'typedefs': '\n'.join(['typedef %s %s;' % typedef for typedef in typedefs]), } @@ -67,7 +66,8 @@ sections = [] sections.append(self.generate_license()) sections.append(Template(CppTemplates.HeaderPrelude).substitute(None, **header_args)) - sections.append(self._generate_alternate_handler_forward_declarations_for_domains(domains)) + if self.model().framework.setting('alternate_dispatchers', False): + sections.append(self._generate_alternate_handler_forward_declarations_for_domains(domains)) sections.extend(map(self._generate_handler_declarations_for_domain, domains)) sections.extend(map(self._generate_dispatcher_declarations_for_domain, domains)) sections.append(Template(CppTemplates.HeaderPostlude).substitute(None, **header_args)) @@ -133,7 +133,7 @@ parameters.append("%s %s" % (CppGenerator.cpp_type_for_unchecked_formal_in_parameter(_parameter), parameter_name)) - if isinstance(_parameter.type, EnumType) and _parameter.parameter_name not in used_enum_names: + if isinstance(_parameter.type, EnumType) and _parameter.type.is_anonymous and _parameter.parameter_name not in used_enum_names: lines.append(self._generate_anonymous_enum_for_parameter(_parameter, command)) used_enum_names.add(_parameter.parameter_name) @@ -143,7 +143,7 @@ parameter_name = 'opt_' + parameter_name parameters.append("%s %s" % (CppGenerator.cpp_type_for_formal_out_parameter(_parameter), parameter_name)) - if isinstance(_parameter.type, EnumType) and _parameter.parameter_name not in used_enum_names: + if isinstance(_parameter.type, EnumType) and _parameter.type.is_anonymous and _parameter.parameter_name not in used_enum_names: lines.append(self._generate_anonymous_enum_for_parameter(_parameter, command)) used_enum_names.add(_parameter.parameter_name) @@ -196,6 +196,14 @@ declarations.append('private:') declarations.extend(map(self._generate_dispatcher_declaration_for_command, domain.commands)) + declaration_args = { + 'domainName': domain.domain_name, + } + + # Add in a few more declarations at the end if needed. + if self.model().framework.setting('alternate_dispatchers', False): + declarations.append(Template(CppTemplates.BackendDispatcherHeaderDomainDispatcherAlternatesDeclaration).substitute(None, **declaration_args)) + handler_args = { 'classAndExportMacro': " ".join(classComponents), 'domainName': domain.domain_name, diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_backend_dispatcher_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014, 2015 Apple Inc. All rights reserved. +# Copyright (c) 2014-2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,12 +37,12 @@ log = logging.getLogger('global') -class CppBackendDispatcherImplementationGenerator(Generator): +class CppBackendDispatcherImplementationGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return "InspectorBackendDispatchers.cpp" + return "%sBackendDispatchers.cpp" % self.protocol_name() def domains_to_generate(self): return filter(lambda domain: len(domain.commands) > 0, Generator.domains_to_generate(self)) @@ -55,13 +55,15 @@ ''] secondary_includes = ['#include %s' % header for header in secondary_headers] - secondary_includes.append('') - secondary_includes.append('#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)') - secondary_includes.append('#include "InspectorAlternateBackendDispatchers.h"') - secondary_includes.append('#endif') + + if self.model().framework.setting('alternate_dispatchers', False): + secondary_includes.append('') + secondary_includes.append('#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)') + secondary_includes.append('#include "%sAlternateBackendDispatchers.h"' % self.protocol_name()) + secondary_includes.append('#endif') header_args = { - 'primaryInclude': '"InspectorBackendDispatchers.h"', + 'primaryInclude': '"%sBackendDispatchers.h"' % self.protocol_name(), 'secondaryIncludes': '\n'.join(secondary_includes), } @@ -143,6 +145,7 @@ 'parameterKey': parameter.parameter_name, 'parameterName': parameter.parameter_name, 'parameterType': CppGenerator.cpp_type_for_stack_in_parameter(parameter), + 'helpersNamespace': self.helpers_namespace(), } formal_parameters.append('%s %s' % (CppGenerator.cpp_type_for_formal_async_parameter(parameter), parameter.parameter_name)) @@ -155,7 +158,7 @@ out_parameter_assignments.append(' if (%(parameterName)s)' % param_args) out_parameter_assignments.append(' jsonMessage->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), %(parameterName)s);' % param_args) elif parameter.type.is_enum(): - out_parameter_assignments.append(' jsonMessage->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), Inspector::Protocol::getEnumConstantValue(%(parameterName)s));' % param_args) + out_parameter_assignments.append(' jsonMessage->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), Inspector::Protocol::%(helpersNamespace)s::getEnumConstantValue(%(parameterName)s));' % param_args) else: out_parameter_assignments.append(' jsonMessage->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), %(parameterName)s);' % param_args) @@ -236,7 +239,7 @@ 'parameterKey': parameter.parameter_name, 'parameterName': parameter.parameter_name, 'keyedSetMethod': CppGenerator.cpp_setter_method_for_type(parameter.type), - + 'helpersNamespace': self.helpers_namespace(), } out_parameter_declarations.append(' %(parameterType)s out_%(parameterName)s;' % param_args) @@ -248,7 +251,7 @@ out_parameter_assignments.append(' if (out_%(parameterName)s)' % param_args) out_parameter_assignments.append(' result->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), out_%(parameterName)s);' % param_args) elif parameter.type.is_enum(): - out_parameter_assignments.append(' result->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), Inspector::Protocol::getEnumConstantValue(out_%(parameterName)s));' % param_args) + out_parameter_assignments.append(' result->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), Inspector::Protocol::%(helpersNamespace)s::getEnumConstantValue(out_%(parameterName)s));' % param_args) else: out_parameter_assignments.append(' result->%(keyedSetMethod)s(ASCIILiteral("%(parameterKey)s"), out_%(parameterName)s);' % param_args) @@ -276,13 +279,14 @@ if len(command.call_parameters) > 0: lines.append(Template(CppTemplates.BackendDispatcherImplementationPrepareCommandArguments).substitute(None, **command_args)) - lines.append('#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)') - lines.append(' if (m_alternateDispatcher) {') - lines.append(' m_alternateDispatcher->%(commandName)s(%(alternateInvocationParameters)s);' % command_args) - lines.append(' return;') - lines.append(' }') - lines.append('#endif') - lines.append('') + if self.model().framework.setting('alternate_dispatchers', False): + lines.append('#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS)') + lines.append(' if (m_alternateDispatcher) {') + lines.append(' m_alternateDispatcher->%(commandName)s(%(alternateInvocationParameters)s);' % command_args) + lines.append(' return;') + lines.append(' }') + lines.append('#endif') + lines.append('') lines.append(' ErrorString error;') lines.append(' Ref result = InspectorObject::create();') diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014, 2015 Apple Inc. All rights reserved. +# Copyright (c) 2014-2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -38,24 +38,23 @@ log = logging.getLogger('global') -class CppFrontendDispatcherHeaderGenerator(Generator): +class CppFrontendDispatcherHeaderGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return "InspectorFrontendDispatchers.h" + return "%sFrontendDispatchers.h" % self.protocol_name() def domains_to_generate(self): return filter(lambda domain: len(domain.events) > 0, Generator.domains_to_generate(self)) def generate_output(self): headers = [ - '"InspectorProtocolObjects.h"', + '"%sProtocolObjects.h"' % self.protocol_name(), '', ''] header_args = { - 'headerGuardString': re.sub('\W+', '_', self.output_filename()), 'includes': '\n'.join(['#include ' + header for header in headers]), 'typedefs': 'class FrontendRouter;', } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_frontend_dispatcher_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014, 2015 Apple Inc. All rights reserved. +# Copyright (c) 2014-2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,12 +37,12 @@ log = logging.getLogger('global') -class CppFrontendDispatcherImplementationGenerator(Generator): +class CppFrontendDispatcherImplementationGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return "InspectorFrontendDispatchers.cpp" + return "%sFrontendDispatchers.cpp" % self.protocol_name() def domains_to_generate(self): return filter(lambda domain: len(domain.events) > 0, Generator.domains_to_generate(self)) @@ -54,7 +54,7 @@ ] header_args = { - 'primaryInclude': '"InspectorFrontendDispatchers.h"', + 'primaryInclude': '"%sFrontendDispatchers.h"' % self.protocol_name(), 'secondaryIncludes': "\n".join(['#include %s' % header for header in secondary_headers]), } @@ -85,7 +85,7 @@ if parameter.is_optional and not CppGenerator.should_pass_by_copy_for_return_type(parameter.type): parameter_value = '*' + parameter_value if parameter.type.is_enum(): - parameter_value = 'Inspector::Protocol::getEnumConstantValue(%s)' % parameter_value + parameter_value = 'Inspector::Protocol::%s::getEnumConstantValue(%s)' % (self.helpers_namespace(), parameter_value) parameter_args = { 'parameterType': CppGenerator.cpp_type_for_stack_out_parameter(parameter), diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ import logging import re import string +from operator import methodcaller from string import Template from cpp_generator import CppGenerator @@ -38,12 +39,12 @@ log = logging.getLogger('global') -class CppProtocolTypesHeaderGenerator(Generator): +class CppProtocolTypesHeaderGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return "InspectorProtocolObjects.h" + return "%sProtocolObjects.h" % self.protocol_name() def generate_output(self): domains = self.domains_to_generate() @@ -54,35 +55,22 @@ '', ]) - export_macro = self.model().framework.setting('export_macro', None) - header_args = { - 'headerGuardString': re.sub('\W+', '_', self.output_filename()), 'includes': '\n'.join(['#include ' + header for header in sorted(headers)]), 'typedefs': '', } - return_type = 'String' - return_type_with_export_macro = [return_type] - if export_macro is not None: - return_type_with_export_macro[:0] = [export_macro] - sections = [] sections.append(self.generate_license()) sections.append(Template(CppTemplates.HeaderPrelude).substitute(None, **header_args)) sections.append('namespace Protocol {') sections.append(self._generate_forward_declarations(domains)) sections.append(self._generate_typedefs(domains)) - sections.append('%s getEnumConstantValue(int code);' % ' '.join(return_type_with_export_macro)) - sections.append('\n'.join([ - 'template %s getEnumConstantValue(T enumValue)' % return_type, - '{', - ' return getEnumConstantValue(static_cast(enumValue));', - '}'])) - + sections.extend(self._generate_enum_constant_value_conversion_methods()) builder_sections = map(self._generate_builders_for_domain, domains) sections.extend(filter(lambda section: len(section) > 0, builder_sections)) sections.append(self._generate_forward_declarations_for_binding_traits()) + sections.extend(self._generate_declarations_for_enum_conversion_methods()) sections.append('} // namespace Protocol') sections.append(Template(CppTemplates.HeaderPostlude).substitute(None, **header_args)) return "\n\n".join(sections) @@ -98,18 +86,18 @@ declaration_types = [decl.type for decl in domain.type_declarations] object_types = filter(lambda _type: isinstance(_type, ObjectType), declaration_types) enum_types = filter(lambda _type: isinstance(_type, EnumType), declaration_types) + sorted(object_types, key=methodcaller('raw_name')) + sorted(enum_types, key=methodcaller('raw_name')) + if len(object_types) + len(enum_types) == 0: continue domain_lines = [] domain_lines.append('namespace %s {' % domain.domain_name) - object_type_names = [_type.raw_name() for _type in object_types] - enum_type_names = [_type.raw_name() for _type in enum_types] - # Forward-declare all classes so the type builders won't break if rearranged. - domain_lines.extend('class %s;' % name for name in sorted(object_type_names)) - domain_lines.extend('enum class %s;' % name for name in sorted(enum_type_names)) + domain_lines.extend('class %s;' % object_type.raw_name() for object_type in object_types) + domain_lines.extend('enum class %s;' % enum_type.raw_name() for enum_type in enum_types) domain_lines.append('} // %s' % domain.domain_name) sections.append(self.wrap_with_guard_for_domain(domain, '\n'.join(domain_lines))) @@ -161,6 +149,29 @@ lines.append('} // %s' % domain.domain_name) return self.wrap_with_guard_for_domain(domain, '\n'.join(lines)) + def _generate_enum_constant_value_conversion_methods(self): + if not self.assigned_enum_values(): + return [] + + return_type = 'String' + return_type_with_export_macro = [return_type] + export_macro = self.model().framework.setting('export_macro', None) + if export_macro is not None: + return_type_with_export_macro[:0] = [export_macro] + + lines = [] + lines.append('namespace %s {' % self.helpers_namespace()) + lines.append('\n'.join([ + '%s getEnumConstantValue(int code);' % ' '.join(return_type_with_export_macro), + '', + 'template %s getEnumConstantValue(T enumValue)' % return_type, + '{', + ' return getEnumConstantValue(static_cast(enumValue));', + '}', + ])) + lines.append('} // namespace %s' % self.helpers_namespace()) + return lines + def _generate_builders_for_domain(self, domain): sections = [] @@ -280,7 +291,8 @@ 'camelName': ucfirst(type_member.member_name), 'keyedSet': CppGenerator.cpp_setter_method_for_type(type_member.type), 'name': type_member.member_name, - 'parameterType': CppGenerator.cpp_type_for_type_member(type_member) + 'parameterType': CppGenerator.cpp_type_for_type_member(type_member), + 'helpersNamespace': self.helpers_namespace(), } lines = [] @@ -290,7 +302,7 @@ lines.append(' COMPILE_ASSERT(!(STATE & %(camelName)sSet), property_%(name)s_already_set);' % setter_args) if isinstance(type_member.type, EnumType): - lines.append(' m_result->%(keyedSet)s(ASCIILiteral("%(name)s"), Inspector::Protocol::getEnumConstantValue(static_cast(value)));' % setter_args) + lines.append(' m_result->%(keyedSet)s(ASCIILiteral("%(name)s"), Inspector::Protocol::%(helpersNamespace)s::getEnumConstantValue(value));' % setter_args) else: lines.append(' m_result->%(keyedSet)s(ASCIILiteral("%(name)s"), value);' % setter_args) lines.append(' return castState<%(camelName)sSet>();' % setter_args) @@ -302,7 +314,8 @@ 'camelName': ucfirst(type_member.member_name), 'keyedSet': CppGenerator.cpp_setter_method_for_type(type_member.type), 'name': type_member.member_name, - 'parameterType': CppGenerator.cpp_type_for_type_member(type_member) + 'parameterType': CppGenerator.cpp_type_for_type_member(type_member), + 'helpersNamespace': self.helpers_namespace(), } lines = [] @@ -310,7 +323,7 @@ lines.append(' void set%(camelName)s(%(parameterType)s value)' % setter_args) lines.append(' {') if isinstance(type_member.type, EnumType): - lines.append(' InspectorObjectBase::%(keyedSet)s(ASCIILiteral("%(name)s"), Inspector::Protocol::getEnumConstantValue(static_cast(value)));' % setter_args) + lines.append(' InspectorObjectBase::%(keyedSet)s(ASCIILiteral("%(name)s"), Inspector::Protocol::%(helpersNamespace)s::getEnumConstantValue(value));' % setter_args) elif CppGenerator.should_use_references_for_type(type_member.type): lines.append(' InspectorObjectBase::%(keyedSet)s(ASCIILiteral("%(name)s"), WTFMove(value));' % setter_args) else: @@ -350,3 +363,58 @@ lines.append('#endif // !ASSERT_DISABLED') lines.append('};') return '\n'.join(lines) + + def _generate_declarations_for_enum_conversion_methods(self): + sections = [] + sections.append('\n'.join([ + 'namespace %s {' % self.helpers_namespace(), + '', + 'template', + 'Optional parseEnumValueFromString(const String&);', + ])) + + def return_type_with_export_macro(cpp_protocol_type): + enum_return_type = 'Optional<%s>' % cpp_protocol_type + result_terms = [enum_return_type] + export_macro = self.model().framework.setting('export_macro', None) + if export_macro is not None: + result_terms[:0] = [export_macro] + return ' '.join(result_terms) + + def type_member_is_anonymous_enum_type(type_member): + return isinstance(type_member.type, EnumType) and type_member.type.is_anonymous + + for domain in self.domains_to_generate(): + declaration_types = [decl.type for decl in domain.type_declarations] + object_types = filter(lambda _type: isinstance(_type, ObjectType), declaration_types) + enum_types = filter(lambda _type: isinstance(_type, EnumType), declaration_types) + if len(object_types) + len(enum_types) == 0: + continue + + sorted(object_types, key=methodcaller('raw_name')) + sorted(enum_types, key=methodcaller('raw_name')) + + domain_lines = [] + domain_lines.append("// Enums in the '%s' Domain" % domain.domain_name) + for enum_type in enum_types: + cpp_protocol_type = CppGenerator.cpp_protocol_type_for_type(enum_type) + domain_lines.append('template<>') + domain_lines.append('%s parseEnumValueFromString<%s>(const String&);' % (return_type_with_export_macro(cpp_protocol_type), cpp_protocol_type)) + + for object_type in object_types: + for enum_member in filter(type_member_is_anonymous_enum_type, object_type.members): + cpp_protocol_type = CppGenerator.cpp_protocol_type_for_type_member(enum_member, object_type.declaration()) + domain_lines.append('template<>') + domain_lines.append('%s parseEnumValueFromString<%s>(const String&);' % (return_type_with_export_macro(cpp_protocol_type), cpp_protocol_type)) + + if len(domain_lines) == 1: + continue # No real declarations to emit, just the domain comment. Skip. + + sections.append(self.wrap_with_guard_for_domain(domain, '\n'.join(domain_lines))) + + if len(sections) == 1: + return [] # No real sections to emit, just the namespace and template declaration. Skip. + + sections.append('} // namespace %s' % self.helpers_namespace()) + + return ['\n\n'.join(sections)] diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ import logging import string from string import Template +from operator import methodcaller from cpp_generator import CppGenerator from cpp_generator_templates import CppGeneratorTemplates as CppTemplates @@ -37,21 +38,24 @@ log = logging.getLogger('global') -class CppProtocolTypesImplementationGenerator(Generator): +class CppProtocolTypesImplementationGenerator(CppGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + CppGenerator.__init__(self, model, input_filepath) def output_filename(self): - return "InspectorProtocolObjects.cpp" + return "%sProtocolObjects.cpp" % self.protocol_name() def generate_output(self): domains = self.domains_to_generate() self.calculate_types_requiring_shape_assertions(domains) - secondary_headers = [''] + secondary_headers = [ + '', + '', + ] header_args = { - 'primaryInclude': '"InspectorProtocolObjects.h"', + 'primaryInclude': '"%sProtocolObjects.h"' % self.protocol_name(), 'secondaryIncludes': "\n".join(['#include %s' % header for header in secondary_headers]), } @@ -59,7 +63,7 @@ sections.append(self.generate_license()) sections.append(Template(CppTemplates.ImplementationPrelude).substitute(None, **header_args)) sections.append('namespace Protocol {') - sections.append(self._generate_enum_mapping()) + sections.extend(self._generate_enum_mapping_and_conversion_methods(domains)) sections.append(self._generate_open_field_names()) builder_sections = map(self._generate_builders_for_domain, domains) sections.extend(filter(lambda section: len(section) > 0, builder_sections)) @@ -71,6 +75,9 @@ # Private methods. def _generate_enum_mapping(self): + if not self.assigned_enum_values(): + return [] + lines = [] lines.append('static const char* const enum_constant_values[] = {') lines.extend([' "%s",' % enum_value for enum_value in self.assigned_enum_values()]) @@ -79,7 +86,74 @@ lines.append('String getEnumConstantValue(int code) {') lines.append(' return enum_constant_values[code];') lines.append('}') - return '\n'.join(lines) + return ['\n'.join(lines)] + + def _generate_enum_conversion_methods_for_domain(self, domain): + + def type_member_is_anonymous_enum_type(type_member): + return isinstance(type_member.type, EnumType) and type_member.type.is_anonymous + + def generate_conversion_method_body(enum_type, cpp_protocol_type): + body_lines = [] + body_lines.extend([ + 'template<>', + 'Optional<%s> parseEnumValueFromString<%s>(const String& protocolString)' % (cpp_protocol_type, cpp_protocol_type), + '{', + ' static const size_t constantValues[] = {', + ]) + + enum_values = enum_type.enum_values() + for enum_value in enum_values: + body_lines.append(' (size_t)%s::%s,' % (cpp_protocol_type, Generator.stylized_name_for_enum_value(enum_value))) + + body_lines.extend([ + ' };', + ' for (size_t i = 0; i < %d; ++i)' % len(enum_values), + ' if (protocolString == enum_constant_values[constantValues[i]])', + ' return (%s)constantValues[i];' % cpp_protocol_type, + '', + ' return Nullopt;', + '}', + '', + ]) + return body_lines + + declaration_types = [decl.type for decl in domain.type_declarations] + object_types = filter(lambda _type: isinstance(_type, ObjectType), declaration_types) + enum_types = filter(lambda _type: isinstance(_type, EnumType), declaration_types) + if len(object_types) + len(enum_types) == 0: + return '' + + sorted(object_types, key=methodcaller('raw_name')) + sorted(enum_types, key=methodcaller('raw_name')) + + lines = [] + lines.append("// Enums in the '%s' Domain" % domain.domain_name) + for enum_type in enum_types: + cpp_protocol_type = CppGenerator.cpp_protocol_type_for_type(enum_type) + lines.extend(generate_conversion_method_body(enum_type, cpp_protocol_type)) + + for object_type in object_types: + for enum_member in filter(type_member_is_anonymous_enum_type, object_type.members): + cpp_protocol_type = CppGenerator.cpp_protocol_type_for_type_member(enum_member, object_type.declaration()) + lines.extend(generate_conversion_method_body(enum_member.type, cpp_protocol_type)) + + if len(lines) == 1: + return '' # No real declarations to emit, just the domain comment. + + return self.wrap_with_guard_for_domain(domain, '\n'.join(lines)) + + def _generate_enum_mapping_and_conversion_methods(self, domains): + sections = [] + sections.append('namespace %s {' % self.helpers_namespace()) + sections.extend(self._generate_enum_mapping()) + enum_parser_sections = map(self._generate_enum_conversion_methods_for_domain, domains) + sections.extend(filter(lambda section: len(section) > 0, enum_parser_sections)) + if len(sections) == 1: + return [] # No declarations to emit, just the namespace. + + sections.append('} // namespace %s' % self.helpers_namespace()) + return sections def _generate_open_field_names(self): lines = [] diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_header.py 2016-11-03 07:04:20.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -39,12 +39,12 @@ log = logging.getLogger('global') -class ObjCBackendDispatcherHeaderGenerator(Generator): +class ObjCBackendDispatcherHeaderGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sBackendDispatchers.h' % ObjCGenerator.OBJC_PREFIX + return '%sBackendDispatchers.h' % self.protocol_name() def domains_to_generate(self): return filter(ObjCGenerator.should_generate_domain_command_handler_filter(self.model()), Generator.domains_to_generate(self)) @@ -73,7 +73,7 @@ lines = [] for domain in self.domains_to_generate(): if domain.commands: - lines.append('@protocol %s%sDomainHandler;' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name)) + lines.append('@protocol %s%sDomainHandler;' % (self.objc_prefix(), domain.domain_name)) return '\n'.join(lines) def _generate_objc_handler_declarations_for_domain(self, domain): @@ -87,7 +87,7 @@ handler_args = { 'domainName': domain.domain_name, 'commandDeclarations': '\n'.join(command_declarations), - 'objcPrefix': ObjCGenerator.OBJC_PREFIX, + 'objcPrefix': self.objc_prefix(), } return self.wrap_with_guard_for_domain(domain, Template(ObjCTemplates.BackendDispatcherHeaderDomainHandlerObjCDeclaration).substitute(None, **handler_args)) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_backend_dispatcher_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014, 2015 Apple Inc. All rights reserved. +# Copyright (c) 2014-2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -39,25 +39,25 @@ log = logging.getLogger('global') -class ObjCConfigurationImplementationGenerator(Generator): +class ObjCConfigurationImplementationGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sBackendDispatchers.mm' % ObjCGenerator.OBJC_PREFIX + return '%sBackendDispatchers.mm' % self.protocol_name() def domains_to_generate(self): return filter(ObjCGenerator.should_generate_domain_command_handler_filter(self.model()), Generator.domains_to_generate(self)) def generate_output(self): secondary_headers = [ - '"%sInternal.h"' % ObjCGenerator.OBJC_PREFIX, - '"%sEnumConversionHelpers.h"' % ObjCGenerator.OBJC_PREFIX, + '"%sInternal.h"' % self.protocol_name(), + '"%sTypeConversions.h"' % self.protocol_name(), '', ] header_args = { - 'primaryInclude': '"%sBackendDispatchers.h"' % ObjCGenerator.OBJC_PREFIX, + 'primaryInclude': '"%sBackendDispatchers.h"' % self.protocol_name(), 'secondaryIncludes': '\n'.join(['#include %s' % header for header in secondary_headers]), } @@ -102,7 +102,7 @@ if command.return_parameters: success_block_parameters = [] for parameter in command.return_parameters: - objc_type = ObjCGenerator.objc_type_for_param(domain, command.command_name, parameter) + objc_type = self.objc_type_for_param(domain, command.command_name, parameter) var_name = ObjCGenerator.identifier_to_objc_identifier(parameter.parameter_name) success_block_parameters.append(join_type_and_name(objc_type, var_name)) lines.append(' id successCallback = ^(%s) {' % ', '.join(success_block_parameters)) @@ -116,23 +116,23 @@ for parameter in required_pointer_parameters: var_name = ObjCGenerator.identifier_to_objc_identifier(parameter.parameter_name) lines.append(' THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(%s, @"%s");' % (var_name, var_name)) - objc_array_class = ObjCGenerator.objc_class_for_array_type(parameter.type) - if objc_array_class and objc_array_class.startswith(ObjCGenerator.OBJC_PREFIX): + objc_array_class = self.objc_class_for_array_type(parameter.type) + if objc_array_class and objc_array_class.startswith(self.objc_prefix()): lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(%s, [%s class]);' % (var_name, objc_array_class)) optional_pointer_parameters = filter(lambda parameter: parameter.is_optional and ObjCGenerator.is_type_objc_pointer_type(parameter.type), command.return_parameters) for parameter in optional_pointer_parameters: var_name = ObjCGenerator.identifier_to_objc_identifier(parameter.parameter_name) lines.append(' THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(%s, @"%s");' % (var_name, var_name)) - objc_array_class = ObjCGenerator.objc_class_for_array_type(parameter.type) - if objc_array_class and objc_array_class.startswith(ObjCGenerator.OBJC_PREFIX): + objc_array_class = self.objc_class_for_array_type(parameter.type) + if objc_array_class and objc_array_class.startswith(self.objc_prefix()): lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE_IN_OPTIONAL_ARRAY(%s, [%s class]);' % (var_name, objc_array_class)) for parameter in command.return_parameters: keyed_set_method = CppGenerator.cpp_setter_method_for_type(parameter.type) var_name = ObjCGenerator.identifier_to_objc_identifier(parameter.parameter_name) var_expression = '*%s' % var_name if parameter.is_optional else var_name - export_expression = ObjCGenerator.objc_protocol_export_expression_for_variable(parameter.type, var_expression) + export_expression = self.objc_protocol_export_expression_for_variable(parameter.type, var_expression) if not parameter.is_optional: lines.append(' resultObject->%s(ASCIILiteral("%s"), %s);' % (keyed_set_method, parameter.parameter_name, export_expression)) else: @@ -165,9 +165,9 @@ for parameter in command.call_parameters: in_param_name = 'in_%s' % parameter.parameter_name objc_in_param_name = 'o_%s' % in_param_name - objc_type = ObjCGenerator.objc_type_for_param(domain, command.command_name, parameter, False) + objc_type = self.objc_type_for_param(domain, command.command_name, parameter, False) param_expression = in_param_expression(in_param_name, parameter) - import_expression = ObjCGenerator.objc_protocol_import_expression_for_parameter(param_expression, domain, command.command_name, parameter) + import_expression = self.objc_protocol_import_expression_for_parameter(param_expression, domain, command.command_name, parameter) if not parameter.is_optional: lines.append(' %s = %s;' % (join_type_and_name(objc_type, objc_in_param_name), import_expression)) else: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,16 +36,16 @@ log = logging.getLogger('global') -class ObjCConfigurationHeaderGenerator(Generator): +class ObjCConfigurationHeaderGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sConfiguration.h' % ObjCGenerator.OBJC_PREFIX + return '%sConfiguration.h' % self.protocol_name() def generate_output(self): headers = [ - '' % ObjCGenerator.OBJC_PREFIX, + '' % self.protocol_name(), ] header_args = { @@ -66,7 +66,7 @@ def _generate_configuration_interface_for_domains(self, domains): lines = [] lines.append('__attribute__((visibility ("default")))') - lines.append('@interface %sConfiguration : NSObject' % ObjCGenerator.OBJC_PREFIX) + lines.append('@interface %sConfiguration : NSObject' % self.protocol_name()) for domain in domains: lines.extend(self._generate_properties_for_domain(domain)) lines.append('@end') @@ -74,7 +74,7 @@ def _generate_properties_for_domain(self, domain): property_args = { - 'objcPrefix': ObjCGenerator.OBJC_PREFIX, + 'objcPrefix': self.objc_prefix(), 'domainName': domain.domain_name, 'variableNamePrefix': ObjCGenerator.variable_name_prefix_for_domain(domain), } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_configuration_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,17 +36,17 @@ log = logging.getLogger('global') -class ObjCBackendDispatcherImplementationGenerator(Generator): +class ObjCBackendDispatcherImplementationGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sConfiguration.mm' % ObjCGenerator.OBJC_PREFIX + return '%sConfiguration.mm' % self.protocol_name() def generate_output(self): secondary_headers = [ - '"%sInternal.h"' % ObjCGenerator.OBJC_PREFIX, - '"%sBackendDispatchers.h"' % ObjCGenerator.OBJC_PREFIX, + '"%sInternal.h"' % self.protocol_name(), + '"%sBackendDispatchers.h"' % self.protocol_name(), '', '', '', @@ -54,7 +54,7 @@ ] header_args = { - 'primaryInclude': '"%sConfiguration.h"' % ObjCGenerator.OBJC_PREFIX, + 'primaryInclude': '"%sConfiguration.h"' % self.protocol_name(), 'secondaryIncludes': '\n'.join(['#import %s' % header for header in secondary_headers]), } @@ -71,7 +71,7 @@ def _generate_configuration_implementation_for_domains(self, domains): lines = [] - lines.append('@implementation %sConfiguration' % ObjCGenerator.OBJC_PREFIX) + lines.append('@implementation %sConfiguration' % self.protocol_name()) lines.append('{') lines.append(' AugmentableInspectorController* _controller;') lines.extend(self._generate_ivars(domains)) @@ -103,11 +103,11 @@ lines = [] for domain in domains: if domain.commands and self._command_filter(domain): - objc_class_name = '%s%sDomainHandler' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name) + objc_class_name = '%s%sDomainHandler' % (self.objc_prefix(), domain.domain_name) ivar_name = '_%sHandler' % ObjCGenerator.variable_name_prefix_for_domain(domain) lines.append(' id<%s> %s;' % (objc_class_name, ivar_name)) if domain.events and self._event_filter(domain): - objc_class_name = '%s%sDomainEventDispatcher' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name) + objc_class_name = '%s%sDomainEventDispatcher' % (self.objc_prefix(), domain.domain_name) ivar_name = '_%sEventDispatcher' % ObjCGenerator.variable_name_prefix_for_domain(domain) lines.append(' %s *%s;' % (objc_class_name, ivar_name)) return lines @@ -127,7 +127,7 @@ def _generate_handler_setter_for_domain(self, domain): setter_args = { - 'objcPrefix': ObjCGenerator.OBJC_PREFIX, + 'objcPrefix': self.objc_prefix(), 'domainName': domain.domain_name, 'variableNamePrefix': ObjCGenerator.variable_name_prefix_for_domain(domain), } @@ -135,7 +135,7 @@ def _generate_event_dispatcher_getter_for_domain(self, domain): getter_args = { - 'objcPrefix': ObjCGenerator.OBJC_PREFIX, + 'objcPrefix': self.objc_prefix(), 'domainName': domain.domain_name, 'variableNamePrefix': ObjCGenerator.variable_name_prefix_for_domain(domain), } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_conversion_helpers.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_conversion_helpers.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_conversion_helpers.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_conversion_helpers.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,155 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2014 Apple Inc. All rights reserved. -# Copyright (c) 2014 University of Washington. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -# THE POSSIBILITY OF SUCH DAMAGE. - - -import logging -import string -from string import Template - -from generator import Generator -from models import EnumType -from objc_generator import ObjCGenerator -from objc_generator_templates import ObjCGeneratorTemplates as ObjCTemplates - -log = logging.getLogger('global') - - -def add_newline(lines): - if lines and lines[-1] == '': - return - lines.append('') - - -class ObjCConversionHelpersGenerator(Generator): - def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) - - def output_filename(self): - return '%sEnumConversionHelpers.h' % ObjCGenerator.OBJC_PREFIX - - def domains_to_generate(self): - return filter(ObjCGenerator.should_generate_domain_types_filter(self.model()), Generator.domains_to_generate(self)) - - def generate_output(self): - headers = [ - '"%sArrayConversionHelpers.h"' % ObjCGenerator.OBJC_PREFIX, - ] - - header_args = { - 'includes': '\n'.join(['#import ' + header for header in headers]), - } - - domains = self.domains_to_generate() - sections = [] - sections.append(self.generate_license()) - sections.append(Template(ObjCTemplates.ConversionHelpersPrelude).substitute(None, **header_args)) - sections.append(Template(ObjCTemplates.ConversionHelpersStandard).substitute(None)) - sections.extend(map(self._generate_enum_conversion_functions, domains)) - sections.append(Template(ObjCTemplates.ConversionHelpersPostlude).substitute(None, **header_args)) - return '\n\n'.join(sections) - - def _generate_enum_conversion_functions(self, domain): - lines = [] - - # Type enums and member enums. - for declaration in domain.type_declarations: - if isinstance(declaration.type, EnumType): - add_newline(lines) - lines.append(self._generate_anonymous_enum_conversion_for_declaration(domain, declaration)) - else: - for member in declaration.type_members: - if (isinstance(member.type, EnumType) and member.type.is_anonymous): - add_newline(lines) - lines.append(self._generate_anonymous_enum_conversion_for_member(domain, declaration, member)) - - # Anonymous command enums. - for command in domain.commands: - for parameter in command.call_parameters: - if (isinstance(parameter.type, EnumType) and parameter.type.is_anonymous): - add_newline(lines) - lines.append(self._generate_anonymous_enum_conversion_for_parameter(domain, command.command_name, parameter)) - for parameter in command.return_parameters: - if (isinstance(parameter.type, EnumType) and parameter.type.is_anonymous): - add_newline(lines) - lines.append(self._generate_anonymous_enum_conversion_for_parameter(domain, command.command_name, parameter)) - - # Anonymous event enums. - for event in domain.events: - for parameter in event.event_parameters: - if (isinstance(parameter.type, EnumType) and parameter.type.is_anonymous): - add_newline(lines) - lines.append(self._generate_anonymous_enum_conversion_for_parameter(domain, event.event_name, parameter)) - - return '\n'.join(lines) - - def _generate_anonymous_enum_conversion_for_declaration(self, domain, declaration): - objc_enum_name = ObjCGenerator.objc_enum_name_for_anonymous_enum_declaration(declaration) - enum_values = declaration.type.enum_values() - lines = [] - lines.append(self._generate_enum_objc_to_protocol_string(objc_enum_name, enum_values)) - lines.append(self._generate_enum_from_protocol_string(objc_enum_name, enum_values)) - return '\n\n'.join(lines) - - def _generate_anonymous_enum_conversion_for_member(self, domain, declaration, member): - objc_enum_name = ObjCGenerator.objc_enum_name_for_anonymous_enum_member(declaration, member) - enum_values = member.type.enum_values() - lines = [] - lines.append(self._generate_enum_objc_to_protocol_string(objc_enum_name, enum_values)) - lines.append(self._generate_enum_from_protocol_string(objc_enum_name, enum_values)) - return '\n\n'.join(lines) - - def _generate_anonymous_enum_conversion_for_parameter(self, domain, event_or_command_name, parameter): - objc_enum_name = ObjCGenerator.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter) - enum_values = parameter.type.enum_values() - lines = [] - lines.append(self._generate_enum_objc_to_protocol_string(objc_enum_name, enum_values)) - lines.append(self._generate_enum_from_protocol_string(objc_enum_name, enum_values)) - return '\n\n'.join(lines) - - def _generate_enum_objc_to_protocol_string(self, objc_enum_name, enum_values): - lines = [] - lines.append('inline String toProtocolString(%s value)' % objc_enum_name) - lines.append('{') - lines.append(' switch(value) {') - for enum_value in enum_values: - lines.append(' case %s%s:' % (objc_enum_name, Generator.stylized_name_for_enum_value(enum_value))) - lines.append(' return ASCIILiteral("%s");' % enum_value) - lines.append(' }') - lines.append('}') - return '\n'.join(lines) - - def _generate_enum_from_protocol_string(self, objc_enum_name, enum_values): - lines = [] - lines.append('template<>') - lines.append('inline %s fromProtocolString(const String& value)' % objc_enum_name) - lines.append('{') - for enum_value in enum_values: - lines.append(' if (value == "%s")' % enum_value) - lines.append(' return %s%s;' % (objc_enum_name, Generator.stylized_name_for_enum_value(enum_value))) - lines.append(' ASSERT_NOT_REACHED();') - lines.append(' return %s%s;' % (objc_enum_name, Generator.stylized_name_for_enum_value(enum_values[0]))) - lines.append('}') - return '\n'.join(lines) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_frontend_dispatcher_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014, 2015 Apple Inc. All rights reserved. +# Copyright (c) 2014-2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,24 +37,24 @@ log = logging.getLogger('global') -class ObjCFrontendDispatcherImplementationGenerator(Generator): +class ObjCFrontendDispatcherImplementationGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sEventDispatchers.mm' % ObjCGenerator.OBJC_PREFIX + return '%sEventDispatchers.mm' % self.protocol_name() def domains_to_generate(self): return filter(ObjCGenerator.should_generate_domain_event_dispatcher_filter(self.model()), Generator.domains_to_generate(self)) def generate_output(self): secondary_headers = [ - '"%sEnumConversionHelpers.h"' % ObjCGenerator.OBJC_PREFIX, + '"%sTypeConversions.h"' % self.protocol_name(), '', ] header_args = { - 'primaryInclude': '"%sInternal.h"' % ObjCGenerator.OBJC_PREFIX, + 'primaryInclude': '"%sInternal.h"' % self.protocol_name(), 'secondaryIncludes': '\n'.join(['#import %s' % header for header in secondary_headers]), } @@ -71,7 +71,7 @@ return '' lines = [] - objc_name = '%s%sDomainEventDispatcher' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name) + objc_name = '%s%sDomainEventDispatcher' % (self.objc_prefix(), domain.domain_name) lines.append('@implementation %s' % objc_name) lines.append('{') lines.append(' AugmentableInspectorController* _controller;') @@ -104,16 +104,16 @@ for parameter in required_pointer_parameters: var_name = ObjCGenerator.identifier_to_objc_identifier(parameter.parameter_name) lines.append(' THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(%s, @"%s");' % (var_name, var_name)) - objc_array_class = ObjCGenerator.objc_class_for_array_type(parameter.type) - if objc_array_class and objc_array_class.startswith(ObjCGenerator.OBJC_PREFIX): + objc_array_class = self.objc_class_for_array_type(parameter.type) + if objc_array_class and objc_array_class.startswith(self.objc_prefix()): lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(%s, [%s class]);' % (var_name, objc_array_class)) optional_pointer_parameters = filter(lambda parameter: parameter.is_optional and ObjCGenerator.is_type_objc_pointer_type(parameter.type), event.event_parameters) for parameter in optional_pointer_parameters: var_name = ObjCGenerator.identifier_to_objc_identifier(parameter.parameter_name) lines.append(' THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(%s, @"%s");' % (var_name, var_name)) - objc_array_class = ObjCGenerator.objc_class_for_array_type(parameter.type) - if objc_array_class and objc_array_class.startswith(ObjCGenerator.OBJC_PREFIX): + objc_array_class = self.objc_class_for_array_type(parameter.type) + if objc_array_class and objc_array_class.startswith(self.objc_prefix()): lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE_IN_OPTIONAL_ARRAY(%s, [%s class]);' % (var_name, objc_array_class)) if required_pointer_parameters or optional_pointer_parameters: @@ -133,7 +133,7 @@ pairs = [] for parameter in event.event_parameters: param_name = parameter.parameter_name - pairs.append('%s:(%s)%s' % (param_name, ObjCGenerator.objc_type_for_param(domain, event.event_name, parameter), param_name)) + pairs.append('%s:(%s)%s' % (param_name, self.objc_type_for_param(domain, event.event_name, parameter), param_name)) pairs[0] = ucfirst(pairs[0]) return '- (void)%sWith%s' % (event.event_name, ' '.join(pairs)) @@ -144,7 +144,7 @@ keyed_set_method = CppGenerator.cpp_setter_method_for_type(parameter.type) var_name = parameter.parameter_name safe_var_name = '(*%s)' % var_name if parameter.is_optional else var_name - export_expression = ObjCGenerator.objc_protocol_export_expression_for_variable(parameter.type, safe_var_name) + export_expression = self.objc_protocol_export_expression_for_variable(parameter.type, safe_var_name) if not parameter.is_optional: lines.append(' paramsObject->%s(ASCIILiteral("%s"), %s);' % (keyed_set_method, parameter.parameter_name, export_expression)) else: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -43,16 +43,16 @@ lines.append('') -class ObjCHeaderGenerator(Generator): +class ObjCHeaderGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%s.h' % ObjCGenerator.OBJC_PREFIX + return '%s.h' % self.protocol_name() def generate_output(self): headers = set([ - '' % ObjCGenerator.OBJC_PREFIX, + '' % ObjCGenerator.OBJC_STATIC_PREFIX, ]) header_args = { @@ -75,8 +75,11 @@ sections.append('\n'.join(filter(None, map(self._generate_forward_declarations, type_domains)))) sections.append('\n'.join(filter(None, map(self._generate_enums, type_domains)))) sections.append('\n'.join(filter(None, map(self._generate_types, type_domains)))) - sections.append('\n\n'.join(filter(None, map(self._generate_command_protocols, command_domains)))) - sections.append('\n\n'.join(filter(None, map(self._generate_event_interfaces, event_domains)))) + + if self.get_generator_setting('generate_backend', False): + sections.append('\n\n'.join(filter(None, map(self._generate_command_protocols, command_domains)))) + sections.append('\n\n'.join(filter(None, map(self._generate_event_interfaces, event_domains)))) + sections.append(Template(ObjCTemplates.HeaderPostlude).substitute(None)) return '\n\n'.join(sections) @@ -84,7 +87,7 @@ lines = [] for declaration in domain.type_declarations: if (isinstance(declaration.type, ObjectType)): - objc_name = ObjCGenerator.objc_name_for_type(declaration.type) + objc_name = self.objc_name_for_type(declaration.type) lines.append('@class %s;' % objc_name) return '\n'.join(lines) @@ -132,15 +135,15 @@ return '\n'.join(lines) def _generate_anonymous_enum_for_declaration(self, domain, declaration): - objc_enum_name = ObjCGenerator.objc_enum_name_for_anonymous_enum_declaration(declaration) + objc_enum_name = self.objc_enum_name_for_anonymous_enum_declaration(declaration) return self._generate_enum(objc_enum_name, declaration.type.enum_values()) def _generate_anonymous_enum_for_member(self, domain, declaration, member): - objc_enum_name = ObjCGenerator.objc_enum_name_for_anonymous_enum_member(declaration, member) + objc_enum_name = self.objc_enum_name_for_anonymous_enum_member(declaration, member) return self._generate_enum(objc_enum_name, member.type.enum_values()) def _generate_anonymous_enum_for_parameter(self, domain, event_or_command_name, parameter): - objc_enum_name = ObjCGenerator.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter) + objc_enum_name = self.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter) return self._generate_enum(objc_enum_name, parameter.type.enum_values()) def _generate_enum(self, enum_name, enum_values): @@ -153,9 +156,15 @@ def _generate_type_interface(self, domain, declaration): lines = [] - objc_name = ObjCGenerator.objc_name_for_type(declaration.type) + objc_name = self.objc_name_for_type(declaration.type) lines.append('__attribute__((visibility ("default")))') - lines.append('@interface %s : %s' % (objc_name, ObjCGenerator.OBJC_JSON_OBJECT_BASE)) + lines.append('@interface %s : %sJSONObject' % (objc_name, ObjCGenerator.OBJC_STATIC_PREFIX)) + + # The initializers that take a payload or inspector object are only needed by the frontend. + if self.get_generator_setting('generate_frontend', False): + lines.append('- (instancetype)initWithPayload:(NSDictionary *)payload;') + lines.append('- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject;') + required_members = filter(lambda member: not member.is_optional, declaration.type_members) optional_members = filter(lambda member: member.is_optional, declaration.type_members) if required_members: @@ -170,21 +179,21 @@ def _generate_init_method_for_required_members(self, domain, declaration, required_members): pairs = [] for member in required_members: - objc_type = ObjCGenerator.objc_type_for_member(declaration, member) + objc_type = self.objc_type_for_member(declaration, member) var_name = ObjCGenerator.identifier_to_objc_identifier(member.member_name) pairs.append('%s:(%s)%s' % (var_name, objc_type, var_name)) pairs[0] = ucfirst(pairs[0]) return '- (instancetype)initWith%s;' % ' '.join(pairs) def _generate_member_property(self, declaration, member): - accessor_type = ObjCGenerator.objc_accessor_type_for_member(member) - objc_type = ObjCGenerator.objc_type_for_member(declaration, member) + accessor_type = self.objc_accessor_type_for_member(member) + objc_type = self.objc_type_for_member(declaration, member) return '@property (nonatomic, %s) %s;' % (accessor_type, join_type_and_name(objc_type, ObjCGenerator.identifier_to_objc_identifier(member.member_name))) def _generate_command_protocols(self, domain): lines = [] if domain.commands: - objc_name = '%s%sDomainHandler' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name) + objc_name = '%s%sDomainHandler' % (self.objc_prefix(), domain.domain_name) lines.append('@protocol %s ' % objc_name) lines.append('@required') for command in domain.commands: @@ -198,19 +207,19 @@ pairs.append('successCallback:(%s)successCallback' % self._callback_block_for_command(domain, command)) for parameter in command.call_parameters: param_name = parameter.parameter_name - pairs.append('%s:(%s)%s' % (param_name, ObjCGenerator.objc_type_for_param(domain, command.command_name, parameter), param_name)) + pairs.append('%s:(%s)%s' % (param_name, self.objc_type_for_param(domain, command.command_name, parameter), param_name)) return '- (void)%sWith%s;' % (command.command_name, ' '.join(pairs)) def _callback_block_for_command(self, domain, command): pairs = [] for parameter in command.return_parameters: - pairs.append(join_type_and_name(ObjCGenerator.objc_type_for_param(domain, command.command_name, parameter), parameter.parameter_name)) + pairs.append(join_type_and_name(self.objc_type_for_param(domain, command.command_name, parameter), parameter.parameter_name)) return 'void(^)(%s)' % ', '.join(pairs) def _generate_event_interfaces(self, domain): lines = [] if domain.events: - objc_name = '%s%sDomainEventDispatcher' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name) + objc_name = '%s%sDomainEventDispatcher' % (self.objc_prefix(), domain.domain_name) lines.append('__attribute__((visibility ("default")))') lines.append('@interface %s : NSObject' % objc_name) for event in domain.events: @@ -224,6 +233,6 @@ pairs = [] for parameter in event.event_parameters: param_name = parameter.parameter_name - pairs.append('%s:(%s)%s' % (param_name, ObjCGenerator.objc_type_for_param(domain, event.event_name, parameter), param_name)) + pairs.append('%s:(%s)%s' % (param_name, self.objc_type_for_param(domain, event.event_name, parameter), param_name)) pairs[0] = ucfirst(pairs[0]) return '- (void)%sWith%s;' % (event.event_name, ' '.join(pairs)) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_internal_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_internal_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_internal_header.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_internal_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,17 +36,17 @@ log = logging.getLogger('global') -class ObjCInternalHeaderGenerator(Generator): +class ObjCInternalHeaderGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sInternal.h' % ObjCGenerator.OBJC_PREFIX + return '%sInternal.h' % self.protocol_name() def generate_output(self): headers = set([ - '"%s.h"' % ObjCGenerator.OBJC_PREFIX, - '"%sJSONObjectInternal.h"' % ObjCGenerator.OBJC_PREFIX, + '"%s.h"' % self.protocol_name(), + '"%sJSONObjectPrivate.h"' % self.protocol_name(), '', '', ]) @@ -68,7 +68,7 @@ def _generate_event_dispatcher_private_interfaces(self, domain): lines = [] if domain.events: - objc_name = '%s%sDomainEventDispatcher' % (ObjCGenerator.OBJC_PREFIX, domain.domain_name) + objc_name = '%s%sDomainEventDispatcher' % (self.objc_prefix(), domain.domain_name) lines.append('@interface %s (Private)' % objc_name) lines.append('- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller;') lines.append('@end') diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_header.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_header.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_header.py 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_header.py 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. +# Copyright (c) 2014 University of Washington. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + + +import logging +import string +from string import Template + +from generator import Generator +from models import EnumType +from objc_generator import ObjCGenerator +from objc_generator_templates import ObjCGeneratorTemplates as ObjCTemplates + +log = logging.getLogger('global') + + +def add_newline(lines): + if lines and lines[-1] == '': + return + lines.append('') + + +class ObjCProtocolTypeConversionsHeaderGenerator(ObjCGenerator): + def __init__(self, model, input_filepath): + ObjCGenerator.__init__(self, model, input_filepath) + + def output_filename(self): + return '%sTypeConversions.h' % self.protocol_name() + + def domains_to_generate(self): + return filter(ObjCGenerator.should_generate_domain_types_filter(self.model()), Generator.domains_to_generate(self)) + + def generate_output(self): + headers = [ + '"%s.h"' % self.protocol_name(), + '"%sArrayConversions.h"' % ObjCGenerator.OBJC_STATIC_PREFIX, + ] + headers.sort() + + header_args = { + 'includes': '\n'.join(['#import ' + header for header in headers]), + } + + domains = self.domains_to_generate() + sections = [] + sections.append(self.generate_license()) + sections.append(Template(ObjCTemplates.TypeConversionsHeaderPrelude).substitute(None, **header_args)) + sections.append(Template(ObjCTemplates.TypeConversionsHeaderStandard).substitute(None)) + sections.extend(map(self._generate_enum_conversion_functions, domains)) + sections.append(Template(ObjCTemplates.TypeConversionsHeaderPostlude).substitute(None, **header_args)) + return '\n\n'.join(sections) + + def _generate_enum_conversion_functions(self, domain): + lines = [] + + # Type enums and member enums. + for declaration in domain.type_declarations: + if isinstance(declaration.type, EnumType): + add_newline(lines) + lines.append(self._generate_anonymous_enum_conversion_for_declaration(domain, declaration)) + else: + for member in declaration.type_members: + if (isinstance(member.type, EnumType) and member.type.is_anonymous): + add_newline(lines) + lines.append(self._generate_anonymous_enum_conversion_for_member(domain, declaration, member)) + + # Anonymous command enums. + for command in domain.commands: + for parameter in command.call_parameters: + if (isinstance(parameter.type, EnumType) and parameter.type.is_anonymous): + add_newline(lines) + lines.append(self._generate_anonymous_enum_conversion_for_parameter(domain, command.command_name, parameter)) + for parameter in command.return_parameters: + if (isinstance(parameter.type, EnumType) and parameter.type.is_anonymous): + add_newline(lines) + lines.append(self._generate_anonymous_enum_conversion_for_parameter(domain, command.command_name, parameter)) + + # Anonymous event enums. + for event in domain.events: + for parameter in event.event_parameters: + if (isinstance(parameter.type, EnumType) and parameter.type.is_anonymous): + add_newline(lines) + lines.append(self._generate_anonymous_enum_conversion_for_parameter(domain, event.event_name, parameter)) + + return '\n'.join(lines) + + def _generate_anonymous_enum_conversion_for_declaration(self, domain, declaration): + objc_enum_name = self.objc_enum_name_for_anonymous_enum_declaration(declaration) + enum_values = declaration.type.enum_values() + lines = [] + lines.append(self._generate_enum_objc_to_protocol_string(objc_enum_name, enum_values)) + lines.append(self._generate_enum_from_protocol_string(objc_enum_name, enum_values)) + return '\n\n'.join(lines) + + def _generate_anonymous_enum_conversion_for_member(self, domain, declaration, member): + objc_enum_name = self.objc_enum_name_for_anonymous_enum_member(declaration, member) + enum_values = member.type.enum_values() + lines = [] + lines.append(self._generate_enum_objc_to_protocol_string(objc_enum_name, enum_values)) + lines.append(self._generate_enum_from_protocol_string(objc_enum_name, enum_values)) + return '\n\n'.join(lines) + + def _generate_anonymous_enum_conversion_for_parameter(self, domain, event_or_command_name, parameter): + objc_enum_name = self.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter) + enum_values = parameter.type.enum_values() + lines = [] + lines.append(self._generate_enum_objc_to_protocol_string(objc_enum_name, enum_values)) + lines.append(self._generate_enum_from_protocol_string(objc_enum_name, enum_values)) + return '\n\n'.join(lines) + + def _generate_enum_objc_to_protocol_string(self, objc_enum_name, enum_values): + lines = [] + lines.append('inline String toProtocolString(%s value)' % objc_enum_name) + lines.append('{') + lines.append(' switch(value) {') + for enum_value in enum_values: + lines.append(' case %s%s:' % (objc_enum_name, Generator.stylized_name_for_enum_value(enum_value))) + lines.append(' return ASCIILiteral("%s");' % enum_value) + lines.append(' }') + lines.append('}') + return '\n'.join(lines) + + def _generate_enum_from_protocol_string(self, objc_enum_name, enum_values): + lines = [] + lines.append('template<>') + lines.append('inline %s fromProtocolString(const String& value)' % objc_enum_name) + lines.append('{') + for enum_value in enum_values: + lines.append(' if (value == "%s")' % enum_value) + lines.append(' return %s%s;' % (objc_enum_name, Generator.stylized_name_for_enum_value(enum_value))) + lines.append(' ASSERT_NOT_REACHED();') + lines.append(' return %s%s;' % (objc_enum_name, Generator.stylized_name_for_enum_value(enum_values[0]))) + lines.append('}') + return '\n'.join(lines) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_implementation.py 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_type_conversions_implementation.py 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# +# Copyright (c) 2016 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + + +import logging +import string +from string import Template + +from generator import Generator +from models import EnumType, ObjectType, ArrayType, AliasedType, PrimitiveType, Frameworks +from objc_generator import ObjCGenerator +from objc_generator_templates import ObjCGeneratorTemplates as ObjCTemplates + +log = logging.getLogger('global') + + +def add_newline(lines): + if lines and lines[-1] == '': + return + lines.append('') + + +class ObjCProtocolTypeConversionsImplementationGenerator(ObjCGenerator): + def __init__(self, model, input_filepath): + ObjCGenerator.__init__(self, model, input_filepath) + + def output_filename(self): + return '%sTypeConversions.mm' % self.protocol_name() + + def domains_to_generate(self): + return filter(ObjCGenerator.should_generate_domain_types_filter(self.model()), Generator.domains_to_generate(self)) + + def generate_output(self): + secondary_headers = [ + '"%s.h"' % self.protocol_name(), + '"%sTypeParser.h"' % self.protocol_name(), + Generator.string_for_file_include('%sJSONObjectPrivate.h' % ObjCGenerator.OBJC_STATIC_PREFIX, Frameworks.WebInspector, self.model().framework), + ] + secondary_headers.sort() + + header_args = { + 'primaryInclude': '"%sTypeConversions.h"' % self.protocol_name(), + 'secondaryIncludes': '\n'.join(['#import ' + header for header in secondary_headers]), + } + + domains = self.domains_to_generate() + sections = [] + sections.append(self.generate_license()) + sections.append(Template(ObjCTemplates.ImplementationPrelude).substitute(None, **header_args)) + sections.append(self._generate_type_factory_category_interface(domains)) + sections.append(self._generate_type_factory_category_implementation(domains)) + sections.append(Template(ObjCTemplates.ImplementationPostlude).substitute(None, **header_args)) + return '\n\n'.join(sections) + + def _generate_type_factory_category_interface(self, domains): + lines = [] + for domain in domains: + lines.append('@interface %sTypeConversions (%sDomain)' % (self.protocol_name(), domain.domain_name)) + lines.append('') + + for declaration in domain.type_declarations: + lines.append(self._generate_type_factory_method_declaration(domain, declaration)) + + add_newline(lines) + lines.append('@end') + + return '\n'.join(lines) + + def _generate_type_factory_method_declaration(self, domain, declaration): + resolved_type = declaration.type + if isinstance(resolved_type, AliasedType): + resolved_type = resolved_type.aliased_type + if isinstance(resolved_type, (ObjectType, ArrayType, PrimitiveType)): + objc_type = self.objc_class_for_type(resolved_type) + return '+ (void)_parse%s:(%s **)outValue fromPayload:(id)payload;' % (declaration.type.raw_name(), objc_type) + if isinstance(resolved_type, EnumType): + return '+ (void)_parse%s:(NSNumber **)outValue fromPayload:(id)payload;' % declaration.type.raw_name() + + def _generate_type_factory_category_implementation(self, domains): + lines = [] + for domain in domains: + lines.append('@implementation %sTypeConversions (%sDomain)' % (self.protocol_name(), domain.domain_name)) + lines.append('') + + for declaration in domain.type_declarations: + lines.append(self._generate_type_factory_method_implementation(domain, declaration)) + add_newline(lines) + lines.append('@end') + return '\n'.join(lines) + + def _generate_type_factory_method_implementation(self, domain, declaration): + lines = [] + resolved_type = declaration.type + if isinstance(resolved_type, AliasedType): + resolved_type = resolved_type.aliased_type + + objc_class = self.objc_class_for_type(resolved_type) + if isinstance(resolved_type, (ObjectType, ArrayType, PrimitiveType)): + lines.append('+ (void)_parse%s:(%s **)outValue fromPayload:(id)payload' % (declaration.type.raw_name(), objc_class)) + if isinstance(resolved_type, EnumType): + lines.append('+ (void)_parse%s:(NSNumber **)outValue fromPayload:(id)payload' % declaration.type.raw_name()) + + lines.append('{') + if isinstance(resolved_type, EnumType): + lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]);') + lines.append(' *outValue = @(Inspector::fromProtocolString<%s>(payload));' % self.objc_name_for_type(resolved_type)) + elif isinstance(resolved_type, (ArrayType, PrimitiveType)): + lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE(payload, [%s class]);' % objc_class) + lines.append(' *outValue = (%s *)payload;' % objc_class) + elif isinstance(resolved_type, ObjectType): + lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]);') + lines.append(' *outValue = [[%s alloc] initWithPayload:payload];' % (objc_class)) + lines.append('}') + return '\n'.join(lines) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_types_implementation.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_types_implementation.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_types_implementation.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generate_objc_protocol_types_implementation.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ from string import Template from generator import Generator, ucfirst -from models import ObjectType +from models import ObjectType, Frameworks from objc_generator import ObjCGenerator from objc_generator_templates import ObjCGeneratorTemplates as ObjCTemplates @@ -43,25 +43,31 @@ lines.append('') -class ObjCProtocolTypesImplementationGenerator(Generator): +class ObjCProtocolTypesImplementationGenerator(ObjCGenerator): def __init__(self, model, input_filepath): - Generator.__init__(self, model, input_filepath) + ObjCGenerator.__init__(self, model, input_filepath) def output_filename(self): - return '%sTypes.mm' % ObjCGenerator.OBJC_PREFIX + return '%sTypes.mm' % self.protocol_name() def domains_to_generate(self): return filter(ObjCGenerator.should_generate_domain_types_filter(self.model()), Generator.domains_to_generate(self)) def generate_output(self): secondary_headers = [ - '"%sEnumConversionHelpers.h"' % ObjCGenerator.OBJC_PREFIX, + '"%sTypeConversions.h"' % self.protocol_name(), + Generator.string_for_file_include('%sJSONObjectPrivate.h' % ObjCGenerator.OBJC_STATIC_PREFIX, Frameworks.WebInspector, self.model().framework), '', '', ] + # The FooProtocolInternal.h header is only needed to declare the backend-side event dispatcher bindings. + primaryIncludeName = self.protocol_name() + if self.get_generator_setting('generate_backend', False): + primaryIncludeName += 'Internal' + header_args = { - 'primaryInclude': '"%sInternal.h"' % ObjCGenerator.OBJC_PREFIX, + 'primaryInclude': '"%s.h"' % primaryIncludeName, 'secondaryIncludes': '\n'.join(['#import %s' % header for header in secondary_headers]), } @@ -83,7 +89,12 @@ def generate_type_implementation(self, domain, declaration): lines = [] - lines.append('@implementation %s' % ObjCGenerator.objc_name_for_type(declaration.type)) + lines.append('@implementation %s' % self.objc_name_for_type(declaration.type)) + # The initializer that takes a payload is only needed by the frontend. + if self.get_generator_setting('generate_frontend', False): + lines.append('') + lines.append(self._generate_init_method_for_payload(domain, declaration)) + lines.append(self._generate_init_method_for_json_object(domain, declaration)) required_members = filter(lambda member: not member.is_optional, declaration.type_members) if required_members: lines.append('') @@ -97,18 +108,48 @@ lines.append('@end') return '\n'.join(lines) + def _generate_init_method_for_json_object(self, domain, declaration): + lines = [] + lines.append('- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject') + lines.append('{') + lines.append(' if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()]))') + lines.append(' return nil;') + lines.append('') + lines.append(' return self;') + lines.append('}') + return '\n'.join(lines) + + def _generate_init_method_for_payload(self, domain, declaration): + lines = [] + lines.append('- (instancetype)initWithPayload:(nonnull NSDictionary *)payload') + lines.append('{') + lines.append(' if (!(self = [super init]))') + lines.append(' return nil;') + lines.append('') + + for member in declaration.type_members: + var_name = ObjCGenerator.identifier_to_objc_identifier(member.member_name) + if not member.is_optional: + lines.append(' THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"%s"], @"%s");' % (var_name, var_name)) + conversion_expression = self.payload_to_objc_expression_for_member(declaration, member) + lines.append(' self.%s = %s;' % (var_name, conversion_expression)) + lines.append('') + + lines.append(' return self;') + lines.append('}') + return '\n'.join(lines) + def _generate_init_method_for_required_members(self, domain, declaration, required_members): pairs = [] for member in required_members: - objc_type = ObjCGenerator.objc_type_for_member(declaration, member) + objc_type = self.objc_type_for_member(declaration, member) var_name = ObjCGenerator.identifier_to_objc_identifier(member.member_name) pairs.append('%s:(%s)%s' % (var_name, objc_type, var_name)) pairs[0] = ucfirst(pairs[0]) lines = [] lines.append('- (instancetype)initWith%s;' % ' '.join(pairs)) lines.append('{') - lines.append(' self = [super init];') - lines.append(' if (!self)') + lines.append(' if (!(self = [super init]))') lines.append(' return nil;') lines.append('') @@ -117,8 +158,8 @@ for member in required_pointer_members: var_name = ObjCGenerator.identifier_to_objc_identifier(member.member_name) lines.append(' THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(%s, @"%s");' % (var_name, var_name)) - objc_array_class = ObjCGenerator.objc_class_for_array_type(member.type) - if objc_array_class and objc_array_class.startswith(ObjCGenerator.OBJC_PREFIX): + objc_array_class = self.objc_class_for_array_type(member.type) + if objc_array_class and objc_array_class.startswith(self.objc_prefix()): lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(%s, [%s class]);' % (var_name, objc_array_class)) lines.append('') @@ -132,26 +173,26 @@ return '\n'.join(lines) def _generate_setter_for_member(self, domain, declaration, member): - objc_type = ObjCGenerator.objc_type_for_member(declaration, member) + objc_type = self.objc_type_for_member(declaration, member) var_name = ObjCGenerator.identifier_to_objc_identifier(member.member_name) setter_method = ObjCGenerator.objc_setter_method_for_member(declaration, member) - conversion_expression = ObjCGenerator.objc_to_protocol_expression_for_member(declaration, member, var_name) + conversion_expression = self.objc_to_protocol_expression_for_member(declaration, member, var_name) lines = [] lines.append('- (void)set%s:(%s)%s' % (ucfirst(var_name), objc_type, var_name)) lines.append('{') - objc_array_class = ObjCGenerator.objc_class_for_array_type(member.type) - if objc_array_class and objc_array_class.startswith(ObjCGenerator.OBJC_PREFIX): + objc_array_class = self.objc_class_for_array_type(member.type) + if objc_array_class and objc_array_class.startswith(self.objc_prefix()): lines.append(' THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(%s, [%s class]);' % (var_name, objc_array_class)) lines.append(' [super %s:%s forKey:@"%s"];' % (setter_method, conversion_expression, member.member_name)) lines.append('}') return '\n'.join(lines) def _generate_getter_for_member(self, domain, declaration, member): - objc_type = ObjCGenerator.objc_type_for_member(declaration, member) + objc_type = self.objc_type_for_member(declaration, member) var_name = ObjCGenerator.identifier_to_objc_identifier(member.member_name) getter_method = ObjCGenerator.objc_getter_method_for_member(declaration, member) basic_expression = '[super %s:@"%s"]' % (getter_method, member.member_name) - conversion_expression = ObjCGenerator.protocol_to_objc_expression_for_member(declaration, member, basic_expression) + conversion_expression = self.protocol_to_objc_expression_for_member(declaration, member, basic_expression) lines = [] lines.append('- (%s)%s' % (objc_type, var_name)) lines.append('{') diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generator.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generator.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generator.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generator.py 2016-09-16 09:56:47.000000000 +0000 @@ -47,6 +47,7 @@ # FIXME: This should be converted into a property in JSON. _TYPES_NEEDING_RUNTIME_CASTS = set([ + "Runtime.ObjectPreview", "Runtime.RemoteObject", "Runtime.PropertyDescriptor", "Runtime.InternalPropertyDescriptor", @@ -78,10 +79,18 @@ def __init__(self, model, input_filepath): self._model = model self._input_filepath = input_filepath + self._settings = {} def model(self): return self._model + def set_generator_setting(self, key, value): + self._settings[key] = value + + # The goofy name is to disambiguate generator settings from framework settings. + def get_generator_setting(self, key, default=None): + return self._settings.get(key, default) + def generate_license(self): return Template(Templates.CopyrightBlock).substitute(None, inputFilename=os.path.basename(self._input_filepath)) @@ -239,3 +248,10 @@ return 'number' else: return _type.qualified_name() + + @staticmethod + def string_for_file_include(filename, file_framework, target_framework): + if file_framework is target_framework: + return '"%s"' % filename + else: + return '<%s/%s>' % (file_framework.name, filename) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generator_templates.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generator_templates.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/generator_templates.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/generator_templates.py 2016-09-16 09:56:47.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # Copyright (c) 2014 University of Washington. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ CopyrightBlock = ( """/* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/__init__.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/__init__.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/__init__.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/__init__.py 2016-09-16 09:56:47.000000000 +0000 @@ -17,8 +17,9 @@ from generate_objc_backend_dispatcher_implementation import * from generate_objc_configuration_header import * from generate_objc_configuration_implementation import * -from generate_objc_conversion_helpers import * from generate_objc_frontend_dispatcher_implementation import * from generate_objc_header import * from generate_objc_internal_header import * from generate_objc_protocol_types_implementation import * +from generate_objc_protocol_type_conversions_header import * +from generate_objc_protocol_type_conversions_implementation import * diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/models.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/models.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/models.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/models.py 2016-09-19 12:18:06.000000000 +0000 @@ -42,12 +42,25 @@ "Global": { }, "JavaScriptCore": { - "export_macro": "JS_EXPORT_PRIVATE" + "cpp_protocol_group": "Inspector", + "export_macro": "JS_EXPORT_PRIVATE", + "alternate_dispatchers": True, + }, + "WebKit": { + "cpp_protocol_group": "Automation", + "objc_protocol_group": "WD", + "objc_prefix": "WD", }, "WebInspector": { + "objc_protocol_group": "RWI", + "objc_prefix": "RWI", }, # Used for code generator tests. "Test": { + "alternate_dispatchers": True, + "cpp_protocol_group": "Test", + "objc_protocol_group": "Test", + "objc_prefix": "Test", } } @@ -76,6 +89,9 @@ if frameworkString == "JavaScriptCore": return Frameworks.JavaScriptCore + if frameworkString == "WebKit": + return Frameworks.WebKit + if frameworkString == "WebInspector": return Frameworks.WebInspector @@ -88,6 +104,7 @@ class Frameworks: Global = Framework("Global") JavaScriptCore = Framework("JavaScriptCore") + WebKit = Framework("WebKit") WebInspector = Framework("WebInspector") Test = Framework("Test") @@ -105,6 +122,10 @@ if type_kind is not None and referenced_type_name is not None: raise ParseException("Type reference cannot have both 'type' and '$ref' keys.") + all_primitive_types = ["integer", "number", "string", "boolean", "enum", "object", "array", "any"] + if type_kind is not None and type_kind not in all_primitive_types: + raise ParseException("Type reference '%s' is not a primitive type. Allowed values: %s" % (type_kind, ', '.join(all_primitive_types))) + if type_kind == "array" and array_items is None: raise ParseException("Type reference with type 'array' must have key 'items' to define array element type.") @@ -115,7 +136,7 @@ if self.referenced_type_name is not None: return self.referenced_type_name else: - return self.type_kind # integer, string, number, boolean, enum, object, array + return self.type_kind # one of all_primitive_types class Type: @@ -161,8 +182,9 @@ class AliasedType(Type): - def __init__(self, name, domain, aliased_type_ref): - self._name = name + def __init__(self, declaration, domain, aliased_type_ref): + self._name = declaration.type_name + self._declaration = declaration self._domain = domain self._aliased_type_ref = aliased_type_ref self.aliased_type = None @@ -191,8 +213,9 @@ class EnumType(Type): - def __init__(self, name, domain, values, primitive_type_ref, is_anonymous=False): - self._name = name + def __init__(self, declaration, domain, values, primitive_type_ref, is_anonymous=False): + self._name = "(anonymous)" if declaration is None else declaration.type_name + self._declaration = declaration self._domain = domain self._values = values self._primitive_type_ref = primitive_type_ref @@ -205,11 +228,14 @@ def is_enum(self): return True + def enum_values(self): + return self._values + def type_domain(self): return self._domain - def enum_values(self): - return self._values + def declaration(self): + return self._declaration def qualified_name(self): return ".".join([self.type_domain().domain_name, self.raw_name()]) @@ -224,8 +250,9 @@ class ArrayType(Type): - def __init__(self, name, element_type_ref, domain): - self._name = name + def __init__(self, declaration, element_type_ref, domain): + self._name = None if declaration is None else declaration.type_name + self._declaration = declaration self._domain = domain self._element_type_ref = element_type_ref self.element_type = None @@ -236,6 +263,9 @@ else: return 'ArrayType[element_type=(unresolved)]' + def declaration(self): + return self._declaration + def type_domain(self): return self._domain @@ -251,14 +281,18 @@ class ObjectType(Type): - def __init__(self, name, domain, members): - self._name = name + def __init__(self, declaration, domain): + self._name = declaration.type_name + self._declaration = declaration self._domain = domain - self.members = members + self.members = declaration.type_members def __repr__(self): return 'ObjectType[%s]' % self.qualified_name() + def declaration(self): + return self._declaration + def type_domain(self): return self._domain @@ -425,13 +459,13 @@ kind = declaration.type_ref.type_kind if declaration.type_ref.enum_values is not None: primitive_type_ref = TypeReference(declaration.type_ref.type_kind, None, None, None) - type_instance = EnumType(declaration.type_name, domain, declaration.type_ref.enum_values, primitive_type_ref) + type_instance = EnumType(declaration, domain, declaration.type_ref.enum_values, primitive_type_ref) elif kind == "array": - type_instance = ArrayType(declaration.type_name, declaration.type_ref.array_type_ref, domain) + type_instance = ArrayType(declaration, declaration.type_ref.array_type_ref, domain) elif kind == "object": - type_instance = ObjectType(declaration.type_name, domain, declaration.type_members) + type_instance = ObjectType(declaration, domain) else: - type_instance = AliasedType(declaration.type_name, domain, declaration.type_ref) + type_instance = AliasedType(declaration, domain, declaration.type_ref) log.debug("< Created fresh type %r for declaration %s" % (type_instance, qualified_type_name)) self.types_by_name[qualified_type_name] = type_instance @@ -462,7 +496,7 @@ if type_ref.enum_values is not None: # We need to create a type reference without enum values as the enum's nested type. primitive_type_ref = TypeReference(type_ref.type_kind, None, None, None) - type_instance = EnumType("(anonymous)", domain, type_ref.enum_values, primitive_type_ref, True) + type_instance = EnumType(None, domain, type_ref.enum_values, primitive_type_ref, True) type_instance.resolve_type_references(self) log.debug("< Created fresh type instance for anonymous enum type: %s" % type_instance.qualified_name()) return type_instance diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator.py 2016-09-19 12:18:06.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2014 Apple Inc. All rights reserved. +# Copyright (c) 2014, 2016 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -79,14 +79,32 @@ return ObjCTypeCategory.category_for_type(_type.primitive_type) return None +# Almost all Objective-C class names require the use of a prefix that depends on the +# target framework's 'objc_prefix' setting. So, most helpers are instance methods. - -# This class contains extra static methods used for generation, but does -# not participate in any inheritance hierarchy. File generators should -# extend the generic "Generator" class instead. -class ObjCGenerator: - OBJC_PREFIX = 'RWIProtocol' - OBJC_JSON_OBJECT_BASE = '%sJSONObject' % OBJC_PREFIX +class ObjCGenerator(Generator): + # Do not use a dynamic prefix for RWIProtocolJSONObject since it's used as a common + # base class and needs a consistent Objective-C prefix to be in a reusable framework. + OBJC_HELPER_PREFIX = 'RWI' + OBJC_SHARED_PREFIX = 'Protocol' + OBJC_STATIC_PREFIX = '%s%s' % (OBJC_HELPER_PREFIX, OBJC_SHARED_PREFIX) + + def __init__(self, model, input_filepath): + Generator.__init__(self, model, input_filepath) + + # The 'protocol name' is used to prefix filenames for a protocol group (a set of domains generated together). + def protocol_name(self): + protocol_group = self.model().framework.setting('objc_protocol_group', '') + return '%s%s' % (protocol_group, ObjCGenerator.OBJC_SHARED_PREFIX) + + # The 'ObjC prefix' is used to prefix Objective-C class names and enums with a + # framework-specific prefix. It is separate from filename prefixes. + def objc_prefix(self): + framework_prefix = self.model().framework.setting('objc_prefix', None) + if not framework_prefix: + return '' + else: + return '%s%s' % (framework_prefix, ObjCGenerator.OBJC_SHARED_PREFIX) # Adjust identifier names that collide with ObjC keywords. @@ -100,7 +118,7 @@ # Generate ObjC types, command handlers, and event dispatchers for a subset of domains. - DOMAINS_TO_GENERATE = ['CSS', 'DOM', 'DOMStorage', 'Network', 'Page', 'GenericTypes'] + DOMAINS_TO_GENERATE = ['CSS', 'DOM', 'DOMStorage', 'Network', 'Page', 'Automation', 'GenericTypes'] @staticmethod def should_generate_domain_types_filter(model): @@ -133,39 +151,34 @@ # ObjC enum and type names. - @staticmethod - def objc_name_for_type(type): + def objc_name_for_type(self, type): name = type.qualified_name().replace('.', '') name = remove_duplicate_from_str(name, type.type_domain().domain_name) - return '%s%s' % (ObjCGenerator.OBJC_PREFIX, name) + return '%s%s' % (self.objc_prefix(), name) - @staticmethod - def objc_enum_name_for_anonymous_enum_declaration(declaration): + def objc_enum_name_for_anonymous_enum_declaration(self, declaration): domain_name = declaration.type.type_domain().domain_name name = '%s%s' % (domain_name, declaration.type.raw_name()) name = remove_duplicate_from_str(name, domain_name) - return '%s%s' % (ObjCGenerator.OBJC_PREFIX, name) + return '%s%s' % (self.objc_prefix(), name) - @staticmethod - def objc_enum_name_for_anonymous_enum_member(declaration, member): + def objc_enum_name_for_anonymous_enum_member(self, declaration, member): domain_name = member.type.type_domain().domain_name name = '%s%s%s' % (domain_name, declaration.type.raw_name(), ucfirst(member.member_name)) name = remove_duplicate_from_str(name, domain_name) - return '%s%s' % (ObjCGenerator.OBJC_PREFIX, name) + return '%s%s' % (self.objc_prefix(), name) - @staticmethod - def objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter): + def objc_enum_name_for_anonymous_enum_parameter(self, domain, event_or_command_name, parameter): domain_name = domain.domain_name name = '%s%s%s' % (domain_name, ucfirst(event_or_command_name), ucfirst(parameter.parameter_name)) name = remove_duplicate_from_str(name, domain_name) - return '%s%s' % (ObjCGenerator.OBJC_PREFIX, name) + return '%s%s' % (self.objc_prefix(), name) - @staticmethod - def objc_enum_name_for_non_anonymous_enum(_type): + def objc_enum_name_for_non_anonymous_enum(self, _type): domain_name = _type.type_domain().domain_name name = _type.qualified_name().replace('.', '') name = remove_duplicate_from_str(name, domain_name) - return '%s%s' % (ObjCGenerator.OBJC_PREFIX, name) + return '%s%s' % (self.objc_prefix(), name) # Miscellaneous name handling. @@ -203,7 +216,7 @@ if raw_name is 'boolean': return 'BOOL' if raw_name in ['any', 'object']: - return '%s *' % ObjCGenerator.OBJC_JSON_OBJECT_BASE + return '%sJSONObject *' % ObjCGenerator.OBJC_STATIC_PREFIX return None @staticmethod @@ -215,7 +228,7 @@ if raw_name in ['integer', 'number', 'boolean']: return 'NSNumber' if raw_name in ['any', 'object']: - return ObjCGenerator.OBJC_JSON_OBJECT_BASE + return '%sJSONObject' % ObjCGenerator.OBJC_STATIC_PREFIX return None # FIXME: Can these protocol_type functions be removed in favor of C++ generators functions? @@ -263,8 +276,7 @@ return True return None - @staticmethod - def objc_class_for_type(_type): + def objc_class_for_type(self, _type): if (isinstance(_type, AliasedType)): _type = _type.aliased_type if (isinstance(_type, PrimitiveType)): @@ -272,30 +284,27 @@ if (isinstance(_type, EnumType)): return ObjCGenerator.objc_class_for_raw_name(_type.primitive_type.raw_name()) if (isinstance(_type, ObjectType)): - return ObjCGenerator.objc_name_for_type(_type) + return self.objc_name_for_type(_type) if (isinstance(_type, ArrayType)): - sub_type = strip_block_comment_markers(ObjCGenerator.objc_class_for_type(_type.element_type)) + sub_type = strip_block_comment_markers(self.objc_class_for_type(_type.element_type)) return 'NSArray/*<%s>*/' % sub_type return None - @staticmethod - def objc_class_for_array_type(_type): + def objc_class_for_array_type(self, _type): if isinstance(_type, AliasedType): _type = _type.aliased_type if isinstance(_type, ArrayType): - return ObjCGenerator.objc_class_for_type(_type.element_type) + return self.objc_class_for_type(_type.element_type) return None - @staticmethod - def objc_accessor_type_for_member(member): - return ObjCGenerator.objc_accessor_type_for_member_internal(member.type) + def objc_accessor_type_for_member(self, member): + return self.objc_accessor_type_for_member_internal(member.type) - @staticmethod - def objc_accessor_type_for_member_internal(_type): + def objc_accessor_type_for_member_internal(self, _type): if (isinstance(_type, AliasedType)): _type = _type.aliased_type if (isinstance(_type, PrimitiveType)): - return ObjCGenerator.objc_accessor_type_for_raw_name(_type.raw_name()) + return self.objc_accessor_type_for_raw_name(_type.raw_name()) if (isinstance(_type, EnumType)): return 'assign' if (isinstance(_type, ObjectType)): @@ -304,50 +313,46 @@ return 'copy' return None - @staticmethod - def objc_type_for_member(declaration, member): - return ObjCGenerator.objc_type_for_member_internal(member.type, declaration, member) + def objc_type_for_member(self, declaration, member): + return self.objc_type_for_member_internal(member.type, declaration, member) - @staticmethod - def objc_type_for_member_internal(_type, declaration, member): + def objc_type_for_member_internal(self, _type, declaration, member): if (isinstance(_type, AliasedType)): _type = _type.aliased_type if (isinstance(_type, PrimitiveType)): - return ObjCGenerator.objc_type_for_raw_name(_type.raw_name()) + return self.objc_type_for_raw_name(_type.raw_name()) if (isinstance(_type, EnumType)): if (_type.is_anonymous): - return ObjCGenerator.objc_enum_name_for_anonymous_enum_member(declaration, member) - return ObjCGenerator.objc_enum_name_for_non_anonymous_enum(_type) + return self.objc_enum_name_for_anonymous_enum_member(declaration, member) + return self.objc_enum_name_for_non_anonymous_enum(_type) if (isinstance(_type, ObjectType)): - return ObjCGenerator.objc_name_for_type(_type) + ' *' + return self.objc_name_for_type(_type) + ' *' if (isinstance(_type, ArrayType)): - sub_type = strip_block_comment_markers(ObjCGenerator.objc_class_for_type(_type.element_type)) + sub_type = strip_block_comment_markers(self.objc_class_for_type(_type.element_type)) return 'NSArray/*<%s>*/ *' % sub_type return None - @staticmethod - def objc_type_for_param(domain, event_or_command_name, parameter, respect_optional=True): - objc_type = ObjCGenerator.objc_type_for_param_internal(parameter.type, domain, event_or_command_name, parameter) + def objc_type_for_param(self, domain, event_or_command_name, parameter, respect_optional=True): + objc_type = self.objc_type_for_param_internal(parameter.type, domain, event_or_command_name, parameter) if respect_optional and parameter.is_optional: if objc_type.endswith('*'): return objc_type + '*' return objc_type + ' *' return objc_type - @staticmethod - def objc_type_for_param_internal(_type, domain, event_or_command_name, parameter): + def objc_type_for_param_internal(self, _type, domain, event_or_command_name, parameter): if (isinstance(_type, AliasedType)): _type = _type.aliased_type if (isinstance(_type, PrimitiveType)): - return ObjCGenerator.objc_type_for_raw_name(_type.raw_name()) + return self.objc_type_for_raw_name(_type.raw_name()) if (isinstance(_type, EnumType)): if _type.is_anonymous: - return ObjCGenerator.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter) - return ObjCGenerator.objc_enum_name_for_non_anonymous_enum(_type) + return self.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter) + return self.objc_enum_name_for_non_anonymous_enum(_type) if (isinstance(_type, ObjectType)): - return ObjCGenerator.objc_name_for_type(_type) + ' *' + return self.objc_name_for_type(_type) + ' *' if (isinstance(_type, ArrayType)): - sub_type = strip_block_comment_markers(ObjCGenerator.objc_class_for_type(_type.element_type)) + sub_type = strip_block_comment_markers(self.objc_class_for_type(_type.element_type)) return 'NSArray/*<%s>*/ *' % sub_type return None @@ -356,8 +361,7 @@ # - convert a command return parameter in callback block from ObjC to Protocol to send # - convert an event parameter from ObjC API to Protocol to send - @staticmethod - def objc_protocol_export_expression_for_variable(var_type, var_name): + def objc_protocol_export_expression_for_variable(self, var_type, var_name): category = ObjCTypeCategory.category_for_type(var_type) if category in [ObjCTypeCategory.Simple, ObjCTypeCategory.String]: if isinstance(var_type, EnumType): @@ -367,7 +371,7 @@ return '[%s toInspectorObject]' % var_name if category is ObjCTypeCategory.Array: protocol_type = ObjCGenerator.protocol_type_for_type(var_type.element_type) - objc_class = ObjCGenerator.objc_class_for_type(var_type.element_type) + objc_class = self.objc_class_for_type(var_type.element_type) if protocol_type == 'Inspector::Protocol::Array': return 'inspectorStringArrayArray(%s)' % var_name if protocol_type is 'String' and objc_class is 'NSString': @@ -378,32 +382,29 @@ return 'inspectorDoubleArray(%s)' % var_name return 'inspectorObjectArray(%s)' % var_name - @staticmethod - def objc_protocol_import_expression_for_member(name, declaration, member): + def objc_protocol_import_expression_for_member(self, name, declaration, member): if isinstance(member.type, EnumType): if member.type.is_anonymous: - return 'fromProtocolString<%s>(%s)' % (ObjCGenerator.objc_enum_name_for_anonymous_enum_member(declaration, member), name) - return 'fromProtocolString<%s>(%s)' % (ObjCGenerator.objc_enum_name_for_non_anonymous_enum(member.type), name) - return ObjCGenerator.objc_protocol_import_expression_for_variable(member.type, name) + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_anonymous_enum_member(declaration, member), name) + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_non_anonymous_enum(member.type), name) + return self.objc_protocol_import_expression_for_variable(member.type, name) - @staticmethod - def objc_protocol_import_expression_for_parameter(name, domain, event_or_command_name, parameter): + def objc_protocol_import_expression_for_parameter(self, name, domain, event_or_command_name, parameter): if isinstance(parameter.type, EnumType): if parameter.type.is_anonymous: - return 'fromProtocolString<%s>(%s)' % (ObjCGenerator.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter), name) - return 'fromProtocolString<%s>(%s)' % (ObjCGenerator.objc_enum_name_for_non_anonymous_enum(parameter.type), name) - return ObjCGenerator.objc_protocol_import_expression_for_variable(parameter.type, name) + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_anonymous_enum_parameter(domain, event_or_command_name, parameter), name) + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_non_anonymous_enum(parameter.type), name) + return self.objc_protocol_import_expression_for_variable(parameter.type, name) - @staticmethod - def objc_protocol_import_expression_for_variable(var_type, var_name): + def objc_protocol_import_expression_for_variable(self, var_type, var_name): category = ObjCTypeCategory.category_for_type(var_type) if category in [ObjCTypeCategory.Simple, ObjCTypeCategory.String]: return var_name if category is ObjCTypeCategory.Object: - objc_class = ObjCGenerator.objc_class_for_type(var_type) + objc_class = self.objc_class_for_type(var_type) return '[[[%s alloc] initWithInspectorObject:%s] autorelease]' % (objc_class, var_name) if category is ObjCTypeCategory.Array: - objc_class = ObjCGenerator.objc_class_for_type(var_type.element_type) + objc_class = self.objc_class_for_type(var_type.element_type) if objc_class is 'NSString': return 'objcStringArray(%s)' % var_name if objc_class is 'NSNumber': # FIXME: Integer or Double? @@ -414,8 +415,7 @@ # - convert a member setter from ObjC API to JSON object setter # - convert a member getter from JSON object to ObjC API - @staticmethod - def objc_to_protocol_expression_for_member(declaration, member, sub_expression): + def objc_to_protocol_expression_for_member(self, declaration, member, sub_expression): category = ObjCTypeCategory.category_for_type(member.type) if category in [ObjCTypeCategory.Simple, ObjCTypeCategory.String]: if isinstance(member.type, EnumType): @@ -424,7 +424,7 @@ if category is ObjCTypeCategory.Object: return sub_expression if category is ObjCTypeCategory.Array: - objc_class = ObjCGenerator.objc_class_for_type(member.type.element_type) + objc_class = self.objc_class_for_type(member.type.element_type) if objc_class is 'NSString': return 'inspectorStringArray(%s)' % sub_expression if objc_class is 'NSNumber': @@ -434,21 +434,20 @@ return 'inspectorIntegerArray(%s)' % sub_expression return 'inspectorObjectArray(%s)' % sub_expression - @staticmethod - def protocol_to_objc_expression_for_member(declaration, member, sub_expression): + def protocol_to_objc_expression_for_member(self, declaration, member, sub_expression): category = ObjCTypeCategory.category_for_type(member.type) if category in [ObjCTypeCategory.Simple, ObjCTypeCategory.String]: if isinstance(member.type, EnumType): if member.type.is_anonymous: - return 'fromProtocolString<%s>(%s)' % (ObjCGenerator.objc_enum_name_for_anonymous_enum_member(declaration, member), sub_expression) - return 'fromProtocolString<%s>(%s)' % (ObjCGenerator.objc_enum_name_for_non_anonymous_enum(member.type), sub_expression) + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_anonymous_enum_member(declaration, member), sub_expression) + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_non_anonymous_enum(member.type), sub_expression) return sub_expression if category is ObjCTypeCategory.Object: - objc_type = ObjCGenerator.objc_type_for_member(declaration, member) - return '(%s)%s' % (objc_type, sub_expression) + objc_class = self.objc_class_for_type(member.type) + return '[[%s alloc] initWithInspectorObject:[%s toInspectorObject].get()]' % (objc_class, sub_expression) if category is ObjCTypeCategory.Array: protocol_type = ObjCGenerator.protocol_type_for_type(member.type.element_type) - objc_class = ObjCGenerator.objc_class_for_type(member.type.element_type) + objc_class = self.objc_class_for_type(member.type.element_type) if objc_class is 'NSString': return 'objcStringArray(%s)' % sub_expression if objc_class is 'NSNumber': @@ -458,6 +457,35 @@ return 'objcIntegerArray(%s)' % sub_expression return 'objcArray<%s>(%s)' % (objc_class, sub_expression) + def payload_to_objc_expression_for_member(self, declaration, member): + _type = member.type + if isinstance(_type, AliasedType): + _type = _type.aliased_type + if isinstance(_type, PrimitiveType): + sub_expression = 'payload[@"%s"]' % member.member_name + raw_name = _type.raw_name() + if raw_name is 'boolean': + return '[%s boolValue]' % sub_expression + if raw_name is 'integer': + return '[%s integerValue]' % sub_expression + if raw_name is 'number': + return '[%s doubleValue]' % sub_expression + if raw_name in ['any', 'object', 'array', 'string']: + return sub_expression # The setter will check the incoming value. + return None + if isinstance(member.type, EnumType): + sub_expression = 'payload[@"%s"]' % member.member_name + if member.type.is_anonymous: + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_anonymous_enum_member(declaration, member), sub_expression) + else: + return 'fromProtocolString<%s>(%s)' % (self.objc_enum_name_for_non_anonymous_enum(member.type), sub_expression) + if isinstance(_type, ObjectType): + objc_class = self.objc_class_for_type(member.type) + return '[[%s alloc] initWithPayload:payload[@"%s"]]' % (objc_class, member.member_name) + if isinstance(_type, ArrayType): + objc_class = self.objc_class_for_type(member.type.element_type) + return 'objcArrayFromPayload<%s>(payload[@"%s"])' % (objc_class, member.member_name) + # JSON object setter/getter selectors for types. @staticmethod diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator_templates.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator_templates.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator_templates.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/codegen/objc_generator_templates.py 2016-09-16 09:56:47.000000000 +0000 @@ -38,12 +38,12 @@ HeaderPostlude = ( """""") - ConversionHelpersPrelude = ( + TypeConversionsHeaderPrelude = ( """${includes} namespace Inspector {""") - ConversionHelpersPostlude = ( + TypeConversionsHeaderPostlude = ( """} // namespace Inspector """) @@ -53,7 +53,7 @@ GenericHeaderPostlude = ( """""") - ConversionHelpersStandard = ( + TypeConversionsHeaderStandard = ( """template ObjCEnumType fromProtocolString(const String& value);""") diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py 2016-09-16 09:56:47.000000000 +0000 @@ -68,10 +68,11 @@ from generate_objc_backend_dispatcher_implementation import * from generate_objc_configuration_header import * from generate_objc_configuration_implementation import * - from generate_objc_conversion_helpers import * from generate_objc_frontend_dispatcher_implementation import * from generate_objc_header import * from generate_objc_internal_header import * + from generate_objc_protocol_type_conversions_header import * + from generate_objc_protocol_type_conversions_implementation import * from generate_objc_protocol_types_implementation import * @@ -112,7 +113,9 @@ concatenate_output=False, output_dirpath=None, force_output=False, - framework_name=""): + framework_name="", + generate_frontend=True, + generate_backend=True): def load_specification(protocol, filepath, isSupplemental=False): try: @@ -120,7 +123,7 @@ parsed_json = json.load(input_file) protocol.parse_specification(parsed_json, isSupplemental) except ValueError as e: - raise Exception("Error parsing valid JSON in file: " + filepath) + raise Exception("Error parsing valid JSON in file: " + filepath + "\nParse error: " + str(e)) protocol = models.Protocol(framework_name) for specification in supplemental_specification_filepaths: @@ -130,30 +133,69 @@ protocol.resolve_types() generators = [] - is_test = protocol.framework is Frameworks.Test - if is_test or protocol.framework is not Frameworks.WebInspector: - generators.append(CppAlternateBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) + if protocol.framework is Frameworks.Test: generators.append(JSBackendCommandsGenerator(protocol, primary_specification_filepath)) + generators.append(CppAlternateBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) generators.append(CppBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) generators.append(CppBackendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) generators.append(CppFrontendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) generators.append(CppFrontendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) generators.append(CppProtocolTypesHeaderGenerator(protocol, primary_specification_filepath)) generators.append(CppProtocolTypesImplementationGenerator(protocol, primary_specification_filepath)) - if is_test or protocol.framework is Frameworks.WebInspector: generators.append(ObjCBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) generators.append(ObjCBackendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) generators.append(ObjCConfigurationHeaderGenerator(protocol, primary_specification_filepath)) generators.append(ObjCConfigurationImplementationGenerator(protocol, primary_specification_filepath)) - generators.append(ObjCConversionHelpersGenerator(protocol, primary_specification_filepath)) generators.append(ObjCFrontendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) generators.append(ObjCHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCInternalHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypeConversionsHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypeConversionsImplementationGenerator(protocol, primary_specification_filepath)) generators.append(ObjCProtocolTypesImplementationGenerator(protocol, primary_specification_filepath)) + + elif protocol.framework is Frameworks.JavaScriptCore: + generators.append(JSBackendCommandsGenerator(protocol, primary_specification_filepath)) + generators.append(CppAlternateBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(CppBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(CppBackendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(CppFrontendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(CppFrontendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(CppProtocolTypesHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(CppProtocolTypesImplementationGenerator(protocol, primary_specification_filepath)) + + elif protocol.framework is Frameworks.WebKit and generate_backend: + generators.append(CppBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(CppBackendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(CppProtocolTypesHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(CppProtocolTypesImplementationGenerator(protocol, primary_specification_filepath)) + + elif protocol.framework is Frameworks.WebKit and generate_frontend: + generators.append(ObjCHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypeConversionsHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypeConversionsImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypesImplementationGenerator(protocol, primary_specification_filepath)) + + elif protocol.framework is Frameworks.WebInspector: + generators.append(ObjCBackendDispatcherHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCBackendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCConfigurationHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCConfigurationImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCFrontendDispatcherImplementationGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCHeaderGenerator(protocol, primary_specification_filepath)) generators.append(ObjCInternalHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypeConversionsHeaderGenerator(protocol, primary_specification_filepath)) + generators.append(ObjCProtocolTypesImplementationGenerator(protocol, primary_specification_filepath)) single_output_file_contents = [] for generator in generators: + # Only some generators care whether frontend or backend was specified, but it is + # set on all of them to avoid adding more constructor arguments or thinking too hard. + if generate_backend: + generator.set_generator_setting('generate_backend', True) + if generate_frontend: + generator.set_generator_setting('generate_frontend', True) + output = generator.generate_output() if concatenate_output: single_output_file_contents.append('### Begin File: %s' % generator.output_filename()) @@ -173,14 +215,15 @@ if __name__ == '__main__': - allowed_framework_names = ['JavaScriptCore', 'WebInspector', 'Test'] + allowed_framework_names = ['JavaScriptCore', 'WebInspector', 'WebKit', 'Test'] cli_parser = optparse.OptionParser(usage="usage: %prog [options] PrimaryProtocol.json [SupplementalProtocol.json ...]") cli_parser.add_option("-o", "--outputDir", help="Directory where generated files should be written.") cli_parser.add_option("--framework", type="choice", choices=allowed_framework_names, help="The framework that the primary specification belongs to.") cli_parser.add_option("--force", action="store_true", help="Force output of generated scripts, even if nothing changed.") cli_parser.add_option("-v", "--debug", action="store_true", help="Log extra output for debugging the generator itself.") cli_parser.add_option("-t", "--test", action="store_true", help="Enable test mode. Use unique output filenames created by prepending the input filename.") - + cli_parser.add_option("--frontend", action="store_true", help="Generate code for the frontend-side of the protocol only.") + cli_parser.add_option("--backend", action="store_true", help="Generate code for the backend-side of the protocol only.") options = None arg_options, arg_values = cli_parser.parse_args() @@ -193,13 +236,22 @@ if arg_options.debug: log.setLevel(logging.DEBUG) + generate_backend = arg_options.backend; + generate_frontend = arg_options.frontend; + # Default to generating both the frontend and backend if neither is specified. + if not generate_backend and not generate_frontend: + generate_backend = True + generate_frontend = True + options = { 'primary_specification_filepath': arg_values[0], 'supplemental_specification_filepaths': arg_values[1:], 'output_dirpath': arg_options.outputDir, 'concatenate_output': arg_options.test, 'framework_name': arg_options.framework, - 'force_output': arg_options.force + 'force_output': arg_options.force, + 'generate_backend': generate_backend, + 'generate_frontend': generate_frontend, } try: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-async-attribute.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-async-attribute.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-async-attribute.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-async-attribute.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,46 +29,20 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - -class AlternateDatabaseBackendDispatcher : public AlternateBackendDispatcher { -public: - virtual ~AlternateDatabaseBackendDispatcher() { } - virtual void executeSQLSyncOptionalReturnValues(long callId, int in_databaseId, const String& in_query) = 0; - virtual void executeSQLAsyncOptionalReturnValues(long callId, int in_databaseId, const String& in_query) = 0; - virtual void executeSQLSync(long callId, int in_databaseId, const String& in_query) = 0; - virtual void executeSQLAsync(long callId, int in_databaseId, const String& in_query) = 0; -}; - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Database. +InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); +InspectorBackend.registerEnum("Database.PrimaryColors", {Red: "red", Green: "green", Blue: "blue"}); +InspectorBackend.registerCommand("Database.executeSQLSyncOptionalReturnValues", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.registerCommand("Database.executeSQLAsyncOptionalReturnValues", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.registerCommand("Database.executeSQLSync", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "alternateColors", "screenColor", "printColor"]); +InspectorBackend.registerCommand("Database.executeSQLAsync", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.activateDomain("Database"); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -96,20 +70,43 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Database. -InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); -InspectorBackend.registerEnum("Database.PrimaryColors", {Red: "red", Green: "green", Blue: "blue"}); -InspectorBackend.registerCommand("Database.executeSQLSyncOptionalReturnValues", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.registerCommand("Database.executeSQLAsyncOptionalReturnValues", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.registerCommand("Database.executeSQLSync", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "alternateColors", "screenColor", "printColor"]); -InspectorBackend.registerCommand("Database.executeSQLAsync", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.activateDomain("Database"); -### End File: InspectorBackendCommands.js +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + -### Begin File: InspectorBackendDispatchers.h +class AlternateDatabaseBackendDispatcher : public AlternateBackendDispatcher { +public: + virtual ~AlternateDatabaseBackendDispatcher() { } + virtual void executeSQLSyncOptionalReturnValues(long callId, int in_databaseId, const String& in_query) = 0; + virtual void executeSQLAsyncOptionalReturnValues(long callId, int in_databaseId, const String& in_query) = 0; + virtual void executeSQLSync(long callId, int in_databaseId, const String& in_query) = 0; + virtual void executeSQLAsync(long callId, int in_databaseId, const String& in_query) = 0; +}; + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -137,10 +134,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -154,12 +150,6 @@ class DatabaseBackendDispatcherHandler { public: - // Named after parameter 'screenColor' while generating command/event executeSQLSyncOptionalReturnValues. - enum class ScreenColor { - Red = 0, - Green = 1, - Blue = 2, - }; // enum class ScreenColor // Named after parameter 'printColor' while generating command/event executeSQLSyncOptionalReturnValues. enum class PrintColor { Cyan = 3, @@ -188,32 +178,30 @@ class DatabaseBackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref create(BackendDispatcher&, DatabaseBackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; private: void executeSQLSyncOptionalReturnValues(long requestId, RefPtr&& parameters); void executeSQLAsyncOptionalReturnValues(long requestId, RefPtr&& parameters); void executeSQLSync(long requestId, RefPtr&& parameters); void executeSQLAsync(long requestId, RefPtr&& parameters); -private: - DatabaseBackendDispatcher(BackendDispatcher&, DatabaseBackendDispatcherHandler*); - DatabaseBackendDispatcherHandler* m_agent; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(AlternateDatabaseBackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - AlternateDatabaseBackendDispatcher* m_alternateDispatcher; + AlternateDatabaseBackendDispatcher* m_alternateDispatcher { nullptr }; #endif +private: + DatabaseBackendDispatcher(BackendDispatcher&, DatabaseBackendDispatcherHandler*); + DatabaseBackendDispatcherHandler* m_agent { nullptr }; }; } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -242,7 +230,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -250,7 +238,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -265,9 +253,6 @@ DatabaseBackendDispatcher::DatabaseBackendDispatcher(BackendDispatcher& backendDispatcher, DatabaseBackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("Database"), this); } @@ -444,8 +429,8 @@ result->setInteger(ASCIILiteral("databaseId"), out_databaseId); result->setObject(ASCIILiteral("sqlError"), out_sqlError); result->setArray(ASCIILiteral("alternateColors"), out_alternateColors); - result->setString(ASCIILiteral("screenColor"), Inspector::Protocol::getEnumConstantValue(out_screenColor)); - result->setString(ASCIILiteral("printColor"), Inspector::Protocol::getEnumConstantValue(out_printColor)); + result->setString(ASCIILiteral("screenColor"), Inspector::Protocol::TestHelpers::getEnumConstantValue(out_screenColor)); + result->setString(ASCIILiteral("printColor"), Inspector::Protocol::TestHelpers::getEnumConstantValue(out_printColor)); } if (!error.length()) m_backendDispatcher->sendResponse(requestId, WTFMove(result)); @@ -465,9 +450,9 @@ jsonMessage->setValue(ASCIILiteral("payload"), payload); jsonMessage->setInteger(ASCIILiteral("databaseId"), databaseId); jsonMessage->setObject(ASCIILiteral("sqlError"), sqlError); - jsonMessage->setString(ASCIILiteral("screenColor"), Inspector::Protocol::getEnumConstantValue(screenColor)); + jsonMessage->setString(ASCIILiteral("screenColor"), Inspector::Protocol::TestHelpers::getEnumConstantValue(screenColor)); jsonMessage->setArray(ASCIILiteral("alternateColors"), alternateColors); - jsonMessage->setString(ASCIILiteral("printColor"), Inspector::Protocol::getEnumConstantValue(printColor)); + jsonMessage->setString(ASCIILiteral("printColor"), Inspector::Protocol::TestHelpers::getEnumConstantValue(printColor)); CallbackBase::sendSuccess(WTFMove(jsonMessage)); } @@ -501,12 +486,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -534,10 +519,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -546,14 +530,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -582,7 +564,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -591,12 +573,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -624,8 +606,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -652,6 +633,8 @@ } // Database // End of typedefs. +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -659,6 +642,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace Database { /* */ enum class PrimaryColors { @@ -735,17 +720,26 @@ +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'Database' Domain +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -774,14 +768,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "red", "green", @@ -796,18 +793,37 @@ return enum_constant_values[code]; } +// Enums in the 'Database' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Database::PrimaryColors::Red, + (size_t)Inspector::Protocol::Database::PrimaryColors::Green, + (size_t)Inspector::Protocol::Database::PrimaryColors::Blue, + }; + for (size_t i = 0; i < 3; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Database::PrimaryColors)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -838,30 +854,30 @@ #include #include -@protocol RWIProtocolDatabaseDomainHandler; +@protocol TestProtocolDatabaseDomainHandler; namespace Inspector { class ObjCInspectorDatabaseBackendDispatcher final : public AlternateDatabaseBackendDispatcher { public: - ObjCInspectorDatabaseBackendDispatcher(id handler) { m_delegate = handler; } + ObjCInspectorDatabaseBackendDispatcher(id handler) { m_delegate = handler; } virtual void executeSQLSyncOptionalReturnValues(long requestId, int in_databaseId, const String& in_query) override; virtual void executeSQLAsyncOptionalReturnValues(long requestId, int in_databaseId, const String& in_query) override; virtual void executeSQLSync(long requestId, int in_databaseId, const String& in_query) override; virtual void executeSQLAsync(long requestId, int in_databaseId, const String& in_query) override; private: - RetainPtr> m_delegate; + RetainPtr> m_delegate; }; } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -890,10 +906,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -901,10 +917,10 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; - id _databaseHandler; + id _databaseHandler; } - (instancetype)initWithController:(AugmentableInspectorController*)controller @@ -923,7 +939,7 @@ [super dealloc]; } -- (void)setDatabaseHandler:(id)handler +- (void)setDatabaseHandler:(id)handler { if (handler == _databaseHandler) return; @@ -936,7 +952,7 @@ _controller->appendExtraAgent(WTFMove(alternateAgent)); } -- (id)databaseHandler +- (id)databaseHandler { return _databaseHandler; } @@ -944,12 +960,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -977,20 +993,20 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject -@property (nonatomic, retain, setter=setDatabaseHandler:) id databaseHandler; +@interface TestProtocolConfiguration : NSObject +@property (nonatomic, retain, setter=setDatabaseHandler:) id databaseHandler; @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1019,10 +1035,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -1034,7 +1050,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, RWIProtocolDatabaseError **sqlError, RWIProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor *printColor) { + id successCallback = ^(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, TestProtocolDatabaseError **sqlError, TestProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor *printColor) { Ref resultObject = InspectorObject::create(); THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(columnNames, @"columnNames"); THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(notes, @"notes"); @@ -1078,7 +1094,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, RWIProtocolDatabaseError **sqlError, RWIProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor *printColor) { + id successCallback = ^(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, TestProtocolDatabaseError **sqlError, TestProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor *printColor) { Ref resultObject = InspectorObject::create(); THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(columnNames, @"columnNames"); THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(notes, @"notes"); @@ -1122,7 +1138,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, RWIProtocolDatabaseError *sqlError, NSArray/**/ *alternateColors, RWIProtocolDatabasePrimaryColors screenColor, RWIProtocolDatabaseExecuteSQLSyncPrintColor printColor) { + id successCallback = ^(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, TestProtocolDatabaseError *sqlError, NSArray/**/ *alternateColors, TestProtocolDatabasePrimaryColors screenColor, TestProtocolDatabaseExecuteSQLSyncPrintColor printColor) { Ref resultObject = InspectorObject::create(); THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(columnNames, @"columnNames"); THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(notes, @"notes"); @@ -1156,7 +1172,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, RWIProtocolDatabaseError *sqlError, RWIProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, RWIProtocolDatabaseExecuteSQLAsyncPrintColor printColor) { + id successCallback = ^(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, TestProtocolDatabaseError *sqlError, TestProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, TestProtocolDatabaseExecuteSQLAsyncPrintColor printColor) { Ref resultObject = InspectorObject::create(); THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(columnNames, @"columnNames"); THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(notes, @"notes"); @@ -1186,12 +1202,193 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm + +### Begin File: TestProtocolEventDispatchers.mm +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import + +using namespace Inspector; + + + + +### End File: TestProtocolEventDispatchers.mm + +### Begin File: TestProtocol.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import + +#import + + +@class TestProtocolDatabaseError; + + +typedef NS_ENUM(NSInteger, TestProtocolDatabasePrimaryColors) { + TestProtocolDatabasePrimaryColorsRed, + TestProtocolDatabasePrimaryColorsGreen, + TestProtocolDatabasePrimaryColorsBlue, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor) { + TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan, + TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorMagenta, + TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorYellow, + TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorBlack, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor) { + TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan, + TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorMagenta, + TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorYellow, + TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorBlack, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteSQLSyncPrintColor) { + TestProtocolDatabaseExecuteSQLSyncPrintColorCyan, + TestProtocolDatabaseExecuteSQLSyncPrintColorMagenta, + TestProtocolDatabaseExecuteSQLSyncPrintColorYellow, + TestProtocolDatabaseExecuteSQLSyncPrintColorBlack, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteSQLAsyncPrintColor) { + TestProtocolDatabaseExecuteSQLAsyncPrintColorCyan, + TestProtocolDatabaseExecuteSQLAsyncPrintColorMagenta, + TestProtocolDatabaseExecuteSQLAsyncPrintColorYellow, + TestProtocolDatabaseExecuteSQLAsyncPrintColorBlack, +}; + + +__attribute__((visibility ("default"))) +@interface TestProtocolDatabaseError : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithMessage:(NSString *)message code:(int)code; +/* required */ @property (nonatomic, copy) NSString *message; +/* required */ @property (nonatomic, assign) int code; +@end + +@protocol TestProtocolDatabaseDomainHandler +@required +- (void)executeSQLSyncOptionalReturnValuesWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, TestProtocolDatabaseError **sqlError, TestProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor *printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; +- (void)executeSQLAsyncOptionalReturnValuesWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, TestProtocolDatabaseError **sqlError, TestProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor *printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; +- (void)executeSQLSyncWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, TestProtocolDatabaseError *sqlError, NSArray/**/ *alternateColors, TestProtocolDatabasePrimaryColors screenColor, TestProtocolDatabaseExecuteSQLSyncPrintColor printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; +- (void)executeSQLAsyncWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, TestProtocolDatabaseError *sqlError, TestProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, TestProtocolDatabaseExecuteSQLAsyncPrintColor printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; +@end + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import + + -### Begin File: RWIProtocolEnumConversionHelpers.h + +### End File: TestProtocolInternal.h + +### Begin File: TestProtocolTypeConversions.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1219,7 +1416,8 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" namespace Inspector { @@ -1227,155 +1425,155 @@ ObjCEnumType fromProtocolString(const String& value); -inline String toProtocolString(RWIProtocolDatabasePrimaryColors value) +inline String toProtocolString(TestProtocolDatabasePrimaryColors value) { switch(value) { - case RWIProtocolDatabasePrimaryColorsRed: + case TestProtocolDatabasePrimaryColorsRed: return ASCIILiteral("red"); - case RWIProtocolDatabasePrimaryColorsGreen: + case TestProtocolDatabasePrimaryColorsGreen: return ASCIILiteral("green"); - case RWIProtocolDatabasePrimaryColorsBlue: + case TestProtocolDatabasePrimaryColorsBlue: return ASCIILiteral("blue"); } } template<> -inline RWIProtocolDatabasePrimaryColors fromProtocolString(const String& value) +inline TestProtocolDatabasePrimaryColors fromProtocolString(const String& value) { if (value == "red") - return RWIProtocolDatabasePrimaryColorsRed; + return TestProtocolDatabasePrimaryColorsRed; if (value == "green") - return RWIProtocolDatabasePrimaryColorsGreen; + return TestProtocolDatabasePrimaryColorsGreen; if (value == "blue") - return RWIProtocolDatabasePrimaryColorsBlue; + return TestProtocolDatabasePrimaryColorsBlue; ASSERT_NOT_REACHED(); - return RWIProtocolDatabasePrimaryColorsRed; + return TestProtocolDatabasePrimaryColorsRed; } -inline String toProtocolString(RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan: + case TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorMagenta: + case TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorYellow: + case TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorBlack: + case TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan; + return TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorMagenta; + return TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorYellow; + return TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorBlack; + return TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan; + return TestProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan; } -inline String toProtocolString(RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan: + case TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorMagenta: + case TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorYellow: + case TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorBlack: + case TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan; + return TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorMagenta; + return TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorYellow; + return TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorBlack; + return TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan; + return TestProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan; } -inline String toProtocolString(RWIProtocolDatabaseExecuteSQLSyncPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteSQLSyncPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteSQLSyncPrintColorCyan: + case TestProtocolDatabaseExecuteSQLSyncPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteSQLSyncPrintColorMagenta: + case TestProtocolDatabaseExecuteSQLSyncPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteSQLSyncPrintColorYellow: + case TestProtocolDatabaseExecuteSQLSyncPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteSQLSyncPrintColorBlack: + case TestProtocolDatabaseExecuteSQLSyncPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteSQLSyncPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteSQLSyncPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteSQLSyncPrintColorCyan; + return TestProtocolDatabaseExecuteSQLSyncPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteSQLSyncPrintColorMagenta; + return TestProtocolDatabaseExecuteSQLSyncPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteSQLSyncPrintColorYellow; + return TestProtocolDatabaseExecuteSQLSyncPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteSQLSyncPrintColorBlack; + return TestProtocolDatabaseExecuteSQLSyncPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteSQLSyncPrintColorCyan; + return TestProtocolDatabaseExecuteSQLSyncPrintColorCyan; } -inline String toProtocolString(RWIProtocolDatabaseExecuteSQLAsyncPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteSQLAsyncPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteSQLAsyncPrintColorCyan: + case TestProtocolDatabaseExecuteSQLAsyncPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteSQLAsyncPrintColorMagenta: + case TestProtocolDatabaseExecuteSQLAsyncPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteSQLAsyncPrintColorYellow: + case TestProtocolDatabaseExecuteSQLAsyncPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteSQLAsyncPrintColorBlack: + case TestProtocolDatabaseExecuteSQLAsyncPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteSQLAsyncPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteSQLAsyncPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteSQLAsyncPrintColorCyan; + return TestProtocolDatabaseExecuteSQLAsyncPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteSQLAsyncPrintColorMagenta; + return TestProtocolDatabaseExecuteSQLAsyncPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteSQLAsyncPrintColorYellow; + return TestProtocolDatabaseExecuteSQLAsyncPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteSQLAsyncPrintColorBlack; + return TestProtocolDatabaseExecuteSQLAsyncPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteSQLAsyncPrintColorCyan; + return TestProtocolDatabaseExecuteSQLAsyncPrintColorCyan; } } // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1404,116 +1602,58 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (DatabaseDomain) ++ (void)_parseDatabaseId:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parsePrimaryColors:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseColorList:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload; +@end -### End File: RWIProtocolEventDispatchers.mm - -### Begin File: RWIProtocol.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import - -#import - - -@class RWIProtocolDatabaseError; - - -typedef NS_ENUM(NSInteger, RWIProtocolDatabasePrimaryColors) { - RWIProtocolDatabasePrimaryColorsRed, - RWIProtocolDatabasePrimaryColorsGreen, - RWIProtocolDatabasePrimaryColorsBlue, -}; - -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor) { - RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorCyan, - RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorMagenta, - RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorYellow, - RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColorBlack, -}; - -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor) { - RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorCyan, - RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorMagenta, - RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorYellow, - RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColorBlack, -}; +@implementation TestProtocolTypeConversions (DatabaseDomain) -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteSQLSyncPrintColor) { - RWIProtocolDatabaseExecuteSQLSyncPrintColorCyan, - RWIProtocolDatabaseExecuteSQLSyncPrintColorMagenta, - RWIProtocolDatabaseExecuteSQLSyncPrintColorYellow, - RWIProtocolDatabaseExecuteSQLSyncPrintColorBlack, -}; ++ (void)_parseDatabaseId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteSQLAsyncPrintColor) { - RWIProtocolDatabaseExecuteSQLAsyncPrintColorCyan, - RWIProtocolDatabaseExecuteSQLAsyncPrintColorMagenta, - RWIProtocolDatabaseExecuteSQLAsyncPrintColorYellow, - RWIProtocolDatabaseExecuteSQLAsyncPrintColorBlack, -}; ++ (void)_parsePrimaryColors:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} ++ (void)_parseColorList:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} -__attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseError : RWIProtocolJSONObject -- (instancetype)initWithMessage:(NSString *)message code:(int)code; -/* required */ @property (nonatomic, copy) NSString *message; -/* required */ @property (nonatomic, assign) int code; -@end ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseError alloc] initWithPayload:payload]; +} -@protocol RWIProtocolDatabaseDomainHandler -@required -- (void)executeSQLSyncOptionalReturnValuesWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, RWIProtocolDatabaseError **sqlError, RWIProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, RWIProtocolDatabaseExecuteSQLSyncOptionalReturnValuesPrintColor *printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; -- (void)executeSQLAsyncOptionalReturnValuesWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, RWIProtocolDatabaseError **sqlError, RWIProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, RWIProtocolDatabaseExecuteSQLAsyncOptionalReturnValuesPrintColor *printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; -- (void)executeSQLSyncWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, RWIProtocolDatabaseError *sqlError, NSArray/**/ *alternateColors, RWIProtocolDatabasePrimaryColors screenColor, RWIProtocolDatabaseExecuteSQLSyncPrintColor printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; -- (void)executeSQLAsyncWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, RWIProtocolDatabaseError *sqlError, RWIProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, RWIProtocolDatabaseExecuteSQLAsyncPrintColor printColor))successCallback databaseId:(int)databaseId query:(NSString *)query; @end +### End File: TestProtocolTypeConversions.mm - -### End File: RWIProtocol.h - -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1542,21 +1682,42 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolInternal.h" -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocolTypeConversions.h" +#import #import #import using namespace Inspector; -@implementation RWIProtocolDatabaseError +@implementation TestProtocolDatabaseError + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"message"], @"message"); + self.message = payload[@"message"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"code"], @"code"); + self.code = [payload[@"code"] integerValue]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} - (instancetype)initWithMessage:(NSString *)message code:(int)code; { - self = [super init]; - if (!self) + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); @@ -1590,45 +1751,4 @@ @end -### End File: RWIProtocolTypes.mm - -### Begin File: RWIProtocolInternal.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-async-attribute.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import -#import - - - - -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-optional-call-return-parameters.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-optional-call-return-parameters.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-optional-call-return-parameters.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/commands-with-optional-call-return-parameters.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,44 +29,17 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - -class AlternateDatabaseBackendDispatcher : public AlternateBackendDispatcher { -public: - virtual ~AlternateDatabaseBackendDispatcher() { } - virtual void executeAllOptionalParameters(long callId, const Inspector::InspectorArray* in_columnNames, const String* in_notes, const double* in_timestamp, const Inspector::InspectorObject* in_values, const Inspector::InspectorValue* in_payload, const int* in_databaseId, const Inspector::InspectorObject* in_sqlError, const String* in_screenColor, const Inspector::InspectorArray* in_alternateColors, const String* in_printColor) = 0; - virtual void executeNoOptionalParameters(long callId, const Inspector::InspectorArray& in_columnNames, const String& in_notes, double in_timestamp, const Inspector::InspectorObject& in_values, Inspector::InspectorValue in_payload, int in_databaseId, const Inspector::InspectorObject& in_sqlError, const String& in_screenColor, const Inspector::InspectorArray& in_alternateColors, const String& in_printColor) = 0; -}; - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Database. +InspectorBackend.registerEnum("Database.PrimaryColors", {Red: "red", Green: "green", Blue: "blue"}); +InspectorBackend.registerCommand("Database.executeAllOptionalParameters", [{"name": "columnNames", "type": "object", "optional": true}, {"name": "notes", "type": "string", "optional": true}, {"name": "timestamp", "type": "number", "optional": true}, {"name": "values", "type": "object", "optional": true}, {"name": "payload", "type": "object", "optional": true}, {"name": "databaseId", "type": "number", "optional": true}, {"name": "sqlError", "type": "object", "optional": true}, {"name": "screenColor", "type": "string", "optional": true}, {"name": "alternateColors", "type": "object", "optional": true}, {"name": "printColor", "type": "string", "optional": true}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.registerCommand("Database.executeNoOptionalParameters", [{"name": "columnNames", "type": "object", "optional": false}, {"name": "notes", "type": "string", "optional": false}, {"name": "timestamp", "type": "number", "optional": false}, {"name": "values", "type": "object", "optional": false}, {"name": "payload", "type": "object", "optional": false}, {"name": "databaseId", "type": "number", "optional": false}, {"name": "sqlError", "type": "object", "optional": false}, {"name": "screenColor", "type": "string", "optional": false}, {"name": "alternateColors", "type": "object", "optional": false}, {"name": "printColor", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.activateDomain("Database"); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -94,17 +67,41 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Database. -InspectorBackend.registerEnum("Database.PrimaryColors", {Red: "red", Green: "green", Blue: "blue"}); -InspectorBackend.registerCommand("Database.executeAllOptionalParameters", [{"name": "columnNames", "type": "object", "optional": true}, {"name": "notes", "type": "string", "optional": true}, {"name": "timestamp", "type": "number", "optional": true}, {"name": "values", "type": "object", "optional": true}, {"name": "payload", "type": "object", "optional": true}, {"name": "databaseId", "type": "number", "optional": true}, {"name": "sqlError", "type": "object", "optional": true}, {"name": "screenColor", "type": "string", "optional": true}, {"name": "alternateColors", "type": "object", "optional": true}, {"name": "printColor", "type": "string", "optional": true}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.registerCommand("Database.executeNoOptionalParameters", [{"name": "columnNames", "type": "object", "optional": false}, {"name": "notes", "type": "string", "optional": false}, {"name": "timestamp", "type": "number", "optional": false}, {"name": "values", "type": "object", "optional": false}, {"name": "payload", "type": "object", "optional": false}, {"name": "databaseId", "type": "number", "optional": false}, {"name": "sqlError", "type": "object", "optional": false}, {"name": "screenColor", "type": "string", "optional": false}, {"name": "alternateColors", "type": "object", "optional": false}, {"name": "printColor", "type": "string", "optional": false}], ["columnNames", "notes", "timestamp", "values", "payload", "databaseId", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.activateDomain("Database"); -### End File: InspectorBackendCommands.js +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + +class AlternateDatabaseBackendDispatcher : public AlternateBackendDispatcher { +public: + virtual ~AlternateDatabaseBackendDispatcher() { } + virtual void executeAllOptionalParameters(long callId, const Inspector::InspectorArray* in_columnNames, const String* in_notes, const double* in_timestamp, const Inspector::InspectorObject* in_values, const Inspector::InspectorValue* in_payload, const int* in_databaseId, const Inspector::InspectorObject* in_sqlError, const String* in_screenColor, const Inspector::InspectorArray* in_alternateColors, const String* in_printColor) = 0; + virtual void executeNoOptionalParameters(long callId, const Inspector::InspectorArray& in_columnNames, const String& in_notes, double in_timestamp, const Inspector::InspectorObject& in_values, Inspector::InspectorValue in_payload, int in_databaseId, const Inspector::InspectorObject& in_sqlError, const String& in_screenColor, const Inspector::InspectorArray& in_alternateColors, const String& in_printColor) = 0; +}; -### Begin File: InspectorBackendDispatchers.h +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,10 +129,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -149,12 +145,6 @@ class DatabaseBackendDispatcherHandler { public: - // Named after parameter 'screenColor' while generating command/event executeAllOptionalParameters. - enum class ScreenColor { - Red = 0, - Green = 1, - Blue = 2, - }; // enum class ScreenColor // Named after parameter 'printColor' while generating command/event executeAllOptionalParameters. enum class PrintColor { Cyan = 3, @@ -171,30 +161,28 @@ class DatabaseBackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref create(BackendDispatcher&, DatabaseBackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; private: void executeAllOptionalParameters(long requestId, RefPtr&& parameters); void executeNoOptionalParameters(long requestId, RefPtr&& parameters); -private: - DatabaseBackendDispatcher(BackendDispatcher&, DatabaseBackendDispatcherHandler*); - DatabaseBackendDispatcherHandler* m_agent; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(AlternateDatabaseBackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - AlternateDatabaseBackendDispatcher* m_alternateDispatcher; + AlternateDatabaseBackendDispatcher* m_alternateDispatcher { nullptr }; #endif +private: + DatabaseBackendDispatcher(BackendDispatcher&, DatabaseBackendDispatcherHandler*); + DatabaseBackendDispatcherHandler* m_agent { nullptr }; }; } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -223,7 +211,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -231,7 +219,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -246,9 +234,6 @@ DatabaseBackendDispatcher::DatabaseBackendDispatcher(BackendDispatcher& backendDispatcher, DatabaseBackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("Database"), this); } @@ -390,9 +375,9 @@ result->setValue(ASCIILiteral("payload"), out_payload); result->setInteger(ASCIILiteral("databaseId"), out_databaseId); result->setObject(ASCIILiteral("sqlError"), out_sqlError); - result->setString(ASCIILiteral("screenColor"), Inspector::Protocol::getEnumConstantValue(out_screenColor)); + result->setString(ASCIILiteral("screenColor"), Inspector::Protocol::TestHelpers::getEnumConstantValue(out_screenColor)); result->setArray(ASCIILiteral("alternateColors"), out_alternateColors); - result->setString(ASCIILiteral("printColor"), Inspector::Protocol::getEnumConstantValue(out_printColor)); + result->setString(ASCIILiteral("printColor"), Inspector::Protocol::TestHelpers::getEnumConstantValue(out_printColor)); } if (!error.length()) m_backendDispatcher->sendResponse(requestId, WTFMove(result)); @@ -402,12 +387,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -435,10 +420,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -447,14 +431,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -483,7 +465,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -492,12 +474,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -525,8 +507,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -553,6 +534,8 @@ } // Database // End of typedefs. +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -560,6 +543,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace Database { /* */ enum class PrimaryColors { @@ -636,17 +621,26 @@ +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'Database' Domain +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -675,14 +669,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "red", "green", @@ -697,18 +694,37 @@ return enum_constant_values[code]; } +// Enums in the 'Database' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Database::PrimaryColors::Red, + (size_t)Inspector::Protocol::Database::PrimaryColors::Green, + (size_t)Inspector::Protocol::Database::PrimaryColors::Blue, + }; + for (size_t i = 0; i < 3; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Database::PrimaryColors)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -739,28 +755,28 @@ #include #include -@protocol RWIProtocolDatabaseDomainHandler; +@protocol TestProtocolDatabaseDomainHandler; namespace Inspector { class ObjCInspectorDatabaseBackendDispatcher final : public AlternateDatabaseBackendDispatcher { public: - ObjCInspectorDatabaseBackendDispatcher(id handler) { m_delegate = handler; } + ObjCInspectorDatabaseBackendDispatcher(id handler) { m_delegate = handler; } virtual void executeAllOptionalParameters(long requestId, const Inspector::InspectorArray* in_columnNames, const String* in_notes, const double* in_timestamp, const Inspector::InspectorObject* in_values, const Inspector::InspectorValue* in_payload, const int* in_databaseId, const Inspector::InspectorObject* in_sqlError, const String* in_screenColor, const Inspector::InspectorArray* in_alternateColors, const String* in_printColor) override; virtual void executeNoOptionalParameters(long requestId, const Inspector::InspectorArray& in_columnNames, const String& in_notes, double in_timestamp, const Inspector::InspectorObject& in_values, Inspector::InspectorValue in_payload, int in_databaseId, const Inspector::InspectorObject& in_sqlError, const String& in_screenColor, const Inspector::InspectorArray& in_alternateColors, const String& in_printColor) override; private: - RetainPtr> m_delegate; + RetainPtr> m_delegate; }; } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -789,10 +805,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -800,10 +816,10 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; - id _databaseHandler; + id _databaseHandler; } - (instancetype)initWithController:(AugmentableInspectorController*)controller @@ -822,7 +838,7 @@ [super dealloc]; } -- (void)setDatabaseHandler:(id)handler +- (void)setDatabaseHandler:(id)handler { if (handler == _databaseHandler) return; @@ -835,7 +851,7 @@ _controller->appendExtraAgent(WTFMove(alternateAgent)); } -- (id)databaseHandler +- (id)databaseHandler { return _databaseHandler; } @@ -843,12 +859,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -876,20 +892,20 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject -@property (nonatomic, retain, setter=setDatabaseHandler:) id databaseHandler; +@interface TestProtocolConfiguration : NSObject +@property (nonatomic, retain, setter=setDatabaseHandler:) id databaseHandler; @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -918,10 +934,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -933,7 +949,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, RWIProtocolDatabaseError **sqlError, RWIProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor *printColor) { + id successCallback = ^(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, TestProtocolDatabaseError **sqlError, TestProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, TestProtocolDatabaseExecuteAllOptionalParametersPrintColor *printColor) { Ref resultObject = InspectorObject::create(); THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(columnNames, @"columnNames"); THROW_EXCEPTION_FOR_BAD_OPTIONAL_PARAMETER(notes, @"notes"); @@ -982,18 +998,18 @@ int o_in_databaseId; if (in_databaseId) o_in_databaseId = *in_databaseId; - RWIProtocolDatabaseError *o_in_sqlError; + TestProtocolDatabaseError *o_in_sqlError; if (in_sqlError) - o_in_sqlError = [[[RWIProtocolDatabaseError alloc] initWithInspectorObject:in_sqlError] autorelease]; - RWIProtocolDatabasePrimaryColors o_in_screenColor; + o_in_sqlError = [[[TestProtocolDatabaseError alloc] initWithInspectorObject:in_sqlError] autorelease]; + TestProtocolDatabasePrimaryColors o_in_screenColor; if (in_screenColor) - o_in_screenColor = fromProtocolString(*in_screenColor); + o_in_screenColor = fromProtocolString(*in_screenColor); NSArray/**/ *o_in_alternateColors; if (in_alternateColors) o_in_alternateColors = objcStringArray(in_alternateColors); - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor o_in_printColor; + TestProtocolDatabaseExecuteAllOptionalParametersPrintColor o_in_printColor; if (in_printColor) - o_in_printColor = fromProtocolString(*in_printColor); + o_in_printColor = fromProtocolString(*in_printColor); [m_delegate executeAllOptionalParametersWithErrorCallback:errorCallback successCallback:successCallback columnNames:(in_columnNames ? &o_in_columnNames : nil) notes:(in_notes ? &o_in_notes : nil) timestamp:(in_timestamp ? &o_in_timestamp : nil) values:(in_values ? &o_in_values : nil) payload:(in_payload ? &o_in_payload : nil) databaseId:(in_databaseId ? &o_in_databaseId : nil) sqlError:(in_sqlError ? &o_in_sqlError : nil) screenColor:(in_screenColor ? &o_in_screenColor : nil) alternateColors:(in_alternateColors ? &o_in_alternateColors : nil) printColor:(in_printColor ? &o_in_printColor : nil)]; } @@ -1005,7 +1021,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, RWIProtocolDatabaseError *sqlError, RWIProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor printColor) { + id successCallback = ^(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, TestProtocolDatabaseError *sqlError, TestProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, TestProtocolDatabaseExecuteNoOptionalParametersPrintColor printColor) { Ref resultObject = InspectorObject::create(); THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(columnNames, @"columnNames"); THROW_EXCEPTION_FOR_REQUIRED_PARAMETER(notes, @"notes"); @@ -1032,10 +1048,10 @@ RWIProtocolJSONObject *o_in_values = [[[RWIProtocolJSONObject alloc] initWithInspectorObject:&in_values] autorelease]; RWIProtocolJSONObject *o_in_payload = [[[RWIProtocolJSONObject alloc] initWithInspectorObject:&in_payload] autorelease]; int o_in_databaseId = in_databaseId; - RWIProtocolDatabaseError *o_in_sqlError = [[[RWIProtocolDatabaseError alloc] initWithInspectorObject:&in_sqlError] autorelease]; - RWIProtocolDatabasePrimaryColors o_in_screenColor = fromProtocolString(in_screenColor); + TestProtocolDatabaseError *o_in_sqlError = [[[TestProtocolDatabaseError alloc] initWithInspectorObject:&in_sqlError] autorelease]; + TestProtocolDatabasePrimaryColors o_in_screenColor = fromProtocolString(in_screenColor); NSArray/**/ *o_in_alternateColors = objcStringArray(&in_alternateColors); - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor o_in_printColor = fromProtocolString(in_printColor); + TestProtocolDatabaseExecuteNoOptionalParametersPrintColor o_in_printColor = fromProtocolString(in_printColor); [m_delegate executeNoOptionalParametersWithErrorCallback:errorCallback successCallback:successCallback columnNames:o_in_columnNames notes:o_in_notes timestamp:o_in_timestamp values:o_in_values payload:o_in_payload databaseId:o_in_databaseId sqlError:o_in_sqlError screenColor:o_in_screenColor alternateColors:o_in_alternateColors printColor:o_in_printColor]; } @@ -1043,12 +1059,191 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm + +### Begin File: TestProtocolEventDispatchers.mm +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import + +using namespace Inspector; + + + + +### End File: TestProtocolEventDispatchers.mm + +### Begin File: TestProtocol.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import + +#import + + +@class TestProtocolDatabaseError; + + +typedef NS_ENUM(NSInteger, TestProtocolDatabasePrimaryColors) { + TestProtocolDatabasePrimaryColorsRed, + TestProtocolDatabasePrimaryColorsGreen, + TestProtocolDatabasePrimaryColorsBlue, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteAllOptionalParametersPrintColor) { + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan, + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta, + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow, + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteAllOptionalParametersPrintColor) { + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan, + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta, + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow, + TestProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteNoOptionalParametersPrintColor) { + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan, + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta, + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow, + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack, +}; + +typedef NS_ENUM(NSInteger, TestProtocolDatabaseExecuteNoOptionalParametersPrintColor) { + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan, + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta, + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow, + TestProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack, +}; + + +__attribute__((visibility ("default"))) +@interface TestProtocolDatabaseError : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithMessage:(NSString *)message code:(int)code; +/* required */ @property (nonatomic, copy) NSString *message; +/* required */ @property (nonatomic, assign) int code; +@end + +@protocol TestProtocolDatabaseDomainHandler +@required +- (void)executeAllOptionalParametersWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, TestProtocolDatabaseError **sqlError, TestProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, TestProtocolDatabaseExecuteAllOptionalParametersPrintColor *printColor))successCallback columnNames:(NSArray/**/ **)columnNames notes:(NSString **)notes timestamp:(double *)timestamp values:(RWIProtocolJSONObject **)values payload:(RWIProtocolJSONObject **)payload databaseId:(int *)databaseId sqlError:(TestProtocolDatabaseError **)sqlError screenColor:(TestProtocolDatabasePrimaryColors *)screenColor alternateColors:(NSArray/**/ **)alternateColors printColor:(TestProtocolDatabaseExecuteAllOptionalParametersPrintColor *)printColor; +- (void)executeNoOptionalParametersWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, TestProtocolDatabaseError *sqlError, TestProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, TestProtocolDatabaseExecuteNoOptionalParametersPrintColor printColor))successCallback columnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload databaseId:(int)databaseId sqlError:(TestProtocolDatabaseError *)sqlError screenColor:(TestProtocolDatabasePrimaryColors)screenColor alternateColors:(NSArray/**/ *)alternateColors printColor:(TestProtocolDatabaseExecuteNoOptionalParametersPrintColor)printColor; +@end + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import + + + -### Begin File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolInternal.h + +### Begin File: TestProtocolTypeConversions.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1076,7 +1271,8 @@ // DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" namespace Inspector { @@ -1084,155 +1280,155 @@ ObjCEnumType fromProtocolString(const String& value); -inline String toProtocolString(RWIProtocolDatabasePrimaryColors value) +inline String toProtocolString(TestProtocolDatabasePrimaryColors value) { switch(value) { - case RWIProtocolDatabasePrimaryColorsRed: + case TestProtocolDatabasePrimaryColorsRed: return ASCIILiteral("red"); - case RWIProtocolDatabasePrimaryColorsGreen: + case TestProtocolDatabasePrimaryColorsGreen: return ASCIILiteral("green"); - case RWIProtocolDatabasePrimaryColorsBlue: + case TestProtocolDatabasePrimaryColorsBlue: return ASCIILiteral("blue"); } } template<> -inline RWIProtocolDatabasePrimaryColors fromProtocolString(const String& value) +inline TestProtocolDatabasePrimaryColors fromProtocolString(const String& value) { if (value == "red") - return RWIProtocolDatabasePrimaryColorsRed; + return TestProtocolDatabasePrimaryColorsRed; if (value == "green") - return RWIProtocolDatabasePrimaryColorsGreen; + return TestProtocolDatabasePrimaryColorsGreen; if (value == "blue") - return RWIProtocolDatabasePrimaryColorsBlue; + return TestProtocolDatabasePrimaryColorsBlue; ASSERT_NOT_REACHED(); - return RWIProtocolDatabasePrimaryColorsRed; + return TestProtocolDatabasePrimaryColorsRed; } -inline String toProtocolString(RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteAllOptionalParametersPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteAllOptionalParametersPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; } -inline String toProtocolString(RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteAllOptionalParametersPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack: + case TestProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteAllOptionalParametersPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan; } -inline String toProtocolString(RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteNoOptionalParametersPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteNoOptionalParametersPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; } -inline String toProtocolString(RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor value) +inline String toProtocolString(TestProtocolDatabaseExecuteNoOptionalParametersPrintColor value) { switch(value) { - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan: return ASCIILiteral("cyan"); - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta: return ASCIILiteral("magenta"); - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow: return ASCIILiteral("yellow"); - case RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack: + case TestProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack: return ASCIILiteral("black"); } } template<> -inline RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor fromProtocolString(const String& value) +inline TestProtocolDatabaseExecuteNoOptionalParametersPrintColor fromProtocolString(const String& value) { if (value == "cyan") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; if (value == "magenta") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta; if (value == "yellow") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow; if (value == "black") - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack; ASSERT_NOT_REACHED(); - return RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; + return TestProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan; } } // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1261,114 +1457,58 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (DatabaseDomain) ++ (void)_parseDatabaseId:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parsePrimaryColors:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseColorList:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload; +@end -### End File: RWIProtocolEventDispatchers.mm - -### Begin File: RWIProtocol.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import - -#import - - -@class RWIProtocolDatabaseError; - - -typedef NS_ENUM(NSInteger, RWIProtocolDatabasePrimaryColors) { - RWIProtocolDatabasePrimaryColorsRed, - RWIProtocolDatabasePrimaryColorsGreen, - RWIProtocolDatabasePrimaryColorsBlue, -}; - -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor) { - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan, - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta, - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow, - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack, -}; - -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor) { - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorCyan, - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorMagenta, - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorYellow, - RWIProtocolDatabaseExecuteAllOptionalParametersPrintColorBlack, -}; +@implementation TestProtocolTypeConversions (DatabaseDomain) -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor) { - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan, - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta, - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow, - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack, -}; ++ (void)_parseDatabaseId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} -typedef NS_ENUM(NSInteger, RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor) { - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorCyan, - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorMagenta, - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorYellow, - RWIProtocolDatabaseExecuteNoOptionalParametersPrintColorBlack, -}; ++ (void)_parsePrimaryColors:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} ++ (void)_parseColorList:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} -__attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseError : RWIProtocolJSONObject -- (instancetype)initWithMessage:(NSString *)message code:(int)code; -/* required */ @property (nonatomic, copy) NSString *message; -/* required */ @property (nonatomic, assign) int code; -@end ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseError alloc] initWithPayload:payload]; +} -@protocol RWIProtocolDatabaseDomainHandler -@required -- (void)executeAllOptionalParametersWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ **columnNames, NSString **notes, double *timestamp, RWIProtocolJSONObject **values, RWIProtocolJSONObject **payload, int *databaseId, RWIProtocolDatabaseError **sqlError, RWIProtocolDatabasePrimaryColors *screenColor, NSArray/**/ **alternateColors, RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor *printColor))successCallback columnNames:(NSArray/**/ **)columnNames notes:(NSString **)notes timestamp:(double *)timestamp values:(RWIProtocolJSONObject **)values payload:(RWIProtocolJSONObject **)payload databaseId:(int *)databaseId sqlError:(RWIProtocolDatabaseError **)sqlError screenColor:(RWIProtocolDatabasePrimaryColors *)screenColor alternateColors:(NSArray/**/ **)alternateColors printColor:(RWIProtocolDatabaseExecuteAllOptionalParametersPrintColor *)printColor; -- (void)executeNoOptionalParametersWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(NSArray/**/ *columnNames, NSString *notes, double timestamp, RWIProtocolJSONObject *values, RWIProtocolJSONObject *payload, int databaseId, RWIProtocolDatabaseError *sqlError, RWIProtocolDatabasePrimaryColors screenColor, NSArray/**/ *alternateColors, RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor printColor))successCallback columnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload databaseId:(int)databaseId sqlError:(RWIProtocolDatabaseError *)sqlError screenColor:(RWIProtocolDatabasePrimaryColors)screenColor alternateColors:(NSArray/**/ *)alternateColors printColor:(RWIProtocolDatabaseExecuteNoOptionalParametersPrintColor)printColor; @end +### End File: TestProtocolTypeConversions.mm - -### End File: RWIProtocol.h - -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1397,21 +1537,42 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolInternal.h" -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocolTypeConversions.h" +#import #import #import using namespace Inspector; -@implementation RWIProtocolDatabaseError +@implementation TestProtocolDatabaseError + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"message"], @"message"); + self.message = payload[@"message"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"code"], @"code"); + self.code = [payload[@"code"] integerValue]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} - (instancetype)initWithMessage:(NSString *)message code:(int)code; { - self = [super init]; - if (!self) + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); @@ -1445,45 +1606,4 @@ @end -### End File: RWIProtocolTypes.mm - -### Begin File: RWIProtocolInternal.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from commands-with-optional-call-return-parameters.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import -#import - - - - -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/domains-with-varying-command-sizes.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/domains-with-varying-command-sizes.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/domains-with-varying-command-sizes.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/domains-with-varying-command-sizes.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,53 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +// Network1. +InspectorBackend.registerCommand("Network1.loadResource1", [], []); +InspectorBackend.activateDomain("Network1"); + +// Network3. +InspectorBackend.registerCommand("Network3.loadResource1", [], []); +InspectorBackend.registerCommand("Network3.loadResource2", [], []); +InspectorBackend.registerCommand("Network3.loadResource3", [], []); +InspectorBackend.registerCommand("Network3.loadResource4", [], []); +InspectorBackend.registerCommand("Network3.loadResource5", [], []); +InspectorBackend.registerCommand("Network3.loadResource6", [], []); +InspectorBackend.registerCommand("Network3.loadResource7", [], []); +InspectorBackend.activateDomain("Network3"); +### End File: InspectorBackendCommands.js + +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,12 +75,11 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h +#pragma once #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorProtocolTypes.h" +#include "TestProtocolTypes.h" #include #include @@ -69,60 +114,12 @@ } // namespace Inspector #endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h - -### Begin File: InspectorBackendCommands.js -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -// Network1. -InspectorBackend.registerCommand("Network1.loadResource1", [], []); -InspectorBackend.activateDomain("Network1"); - -// Network3. -InspectorBackend.registerCommand("Network3.loadResource1", [], []); -InspectorBackend.registerCommand("Network3.loadResource2", [], []); -InspectorBackend.registerCommand("Network3.loadResource3", [], []); -InspectorBackend.registerCommand("Network3.loadResource4", [], []); -InspectorBackend.registerCommand("Network3.loadResource5", [], []); -InspectorBackend.registerCommand("Network3.loadResource6", [], []); -InspectorBackend.registerCommand("Network3.loadResource7", [], []); -InspectorBackend.activateDomain("Network3"); -### End File: InspectorBackendCommands.js - -### Begin File: InspectorBackendDispatchers.h +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -150,10 +147,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -189,24 +185,24 @@ class Network1BackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref create(BackendDispatcher&, Network1BackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; private: void loadResource1(long requestId, RefPtr&& parameters); -private: - Network1BackendDispatcher(BackendDispatcher&, Network1BackendDispatcherHandler*); - Network1BackendDispatcherHandler* m_agent; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(AlternateNetwork1BackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - AlternateNetwork1BackendDispatcher* m_alternateDispatcher; + AlternateNetwork1BackendDispatcher* m_alternateDispatcher { nullptr }; #endif +private: + Network1BackendDispatcher(BackendDispatcher&, Network1BackendDispatcherHandler*); + Network1BackendDispatcherHandler* m_agent { nullptr }; }; class Network3BackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref create(BackendDispatcher&, Network3BackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; private: void loadResource1(long requestId, RefPtr&& parameters); void loadResource2(long requestId, RefPtr&& parameters); @@ -215,26 +211,24 @@ void loadResource5(long requestId, RefPtr&& parameters); void loadResource6(long requestId, RefPtr&& parameters); void loadResource7(long requestId, RefPtr&& parameters); -private: - Network3BackendDispatcher(BackendDispatcher&, Network3BackendDispatcherHandler*); - Network3BackendDispatcherHandler* m_agent; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(AlternateNetwork3BackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - AlternateNetwork3BackendDispatcher* m_alternateDispatcher; + AlternateNetwork3BackendDispatcher* m_alternateDispatcher { nullptr }; #endif +private: + Network3BackendDispatcher(BackendDispatcher&, Network3BackendDispatcherHandler*); + Network3BackendDispatcherHandler* m_agent { nullptr }; }; } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -263,7 +257,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -271,7 +265,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -287,9 +281,6 @@ Network1BackendDispatcher::Network1BackendDispatcher(BackendDispatcher& backendDispatcher, Network1BackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("Network1"), this); } @@ -334,9 +325,6 @@ Network3BackendDispatcher::Network3BackendDispatcher(BackendDispatcher& backendDispatcher, Network3BackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("Network3"), this); } @@ -513,12 +501,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -546,10 +534,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -558,14 +545,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -594,7 +579,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -603,12 +588,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -636,8 +621,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -657,26 +641,17 @@ } // Network2 // End of typedefs. -String getEnumConstantValue(int code); - -template String getEnumConstantValue(T enumValue) -{ - return getEnumConstantValue(static_cast(enumValue)); -} - } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -705,33 +680,27 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { -static const char* const enum_constant_values[] = { -}; - -String getEnumConstantValue(int code) { - return enum_constant_values[code]; -} - } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -762,25 +731,25 @@ #include #include -@protocol RWIProtocolNetwork1DomainHandler; -@protocol RWIProtocolNetwork3DomainHandler; +@protocol TestProtocolNetwork1DomainHandler; +@protocol TestProtocolNetwork3DomainHandler; namespace Inspector { class ObjCInspectorNetwork1BackendDispatcher final : public AlternateNetwork1BackendDispatcher { public: - ObjCInspectorNetwork1BackendDispatcher(id handler) { m_delegate = handler; } + ObjCInspectorNetwork1BackendDispatcher(id handler) { m_delegate = handler; } virtual void loadResource1(long requestId) override; private: - RetainPtr> m_delegate; + RetainPtr> m_delegate; }; class ObjCInspectorNetwork3BackendDispatcher final : public AlternateNetwork3BackendDispatcher { public: - ObjCInspectorNetwork3BackendDispatcher(id handler) { m_delegate = handler; } + ObjCInspectorNetwork3BackendDispatcher(id handler) { m_delegate = handler; } virtual void loadResource1(long requestId) override; virtual void loadResource2(long requestId) override; virtual void loadResource3(long requestId) override; @@ -789,17 +758,17 @@ virtual void loadResource6(long requestId) override; virtual void loadResource7(long requestId) override; private: - RetainPtr> m_delegate; + RetainPtr> m_delegate; }; } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -828,10 +797,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -839,11 +808,11 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; - id _network1Handler; - id _network3Handler; + id _network1Handler; + id _network3Handler; } - (instancetype)initWithController:(AugmentableInspectorController*)controller @@ -863,7 +832,7 @@ [super dealloc]; } -- (void)setNetwork1Handler:(id)handler +- (void)setNetwork1Handler:(id)handler { if (handler == _network1Handler) return; @@ -876,12 +845,12 @@ _controller->appendExtraAgent(WTFMove(alternateAgent)); } -- (id)network1Handler +- (id)network1Handler { return _network1Handler; } -- (void)setNetwork3Handler:(id)handler +- (void)setNetwork3Handler:(id)handler { if (handler == _network3Handler) return; @@ -894,7 +863,7 @@ _controller->appendExtraAgent(WTFMove(alternateAgent)); } -- (id)network3Handler +- (id)network3Handler { return _network3Handler; } @@ -902,12 +871,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -935,21 +904,21 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject -@property (nonatomic, retain, setter=setNetwork1Handler:) id network1Handler; -@property (nonatomic, retain, setter=setNetwork3Handler:) id network3Handler; +@interface TestProtocolConfiguration : NSObject +@property (nonatomic, retain, setter=setNetwork1Handler:) id network1Handler; +@property (nonatomic, retain, setter=setNetwork3Handler:) id network3Handler; @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -978,10 +947,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -1104,12 +1073,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1137,12 +1106,13 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "config.h" +#import "TestProtocolInternal.h" -namespace Inspector { +#import "TestProtocolTypeConversions.h" +#import -template -ObjCEnumType fromProtocolString(const String& value); +using namespace Inspector; @@ -1150,14 +1120,13 @@ -} // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1185,27 +1154,42 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import + +#import + + -#import "RWIProtocolEnumConversionHelpers.h" -#import -using namespace Inspector; +@protocol TestProtocolNetwork1DomainHandler +@required +- (void)loadResource1WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +@end + +@protocol TestProtocolNetwork3DomainHandler +@required +- (void)loadResource1WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +- (void)loadResource2WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +- (void)loadResource3WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +- (void)loadResource4WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +- (void)loadResource5WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +- (void)loadResource6WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +- (void)loadResource7WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +@end -### End File: RWIProtocolEventDispatchers.mm +### End File: TestProtocol.h -### Begin File: RWIProtocol.h +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1233,42 +1217,69 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import -#import +### End File: TestProtocolInternal.h + +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" +namespace Inspector { +template +ObjCEnumType fromProtocolString(const String& value); -@protocol RWIProtocolNetwork1DomainHandler -@required -- (void)loadResource1WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -@end -@protocol RWIProtocolNetwork3DomainHandler -@required -- (void)loadResource1WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -- (void)loadResource2WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -- (void)loadResource3WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -- (void)loadResource4WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -- (void)loadResource5WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -- (void)loadResource6WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -- (void)loadResource7WithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -@end +} // namespace Inspector -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1297,27 +1308,49 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (Network1Domain) + +@end +@interface TestProtocolTypeConversions (Network2Domain) ++ (void)_parseLoaderId:(NSString **)outValue fromPayload:(id)payload; +@end +@interface TestProtocolTypeConversions (Network3Domain) +@end +@implementation TestProtocolTypeConversions (Network1Domain) +@end +@implementation TestProtocolTypeConversions (Network2Domain) ++ (void)_parseLoaderId:(NSString **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = (NSString *)payload; +} -### End File: RWIProtocolTypes.mm +@end +@implementation TestProtocolTypeConversions (Network3Domain) -### Begin File: RWIProtocolInternal.h +@end + + +### End File: TestProtocolTypeConversions.mm + +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1345,12 +1378,21 @@ // DO NOT EDIT THIS FILE. It is automatically generated from domains-with-varying-command-sizes.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + + + -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/enum-values.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/enum-values.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/enum-values.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/enum-values.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,43 +29,24 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - -class AlternateCommandDomainBackendDispatcher : public AlternateBackendDispatcher { -public: - virtual ~AlternateCommandDomainBackendDispatcher() { } - virtual void commandWithEnumReturnValue(long callId) = 0; -}; - -} // namespace Inspector +// TypeDomain. +InspectorBackend.registerEnum("TypeDomain.TypeDomainEnum", {Shared: "shared", Red: "red", Green: "green", Blue: "blue"}); -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +// CommandDomain. +InspectorBackend.registerCommand("CommandDomain.commandWithEnumReturnValue", [], ["returnValue"]); +InspectorBackend.activateDomain("CommandDomain"); -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// EventDomain. +InspectorBackend.registerEventDomainDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "EventDomain"); +InspectorBackend.registerEnum("EventDomain.EventWithEnumParameterParameter", {Shared: "shared", Black: "black", White: "white"}); +InspectorBackend.registerEvent("EventDomain.eventWithEnumParameter", ["parameter"]); +InspectorBackend.activateDomain("EventDomain"); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,24 +74,40 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// TypeDomain. -InspectorBackend.registerEnum("TypeDomain.TypeDomainEnum", {Shared: "shared", Red: "red", Green: "green", Blue: "blue"}); +#pragma once -// CommandDomain. -InspectorBackend.registerCommand("CommandDomain.commandWithEnumReturnValue", [], ["returnValue"]); -InspectorBackend.activateDomain("CommandDomain"); +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -// EventDomain. -InspectorBackend.registerEventDomainDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "EventDomain"); -InspectorBackend.registerEnum("EventDomain.EventWithEnumParameterParameter", {Shared: "shared", Black: "black", White: "white"}); -InspectorBackend.registerEvent("EventDomain.eventWithEnumParameter", ["parameter"]); -InspectorBackend.activateDomain("EventDomain"); -### End File: InspectorBackendCommands.js +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + +class AlternateCommandDomainBackendDispatcher : public AlternateBackendDispatcher { +public: + virtual ~AlternateCommandDomainBackendDispatcher() { } + virtual void commandWithEnumReturnValue(long callId) = 0; +}; + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h -### Begin File: InspectorBackendDispatchers.h +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -138,10 +135,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -170,29 +166,27 @@ class CommandDomainBackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref create(BackendDispatcher&, CommandDomainBackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; private: void commandWithEnumReturnValue(long requestId, RefPtr&& parameters); -private: - CommandDomainBackendDispatcher(BackendDispatcher&, CommandDomainBackendDispatcherHandler*); - CommandDomainBackendDispatcherHandler* m_agent; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(AlternateCommandDomainBackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - AlternateCommandDomainBackendDispatcher* m_alternateDispatcher; + AlternateCommandDomainBackendDispatcher* m_alternateDispatcher { nullptr }; #endif +private: + CommandDomainBackendDispatcher(BackendDispatcher&, CommandDomainBackendDispatcherHandler*); + CommandDomainBackendDispatcherHandler* m_agent { nullptr }; }; } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -221,7 +215,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -229,7 +223,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -244,9 +238,6 @@ CommandDomainBackendDispatcher::CommandDomainBackendDispatcher(BackendDispatcher& backendDispatcher, CommandDomainBackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("CommandDomain"), this); } @@ -279,7 +270,7 @@ m_agent->commandWithEnumReturnValue(error, &out_returnValue); if (!error.length()) - result->setString(ASCIILiteral("returnValue"), Inspector::Protocol::getEnumConstantValue(out_returnValue)); + result->setString(ASCIILiteral("returnValue"), Inspector::Protocol::TestHelpers::getEnumConstantValue(out_returnValue)); if (!error.length()) m_backendDispatcher->sendResponse(requestId, WTFMove(result)); @@ -289,12 +280,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -322,10 +313,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -348,14 +338,12 @@ }; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -384,7 +372,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -396,7 +384,7 @@ Ref jsonMessage = InspectorObject::create(); jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("EventDomain.eventWithEnumParameter")); Ref paramsObject = InspectorObject::create(); - paramsObject->setString(ASCIILiteral("parameter"), Inspector::Protocol::getEnumConstantValue(parameter)); + paramsObject->setString(ASCIILiteral("parameter"), Inspector::Protocol::TestHelpers::getEnumConstantValue(parameter)); jsonMessage->setObject(ASCIILiteral("params"), WTFMove(paramsObject)); m_frontendRouter.sendEvent(jsonMessage->toJSONString()); @@ -404,12 +392,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -437,8 +425,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -458,6 +445,8 @@ +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -465,6 +454,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace TypeDomain { /* */ enum class TypeDomainEnum { @@ -477,17 +468,26 @@ +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'TypeDomain' Domain +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -516,14 +516,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "shared", "red", @@ -540,18 +543,38 @@ return enum_constant_values[code]; } +// Enums in the 'TypeDomain' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::TypeDomain::TypeDomainEnum::Shared, + (size_t)Inspector::Protocol::TypeDomain::TypeDomainEnum::Red, + (size_t)Inspector::Protocol::TypeDomain::TypeDomainEnum::Green, + (size_t)Inspector::Protocol::TypeDomain::TypeDomainEnum::Blue, + }; + for (size_t i = 0; i < 4; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::TypeDomain::TypeDomainEnum)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -582,7 +605,7 @@ #include #include -@protocol RWIProtocolCommandDomainDomainHandler; +@protocol TestProtocolCommandDomainDomainHandler; namespace Inspector { @@ -591,22 +614,22 @@ class ObjCInspectorCommandDomainBackendDispatcher final : public AlternateCommandDomainBackendDispatcher { public: - ObjCInspectorCommandDomainBackendDispatcher(id handler) { m_delegate = handler; } + ObjCInspectorCommandDomainBackendDispatcher(id handler) { m_delegate = handler; } virtual void commandWithEnumReturnValue(long requestId) override; private: - RetainPtr> m_delegate; + RetainPtr> m_delegate; }; } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -635,10 +658,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -646,11 +669,11 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; - id _commandDomainHandler; - RWIProtocolEventDomainDomainEventDispatcher *_eventDomainEventDispatcher; + id _commandDomainHandler; + TestProtocolEventDomainDomainEventDispatcher *_eventDomainEventDispatcher; } - (instancetype)initWithController:(AugmentableInspectorController*)controller @@ -670,7 +693,7 @@ [super dealloc]; } -- (void)setCommandDomainHandler:(id)handler +- (void)setCommandDomainHandler:(id)handler { if (handler == _commandDomainHandler) return; @@ -683,27 +706,27 @@ _controller->appendExtraAgent(WTFMove(alternateAgent)); } -- (id)commandDomainHandler +- (id)commandDomainHandler { return _commandDomainHandler; } -- (RWIProtocolEventDomainDomainEventDispatcher *)eventDomainEventDispatcher +- (TestProtocolEventDomainDomainEventDispatcher *)eventDomainEventDispatcher { if (!_eventDomainEventDispatcher) - _eventDomainEventDispatcher = [[RWIProtocolEventDomainDomainEventDispatcher alloc] initWithController:_controller]; + _eventDomainEventDispatcher = [[TestProtocolEventDomainDomainEventDispatcher alloc] initWithController:_controller]; return _eventDomainEventDispatcher; } @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -731,21 +754,21 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject -@property (nonatomic, retain, setter=setCommandDomainHandler:) id commandDomainHandler; -@property (nonatomic, readonly) RWIProtocolEventDomainDomainEventDispatcher *eventDomainEventDispatcher; +@interface TestProtocolConfiguration : NSObject +@property (nonatomic, retain, setter=setCommandDomainHandler:) id commandDomainHandler; +@property (nonatomic, readonly) TestProtocolEventDomainDomainEventDispatcher *eventDomainEventDispatcher; @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -774,10 +797,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -791,7 +814,7 @@ backendDispatcher()->sendPendingErrors(); }; - id successCallback = ^(RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValue returnValue) { + id successCallback = ^(TestProtocolCommandDomainCommandWithEnumReturnValueReturnValue returnValue) { Ref resultObject = InspectorObject::create(); resultObject->setString(ASCIILiteral("returnValue"), toProtocolString(returnValue)); backendDispatcher()->sendResponse(requestId, WTFMove(resultObject)); @@ -805,12 +828,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -838,107 +861,54 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "config.h" +#import "TestProtocolInternal.h" -namespace Inspector { +#import "TestProtocolTypeConversions.h" +#import -template -ObjCEnumType fromProtocolString(const String& value); +using namespace Inspector; -inline String toProtocolString(RWIProtocolTypeDomainEnum value) -{ - switch(value) { - case RWIProtocolTypeDomainEnumShared: - return ASCIILiteral("shared"); - case RWIProtocolTypeDomainEnumRed: - return ASCIILiteral("red"); - case RWIProtocolTypeDomainEnumGreen: - return ASCIILiteral("green"); - case RWIProtocolTypeDomainEnumBlue: - return ASCIILiteral("blue"); - } -} -template<> -inline RWIProtocolTypeDomainEnum fromProtocolString(const String& value) -{ - if (value == "shared") - return RWIProtocolTypeDomainEnumShared; - if (value == "red") - return RWIProtocolTypeDomainEnumRed; - if (value == "green") - return RWIProtocolTypeDomainEnumGreen; - if (value == "blue") - return RWIProtocolTypeDomainEnumBlue; - ASSERT_NOT_REACHED(); - return RWIProtocolTypeDomainEnumShared; -} -inline String toProtocolString(RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValue value) +@implementation TestProtocolEventDomainDomainEventDispatcher { - switch(value) { - case RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared: - return ASCIILiteral("shared"); - case RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueCyan: - return ASCIILiteral("cyan"); - case RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueMagenta: - return ASCIILiteral("magenta"); - case RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueYellow: - return ASCIILiteral("yellow"); - } + AugmentableInspectorController* _controller; } -template<> -inline RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValue fromProtocolString(const String& value) +- (instancetype)initWithController:(AugmentableInspectorController*)controller; { - if (value == "shared") - return RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared; - if (value == "cyan") - return RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueCyan; - if (value == "magenta") - return RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueMagenta; - if (value == "yellow") - return RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueYellow; - ASSERT_NOT_REACHED(); - return RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared; + self = [super init]; + if (!self) + return nil; + ASSERT(controller); + _controller = controller; + return self; } - -inline String toProtocolString(RWIProtocolEventDomainEventWithEnumParameterParameter value) +- (void)eventWithEnumParameterWithParameter:(TestProtocolEventDomainEventWithEnumParameterParameter)parameter { - switch(value) { - case RWIProtocolEventDomainEventWithEnumParameterParameterShared: - return ASCIILiteral("shared"); - case RWIProtocolEventDomainEventWithEnumParameterParameterBlack: - return ASCIILiteral("black"); - case RWIProtocolEventDomainEventWithEnumParameterParameterWhite: - return ASCIILiteral("white"); - } -} + const FrontendRouter& router = _controller->frontendRouter(); -template<> -inline RWIProtocolEventDomainEventWithEnumParameterParameter fromProtocolString(const String& value) -{ - if (value == "shared") - return RWIProtocolEventDomainEventWithEnumParameterParameterShared; - if (value == "black") - return RWIProtocolEventDomainEventWithEnumParameterParameterBlack; - if (value == "white") - return RWIProtocolEventDomainEventWithEnumParameterParameterWhite; - ASSERT_NOT_REACHED(); - return RWIProtocolEventDomainEventWithEnumParameterParameterShared; + Ref jsonMessage = InspectorObject::create(); + jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("EventDomain.eventWithEnumParameter")); + Ref paramsObject = InspectorObject::create(); + paramsObject->setString(ASCIILiteral("parameter"), toProtocolString(parameter)); + jsonMessage->setObject(ASCIILiteral("params"), WTFMove(paramsObject)); + router.sendEvent(jsonMessage->toJSONString()); } -} // namespace Inspector +@end -### End File: RWIProtocolEnumConversionHelpers.h -### Begin File: RWIProtocolEventDispatchers.mm +### End File: TestProtocolEventDispatchers.mm + +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -966,54 +936,53 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import -using namespace Inspector; +typedef NS_ENUM(NSInteger, TestProtocolTypeDomainEnum) { + TestProtocolTypeDomainEnumShared, + TestProtocolTypeDomainEnumRed, + TestProtocolTypeDomainEnumGreen, + TestProtocolTypeDomainEnumBlue, +}; -@implementation RWIProtocolEventDomainDomainEventDispatcher -{ - AugmentableInspectorController* _controller; -} +typedef NS_ENUM(NSInteger, TestProtocolCommandDomainCommandWithEnumReturnValueReturnValue) { + TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared, + TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueCyan, + TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueMagenta, + TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueYellow, +}; -- (instancetype)initWithController:(AugmentableInspectorController*)controller; -{ - self = [super init]; - if (!self) - return nil; - ASSERT(controller); - _controller = controller; - return self; -} +typedef NS_ENUM(NSInteger, TestProtocolEventDomainEventWithEnumParameterParameter) { + TestProtocolEventDomainEventWithEnumParameterParameterShared, + TestProtocolEventDomainEventWithEnumParameterParameterBlack, + TestProtocolEventDomainEventWithEnumParameterParameterWhite, +}; -- (void)eventWithEnumParameterWithParameter:(RWIProtocolEventDomainEventWithEnumParameterParameter)parameter -{ - const FrontendRouter& router = _controller->frontendRouter(); - Ref jsonMessage = InspectorObject::create(); - jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("EventDomain.eventWithEnumParameter")); - Ref paramsObject = InspectorObject::create(); - paramsObject->setString(ASCIILiteral("parameter"), toProtocolString(parameter)); - jsonMessage->setObject(ASCIILiteral("params"), WTFMove(paramsObject)); - router.sendEvent(jsonMessage->toJSONString()); -} +@protocol TestProtocolCommandDomainDomainHandler +@required +- (void)commandWithEnumReturnValueWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(TestProtocolCommandDomainCommandWithEnumReturnValueReturnValue returnValue))successCallback; +@end + +__attribute__((visibility ("default"))) +@interface TestProtocolEventDomainDomainEventDispatcher : NSObject +- (void)eventWithEnumParameterWithParameter:(TestProtocolEventDomainEventWithEnumParameterParameter)parameter; @end -### End File: RWIProtocolEventDispatchers.mm +### End File: TestProtocol.h -### Begin File: RWIProtocol.h +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1041,53 +1010,151 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import -#import +@interface TestProtocolEventDomainDomainEventDispatcher (Private) +- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller; +@end +### End File: TestProtocolInternal.h +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +// DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -typedef NS_ENUM(NSInteger, RWIProtocolTypeDomainEnum) { - RWIProtocolTypeDomainEnumShared, - RWIProtocolTypeDomainEnumRed, - RWIProtocolTypeDomainEnumGreen, - RWIProtocolTypeDomainEnumBlue, -}; +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" -typedef NS_ENUM(NSInteger, RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValue) { - RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared, - RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueCyan, - RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueMagenta, - RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValueYellow, -}; +namespace Inspector { -typedef NS_ENUM(NSInteger, RWIProtocolEventDomainEventWithEnumParameterParameter) { - RWIProtocolEventDomainEventWithEnumParameterParameterShared, - RWIProtocolEventDomainEventWithEnumParameterParameterBlack, - RWIProtocolEventDomainEventWithEnumParameterParameterWhite, -}; +template +ObjCEnumType fromProtocolString(const String& value); +inline String toProtocolString(TestProtocolTypeDomainEnum value) +{ + switch(value) { + case TestProtocolTypeDomainEnumShared: + return ASCIILiteral("shared"); + case TestProtocolTypeDomainEnumRed: + return ASCIILiteral("red"); + case TestProtocolTypeDomainEnumGreen: + return ASCIILiteral("green"); + case TestProtocolTypeDomainEnumBlue: + return ASCIILiteral("blue"); + } +} -@protocol RWIProtocolCommandDomainDomainHandler -@required -- (void)commandWithEnumReturnValueWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)(RWIProtocolCommandDomainCommandWithEnumReturnValueReturnValue returnValue))successCallback; -@end +template<> +inline TestProtocolTypeDomainEnum fromProtocolString(const String& value) +{ + if (value == "shared") + return TestProtocolTypeDomainEnumShared; + if (value == "red") + return TestProtocolTypeDomainEnumRed; + if (value == "green") + return TestProtocolTypeDomainEnumGreen; + if (value == "blue") + return TestProtocolTypeDomainEnumBlue; + ASSERT_NOT_REACHED(); + return TestProtocolTypeDomainEnumShared; +} -__attribute__((visibility ("default"))) -@interface RWIProtocolEventDomainDomainEventDispatcher : NSObject -- (void)eventWithEnumParameterWithParameter:(RWIProtocolEventDomainEventWithEnumParameterParameter)parameter; -@end +inline String toProtocolString(TestProtocolCommandDomainCommandWithEnumReturnValueReturnValue value) +{ + switch(value) { + case TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared: + return ASCIILiteral("shared"); + case TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueCyan: + return ASCIILiteral("cyan"); + case TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueMagenta: + return ASCIILiteral("magenta"); + case TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueYellow: + return ASCIILiteral("yellow"); + } +} + +template<> +inline TestProtocolCommandDomainCommandWithEnumReturnValueReturnValue fromProtocolString(const String& value) +{ + if (value == "shared") + return TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared; + if (value == "cyan") + return TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueCyan; + if (value == "magenta") + return TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueMagenta; + if (value == "yellow") + return TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueYellow; + ASSERT_NOT_REACHED(); + return TestProtocolCommandDomainCommandWithEnumReturnValueReturnValueShared; +} -### End File: RWIProtocol.h -### Begin File: RWIProtocolTypes.mm +inline String toProtocolString(TestProtocolEventDomainEventWithEnumParameterParameter value) +{ + switch(value) { + case TestProtocolEventDomainEventWithEnumParameterParameterShared: + return ASCIILiteral("shared"); + case TestProtocolEventDomainEventWithEnumParameterParameterBlack: + return ASCIILiteral("black"); + case TestProtocolEventDomainEventWithEnumParameterParameterWhite: + return ASCIILiteral("white"); + } +} + +template<> +inline TestProtocolEventDomainEventWithEnumParameterParameter fromProtocolString(const String& value) +{ + if (value == "shared") + return TestProtocolEventDomainEventWithEnumParameterParameterShared; + if (value == "black") + return TestProtocolEventDomainEventWithEnumParameterParameterBlack; + if (value == "white") + return TestProtocolEventDomainEventWithEnumParameterParameterWhite; + ASSERT_NOT_REACHED(); + return TestProtocolEventDomainEventWithEnumParameterParameterShared; +} + +} // namespace Inspector + +### End File: TestProtocolTypeConversions.h + +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1116,27 +1183,49 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (TypeDomainDomain) ++ (void)_parseTypeDomainEnum:(NSNumber **)outValue fromPayload:(id)payload; +@end +@interface TestProtocolTypeConversions (CommandDomainDomain) +@end +@interface TestProtocolTypeConversions (EventDomainDomain) +@end +@implementation TestProtocolTypeConversions (TypeDomainDomain) ++ (void)_parseTypeDomainEnum:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} -### End File: RWIProtocolTypes.mm +@end +@implementation TestProtocolTypeConversions (CommandDomainDomain) -### Begin File: RWIProtocolInternal.h +@end +@implementation TestProtocolTypeConversions (EventDomainDomain) + +@end + + +### End File: TestProtocolTypeConversions.mm + +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1164,14 +1253,21 @@ // DO NOT EDIT THIS FILE. It is automatically generated from enum-values.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + + + + -@interface RWIProtocolEventDomainDomainEventDispatcher (Private) -- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller; -@end -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/events-with-optional-parameters.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/events-with-optional-parameters.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/events-with-optional-parameters.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/events-with-optional-parameters.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,39 +29,17 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Database. +InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); +InspectorBackend.registerEvent("Database.didExecuteOptionalParameters", ["columnNames", "notes", "timestamp", "values", "payload", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.registerEvent("Database.didExecuteNoOptionalParameters", ["columnNames", "notes", "timestamp", "values", "payload", "sqlError", "screenColor", "alternateColors", "printColor"]); +InspectorBackend.activateDomain("Database"); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,17 +67,36 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Database. -InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); -InspectorBackend.registerEvent("Database.didExecuteOptionalParameters", ["columnNames", "notes", "timestamp", "values", "payload", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.registerEvent("Database.didExecuteNoOptionalParameters", ["columnNames", "notes", "timestamp", "values", "payload", "sqlError", "screenColor", "alternateColors", "printColor"]); -InspectorBackend.activateDomain("Database"); -### End File: InspectorBackendCommands.js +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include -### Begin File: InspectorBackendDispatchers.h +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -127,10 +124,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -141,14 +137,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -177,7 +171,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -185,7 +179,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -194,12 +188,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -227,10 +221,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -248,14 +241,12 @@ }; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -284,7 +275,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -340,12 +331,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -373,8 +364,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -401,13 +391,6 @@ } // Database // End of typedefs. -String getEnumConstantValue(int code); - -template String getEnumConstantValue(T enumValue) -{ - return getEnumConstantValue(static_cast(enumValue)); -} - namespace Database { /* Database error. */ class Error : public Inspector::InspectorObjectBase { @@ -481,14 +464,12 @@ } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -517,33 +498,27 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { -static const char* const enum_constant_values[] = { -}; - -String getEnumConstantValue(int code) { - return enum_constant_values[code]; -} - } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -583,12 +558,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -617,10 +592,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -628,10 +603,10 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; - RWIProtocolDatabaseDomainEventDispatcher *_databaseEventDispatcher; + TestProtocolDatabaseDomainEventDispatcher *_databaseEventDispatcher; } - (instancetype)initWithController:(AugmentableInspectorController*)controller @@ -650,22 +625,22 @@ [super dealloc]; } -- (RWIProtocolDatabaseDomainEventDispatcher *)databaseEventDispatcher +- (TestProtocolDatabaseDomainEventDispatcher *)databaseEventDispatcher { if (!_databaseEventDispatcher) - _databaseEventDispatcher = [[RWIProtocolDatabaseDomainEventDispatcher alloc] initWithController:_controller]; + _databaseEventDispatcher = [[TestProtocolDatabaseDomainEventDispatcher alloc] initWithController:_controller]; return _databaseEventDispatcher; } @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -693,20 +668,20 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject -@property (nonatomic, readonly) RWIProtocolDatabaseDomainEventDispatcher *databaseEventDispatcher; +@interface TestProtocolConfiguration : NSObject +@property (nonatomic, readonly) TestProtocolDatabaseDomainEventDispatcher *databaseEventDispatcher; @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -735,10 +710,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -747,56 +722,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm - -### Begin File: RWIProtocolEnumConversionHelpers.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import "RWIProtocolArrayConversionHelpers.h" - -namespace Inspector { - -template -ObjCEnumType fromProtocolString(const String& value); - - - -} // namespace Inspector - -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -825,14 +756,14 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolInternal.h" -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocolTypeConversions.h" #import using namespace Inspector; -@implementation RWIProtocolDatabaseDomainEventDispatcher +@implementation TestProtocolDatabaseDomainEventDispatcher { AugmentableInspectorController* _controller; } @@ -847,7 +778,7 @@ return self; } -- (void)didExecuteOptionalParametersWithColumnNames:(NSArray/**/ **)columnNames notes:(NSString **)notes timestamp:(double *)timestamp values:(RWIProtocolJSONObject **)values payload:(RWIProtocolJSONObject **)payload sqlError:(RWIProtocolDatabaseError **)sqlError screenColor:(NSString **)screenColor alternateColors:(NSArray/**/ **)alternateColors printColor:(NSString **)printColor +- (void)didExecuteOptionalParametersWithColumnNames:(NSArray/**/ **)columnNames notes:(NSString **)notes timestamp:(double *)timestamp values:(RWIProtocolJSONObject **)values payload:(RWIProtocolJSONObject **)payload sqlError:(TestProtocolDatabaseError **)sqlError screenColor:(NSString **)screenColor alternateColors:(NSArray/**/ **)alternateColors printColor:(NSString **)printColor { const FrontendRouter& router = _controller->frontendRouter(); @@ -885,7 +816,7 @@ router.sendEvent(jsonMessage->toJSONString()); } -- (void)didExecuteNoOptionalParametersWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload sqlError:(RWIProtocolDatabaseError *)sqlError screenColor:(NSString *)screenColor alternateColors:(NSArray/**/ *)alternateColors printColor:(NSString *)printColor +- (void)didExecuteNoOptionalParametersWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload sqlError:(TestProtocolDatabaseError *)sqlError screenColor:(NSString *)screenColor alternateColors:(NSArray/**/ *)alternateColors printColor:(NSString *)printColor { const FrontendRouter& router = _controller->frontendRouter(); @@ -917,12 +848,12 @@ @end -### End File: RWIProtocolEventDispatchers.mm +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocol.h +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -955,13 +886,15 @@ #import -@class RWIProtocolDatabaseError; +@class TestProtocolDatabaseError; __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseError : RWIProtocolJSONObject +@interface TestProtocolDatabaseError : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; - (instancetype)initWithMessage:(NSString *)message code:(int)code; /* required */ @property (nonatomic, copy) NSString *message; /* required */ @property (nonatomic, assign) int code; @@ -970,18 +903,18 @@ __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseDomainEventDispatcher : NSObject -- (void)didExecuteOptionalParametersWithColumnNames:(NSArray/**/ **)columnNames notes:(NSString **)notes timestamp:(double *)timestamp values:(RWIProtocolJSONObject **)values payload:(RWIProtocolJSONObject **)payload sqlError:(RWIProtocolDatabaseError **)sqlError screenColor:(NSString **)screenColor alternateColors:(NSArray/**/ **)alternateColors printColor:(NSString **)printColor; -- (void)didExecuteNoOptionalParametersWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload sqlError:(RWIProtocolDatabaseError *)sqlError screenColor:(NSString *)screenColor alternateColors:(NSArray/**/ *)alternateColors printColor:(NSString *)printColor; +@interface TestProtocolDatabaseDomainEventDispatcher : NSObject +- (void)didExecuteOptionalParametersWithColumnNames:(NSArray/**/ **)columnNames notes:(NSString **)notes timestamp:(double *)timestamp values:(RWIProtocolJSONObject **)values payload:(RWIProtocolJSONObject **)payload sqlError:(TestProtocolDatabaseError **)sqlError screenColor:(NSString **)screenColor alternateColors:(NSArray/**/ **)alternateColors printColor:(NSString **)printColor; +- (void)didExecuteNoOptionalParametersWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload sqlError:(TestProtocolDatabaseError *)sqlError screenColor:(NSString *)screenColor alternateColors:(NSArray/**/ *)alternateColors printColor:(NSString *)printColor; @end -### End File: RWIProtocol.h +### End File: TestProtocol.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1009,61 +942,147 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" - -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import #import -#import -using namespace Inspector; +@interface TestProtocolDatabaseDomainEventDispatcher (Private) +- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller; +@end -@implementation RWIProtocolDatabaseError +### End File: TestProtocolInternal.h -- (instancetype)initWithMessage:(NSString *)message code:(int)code; -{ - self = [super init]; - if (!self) - return nil; +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ - THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); +// DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - self.message = message; - self.code = code; +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" - return self; -} +namespace Inspector { -- (void)setMessage:(NSString *)message +template +ObjCEnumType fromProtocolString(const String& value); + + + +} // namespace Inspector + +### End File: TestProtocolTypeConversions.h + +### Begin File: TestProtocolTypeConversions.mm +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "config.h" +#import "TestProtocolTypeConversions.h" + +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import + +using namespace Inspector; + +@interface TestProtocolTypeConversions (DatabaseDomain) + ++ (void)_parseDatabaseId:(NSString **)outValue fromPayload:(id)payload; ++ (void)_parsePrimaryColors:(NSString **)outValue fromPayload:(id)payload; ++ (void)_parseColorList:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload; + +@end + +@implementation TestProtocolTypeConversions (DatabaseDomain) + ++ (void)_parseDatabaseId:(NSString **)outValue fromPayload:(id)payload { - [super setString:message forKey:@"message"]; + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = (NSString *)payload; } -- (NSString *)message ++ (void)_parsePrimaryColors:(NSString **)outValue fromPayload:(id)payload { - return [super stringForKey:@"message"]; + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = (NSString *)payload; } -- (void)setCode:(int)code ++ (void)_parseColorList:(NSArray/**/ **)outValue fromPayload:(id)payload { - [super setInteger:code forKey:@"code"]; + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; } -- (int)code ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload { - return [super integerForKey:@"code"]; + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseError alloc] initWithPayload:payload]; } @end -### End File: RWIProtocolTypes.mm +### End File: TestProtocolTypeConversions.mm -### Begin File: RWIProtocolInternal.h +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1091,14 +1110,74 @@ // DO NOT EDIT THIS FILE. It is automatically generated from events-with-optional-parameters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + +@implementation TestProtocolDatabaseError + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"message"], @"message"); + self.message = payload[@"message"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"code"], @"code"); + self.code = [payload[@"code"] integerValue]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} + +- (instancetype)initWithMessage:(NSString *)message code:(int)code; +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); + + self.message = message; + self.code = code; + + return self; +} + +- (void)setMessage:(NSString *)message +{ + [super setString:message forKey:@"message"]; +} + +- (NSString *)message +{ + return [super stringForKey:@"message"]; +} + +- (void)setCode:(int)code +{ + [super setInteger:code forKey:@"code"]; +} + +- (int)code +{ + return [super integerForKey:@"code"]; +} -@interface RWIProtocolDatabaseDomainEventDispatcher (Private) -- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller; @end -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-type-reference-as-primitive-type.json-error webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-type-reference-as-primitive-type.json-error --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-type-reference-as-primitive-type.json-error 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-type-reference-as-primitive-type.json-error 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1 @@ +ERROR: Type reference 'DatabaseId' is not a primitive type. Allowed values: integer, number, string, boolean, enum, object, array, any diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-unknown-type-reference-in-type-declaration.json-error webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-unknown-type-reference-in-type-declaration.json-error --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-unknown-type-reference-in-type-declaration.json-error 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/fail-on-unknown-type-reference-in-type-declaration.json-error 2016-09-16 09:56:47.000000000 +0000 @@ -1 +1 @@ -ERROR: Lookup failed for type reference: dragon (referenced from domain: Runtime) +ERROR: Type reference 'dragon' is not a primitive type. Allowed values: integer, number, string, boolean, enum, object, array, any diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/generate-domains-with-feature-guards.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/generate-domains-with-feature-guards.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/generate-domains-with-feature-guards.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/generate-domains-with-feature-guards.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,45 +29,20 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - -#if PLATFORM(WEB_COMMANDS) -class AlternateNetwork1BackendDispatcher : public AlternateBackendDispatcher { -public: - virtual ~AlternateNetwork1BackendDispatcher() { } - virtual void loadResource(long callId) = 0; -}; -#endif // PLATFORM(WEB_COMMANDS) - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +// Network1. +InspectorBackend.registerCommand("Network1.loadResource", [], []); +InspectorBackend.activateDomain("Network1"); -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Network3. +InspectorBackend.registerNetwork3Dispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network3"); +InspectorBackend.registerEvent("Network3.resourceLoaded", []); +InspectorBackend.activateDomain("Network3"); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,20 +70,42 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Network1. -InspectorBackend.registerCommand("Network1.loadResource", [], []); -InspectorBackend.activateDomain("Network1"); +#pragma once -// Network3. -InspectorBackend.registerNetwork3Dispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network3"); -InspectorBackend.registerEvent("Network3.resourceLoaded", []); -InspectorBackend.activateDomain("Network3"); -### End File: InspectorBackendCommands.js +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; -### Begin File: InspectorBackendDispatchers.h + +#if PLATFORM(WEB_COMMANDS) +class AlternateNetwork1BackendDispatcher : public AlternateBackendDispatcher { +public: + virtual ~AlternateNetwork1BackendDispatcher() { } + virtual void loadResource(long callId) = 0; +}; +#endif // PLATFORM(WEB_COMMANDS) + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,10 +133,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -166,30 +162,28 @@ class Network1BackendDispatcher final : public SupplementalBackendDispatcher { public: static Ref create(BackendDispatcher&, Network1BackendDispatcherHandler*); - virtual void dispatch(long requestId, const String& method, Ref&& message) override; + void dispatch(long requestId, const String& method, Ref&& message) override; private: void loadResource(long requestId, RefPtr&& parameters); -private: - Network1BackendDispatcher(BackendDispatcher&, Network1BackendDispatcherHandler*); - Network1BackendDispatcherHandler* m_agent; #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) public: void setAlternateDispatcher(AlternateNetwork1BackendDispatcher* alternateDispatcher) { m_alternateDispatcher = alternateDispatcher; } private: - AlternateNetwork1BackendDispatcher* m_alternateDispatcher; + AlternateNetwork1BackendDispatcher* m_alternateDispatcher { nullptr }; #endif +private: + Network1BackendDispatcher(BackendDispatcher&, Network1BackendDispatcherHandler*); + Network1BackendDispatcherHandler* m_agent { nullptr }; }; #endif // PLATFORM(WEB_COMMANDS) } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -218,7 +212,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -226,7 +220,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -244,9 +238,6 @@ Network1BackendDispatcher::Network1BackendDispatcher(BackendDispatcher& backendDispatcher, Network1BackendDispatcherHandler* agent) : SupplementalBackendDispatcher(backendDispatcher) , m_agent(agent) -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - , m_alternateDispatcher(nullptr) -#endif { m_backendDispatcher->registerDispatcherForDomain(ASCIILiteral("Network1"), this); } @@ -286,12 +277,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -319,10 +310,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -341,14 +331,12 @@ #endif // PLATFORM(WEB_EVENTS) } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -377,7 +365,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -396,12 +384,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -429,8 +417,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -452,13 +439,6 @@ -String getEnumConstantValue(int code); - -template String getEnumConstantValue(T enumValue) -{ - return getEnumConstantValue(static_cast(enumValue)); -} - #if PLATFORM(WEB_TYPES) namespace Network2 { class NetworkError : public Inspector::InspectorObjectBase { @@ -533,14 +513,12 @@ } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -569,33 +547,27 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { -static const char* const enum_constant_values[] = { -}; - -String getEnumConstantValue(int code) { - return enum_constant_values[code]; -} - } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -626,7 +598,7 @@ #include #include -@protocol RWIProtocolNetwork1DomainHandler; +@protocol TestProtocolNetwork1DomainHandler; namespace Inspector { @@ -634,10 +606,10 @@ #if PLATFORM(WEB_COMMANDS) class ObjCInspectorNetwork1BackendDispatcher final : public AlternateNetwork1BackendDispatcher { public: - ObjCInspectorNetwork1BackendDispatcher(id handler) { m_delegate = handler; } + ObjCInspectorNetwork1BackendDispatcher(id handler) { m_delegate = handler; } virtual void loadResource(long requestId) override; private: - RetainPtr> m_delegate; + RetainPtr> m_delegate; }; #endif // PLATFORM(WEB_COMMANDS) @@ -647,12 +619,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -681,10 +653,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -692,11 +664,11 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; - id _network1Handler; - RWIProtocolNetwork3DomainEventDispatcher *_network3EventDispatcher; + id _network1Handler; + TestProtocolNetwork3DomainEventDispatcher *_network3EventDispatcher; } - (instancetype)initWithController:(AugmentableInspectorController*)controller @@ -716,7 +688,7 @@ [super dealloc]; } -- (void)setNetwork1Handler:(id)handler +- (void)setNetwork1Handler:(id)handler { if (handler == _network1Handler) return; @@ -729,27 +701,27 @@ _controller->appendExtraAgent(WTFMove(alternateAgent)); } -- (id)network1Handler +- (id)network1Handler { return _network1Handler; } -- (RWIProtocolNetwork3DomainEventDispatcher *)network3EventDispatcher +- (TestProtocolNetwork3DomainEventDispatcher *)network3EventDispatcher { if (!_network3EventDispatcher) - _network3EventDispatcher = [[RWIProtocolNetwork3DomainEventDispatcher alloc] initWithController:_controller]; + _network3EventDispatcher = [[TestProtocolNetwork3DomainEventDispatcher alloc] initWithController:_controller]; return _network3EventDispatcher; } @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -777,21 +749,21 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject -@property (nonatomic, retain, setter=setNetwork1Handler:) id network1Handler; -@property (nonatomic, readonly) RWIProtocolNetwork3DomainEventDispatcher *network3EventDispatcher; +@interface TestProtocolConfiguration : NSObject +@property (nonatomic, retain, setter=setNetwork1Handler:) id network1Handler; +@property (nonatomic, readonly) TestProtocolNetwork3DomainEventDispatcher *network3EventDispatcher; @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -820,10 +792,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -851,12 +823,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -884,27 +856,51 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "config.h" +#import "TestProtocolInternal.h" -namespace Inspector { +#import "TestProtocolTypeConversions.h" +#import -template -ObjCEnumType fromProtocolString(const String& value); +using namespace Inspector; +@implementation TestProtocolNetwork3DomainEventDispatcher +{ + AugmentableInspectorController* _controller; +} +- (instancetype)initWithController:(AugmentableInspectorController*)controller; +{ + self = [super init]; + if (!self) + return nil; + ASSERT(controller); + _controller = controller; + return self; +} -} // namespace Inspector +- (void)resourceLoaded +{ + const FrontendRouter& router = _controller->frontendRouter(); + + Ref jsonMessage = InspectorObject::create(); + jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("Network3.resourceLoaded")); + router.sendEvent(jsonMessage->toJSONString()); +} + +@end -### End File: RWIProtocolEnumConversionHelpers.h -### Begin File: RWIProtocolEventDispatchers.mm +### End File: TestProtocolEventDispatchers.mm + +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -932,51 +928,85 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import -using namespace Inspector; +@class TestProtocolNetwork2NetworkError; -@implementation RWIProtocolNetwork3DomainEventDispatcher -{ - AugmentableInspectorController* _controller; -} +__attribute__((visibility ("default"))) +@interface TestProtocolNetwork2NetworkError : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithMessage:(NSString *)message code:(int)code; +/* required */ @property (nonatomic, copy) NSString *message; +/* required */ @property (nonatomic, assign) int code; +@end -- (instancetype)initWithController:(AugmentableInspectorController*)controller; -{ - self = [super init]; - if (!self) - return nil; - ASSERT(controller); - _controller = controller; - return self; -} +@protocol TestProtocolNetwork1DomainHandler +@required +- (void)loadResourceWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; +@end -- (void)resourceLoaded -{ - const FrontendRouter& router = _controller->frontendRouter(); +__attribute__((visibility ("default"))) +@interface TestProtocolNetwork3DomainEventDispatcher : NSObject +- (void)resourceLoaded; +@end - Ref jsonMessage = InspectorObject::create(); - jsonMessage->setString(ASCIILiteral("method"), ASCIILiteral("Network3.resourceLoaded")); - router.sendEvent(jsonMessage->toJSONString()); -} +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import + +@interface TestProtocolNetwork3DomainEventDispatcher (Private) +- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller; @end -### End File: RWIProtocolEventDispatchers.mm +### End File: TestProtocolInternal.h -### Begin File: RWIProtocol.h +### Begin File: TestProtocolTypeConversions.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1004,40 +1034,28 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" -#import +namespace Inspector { +template +ObjCEnumType fromProtocolString(const String& value); -@class RWIProtocolNetwork2NetworkError; -__attribute__((visibility ("default"))) -@interface RWIProtocolNetwork2NetworkError : RWIProtocolJSONObject -- (instancetype)initWithMessage:(NSString *)message code:(int)code; -/* required */ @property (nonatomic, copy) NSString *message; -/* required */ @property (nonatomic, assign) int code; -@end -@protocol RWIProtocolNetwork1DomainHandler -@required -- (void)loadResourceWithErrorCallback:(void(^)(NSString *error))errorCallback successCallback:(void(^)())successCallback; -@end - -__attribute__((visibility ("default"))) -@interface RWIProtocolNetwork3DomainEventDispatcher : NSObject -- (void)resourceLoaded; -@end +} // namespace Inspector -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1066,64 +1084,49 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (Network1Domain) +@end +@interface TestProtocolTypeConversions (Network2Domain) ++ (void)_parseNetworkError:(TestProtocolNetwork2NetworkError **)outValue fromPayload:(id)payload; -@implementation RWIProtocolNetwork2NetworkError - -- (instancetype)initWithMessage:(NSString *)message code:(int)code; -{ - self = [super init]; - if (!self) - return nil; - - THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); - - self.message = message; - self.code = code; - - return self; -} +@end +@interface TestProtocolTypeConversions (Network3Domain) -- (void)setMessage:(NSString *)message -{ - [super setString:message forKey:@"message"]; -} +@end -- (NSString *)message -{ - return [super stringForKey:@"message"]; -} +@implementation TestProtocolTypeConversions (Network1Domain) -- (void)setCode:(int)code -{ - [super setInteger:code forKey:@"code"]; -} +@end +@implementation TestProtocolTypeConversions (Network2Domain) -- (int)code ++ (void)_parseNetworkError:(TestProtocolNetwork2NetworkError **)outValue fromPayload:(id)payload { - return [super integerForKey:@"code"]; + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolNetwork2NetworkError alloc] initWithPayload:payload]; } @end +@implementation TestProtocolTypeConversions (Network3Domain) +@end +### End File: TestProtocolTypeConversions.mm -### End File: RWIProtocolTypes.mm - -### Begin File: RWIProtocolInternal.h +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1151,14 +1154,78 @@ // DO NOT EDIT THIS FILE. It is automatically generated from generate-domains-with-feature-guards.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + + + +@implementation TestProtocolNetwork2NetworkError + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"message"], @"message"); + self.message = payload[@"message"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"code"], @"code"); + self.code = [payload[@"code"] integerValue]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} + +- (instancetype)initWithMessage:(NSString *)message code:(int)code; +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); + + self.message = message; + self.code = code; + + return self; +} + +- (void)setMessage:(NSString *)message +{ + [super setString:message forKey:@"message"]; +} + +- (NSString *)message +{ + return [super stringForKey:@"message"]; +} + +- (void)setCode:(int)code +{ + [super setInteger:code forKey:@"code"]; +} + +- (int)code +{ + return [super integerForKey:@"code"]; +} -@interface RWIProtocolNetwork3DomainEventDispatcher (Private) -- (instancetype)initWithController:(Inspector::AugmentableInspectorController*)controller; @end -### End File: RWIProtocolInternal.h + + +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/same-type-id-different-domain.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/same-type-id-different-domain.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/same-type-id-different-domain.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/same-type-id-different-domain.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,40 +28,12 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +### End File: InspectorBackendCommands.js -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h - -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,12 +60,37 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendDispatchers.h +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,10 +118,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -135,14 +131,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -171,7 +165,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -179,7 +173,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -188,12 +182,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -221,10 +215,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -233,14 +226,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -269,7 +260,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -278,12 +269,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -311,8 +302,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -337,26 +327,17 @@ } // Runtime2 // End of typedefs. -String getEnumConstantValue(int code); - -template String getEnumConstantValue(T enumValue) -{ - return getEnumConstantValue(static_cast(enumValue)); -} - } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -385,33 +366,27 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { -static const char* const enum_constant_values[] = { -}; - -String getEnumConstantValue(int code) { - return enum_constant_values[code]; -} - } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -453,12 +428,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -487,10 +462,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -498,7 +473,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -521,12 +496,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -554,19 +529,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -595,10 +570,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -609,12 +584,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -642,25 +617,25 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "config.h" +#import "TestProtocolInternal.h" -namespace Inspector { +#import "TestProtocolTypeConversions.h" +#import -template -ObjCEnumType fromProtocolString(const String& value); +using namespace Inspector; -} // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -688,25 +663,28 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import + +#import + + + + -#import "RWIProtocolEnumConversionHelpers.h" -#import -using namespace Inspector; -### End File: RWIProtocolEventDispatchers.mm -### Begin File: RWIProtocol.h +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -734,28 +712,67 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import -#import +### End File: TestProtocolInternal.h + +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +// DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" +namespace Inspector { +template +ObjCEnumType fromProtocolString(const String& value); +} // namespace Inspector -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -784,25 +801,51 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (RuntimeDomain) ++ (void)_parseRemoteObjectId:(NSString **)outValue fromPayload:(id)payload; +@end +@interface TestProtocolTypeConversions (Runtime2Domain) ++ (void)_parseRemoteObjectId:(NSString **)outValue fromPayload:(id)payload; +@end + +@implementation TestProtocolTypeConversions (RuntimeDomain) -### End File: RWIProtocolTypes.mm ++ (void)_parseRemoteObjectId:(NSString **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = (NSString *)payload; +} -### Begin File: RWIProtocolInternal.h +@end +@implementation TestProtocolTypeConversions (Runtime2Domain) + ++ (void)_parseRemoteObjectId:(NSString **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = (NSString *)payload; +} + +@end + + +### End File: TestProtocolTypeConversions.mm + +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -830,12 +873,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from same-type-id-different-domain.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/shadowed-optional-type-setters.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/shadowed-optional-type-setters.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/shadowed-optional-type-setters.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/shadowed-optional-type-setters.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,40 +28,12 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +### End File: InspectorBackendCommands.js -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h - -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,12 +60,37 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendDispatchers.h +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,10 +118,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -135,14 +131,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -171,7 +165,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -179,7 +173,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -188,12 +182,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -221,10 +215,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -233,14 +226,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -269,7 +260,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -278,12 +269,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -311,8 +302,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -332,6 +322,8 @@ +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -339,6 +331,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace Runtime { /* Key path. */ class KeyPath : public Inspector::InspectorObjectBase { @@ -376,7 +370,7 @@ Builder& setType(Type value) { COMPILE_ASSERT(!(STATE & TypeSet), property_type_already_set); - m_result->setString(ASCIILiteral("type"), Inspector::Protocol::getEnumConstantValue(static_cast(value))); + m_result->setString(ASCIILiteral("type"), Inspector::Protocol::TestHelpers::getEnumConstantValue(value)); return castState(); } @@ -416,17 +410,26 @@ +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'Runtime' Domain +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -455,14 +458,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "null", "string", @@ -473,18 +479,37 @@ return enum_constant_values[code]; } +// Enums in the 'Runtime' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Runtime::KeyPath::Type::Null, + (size_t)Inspector::Protocol::Runtime::KeyPath::Type::String, + (size_t)Inspector::Protocol::Runtime::KeyPath::Type::Array, + }; + for (size_t i = 0; i < 3; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Runtime::KeyPath::Type)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -524,12 +549,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -558,10 +583,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -569,7 +594,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -592,12 +617,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -625,19 +650,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -666,10 +691,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -678,12 +703,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -711,47 +736,23 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" - -namespace Inspector { +#import "config.h" +#import "TestProtocolInternal.h" -template -ObjCEnumType fromProtocolString(const String& value); +#import "TestProtocolTypeConversions.h" +#import +using namespace Inspector; -inline String toProtocolString(RWIProtocolRuntimeKeyPathType value) -{ - switch(value) { - case RWIProtocolRuntimeKeyPathTypeNull: - return ASCIILiteral("null"); - case RWIProtocolRuntimeKeyPathTypeString: - return ASCIILiteral("string"); - case RWIProtocolRuntimeKeyPathTypeArray: - return ASCIILiteral("array"); - } -} -template<> -inline RWIProtocolRuntimeKeyPathType fromProtocolString(const String& value) -{ - if (value == "null") - return RWIProtocolRuntimeKeyPathTypeNull; - if (value == "string") - return RWIProtocolRuntimeKeyPathTypeString; - if (value == "array") - return RWIProtocolRuntimeKeyPathTypeArray; - ASSERT_NOT_REACHED(); - return RWIProtocolRuntimeKeyPathTypeNull; -} -} // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -779,23 +780,42 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import + + +@class TestProtocolRuntimeKeyPath; + + +typedef NS_ENUM(NSInteger, TestProtocolRuntimeKeyPathType) { + TestProtocolRuntimeKeyPathTypeNull, + TestProtocolRuntimeKeyPathTypeString, + TestProtocolRuntimeKeyPathTypeArray, +}; + + +__attribute__((visibility ("default"))) +@interface TestProtocolRuntimeKeyPath : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithType:(TestProtocolRuntimeKeyPathType)type; +/* required */ @property (nonatomic, assign) TestProtocolRuntimeKeyPathType type; +/* optional */ @property (nonatomic, copy) NSString *string; +/* optional */ @property (nonatomic, copy) NSArray/**/ *array; +@end -using namespace Inspector; -### End File: RWIProtocolEventDispatchers.mm -### Begin File: RWIProtocol.h +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -823,40 +843,89 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import -#import -@class RWIProtocolRuntimeKeyPath; +### End File: TestProtocolInternal.h -typedef NS_ENUM(NSInteger, RWIProtocolRuntimeKeyPathType) { - RWIProtocolRuntimeKeyPathTypeNull, - RWIProtocolRuntimeKeyPathTypeString, - RWIProtocolRuntimeKeyPathTypeArray, -}; +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +// DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -__attribute__((visibility ("default"))) -@interface RWIProtocolRuntimeKeyPath : RWIProtocolJSONObject -- (instancetype)initWithType:(RWIProtocolRuntimeKeyPathType)type; -/* required */ @property (nonatomic, assign) RWIProtocolRuntimeKeyPathType type; -/* optional */ @property (nonatomic, copy) NSString *string; -/* optional */ @property (nonatomic, copy) NSArray/**/ *array; -@end +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" + +namespace Inspector { +template +ObjCEnumType fromProtocolString(const String& value); +inline String toProtocolString(TestProtocolRuntimeKeyPathType value) +{ + switch(value) { + case TestProtocolRuntimeKeyPathTypeNull: + return ASCIILiteral("null"); + case TestProtocolRuntimeKeyPathTypeString: + return ASCIILiteral("string"); + case TestProtocolRuntimeKeyPathTypeArray: + return ASCIILiteral("array"); + } +} +template<> +inline TestProtocolRuntimeKeyPathType fromProtocolString(const String& value) +{ + if (value == "null") + return TestProtocolRuntimeKeyPathTypeNull; + if (value == "string") + return TestProtocolRuntimeKeyPathTypeString; + if (value == "array") + return TestProtocolRuntimeKeyPathTypeArray; + ASSERT_NOT_REACHED(); + return TestProtocolRuntimeKeyPathTypeNull; +} +} // namespace Inspector -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -885,67 +954,37 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (RuntimeDomain) -@implementation RWIProtocolRuntimeKeyPath - -- (instancetype)initWithType:(RWIProtocolRuntimeKeyPathType)type; -{ - self = [super init]; - if (!self) - return nil; - - self.type = type; - - return self; -} - -- (void)setType:(RWIProtocolRuntimeKeyPathType)type -{ - [super setString:toProtocolString(type) forKey:@"type"]; -} - -- (RWIProtocolRuntimeKeyPathType)type -{ - return fromProtocolString([super stringForKey:@"type"]); -} - -- (void)setString:(NSString *)string -{ - [super setString:string forKey:@"string"]; -} ++ (void)_parseKeyPath:(TestProtocolRuntimeKeyPath **)outValue fromPayload:(id)payload; -- (NSString *)string -{ - return [super stringForKey:@"string"]; -} +@end -- (void)setArray:(NSArray/**/ *)array -{ - [super setInspectorArray:inspectorStringArray(array) forKey:@"array"]; -} +@implementation TestProtocolTypeConversions (RuntimeDomain) -- (NSArray/**/ *)array ++ (void)_parseKeyPath:(TestProtocolRuntimeKeyPath **)outValue fromPayload:(id)payload { - return objcStringArray([super inspectorArrayForKey:@"array"]); + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolRuntimeKeyPath alloc] initWithPayload:payload]; } @end -### End File: RWIProtocolTypes.mm +### End File: TestProtocolTypeConversions.mm -### Begin File: RWIProtocolInternal.h +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -973,12 +1012,82 @@ // DO NOT EDIT THIS FILE. It is automatically generated from shadowed-optional-type-setters.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + +@implementation TestProtocolRuntimeKeyPath + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"type"], @"type"); + self.type = fromProtocolString(payload[@"type"]); + + self.string = payload[@"string"]; + + self.array = objcArrayFromPayload(payload[@"array"]); + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} + +- (instancetype)initWithType:(TestProtocolRuntimeKeyPathType)type; +{ + if (!(self = [super init])) + return nil; + self.type = type; + + return self; +} + +- (void)setType:(TestProtocolRuntimeKeyPathType)type +{ + [super setString:toProtocolString(type) forKey:@"type"]; +} + +- (TestProtocolRuntimeKeyPathType)type +{ + return fromProtocolString([super stringForKey:@"type"]); +} + +- (void)setString:(NSString *)string +{ + [super setString:string forKey:@"string"]; +} +- (NSString *)string +{ + return [super stringForKey:@"string"]; +} + +- (void)setArray:(NSArray/**/ *)array +{ + [super setInspectorArray:inspectorStringArray(array) forKey:@"array"]; +} + +- (NSArray/**/ *)array +{ + return objcStringArray([super inspectorArrayForKey:@"array"]); +} + +@end -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-aliased-primitive-type.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-aliased-primitive-type.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-aliased-primitive-type.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-aliased-primitive-type.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,40 +28,12 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +### End File: InspectorBackendCommands.js -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h - -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,12 +60,37 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendDispatchers.h +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,10 +118,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -135,14 +131,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -171,7 +165,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -179,7 +173,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -188,12 +182,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -221,10 +215,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -233,14 +226,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -269,7 +260,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -278,12 +269,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -311,8 +302,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -332,26 +322,17 @@ } // Runtime // End of typedefs. -String getEnumConstantValue(int code); - -template String getEnumConstantValue(T enumValue) -{ - return getEnumConstantValue(static_cast(enumValue)); -} - } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -380,33 +361,27 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { -static const char* const enum_constant_values[] = { -}; - -String getEnumConstantValue(int code) { - return enum_constant_values[code]; -} - } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -446,12 +421,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -480,10 +455,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -491,7 +466,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -514,12 +489,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -547,19 +522,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -588,10 +563,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -600,12 +575,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -633,23 +608,23 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "config.h" +#import "TestProtocolInternal.h" -namespace Inspector { +#import "TestProtocolTypeConversions.h" +#import -template -ObjCEnumType fromProtocolString(const String& value); +using namespace Inspector; -} // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -677,23 +652,28 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import + +#import + -#import "RWIProtocolEnumConversionHelpers.h" -#import -using namespace Inspector; -### End File: RWIProtocolEventDispatchers.mm -### Begin File: RWIProtocol.h + + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -721,28 +701,65 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import - -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import +### End File: TestProtocolInternal.h +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" +namespace Inspector { +template +ObjCEnumType fromProtocolString(const String& value); +} // namespace Inspector -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -771,23 +788,37 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (RuntimeDomain) + ++ (void)_parseRemoteObjectId:(NSNumber **)outValue fromPayload:(id)payload; + +@end + +@implementation TestProtocolTypeConversions (RuntimeDomain) + ++ (void)_parseRemoteObjectId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} +@end -### End File: RWIProtocolTypes.mm +### End File: TestProtocolTypeConversions.mm -### Begin File: RWIProtocolInternal.h +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -815,12 +846,17 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-aliased-primitive-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-array-type.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-array-type.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-array-type.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-array-type.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,39 +29,14 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Debugger. +InspectorBackend.registerEnum("Debugger.Reason", {Died: "Died", Fainted: "Fainted", Hungry: "Hungry"}); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,14 +64,36 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Debugger. -InspectorBackend.registerEnum("Debugger.Reason", {Died: "Died", Fainted: "Fainted", Hungry: "Hungry"}); -### End File: InspectorBackendCommands.js +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h -### Begin File: InspectorBackendDispatchers.h +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -124,10 +121,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -138,14 +134,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -174,7 +168,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -182,7 +176,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -191,12 +185,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -224,10 +218,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -236,14 +229,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -272,7 +263,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -281,12 +272,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -314,8 +305,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -348,6 +338,8 @@ } // Runtime // End of typedefs. +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -355,6 +347,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace Debugger { /* */ enum class Reason { @@ -366,17 +360,26 @@ +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'Debugger' Domain +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -405,14 +408,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "Died", "Fainted", @@ -423,18 +429,37 @@ return enum_constant_values[code]; } +// Enums in the 'Debugger' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Debugger::Reason::Died, + (size_t)Inspector::Protocol::Debugger::Reason::Fainted, + (size_t)Inspector::Protocol::Debugger::Reason::Hungry, + }; + for (size_t i = 0; i < 3; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Debugger::Reason)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -476,12 +501,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -510,10 +535,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -521,7 +546,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -544,12 +569,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -577,19 +602,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -618,10 +643,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -632,12 +657,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -665,49 +690,25 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" - -namespace Inspector { +#import "config.h" +#import "TestProtocolInternal.h" -template -ObjCEnumType fromProtocolString(const String& value); +#import "TestProtocolTypeConversions.h" +#import +using namespace Inspector; -inline String toProtocolString(RWIProtocolDebuggerReason value) -{ - switch(value) { - case RWIProtocolDebuggerReasonDied: - return ASCIILiteral("Died"); - case RWIProtocolDebuggerReasonFainted: - return ASCIILiteral("Fainted"); - case RWIProtocolDebuggerReasonHungry: - return ASCIILiteral("Hungry"); - } -} -template<> -inline RWIProtocolDebuggerReason fromProtocolString(const String& value) -{ - if (value == "Died") - return RWIProtocolDebuggerReasonDied; - if (value == "Fainted") - return RWIProtocolDebuggerReasonFainted; - if (value == "Hungry") - return RWIProtocolDebuggerReasonHungry; - ASSERT_NOT_REACHED(); - return RWIProtocolDebuggerReasonDied; -} -} // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -735,25 +736,33 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import + +#import -#import "RWIProtocolEnumConversionHelpers.h" -#import -using namespace Inspector; +typedef NS_ENUM(NSInteger, TestProtocolDebuggerReason) { + TestProtocolDebuggerReasonDied, + TestProtocolDebuggerReasonFainted, + TestProtocolDebuggerReasonHungry, +}; -### End File: RWIProtocolEventDispatchers.mm -### Begin File: RWIProtocol.h + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -781,33 +790,91 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import -#import +### End File: TestProtocolInternal.h +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ -typedef NS_ENUM(NSInteger, RWIProtocolDebuggerReason) { - RWIProtocolDebuggerReasonDied, - RWIProtocolDebuggerReasonFainted, - RWIProtocolDebuggerReasonHungry, -}; +// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" +namespace Inspector { +template +ObjCEnumType fromProtocolString(const String& value); +inline String toProtocolString(TestProtocolDebuggerReason value) +{ + switch(value) { + case TestProtocolDebuggerReasonDied: + return ASCIILiteral("Died"); + case TestProtocolDebuggerReasonFainted: + return ASCIILiteral("Fainted"); + case TestProtocolDebuggerReasonHungry: + return ASCIILiteral("Hungry"); + } +} +template<> +inline TestProtocolDebuggerReason fromProtocolString(const String& value) +{ + if (value == "Died") + return TestProtocolDebuggerReasonDied; + if (value == "Fainted") + return TestProtocolDebuggerReasonFainted; + if (value == "Hungry") + return TestProtocolDebuggerReasonHungry; + ASSERT_NOT_REACHED(); + return TestProtocolDebuggerReasonDied; +} -### End File: RWIProtocol.h -### Begin File: RWIProtocolTypes.mm +} // namespace Inspector + +### End File: TestProtocolTypeConversions.h + +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -836,25 +903,93 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (DebuggerDomain) + ++ (void)_parseBreakpointId:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseReason:(NSNumber **)outValue fromPayload:(id)payload; +@end +@interface TestProtocolTypeConversions (RuntimeDomain) ++ (void)_parseObjectId:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseLuckyNumbers:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseBabyNames:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseNewObjects:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseOldObjects:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseStopReasons:(NSArray/**/ **)outValue fromPayload:(id)payload; +@end +@implementation TestProtocolTypeConversions (DebuggerDomain) -### End File: RWIProtocolTypes.mm ++ (void)_parseBreakpointId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} + ++ (void)_parseReason:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} + +@end +@implementation TestProtocolTypeConversions (RuntimeDomain) + ++ (void)_parseObjectId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} + ++ (void)_parseLuckyNumbers:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} -### Begin File: RWIProtocolInternal.h ++ (void)_parseBabyNames:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} + ++ (void)_parseNewObjects:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} + ++ (void)_parseOldObjects:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} + ++ (void)_parseStopReasons:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} + +@end + + +### End File: TestProtocolTypeConversions.mm + +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -882,12 +1017,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-array-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; + + -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-enum-type.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-enum-type.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-enum-type.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-enum-type.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,39 +29,15 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Runtime. +InspectorBackend.registerEnum("Runtime.FarmAnimals", {Pigs: "Pigs", Cows: "Cows", Cats: "Cats", Hens: "Hens"}); +InspectorBackend.registerEnum("Runtime.TwoLeggedAnimals", {Ducks: "Ducks", Hens: "Hens", Crows: "Crows", Flamingos: "Flamingos"}); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,15 +65,36 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Runtime. -InspectorBackend.registerEnum("Runtime.FarmAnimals", {Pigs: "Pigs", Cows: "Cows", Cats: "Cats", Hens: "Hens"}); -InspectorBackend.registerEnum("Runtime.TwoLeggedAnimals", {Ducks: "Ducks", Hens: "Hens", Crows: "Crows", Flamingos: "Flamingos"}); -### End File: InspectorBackendCommands.js +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + -### Begin File: InspectorBackendDispatchers.h + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -125,10 +122,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -139,14 +135,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -175,7 +169,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -183,7 +177,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -192,12 +186,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -225,10 +219,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -237,14 +230,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -273,7 +264,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -282,12 +273,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -315,8 +306,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -337,6 +327,8 @@ +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -344,6 +336,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace Runtime { /* */ enum class FarmAnimals { @@ -363,17 +357,28 @@ +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'Runtime' Domain +template<> +Optional parseEnumValueFromString(const String&); +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -402,14 +407,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "Pigs", "Cows", @@ -424,18 +432,54 @@ return enum_constant_values[code]; } +// Enums in the 'Runtime' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Runtime::FarmAnimals::Pigs, + (size_t)Inspector::Protocol::Runtime::FarmAnimals::Cows, + (size_t)Inspector::Protocol::Runtime::FarmAnimals::Cats, + (size_t)Inspector::Protocol::Runtime::FarmAnimals::Hens, + }; + for (size_t i = 0; i < 4; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Runtime::FarmAnimals)constantValues[i]; + + return Nullopt; +} + +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Runtime::TwoLeggedAnimals::Ducks, + (size_t)Inspector::Protocol::Runtime::TwoLeggedAnimals::Hens, + (size_t)Inspector::Protocol::Runtime::TwoLeggedAnimals::Crows, + (size_t)Inspector::Protocol::Runtime::TwoLeggedAnimals::Flamingos, + }; + for (size_t i = 0; i < 4; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Runtime::TwoLeggedAnimals)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -475,12 +519,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -509,10 +553,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -520,7 +564,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -543,12 +587,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -576,19 +620,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -617,10 +661,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -629,12 +673,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -662,80 +706,23 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" - -namespace Inspector { - -template -ObjCEnumType fromProtocolString(const String& value); - +#import "config.h" +#import "TestProtocolInternal.h" -inline String toProtocolString(RWIProtocolRuntimeFarmAnimals value) -{ - switch(value) { - case RWIProtocolRuntimeFarmAnimalsPigs: - return ASCIILiteral("Pigs"); - case RWIProtocolRuntimeFarmAnimalsCows: - return ASCIILiteral("Cows"); - case RWIProtocolRuntimeFarmAnimalsCats: - return ASCIILiteral("Cats"); - case RWIProtocolRuntimeFarmAnimalsHens: - return ASCIILiteral("Hens"); - } -} +#import "TestProtocolTypeConversions.h" +#import -template<> -inline RWIProtocolRuntimeFarmAnimals fromProtocolString(const String& value) -{ - if (value == "Pigs") - return RWIProtocolRuntimeFarmAnimalsPigs; - if (value == "Cows") - return RWIProtocolRuntimeFarmAnimalsCows; - if (value == "Cats") - return RWIProtocolRuntimeFarmAnimalsCats; - if (value == "Hens") - return RWIProtocolRuntimeFarmAnimalsHens; - ASSERT_NOT_REACHED(); - return RWIProtocolRuntimeFarmAnimalsPigs; -} +using namespace Inspector; -inline String toProtocolString(RWIProtocolRuntimeTwoLeggedAnimals value) -{ - switch(value) { - case RWIProtocolRuntimeTwoLeggedAnimalsDucks: - return ASCIILiteral("Ducks"); - case RWIProtocolRuntimeTwoLeggedAnimalsHens: - return ASCIILiteral("Hens"); - case RWIProtocolRuntimeTwoLeggedAnimalsCrows: - return ASCIILiteral("Crows"); - case RWIProtocolRuntimeTwoLeggedAnimalsFlamingos: - return ASCIILiteral("Flamingos"); - } -} -template<> -inline RWIProtocolRuntimeTwoLeggedAnimals fromProtocolString(const String& value) -{ - if (value == "Ducks") - return RWIProtocolRuntimeTwoLeggedAnimalsDucks; - if (value == "Hens") - return RWIProtocolRuntimeTwoLeggedAnimalsHens; - if (value == "Crows") - return RWIProtocolRuntimeTwoLeggedAnimalsCrows; - if (value == "Flamingos") - return RWIProtocolRuntimeTwoLeggedAnimalsFlamingos; - ASSERT_NOT_REACHED(); - return RWIProtocolRuntimeTwoLeggedAnimalsDucks; -} -} // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -763,23 +750,41 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "config.h" -#import "RWIProtocolInternal.h" +#import -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import -using namespace Inspector; -### End File: RWIProtocolEventDispatchers.mm +typedef NS_ENUM(NSInteger, TestProtocolRuntimeFarmAnimals) { + TestProtocolRuntimeFarmAnimalsPigs, + TestProtocolRuntimeFarmAnimalsCows, + TestProtocolRuntimeFarmAnimalsCats, + TestProtocolRuntimeFarmAnimalsHens, +}; -### Begin File: RWIProtocol.h +typedef NS_ENUM(NSInteger, TestProtocolRuntimeTwoLeggedAnimals) { + TestProtocolRuntimeTwoLeggedAnimalsDucks, + TestProtocolRuntimeTwoLeggedAnimalsHens, + TestProtocolRuntimeTwoLeggedAnimalsCrows, + TestProtocolRuntimeTwoLeggedAnimalsFlamingos, +}; + + + + + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -807,41 +812,122 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import -#import +### End File: TestProtocolInternal.h +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ -typedef NS_ENUM(NSInteger, RWIProtocolRuntimeFarmAnimals) { - RWIProtocolRuntimeFarmAnimalsPigs, - RWIProtocolRuntimeFarmAnimalsCows, - RWIProtocolRuntimeFarmAnimalsCats, - RWIProtocolRuntimeFarmAnimalsHens, -}; +// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -typedef NS_ENUM(NSInteger, RWIProtocolRuntimeTwoLeggedAnimals) { - RWIProtocolRuntimeTwoLeggedAnimalsDucks, - RWIProtocolRuntimeTwoLeggedAnimalsHens, - RWIProtocolRuntimeTwoLeggedAnimalsCrows, - RWIProtocolRuntimeTwoLeggedAnimalsFlamingos, -}; +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" +namespace Inspector { + +template +ObjCEnumType fromProtocolString(const String& value); +inline String toProtocolString(TestProtocolRuntimeFarmAnimals value) +{ + switch(value) { + case TestProtocolRuntimeFarmAnimalsPigs: + return ASCIILiteral("Pigs"); + case TestProtocolRuntimeFarmAnimalsCows: + return ASCIILiteral("Cows"); + case TestProtocolRuntimeFarmAnimalsCats: + return ASCIILiteral("Cats"); + case TestProtocolRuntimeFarmAnimalsHens: + return ASCIILiteral("Hens"); + } +} +template<> +inline TestProtocolRuntimeFarmAnimals fromProtocolString(const String& value) +{ + if (value == "Pigs") + return TestProtocolRuntimeFarmAnimalsPigs; + if (value == "Cows") + return TestProtocolRuntimeFarmAnimalsCows; + if (value == "Cats") + return TestProtocolRuntimeFarmAnimalsCats; + if (value == "Hens") + return TestProtocolRuntimeFarmAnimalsHens; + ASSERT_NOT_REACHED(); + return TestProtocolRuntimeFarmAnimalsPigs; +} +inline String toProtocolString(TestProtocolRuntimeTwoLeggedAnimals value) +{ + switch(value) { + case TestProtocolRuntimeTwoLeggedAnimalsDucks: + return ASCIILiteral("Ducks"); + case TestProtocolRuntimeTwoLeggedAnimalsHens: + return ASCIILiteral("Hens"); + case TestProtocolRuntimeTwoLeggedAnimalsCrows: + return ASCIILiteral("Crows"); + case TestProtocolRuntimeTwoLeggedAnimalsFlamingos: + return ASCIILiteral("Flamingos"); + } +} +template<> +inline TestProtocolRuntimeTwoLeggedAnimals fromProtocolString(const String& value) +{ + if (value == "Ducks") + return TestProtocolRuntimeTwoLeggedAnimalsDucks; + if (value == "Hens") + return TestProtocolRuntimeTwoLeggedAnimalsHens; + if (value == "Crows") + return TestProtocolRuntimeTwoLeggedAnimalsCrows; + if (value == "Flamingos") + return TestProtocolRuntimeTwoLeggedAnimalsFlamingos; + ASSERT_NOT_REACHED(); + return TestProtocolRuntimeTwoLeggedAnimalsDucks; +} +} // namespace Inspector -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -870,23 +956,44 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (RuntimeDomain) + ++ (void)_parseFarmAnimals:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseTwoLeggedAnimals:(NSNumber **)outValue fromPayload:(id)payload; + +@end + +@implementation TestProtocolTypeConversions (RuntimeDomain) + ++ (void)_parseFarmAnimals:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} + ++ (void)_parseTwoLeggedAnimals:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} +@end -### End File: RWIProtocolTypes.mm +### End File: TestProtocolTypeConversions.mm -### Begin File: RWIProtocolInternal.h +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -914,12 +1021,17 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-enum-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import #import +#import + +using namespace Inspector; -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-object-type.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-object-type.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-object-type.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-declaration-object-type.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,40 +28,12 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py +### End File: InspectorBackendCommands.js -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h - -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -88,12 +60,37 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendDispatchers.h +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + + +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -121,10 +118,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -135,14 +131,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -171,7 +165,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -179,7 +173,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -188,12 +182,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -221,10 +215,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -233,14 +226,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -269,7 +260,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -278,12 +269,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -311,8 +302,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -325,11 +315,11 @@ // Forward declarations. namespace Database { -class DummyObject; class Error; -class ObjectWithPropertyNameConflicts; class OptionalParameterBundle; class ParameterBundle; +class ObjectWithPropertyNameConflicts; +class DummyObject; } // Database namespace Test { @@ -344,13 +334,6 @@ } // Database // End of typedefs. -String getEnumConstantValue(int code); - -template String getEnumConstantValue(T enumValue) -{ - return getEnumConstantValue(static_cast(enumValue)); -} - namespace Database { /* Database error. */ class Error : public Inspector::InspectorObjectBase { @@ -809,14 +792,12 @@ } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -845,33 +826,27 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { -static const char* const enum_constant_values[] = { -}; - -String getEnumConstantValue(int code) { - return enum_constant_values[code]; -} - } // namespace Protocol } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -913,12 +888,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -947,10 +922,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -958,7 +933,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -981,12 +956,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1014,19 +989,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1055,10 +1030,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -1069,58 +1044,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm - -### Begin File: RWIProtocolEnumConversionHelpers.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import "RWIProtocolArrayConversionHelpers.h" - -namespace Inspector { - -template -ObjCEnumType fromProtocolString(const String& value); - - - - - -} // namespace Inspector - -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1149,9 +1078,9 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolInternal.h" -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocolTypeConversions.h" #import using namespace Inspector; @@ -1161,12 +1090,12 @@ -### End File: RWIProtocolEventDispatchers.mm +### End File: TestProtocolEventDispatchers.mm -### Begin File: RWIProtocol.h +### Begin File: TestProtocol.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1199,48 +1128,56 @@ #import -@class RWIProtocolDatabaseError; -@class RWIProtocolDatabaseOptionalParameterBundle; -@class RWIProtocolDatabaseParameterBundle; -@class RWIProtocolDatabaseObjectWithPropertyNameConflicts; -@class RWIProtocolDatabaseDummyObject; -@class RWIProtocolTestParameterBundle; +@class TestProtocolDatabaseError; +@class TestProtocolDatabaseOptionalParameterBundle; +@class TestProtocolDatabaseParameterBundle; +@class TestProtocolDatabaseObjectWithPropertyNameConflicts; +@class TestProtocolDatabaseDummyObject; +@class TestProtocolTestParameterBundle; __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseError : RWIProtocolJSONObject +@interface TestProtocolDatabaseError : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; - (instancetype)initWithMessage:(NSString *)message code:(int)code; /* required */ @property (nonatomic, copy) NSString *message; /* required */ @property (nonatomic, assign) int code; @end __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseOptionalParameterBundle : RWIProtocolJSONObject +@interface TestProtocolDatabaseOptionalParameterBundle : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; /* optional */ @property (nonatomic, copy) NSArray/**/ *columnNames; /* optional */ @property (nonatomic, copy) NSString *notes; /* optional */ @property (nonatomic, assign) double timestamp; /* optional */ @property (nonatomic, retain) RWIProtocolJSONObject *values; /* optional */ @property (nonatomic, retain) RWIProtocolJSONObject *payload; -/* optional */ @property (nonatomic, retain) RWIProtocolDatabaseError *error; -/* optional */ @property (nonatomic, copy) NSArray/**/ *errorList; +/* optional */ @property (nonatomic, retain) TestProtocolDatabaseError *error; +/* optional */ @property (nonatomic, copy) NSArray/**/ *errorList; @end __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseParameterBundle : RWIProtocolJSONObject -- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(RWIProtocolDatabaseError *)error errorList:(NSArray/**/ *)errorList; +@interface TestProtocolDatabaseParameterBundle : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(TestProtocolDatabaseError *)error errorList:(NSArray/**/ *)errorList; /* required */ @property (nonatomic, copy) NSArray/**/ *columnNames; /* required */ @property (nonatomic, copy) NSString *notes; /* required */ @property (nonatomic, assign) double timestamp; /* required */ @property (nonatomic, retain) RWIProtocolJSONObject *values; /* required */ @property (nonatomic, retain) RWIProtocolJSONObject *payload; -/* required */ @property (nonatomic, retain) RWIProtocolDatabaseError *error; -/* required */ @property (nonatomic, copy) NSArray/**/ *errorList; +/* required */ @property (nonatomic, retain) TestProtocolDatabaseError *error; +/* required */ @property (nonatomic, copy) NSArray/**/ *errorList; @end __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseObjectWithPropertyNameConflicts : RWIProtocolJSONObject +@interface TestProtocolDatabaseObjectWithPropertyNameConflicts : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; - (instancetype)initWithInteger:(NSString *)integer array:(NSString *)array string:(NSString *)string value:(NSString *)value object:(NSString *)object; /* required */ @property (nonatomic, copy) NSString *integer; /* required */ @property (nonatomic, copy) NSString *array; @@ -1250,31 +1187,231 @@ @end __attribute__((visibility ("default"))) -@interface RWIProtocolDatabaseDummyObject : RWIProtocolJSONObject +@interface TestProtocolDatabaseDummyObject : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; @end __attribute__((visibility ("default"))) -@interface RWIProtocolTestParameterBundle : RWIProtocolJSONObject -- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(RWIProtocolDatabaseError *)error; +@interface TestProtocolTestParameterBundle : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(TestProtocolDatabaseError *)error; /* required */ @property (nonatomic, copy) NSArray/**/ *columnNames; /* required */ @property (nonatomic, copy) NSString *notes; /* required */ @property (nonatomic, assign) double timestamp; /* required */ @property (nonatomic, retain) RWIProtocolJSONObject *values; /* required */ @property (nonatomic, retain) RWIProtocolJSONObject *payload; -/* required */ @property (nonatomic, retain) RWIProtocolDatabaseError *error; +/* required */ @property (nonatomic, retain) TestProtocolDatabaseError *error; +@end + + + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import + + + + +### End File: TestProtocolInternal.h + +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" + +namespace Inspector { + +template +ObjCEnumType fromProtocolString(const String& value); + + + + + +} // namespace Inspector + +### End File: TestProtocolTypeConversions.h + +### Begin File: TestProtocolTypeConversions.mm +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "config.h" +#import "TestProtocolTypeConversions.h" + +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import + +using namespace Inspector; + +@interface TestProtocolTypeConversions (DatabaseDomain) + ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload; ++ (void)_parseErrorList:(NSArray/**/ **)outValue fromPayload:(id)payload; ++ (void)_parseOptionalParameterBundle:(TestProtocolDatabaseOptionalParameterBundle **)outValue fromPayload:(id)payload; ++ (void)_parseParameterBundle:(TestProtocolDatabaseParameterBundle **)outValue fromPayload:(id)payload; ++ (void)_parseObjectWithPropertyNameConflicts:(TestProtocolDatabaseObjectWithPropertyNameConflicts **)outValue fromPayload:(id)payload; ++ (void)_parseDummyObject:(TestProtocolDatabaseDummyObject **)outValue fromPayload:(id)payload; + +@end +@interface TestProtocolTypeConversions (TestDomain) + ++ (void)_parseParameterBundle:(TestProtocolTestParameterBundle **)outValue fromPayload:(id)payload; + @end +@implementation TestProtocolTypeConversions (DatabaseDomain) + ++ (void)_parseError:(TestProtocolDatabaseError **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseError alloc] initWithPayload:payload]; +} + ++ (void)_parseErrorList:(NSArray/**/ **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSArray/**/ class]); + *outValue = (NSArray/**/ *)payload; +} + ++ (void)_parseOptionalParameterBundle:(TestProtocolDatabaseOptionalParameterBundle **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseOptionalParameterBundle alloc] initWithPayload:payload]; +} + ++ (void)_parseParameterBundle:(TestProtocolDatabaseParameterBundle **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseParameterBundle alloc] initWithPayload:payload]; +} + ++ (void)_parseObjectWithPropertyNameConflicts:(TestProtocolDatabaseObjectWithPropertyNameConflicts **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseObjectWithPropertyNameConflicts alloc] initWithPayload:payload]; +} ++ (void)_parseDummyObject:(TestProtocolDatabaseDummyObject **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolDatabaseDummyObject alloc] initWithPayload:payload]; +} +@end +@implementation TestProtocolTypeConversions (TestDomain) ++ (void)_parseParameterBundle:(TestProtocolTestParameterBundle **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolTestParameterBundle alloc] initWithPayload:payload]; +} + +@end -### End File: RWIProtocol.h +### End File: TestProtocolTypeConversions.mm -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1303,21 +1440,42 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolInternal.h" -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocolTypeConversions.h" +#import #import #import using namespace Inspector; -@implementation RWIProtocolDatabaseError +@implementation TestProtocolDatabaseError + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"message"], @"message"); + self.message = payload[@"message"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"code"], @"code"); + self.code = [payload[@"code"] integerValue]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} - (instancetype)initWithMessage:(NSString *)message code:(int)code; { - self = [super init]; - if (!self) + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(message, @"message"); @@ -1350,7 +1508,36 @@ @end -@implementation RWIProtocolDatabaseOptionalParameterBundle +@implementation TestProtocolDatabaseOptionalParameterBundle + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + self.columnNames = objcArrayFromPayload(payload[@"columnNames"]); + + self.notes = payload[@"notes"]; + + self.timestamp = [payload[@"timestamp"] doubleValue]; + + self.values = payload[@"values"]; + + self.payload = payload[@"payload"]; + + self.error = [[TestProtocolDatabaseError alloc] initWithPayload:payload[@"error"]]; + + self.errorList = objcArrayFromPayload(payload[@"errorList"]); + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} - (void)setColumnNames:(NSArray/**/ *)columnNames { @@ -1389,7 +1576,7 @@ - (RWIProtocolJSONObject *)values { - return (RWIProtocolJSONObject *)[super objectForKey:@"values"]; + return [[RWIProtocolJSONObject alloc] initWithInspectorObject:[[super objectForKey:@"values"] toInspectorObject].get()]; } - (void)setPayload:(RWIProtocolJSONObject *)payload @@ -1399,38 +1586,73 @@ - (RWIProtocolJSONObject *)payload { - return (RWIProtocolJSONObject *)[super objectForKey:@"payload"]; + return [[RWIProtocolJSONObject alloc] initWithInspectorObject:[[super objectForKey:@"payload"] toInspectorObject].get()]; } -- (void)setError:(RWIProtocolDatabaseError *)error +- (void)setError:(TestProtocolDatabaseError *)error { [super setObject:error forKey:@"error"]; } -- (RWIProtocolDatabaseError *)error +- (TestProtocolDatabaseError *)error { - return (RWIProtocolDatabaseError *)[super objectForKey:@"error"]; + return [[TestProtocolDatabaseError alloc] initWithInspectorObject:[[super objectForKey:@"error"] toInspectorObject].get()]; } -- (void)setErrorList:(NSArray/**/ *)errorList +- (void)setErrorList:(NSArray/**/ *)errorList { - THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(errorList, [RWIProtocolDatabaseError class]); + THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(errorList, [TestProtocolDatabaseError class]); [super setInspectorArray:inspectorObjectArray(errorList) forKey:@"errorList"]; } -- (NSArray/**/ *)errorList +- (NSArray/**/ *)errorList { - return objcArray([super inspectorArrayForKey:@"errorList"]); + return objcArray([super inspectorArrayForKey:@"errorList"]); } @end -@implementation RWIProtocolDatabaseParameterBundle +@implementation TestProtocolDatabaseParameterBundle -- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(RWIProtocolDatabaseError *)error errorList:(NSArray/**/ *)errorList; +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload { - self = [super init]; - if (!self) + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"columnNames"], @"columnNames"); + self.columnNames = objcArrayFromPayload(payload[@"columnNames"]); + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"notes"], @"notes"); + self.notes = payload[@"notes"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"timestamp"], @"timestamp"); + self.timestamp = [payload[@"timestamp"] doubleValue]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"values"], @"values"); + self.values = payload[@"values"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"payload"], @"payload"); + self.payload = payload[@"payload"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"error"], @"error"); + self.error = [[TestProtocolDatabaseError alloc] initWithPayload:payload[@"error"]]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"errorList"], @"errorList"); + self.errorList = objcArrayFromPayload(payload[@"errorList"]); + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} + +- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(TestProtocolDatabaseError *)error errorList:(NSArray/**/ *)errorList; +{ + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(columnNames, @"columnNames"); @@ -1439,7 +1661,7 @@ THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload, @"payload"); THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(error, @"error"); THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(errorList, @"errorList"); - THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(errorList, [RWIProtocolDatabaseError class]); + THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(errorList, [TestProtocolDatabaseError class]); self.columnNames = columnNames; self.notes = notes; @@ -1489,7 +1711,7 @@ - (RWIProtocolJSONObject *)values { - return (RWIProtocolJSONObject *)[super objectForKey:@"values"]; + return [[RWIProtocolJSONObject alloc] initWithInspectorObject:[[super objectForKey:@"values"] toInspectorObject].get()]; } - (void)setPayload:(RWIProtocolJSONObject *)payload @@ -1499,38 +1721,67 @@ - (RWIProtocolJSONObject *)payload { - return (RWIProtocolJSONObject *)[super objectForKey:@"payload"]; + return [[RWIProtocolJSONObject alloc] initWithInspectorObject:[[super objectForKey:@"payload"] toInspectorObject].get()]; } -- (void)setError:(RWIProtocolDatabaseError *)error +- (void)setError:(TestProtocolDatabaseError *)error { [super setObject:error forKey:@"error"]; } -- (RWIProtocolDatabaseError *)error +- (TestProtocolDatabaseError *)error { - return (RWIProtocolDatabaseError *)[super objectForKey:@"error"]; + return [[TestProtocolDatabaseError alloc] initWithInspectorObject:[[super objectForKey:@"error"] toInspectorObject].get()]; } -- (void)setErrorList:(NSArray/**/ *)errorList +- (void)setErrorList:(NSArray/**/ *)errorList { - THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(errorList, [RWIProtocolDatabaseError class]); + THROW_EXCEPTION_FOR_BAD_TYPE_IN_ARRAY(errorList, [TestProtocolDatabaseError class]); [super setInspectorArray:inspectorObjectArray(errorList) forKey:@"errorList"]; } -- (NSArray/**/ *)errorList +- (NSArray/**/ *)errorList { - return objcArray([super inspectorArrayForKey:@"errorList"]); + return objcArray([super inspectorArrayForKey:@"errorList"]); } @end -@implementation RWIProtocolDatabaseObjectWithPropertyNameConflicts +@implementation TestProtocolDatabaseObjectWithPropertyNameConflicts + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"integer"], @"integer"); + self.integer = payload[@"integer"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"array"], @"array"); + self.array = payload[@"array"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"string"], @"string"); + self.string = payload[@"string"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"value"], @"value"); + self.value = payload[@"value"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"object"], @"object"); + self.object = payload[@"object"]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} - (instancetype)initWithInteger:(NSString *)integer array:(NSString *)array string:(NSString *)string value:(NSString *)value object:(NSString *)object; { - self = [super init]; - if (!self) + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(integer, @"integer"); @@ -1600,17 +1851,64 @@ @end -@implementation RWIProtocolDatabaseDummyObject +@implementation TestProtocolDatabaseDummyObject + +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} @end -@implementation RWIProtocolTestParameterBundle +@implementation TestProtocolTestParameterBundle -- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(RWIProtocolDatabaseError *)error; +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload { - self = [super init]; - if (!self) + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"columnNames"], @"columnNames"); + self.columnNames = objcArrayFromPayload(payload[@"columnNames"]); + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"notes"], @"notes"); + self.notes = payload[@"notes"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"timestamp"], @"timestamp"); + self.timestamp = [payload[@"timestamp"] doubleValue]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"values"], @"values"); + self.values = payload[@"values"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"payload"], @"payload"); + self.payload = payload[@"payload"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"error"], @"error"); + self.error = [[TestProtocolDatabaseError alloc] initWithPayload:payload[@"error"]]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} + +- (instancetype)initWithColumnNames:(NSArray/**/ *)columnNames notes:(NSString *)notes timestamp:(double)timestamp values:(RWIProtocolJSONObject *)values payload:(RWIProtocolJSONObject *)payload error:(TestProtocolDatabaseError *)error; +{ + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(columnNames, @"columnNames"); @@ -1666,7 +1964,7 @@ - (RWIProtocolJSONObject *)values { - return (RWIProtocolJSONObject *)[super objectForKey:@"values"]; + return [[RWIProtocolJSONObject alloc] initWithInspectorObject:[[super objectForKey:@"values"] toInspectorObject].get()]; } - (void)setPayload:(RWIProtocolJSONObject *)payload @@ -1676,61 +1974,20 @@ - (RWIProtocolJSONObject *)payload { - return (RWIProtocolJSONObject *)[super objectForKey:@"payload"]; + return [[RWIProtocolJSONObject alloc] initWithInspectorObject:[[super objectForKey:@"payload"] toInspectorObject].get()]; } -- (void)setError:(RWIProtocolDatabaseError *)error +- (void)setError:(TestProtocolDatabaseError *)error { [super setObject:error forKey:@"error"]; } -- (RWIProtocolDatabaseError *)error +- (TestProtocolDatabaseError *)error { - return (RWIProtocolDatabaseError *)[super objectForKey:@"error"]; + return [[TestProtocolDatabaseError alloc] initWithInspectorObject:[[super objectForKey:@"error"] toInspectorObject].get()]; } @end -### End File: RWIProtocolTypes.mm - -### Begin File: RWIProtocolInternal.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from type-declaration-object-type.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import -#import - - - - -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-requiring-runtime-casts.json-result webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-requiring-runtime-casts.json-result --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/expected/type-requiring-runtime-casts.json-result 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/expected/type-requiring-runtime-casts.json-result 2016-09-19 12:18:06.000000000 +0000 @@ -1,7 +1,7 @@ -### Begin File: InspectorAlternateBackendDispatchers.h +### Begin File: InspectorBackendCommands.js /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,39 +29,15 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorAlternateBackendDispatchers_h -#define InspectorAlternateBackendDispatchers_h - -#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#include "InspectorProtocolTypes.h" -#include -#include - -namespace Inspector { - -class AlternateBackendDispatcher { -public: - void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } - BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } -private: - RefPtr m_backendDispatcher; -}; - - - - -} // namespace Inspector - -#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) - -#endif // !defined(InspectorAlternateBackendDispatchers_h) -### End File: InspectorAlternateBackendDispatchers.h +// Test. +InspectorBackend.registerEnum("Test.UncastedAnimals", {Pigs: "Pigs", Cows: "Cows", Cats: "Cats", Hens: "Hens"}); +InspectorBackend.registerEnum("Test.CastedAnimals", {Ducks: "Ducks", Hens: "Hens", Crows: "Crows", Flamingos: "Flamingos"}); +### End File: InspectorBackendCommands.js -### Begin File: InspectorBackendCommands.js +### Begin File: TestAlternateBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,15 +65,36 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -// Test. -InspectorBackend.registerEnum("Test.UncastedAnimals", {Pigs: "Pigs", Cows: "Cows", Cats: "Cats", Hens: "Hens"}); -InspectorBackend.registerEnum("Test.CastedAnimals", {Ducks: "Ducks", Hens: "Hens", Crows: "Crows", Flamingos: "Flamingos"}); -### End File: InspectorBackendCommands.js +#pragma once + +#if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) + +#include "TestProtocolTypes.h" +#include +#include + +namespace Inspector { + +class AlternateBackendDispatcher { +public: + void setBackendDispatcher(RefPtr&& dispatcher) { m_backendDispatcher = WTFMove(dispatcher); } + BackendDispatcher* backendDispatcher() const { return m_backendDispatcher.get(); } +private: + RefPtr m_backendDispatcher; +}; + + + -### Begin File: InspectorBackendDispatchers.h +} // namespace Inspector + +#endif // ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) +### End File: TestAlternateBackendDispatchers.h + +### Begin File: TestBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -125,10 +122,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorBackendDispatchers_h -#define InspectorBackendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -139,14 +135,12 @@ } // namespace Inspector +### End File: TestBackendDispatchers.h -#endif // !defined(InspectorBackendDispatchers_h) -### End File: InspectorBackendDispatchers.h - -### Begin File: InspectorBackendDispatchers.cpp +### Begin File: TestBackendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -175,7 +169,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorBackendDispatchers.h" +#include "TestBackendDispatchers.h" #include #include @@ -183,7 +177,7 @@ #include #if ENABLE(INSPECTOR_ALTERNATE_DISPATCHERS) -#include "InspectorAlternateBackendDispatchers.h" +#include "TestAlternateBackendDispatchers.h" #endif namespace Inspector { @@ -192,12 +186,12 @@ } // namespace Inspector -### End File: InspectorBackendDispatchers.cpp +### End File: TestBackendDispatchers.cpp -### Begin File: InspectorFrontendDispatchers.h +### Begin File: TestFrontendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -225,10 +219,9 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorFrontendDispatchers_h -#define InspectorFrontendDispatchers_h +#pragma once -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" #include #include @@ -237,14 +230,12 @@ class FrontendRouter; } // namespace Inspector +### End File: TestFrontendDispatchers.h -#endif // !defined(InspectorFrontendDispatchers_h) -### End File: InspectorFrontendDispatchers.h - -### Begin File: InspectorFrontendDispatchers.cpp +### Begin File: TestFrontendDispatchers.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -273,7 +264,7 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorFrontendDispatchers.h" +#include "TestFrontendDispatchers.h" #include "InspectorFrontendRouter.h" #include @@ -282,12 +273,12 @@ } // namespace Inspector -### End File: InspectorFrontendDispatchers.cpp +### End File: TestFrontendDispatchers.cpp -### Begin File: InspectorProtocolObjects.h +### Begin File: TestProtocolObjects.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -315,8 +306,7 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#ifndef InspectorProtocolObjects_h -#define InspectorProtocolObjects_h +#pragma once #include #include @@ -329,11 +319,11 @@ // Forward declarations. namespace Test { +class TypeNeedingCast; class RecursiveObject1; class RecursiveObject2; -class TypeNeedingCast; -enum class CastedAnimals; enum class UncastedAnimals; +enum class CastedAnimals; } // Test // End of forward declarations. @@ -345,6 +335,8 @@ } // Test // End of typedefs. +namespace TestHelpers { + String getEnumConstantValue(int code); template String getEnumConstantValue(T enumValue) @@ -352,6 +344,8 @@ return getEnumConstantValue(static_cast(enumValue)); } +} // namespace TestHelpers + namespace Test { /* A dummy type that requires runtime casts, and forces non-primitive referenced types to also emit runtime cast helpers. */ class TypeNeedingCast : public Inspector::InspectorObjectBase { @@ -401,7 +395,7 @@ Builder& setAnimals(Inspector::Protocol::Test::CastedAnimals value) { COMPILE_ASSERT(!(STATE & AnimalsSet), property_animals_already_set); - m_result->setString(ASCIILiteral("animals"), Inspector::Protocol::getEnumConstantValue(static_cast(value))); + m_result->setString(ASCIILiteral("animals"), Inspector::Protocol::TestHelpers::getEnumConstantValue(value)); return castState(); } @@ -585,17 +579,28 @@ #endif // !ASSERT_DISABLED }; +namespace TestHelpers { + +template +Optional parseEnumValueFromString(const String&); + +// Enums in the 'Test' Domain +template<> +Optional parseEnumValueFromString(const String&); +template<> +Optional parseEnumValueFromString(const String&); + +} // namespace TestHelpers + } // namespace Protocol } // namespace Inspector +### End File: TestProtocolObjects.h -#endif // !defined(InspectorProtocolObjects_h) -### End File: InspectorProtocolObjects.h - -### Begin File: InspectorProtocolObjects.cpp +### Begin File: TestProtocolObjects.cpp /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -624,14 +629,17 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #include "config.h" -#include "InspectorProtocolObjects.h" +#include "TestProtocolObjects.h" +#include #include namespace Inspector { namespace Protocol { +namespace TestHelpers { + static const char* const enum_constant_values[] = { "Ducks", "Hens", @@ -646,6 +654,42 @@ return enum_constant_values[code]; } +// Enums in the 'Test' Domain +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Test::UncastedAnimals::Pigs, + (size_t)Inspector::Protocol::Test::UncastedAnimals::Cows, + (size_t)Inspector::Protocol::Test::UncastedAnimals::Cats, + (size_t)Inspector::Protocol::Test::UncastedAnimals::Hens, + }; + for (size_t i = 0; i < 4; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Test::UncastedAnimals)constantValues[i]; + + return Nullopt; +} + +template<> +Optional parseEnumValueFromString(const String& protocolString) +{ + static const size_t constantValues[] = { + (size_t)Inspector::Protocol::Test::CastedAnimals::Ducks, + (size_t)Inspector::Protocol::Test::CastedAnimals::Hens, + (size_t)Inspector::Protocol::Test::CastedAnimals::Crows, + (size_t)Inspector::Protocol::Test::CastedAnimals::Flamingos, + }; + for (size_t i = 0; i < 4; ++i) + if (protocolString == enum_constant_values[constantValues[i]]) + return (Inspector::Protocol::Test::CastedAnimals)constantValues[i]; + + return Nullopt; +} + + +} // namespace TestHelpers + #if !ASSERT_DISABLED @@ -757,12 +801,12 @@ } // namespace Inspector -### End File: InspectorProtocolObjects.cpp +### End File: TestProtocolObjects.cpp -### Begin File: RWIProtocolBackendDispatchers.h +### Begin File: TestProtocolBackendDispatchers.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -802,12 +846,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.h +### End File: TestProtocolBackendDispatchers.h -### Begin File: RWIProtocolConfiguration.mm +### Begin File: TestProtocolConfiguration.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -836,10 +880,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolConfiguration.h" +#import "TestProtocolConfiguration.h" -#import "RWIProtocolInternal.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolInternal.h" +#import "TestProtocolBackendDispatchers.h" #import #import #import @@ -847,7 +891,7 @@ using namespace Inspector; -@implementation RWIProtocolConfiguration +@implementation TestProtocolConfiguration { AugmentableInspectorController* _controller; } @@ -870,12 +914,12 @@ @end -### End File: RWIProtocolConfiguration.mm +### End File: TestProtocolConfiguration.mm -### Begin File: RWIProtocolConfiguration.h +### Begin File: TestProtocolConfiguration.h /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -903,19 +947,19 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import +#import __attribute__((visibility ("default"))) -@interface RWIProtocolConfiguration : NSObject +@interface TestProtocolConfiguration : NSObject @end -### End File: RWIProtocolConfiguration.h +### End File: TestProtocolConfiguration.h -### Begin File: RWIProtocolBackendDispatchers.mm +### Begin File: TestProtocolBackendDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -944,10 +988,10 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolBackendDispatchers.h" +#import "TestProtocolBackendDispatchers.h" -#include "RWIProtocolInternal.h" -#include "RWIProtocolEnumConversionHelpers.h" +#include "TestProtocolInternal.h" +#include "TestProtocolTypeConversions.h" #include namespace Inspector { @@ -956,12 +1000,12 @@ } // namespace Inspector -### End File: RWIProtocolBackendDispatchers.mm +### End File: TestProtocolBackendDispatchers.mm -### Begin File: RWIProtocolEnumConversionHelpers.h +### Begin File: TestProtocolEventDispatchers.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -989,7 +1033,182 @@ // DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py -#import "RWIProtocolArrayConversionHelpers.h" +#import "config.h" +#import "TestProtocolInternal.h" + +#import "TestProtocolTypeConversions.h" +#import + +using namespace Inspector; + + + + +### End File: TestProtocolEventDispatchers.mm + +### Begin File: TestProtocol.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import + +#import + + +@class TestProtocolTestTypeNeedingCast; +@class TestProtocolTestRecursiveObject1; +@class TestProtocolTestRecursiveObject2; + + +typedef NS_ENUM(NSInteger, TestProtocolTestUncastedAnimals) { + TestProtocolTestUncastedAnimalsPigs, + TestProtocolTestUncastedAnimalsCows, + TestProtocolTestUncastedAnimalsCats, + TestProtocolTestUncastedAnimalsHens, +}; + +typedef NS_ENUM(NSInteger, TestProtocolTestCastedAnimals) { + TestProtocolTestCastedAnimalsDucks, + TestProtocolTestCastedAnimalsHens, + TestProtocolTestCastedAnimalsCrows, + TestProtocolTestCastedAnimalsFlamingos, +}; + + +__attribute__((visibility ("default"))) +@interface TestProtocolTestTypeNeedingCast : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +- (instancetype)initWithString:(NSString *)string number:(int)number animals:(TestProtocolTestCastedAnimals)animals identifier:(int)identifier tree:(TestProtocolTestRecursiveObject1 *)tree; +/* required */ @property (nonatomic, copy) NSString *string; +/* required */ @property (nonatomic, assign) int number; +/* required */ @property (nonatomic, assign) TestProtocolTestCastedAnimals animals; +/* required */ @property (nonatomic, assign) int identifier; +/* required */ @property (nonatomic, retain) TestProtocolTestRecursiveObject1 *tree; +@end + +__attribute__((visibility ("default"))) +@interface TestProtocolTestRecursiveObject1 : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +/* optional */ @property (nonatomic, retain) TestProtocolTestRecursiveObject2 *obj; +@end + +__attribute__((visibility ("default"))) +@interface TestProtocolTestRecursiveObject2 : RWIProtocolJSONObject +- (instancetype)initWithPayload:(NSDictionary *)payload; +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject; +/* optional */ @property (nonatomic, retain) TestProtocolTestRecursiveObject1 *obj; +@end + + + + + + +### End File: TestProtocol.h + +### Begin File: TestProtocolInternal.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "TestProtocol.h" +#import "TestProtocolJSONObjectPrivate.h" +#import +#import + + + + +### End File: TestProtocolInternal.h + +### Begin File: TestProtocolTypeConversions.h +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. + * Copyright (C) 2014 University of Washington. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json +// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + +#import "RWIProtocolArrayConversions.h" +#import "TestProtocol.h" namespace Inspector { @@ -997,72 +1216,72 @@ ObjCEnumType fromProtocolString(const String& value); -inline String toProtocolString(RWIProtocolTestUncastedAnimals value) +inline String toProtocolString(TestProtocolTestUncastedAnimals value) { switch(value) { - case RWIProtocolTestUncastedAnimalsPigs: + case TestProtocolTestUncastedAnimalsPigs: return ASCIILiteral("Pigs"); - case RWIProtocolTestUncastedAnimalsCows: + case TestProtocolTestUncastedAnimalsCows: return ASCIILiteral("Cows"); - case RWIProtocolTestUncastedAnimalsCats: + case TestProtocolTestUncastedAnimalsCats: return ASCIILiteral("Cats"); - case RWIProtocolTestUncastedAnimalsHens: + case TestProtocolTestUncastedAnimalsHens: return ASCIILiteral("Hens"); } } template<> -inline RWIProtocolTestUncastedAnimals fromProtocolString(const String& value) +inline TestProtocolTestUncastedAnimals fromProtocolString(const String& value) { if (value == "Pigs") - return RWIProtocolTestUncastedAnimalsPigs; + return TestProtocolTestUncastedAnimalsPigs; if (value == "Cows") - return RWIProtocolTestUncastedAnimalsCows; + return TestProtocolTestUncastedAnimalsCows; if (value == "Cats") - return RWIProtocolTestUncastedAnimalsCats; + return TestProtocolTestUncastedAnimalsCats; if (value == "Hens") - return RWIProtocolTestUncastedAnimalsHens; + return TestProtocolTestUncastedAnimalsHens; ASSERT_NOT_REACHED(); - return RWIProtocolTestUncastedAnimalsPigs; + return TestProtocolTestUncastedAnimalsPigs; } -inline String toProtocolString(RWIProtocolTestCastedAnimals value) +inline String toProtocolString(TestProtocolTestCastedAnimals value) { switch(value) { - case RWIProtocolTestCastedAnimalsDucks: + case TestProtocolTestCastedAnimalsDucks: return ASCIILiteral("Ducks"); - case RWIProtocolTestCastedAnimalsHens: + case TestProtocolTestCastedAnimalsHens: return ASCIILiteral("Hens"); - case RWIProtocolTestCastedAnimalsCrows: + case TestProtocolTestCastedAnimalsCrows: return ASCIILiteral("Crows"); - case RWIProtocolTestCastedAnimalsFlamingos: + case TestProtocolTestCastedAnimalsFlamingos: return ASCIILiteral("Flamingos"); } } template<> -inline RWIProtocolTestCastedAnimals fromProtocolString(const String& value) +inline TestProtocolTestCastedAnimals fromProtocolString(const String& value) { if (value == "Ducks") - return RWIProtocolTestCastedAnimalsDucks; + return TestProtocolTestCastedAnimalsDucks; if (value == "Hens") - return RWIProtocolTestCastedAnimalsHens; + return TestProtocolTestCastedAnimalsHens; if (value == "Crows") - return RWIProtocolTestCastedAnimalsCrows; + return TestProtocolTestCastedAnimalsCrows; if (value == "Flamingos") - return RWIProtocolTestCastedAnimalsFlamingos; + return TestProtocolTestCastedAnimalsFlamingos; ASSERT_NOT_REACHED(); - return RWIProtocolTestCastedAnimalsDucks; + return TestProtocolTestCastedAnimalsDucks; } } // namespace Inspector -### End File: RWIProtocolEnumConversionHelpers.h +### End File: TestProtocolTypeConversions.h -### Begin File: RWIProtocolEventDispatchers.mm +### Begin File: TestProtocolTypeConversions.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1091,105 +1310,79 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolTypeConversions.h" -#import "RWIProtocolEnumConversionHelpers.h" -#import +#import "TestProtocol.h" +#import "TestProtocolTypeParser.h" +#import using namespace Inspector; +@interface TestProtocolTypeConversions (TestDomain) ++ (void)_parseTypeNeedingCast:(TestProtocolTestTypeNeedingCast **)outValue fromPayload:(id)payload; ++ (void)_parseCastedObjectId:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseUncastedObjectId:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseUncastedAnimals:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseCastedAnimals:(NSNumber **)outValue fromPayload:(id)payload; ++ (void)_parseRecursiveObject1:(TestProtocolTestRecursiveObject1 **)outValue fromPayload:(id)payload; ++ (void)_parseRecursiveObject2:(TestProtocolTestRecursiveObject2 **)outValue fromPayload:(id)payload; +@end -### End File: RWIProtocolEventDispatchers.mm - -### Begin File: RWIProtocol.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -// DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py - -#import - -#import - +@implementation TestProtocolTypeConversions (TestDomain) -@class RWIProtocolTestTypeNeedingCast; -@class RWIProtocolTestRecursiveObject1; -@class RWIProtocolTestRecursiveObject2; ++ (void)_parseTypeNeedingCast:(TestProtocolTestTypeNeedingCast **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolTestTypeNeedingCast alloc] initWithPayload:payload]; +} ++ (void)_parseCastedObjectId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} -typedef NS_ENUM(NSInteger, RWIProtocolTestUncastedAnimals) { - RWIProtocolTestUncastedAnimalsPigs, - RWIProtocolTestUncastedAnimalsCows, - RWIProtocolTestUncastedAnimalsCats, - RWIProtocolTestUncastedAnimalsHens, -}; ++ (void)_parseUncastedObjectId:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSNumber class]); + *outValue = (NSNumber *)payload; +} -typedef NS_ENUM(NSInteger, RWIProtocolTestCastedAnimals) { - RWIProtocolTestCastedAnimalsDucks, - RWIProtocolTestCastedAnimalsHens, - RWIProtocolTestCastedAnimalsCrows, - RWIProtocolTestCastedAnimalsFlamingos, -}; ++ (void)_parseUncastedAnimals:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} ++ (void)_parseCastedAnimals:(NSNumber **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]); + *outValue = @(Inspector::fromProtocolString(payload)); +} -__attribute__((visibility ("default"))) -@interface RWIProtocolTestTypeNeedingCast : RWIProtocolJSONObject -- (instancetype)initWithString:(NSString *)string number:(int)number animals:(RWIProtocolTestCastedAnimals)animals identifier:(int)identifier tree:(RWIProtocolTestRecursiveObject1 *)tree; -/* required */ @property (nonatomic, copy) NSString *string; -/* required */ @property (nonatomic, assign) int number; -/* required */ @property (nonatomic, assign) RWIProtocolTestCastedAnimals animals; -/* required */ @property (nonatomic, assign) int identifier; -/* required */ @property (nonatomic, retain) RWIProtocolTestRecursiveObject1 *tree; -@end ++ (void)_parseRecursiveObject1:(TestProtocolTestRecursiveObject1 **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolTestRecursiveObject1 alloc] initWithPayload:payload]; +} -__attribute__((visibility ("default"))) -@interface RWIProtocolTestRecursiveObject1 : RWIProtocolJSONObject -/* optional */ @property (nonatomic, retain) RWIProtocolTestRecursiveObject2 *obj; -@end ++ (void)_parseRecursiveObject2:(TestProtocolTestRecursiveObject2 **)outValue fromPayload:(id)payload +{ + THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]); + *outValue = [[TestProtocolTestRecursiveObject2 alloc] initWithPayload:payload]; +} -__attribute__((visibility ("default"))) -@interface RWIProtocolTestRecursiveObject2 : RWIProtocolJSONObject -/* optional */ @property (nonatomic, retain) RWIProtocolTestRecursiveObject1 *obj; @end +### End File: TestProtocolTypeConversions.mm - - - -### End File: RWIProtocol.h - -### Begin File: RWIProtocolTypes.mm +### Begin File: TestProtocolTypes.mm /* * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2013-2016 Apple Inc. All rights reserved. * Copyright (C) 2014 University of Washington. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1218,21 +1411,51 @@ // by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py #import "config.h" -#import "RWIProtocolInternal.h" +#import "TestProtocolInternal.h" -#import "RWIProtocolEnumConversionHelpers.h" +#import "TestProtocolTypeConversions.h" +#import #import #import using namespace Inspector; -@implementation RWIProtocolTestTypeNeedingCast +@implementation TestProtocolTestTypeNeedingCast -- (instancetype)initWithString:(NSString *)string number:(int)number animals:(RWIProtocolTestCastedAnimals)animals identifier:(int)identifier tree:(RWIProtocolTestRecursiveObject1 *)tree; +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload { - self = [super init]; - if (!self) + if (!(self = [super init])) + return nil; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"string"], @"string"); + self.string = payload[@"string"]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"number"], @"number"); + self.number = [payload[@"number"] integerValue]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"animals"], @"animals"); + self.animals = fromProtocolString(payload[@"animals"]); + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"identifier"], @"identifier"); + self.identifier = [payload[@"id"] integerValue]; + + THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(payload[@"tree"], @"tree"); + self.tree = [[TestProtocolTestRecursiveObject1 alloc] initWithPayload:payload[@"tree"]]; + + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; + + return self; +} + +- (instancetype)initWithString:(NSString *)string number:(int)number animals:(TestProtocolTestCastedAnimals)animals identifier:(int)identifier tree:(TestProtocolTestRecursiveObject1 *)tree; +{ + if (!(self = [super init])) return nil; THROW_EXCEPTION_FOR_REQUIRED_PROPERTY(string, @"string"); @@ -1267,14 +1490,14 @@ return [super integerForKey:@"number"]; } -- (void)setAnimals:(RWIProtocolTestCastedAnimals)animals +- (void)setAnimals:(TestProtocolTestCastedAnimals)animals { [super setString:toProtocolString(animals) forKey:@"animals"]; } -- (RWIProtocolTestCastedAnimals)animals +- (TestProtocolTestCastedAnimals)animals { - return fromProtocolString([super stringForKey:@"animals"]); + return fromProtocolString([super stringForKey:@"animals"]); } - (void)setIdentifier:(int)identifier @@ -1287,86 +1510,79 @@ return [super integerForKey:@"id"]; } -- (void)setTree:(RWIProtocolTestRecursiveObject1 *)tree +- (void)setTree:(TestProtocolTestRecursiveObject1 *)tree { [super setObject:tree forKey:@"tree"]; } -- (RWIProtocolTestRecursiveObject1 *)tree +- (TestProtocolTestRecursiveObject1 *)tree { - return (RWIProtocolTestRecursiveObject1 *)[super objectForKey:@"tree"]; + return [[TestProtocolTestRecursiveObject1 alloc] initWithInspectorObject:[[super objectForKey:@"tree"] toInspectorObject].get()]; } @end -@implementation RWIProtocolTestRecursiveObject1 +@implementation TestProtocolTestRecursiveObject1 -- (void)setObj:(RWIProtocolTestRecursiveObject2 *)obj +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload { - [super setObject:obj forKey:@"obj"]; -} + if (!(self = [super init])) + return nil; -- (RWIProtocolTestRecursiveObject2 *)obj -{ - return (RWIProtocolTestRecursiveObject2 *)[super objectForKey:@"obj"]; -} + self.obj = [[TestProtocolTestRecursiveObject2 alloc] initWithPayload:payload[@"obj"]]; -@end + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; -@implementation RWIProtocolTestRecursiveObject2 + return self; +} -- (void)setObj:(RWIProtocolTestRecursiveObject1 *)obj +- (void)setObj:(TestProtocolTestRecursiveObject2 *)obj { [super setObject:obj forKey:@"obj"]; } -- (RWIProtocolTestRecursiveObject1 *)obj +- (TestProtocolTestRecursiveObject2 *)obj { - return (RWIProtocolTestRecursiveObject1 *)[super objectForKey:@"obj"]; + return [[TestProtocolTestRecursiveObject2 alloc] initWithInspectorObject:[[super objectForKey:@"obj"] toInspectorObject].get()]; } @end +@implementation TestProtocolTestRecursiveObject2 -### End File: RWIProtocolTypes.mm +- (instancetype)initWithPayload:(nonnull NSDictionary *)payload +{ + if (!(self = [super init])) + return nil; -### Begin File: RWIProtocolInternal.h -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 University of Washington. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ + self.obj = [[TestProtocolTestRecursiveObject1 alloc] initWithPayload:payload[@"obj"]]; -// DO NOT EDIT THIS FILE. It is automatically generated from type-requiring-runtime-casts.json -// by the script: Source/JavaScriptCore/inspector/scripts/generate-inspector-protocol-bindings.py + return self; +} +- (instancetype)initWithJSONObject:(RWIProtocolJSONObject *)jsonObject +{ + if (!(self = [super initWithInspectorObject:[jsonObject toInspectorObject].get()])) + return nil; -#import "RWIProtocol.h" -#import "RWIProtocolJSONObjectInternal.h" -#import -#import + return self; +} +- (void)setObj:(TestProtocolTestRecursiveObject1 *)obj +{ + [super setObject:obj forKey:@"obj"]; +} +- (TestProtocolTestRecursiveObject1 *)obj +{ + return [[TestProtocolTestRecursiveObject1 alloc] initWithInspectorObject:[[super objectForKey:@"obj"] toInspectorObject].get()]; +} + +@end -### End File: RWIProtocolInternal.h +### End File: TestProtocolTypes.mm diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/fail-on-type-reference-as-primitive-type.json webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/fail-on-type-reference-as-primitive-type.json --- webkit2gtk-2.12.3/Source/JavaScriptCore/inspector/scripts/tests/fail-on-type-reference-as-primitive-type.json 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/inspector/scripts/tests/fail-on-type-reference-as-primitive-type.json 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,18 @@ +{ + "domain": "Database", + "types": [ + { + "id": "DatabaseId", + "type": "string", + "description": "Unique identifier of Database object." + } + ], + "events": [ + { + "name": "didExecuteOptionalParameters", + "parameters": [ + { "name": "columnNames", "type": "DatabaseId" } + ] + } + ] +} diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CachedCall.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CachedCall.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CachedCall.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CachedCall.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,6 +33,7 @@ #include "Interpreter.h" #include "ProtoCallFrame.h" #include "VMEntryScope.h" +#include "VMInlines.h" namespace JSC { class CachedCall { @@ -41,14 +42,18 @@ CachedCall(CallFrame* callFrame, JSFunction* function, int argumentCount) : m_valid(false) , m_interpreter(callFrame->interpreter()) - , m_entryScope(callFrame->vm(), function->scope()->globalObject()) + , m_vm(callFrame->vm()) + , m_entryScope(m_vm, function->scope()->globalObject(m_vm)) { + VM& vm = m_entryScope.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + ASSERT(!function->isHostFunctionNonInline()); - if (callFrame->vm().isSafeToRecurse()) { + if (UNLIKELY(vm.isSafeToRecurseSoft())) { m_arguments.resize(argumentCount); m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, &m_protoCallFrame, function, argumentCount + 1, function->scope(), m_arguments.data()); } else - throwStackOverflowError(callFrame); + throwStackOverflowError(callFrame, scope); m_valid = !callFrame->hadException(); } @@ -63,6 +68,7 @@ private: bool m_valid; Interpreter* m_interpreter; + VM& m_vm; VMEntryScope m_entryScope; ProtoCallFrame m_protoCallFrame; Vector m_arguments; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CallFrame.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CallFrame.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CallFrame.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CallFrame.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2013, 2014 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2013-2014, 2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,15 @@ namespace JSC { +void ExecState::initGlobalExec(ExecState* globalExec, JSCallee* globalCallee) +{ + globalExec->setCodeBlock(nullptr); + globalExec->setCallerFrame(noCaller()); + globalExec->setReturnPC(0); + globalExec->setArgumentCountIncludingThis(0); + globalExec->setCallee(globalCallee); +} + bool CallFrame::callSiteBitsAreBytecodeOffset() const { ASSERT(codeBlock()); @@ -76,12 +85,12 @@ unsigned CallFrame::callSiteAsRawBits() const { - return this[JSStack::ArgumentCount].tag(); + return this[CallFrameSlot::argumentCount].tag(); } SUPPRESS_ASAN unsigned CallFrame::unsafeCallSiteAsRawBits() const { - return this[JSStack::ArgumentCount].unsafeTag(); + return this[CallFrameSlot::argumentCount].unsafeTag(); } CallSiteIndex CallFrame::callSiteIndex() const @@ -94,14 +103,6 @@ return CallSiteIndex(unsafeCallSiteAsRawBits()); } -#ifndef NDEBUG -JSStack* CallFrame::stack() -{ - return &interpreter()->stack(); -} - -#endif - #if USE(JSVALUE32_64) Instruction* CallFrame::currentVPC() const { @@ -111,7 +112,7 @@ void CallFrame::setCurrentVPC(Instruction* vpc) { CallSiteIndex callSite(vpc); - this[JSStack::ArgumentCount].tag() = callSite.bits(); + this[CallFrameSlot::argumentCount].tag() = callSite.bits(); } unsigned CallFrame::callSiteBitsAsBytecodeOffset() const @@ -131,7 +132,7 @@ void CallFrame::setCurrentVPC(Instruction* vpc) { CallSiteIndex callSite(vpc - codeBlock()->instructions().begin()); - this[JSStack::ArgumentCount].tag() = static_cast(callSite.bits()); + this[CallFrameSlot::argumentCount].tag() = static_cast(callSite.bits()); } unsigned CallFrame::callSiteBitsAsBytecodeOffset() const @@ -229,7 +230,7 @@ return ASCIILiteral("global code"); case FunctionCode: if (callee()) - return getCalculatedDisplayName(this, callee()); + return getCalculatedDisplayName(vm(), callee()); return emptyString(); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CallFrame.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CallFrame.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CallFrame.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CallFrame.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2007, 2008, 2011, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007-2008, 2011, 2013-2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,7 +24,6 @@ #define CallFrame_h #include "AbstractPC.h" -#include "JSStack.h" #include "MacroAssemblerCodeRef.h" #include "Register.h" #include "StackVisitor.h" @@ -34,9 +33,15 @@ namespace JSC { class Arguments; + class ExecState; class Interpreter; + class JSCallee; class JSScope; + struct Instruction; + + typedef ExecState CallFrame; + struct CallSiteIndex { CallSiteIndex() : m_bits(UINT_MAX) @@ -60,15 +65,33 @@ uint32_t m_bits; }; + struct CallerFrameAndPC { + CallFrame* callerFrame; + Instruction* pc; + static const int sizeInRegisters = 2 * sizeof(void*) / sizeof(Register); + }; + static_assert(CallerFrameAndPC::sizeInRegisters == sizeof(CallerFrameAndPC) / sizeof(Register), "CallerFrameAndPC::sizeInRegisters is incorrect."); + + struct CallFrameSlot { + static const int codeBlock = CallerFrameAndPC::sizeInRegisters; + static const int callee = codeBlock + 1; + static const int argumentCount = callee + 1; + static const int thisArgument = argumentCount + 1; + static const int firstArgument = thisArgument + 1; + }; + // Represents the current state of script execution. // Passed as the first argument to most functions. class ExecState : private Register { public: - JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); } - JSObject* callee() const { return this[JSStack::Callee].object(); } - SUPPRESS_ASAN JSValue unsafeCallee() const { return this[JSStack::Callee].asanUnsafeJSValue(); } - CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); } - SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[JSStack::CodeBlock].Register::asanUnsafeCodeBlock(); } + static const int headerSizeInRegisters = CallFrameSlot::argumentCount + 1; + + JSValue calleeAsValue() const { return this[CallFrameSlot::callee].jsValue(); } + JSObject* callee() const { return this[CallFrameSlot::callee].object(); } + SUPPRESS_ASAN JSValue unsafeCallee() const { return this[CallFrameSlot::callee].asanUnsafeJSValue(); } + CodeBlock* codeBlock() const { return this[CallFrameSlot::codeBlock].Register::codeBlock(); } + CodeBlock** addressOfCodeBlock() const { return bitwise_cast(this + CallFrameSlot::codeBlock); } + SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[CallFrameSlot::codeBlock].Register::asanUnsafeCodeBlock(); } JSScope* scope(int scopeRegisterOffset) const { ASSERT(this[scopeRegisterOffset].Register::scope()); @@ -149,7 +172,7 @@ // This will get you a CodeOrigin. It will always succeed. May return // CodeOrigin(0) if we're in native code. - CodeOrigin codeOrigin(); + JS_EXPORT_PRIVATE CodeOrigin codeOrigin(); Register* topOfFrame() { @@ -164,17 +187,7 @@ void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; } void setScope(int scopeRegisterOffset, JSScope* scope) { static_cast(this)[scopeRegisterOffset] = scope; } - ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, - CallFrame* callerFrame, int argc, JSObject* callee) - { - ASSERT(callerFrame == noCaller() || callerFrame->stack()->containsAddress(this)); - - setCodeBlock(codeBlock); - setCallerFrame(callerFrame); - setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. - setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object) - setCallee(callee); - } + static void initGlobalExec(ExecState* globalExec, JSCallee* globalCallee); // Read a register from the codeframe (or constant from the CodeBlock). Register& r(int); @@ -185,9 +198,9 @@ // Access to arguments as passed. (After capture, arguments may move to a different location.) size_t argumentCount() const { return argumentCountIncludingThis() - 1; } - size_t argumentCountIncludingThis() const { return this[JSStack::ArgumentCount].payload(); } - static int argumentOffset(int argument) { return (JSStack::FirstArgument + argument); } - static int argumentOffsetIncludingThis(int argument) { return (JSStack::ThisArgument + argument); } + size_t argumentCountIncludingThis() const { return this[CallFrameSlot::argumentCount].payload(); } + static int argumentOffset(int argument) { return (CallFrameSlot::firstArgument + argument); } + static int argumentOffsetIncludingThis(int argument) { return (CallFrameSlot::thisArgument + argument); } // In the following (argument() and setArgument()), the 'argument' // parameter is the index of the arguments of the target function of @@ -198,6 +211,7 @@ // arguments(0) will not fetch the 'this' value. To get/set 'this', // use thisValue() and setThisValue() below. + JSValue* addressOfArgumentsStart() const { return bitwise_cast(this + argumentOffset(0)); } JSValue argument(size_t argument) { if (argument >= argumentCount()) @@ -233,21 +247,22 @@ JSValue argumentAfterCapture(size_t argument); - static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + JSStack::ThisArgument - 1; } + static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + CallFrameSlot::thisArgument - 1; } static CallFrame* noCaller() { return 0; } - void setArgumentCountIncludingThis(int count) { static_cast(this)[JSStack::ArgumentCount].payload() = count; } - void setCallee(JSObject* callee) { static_cast(this)[JSStack::Callee] = callee; } - void setCodeBlock(CodeBlock* codeBlock) { static_cast(this)[JSStack::CodeBlock] = codeBlock; } + void setArgumentCountIncludingThis(int count) { static_cast(this)[CallFrameSlot::argumentCount].payload() = count; } + void setCallee(JSObject* callee) { static_cast(this)[CallFrameSlot::callee] = callee; } + void setCodeBlock(CodeBlock* codeBlock) { static_cast(this)[CallFrameSlot::codeBlock] = codeBlock; } void setReturnPC(void* value) { callerFrameAndPC().pc = reinterpret_cast(value); } String friendlyFunctionName(); // CallFrame::iterate() expects a Functor that implements the following method: - // StackVisitor::Status operator()(StackVisitor&); - - template void iterate(Functor& functor) + // StackVisitor::Status operator()(StackVisitor&) const; + // FIXME: This method is improper. We rely on the fact that we can call it with a null + // receiver. We should always be using StackVisitor directly. + template void iterate(const Functor& functor) { StackVisitor::visit(this, functor); } @@ -257,9 +272,6 @@ private: -#ifndef NDEBUG - JSStack* stack(); -#endif ExecState(); ~ExecState(); @@ -278,18 +290,16 @@ int offset = reg - this->registers(); // The offset is defined (based on argumentOffset()) to be: - // offset = JSStack::FirstArgument - argIndex; + // offset = CallFrameSlot::firstArgument - argIndex; // Hence: - // argIndex = JSStack::FirstArgument - offset; - size_t argIndex = offset - JSStack::FirstArgument; + // argIndex = CallFrameSlot::firstArgument - offset; + size_t argIndex = offset - CallFrameSlot::firstArgument; return argIndex; } CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast(this); } const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast(this); } SUPPRESS_ASAN const CallerFrameAndPC& unsafeCallerFrameAndPC() const { return *reinterpret_cast(this); } - - friend class JSStack; }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CLoopStack.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CLoopStack.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CLoopStack.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CLoopStack.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2008, 2013-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CLoopStack.h" + +#if !ENABLE(JIT) + +#include "CLoopStackInlines.h" +#include "ConservativeRoots.h" +#include "Interpreter.h" +#include "JSCInlines.h" +#include "Options.h" +#include + +namespace JSC { + +static size_t committedBytesCount = 0; + +static size_t commitSize() +{ + static size_t size = std::max(16 * 1024, pageSize()); + return size; +} + +static StaticLock stackStatisticsMutex; + +CLoopStack::CLoopStack(VM& vm) + : m_vm(vm) + , m_topCallFrame(vm.topCallFrame) + , m_end(0) + , m_softReservedZoneSizeInRegisters(0) +{ + size_t capacity = Options::maxPerThreadStackUsage(); + ASSERT(capacity && isPageAligned(capacity)); + + m_reservation = PageReservation::reserve(WTF::roundUpToMultipleOf(commitSize(), capacity), OSAllocator::JSVMStackPages); + setCLoopStackLimit(highAddress()); + m_commitTop = highAddress(); + + m_lastStackTop = baseOfStack(); + + m_topCallFrame = 0; +} + +CLoopStack::~CLoopStack() +{ + ptrdiff_t sizeToDecommit = reinterpret_cast(highAddress()) - reinterpret_cast(m_commitTop); + m_reservation.decommit(reinterpret_cast(m_commitTop), sizeToDecommit); + addToCommittedByteCount(-sizeToDecommit); + m_reservation.deallocate(); +} + +bool CLoopStack::grow(Register* newTopOfStack) +{ + Register* newTopOfStackWithReservedZone = newTopOfStack - m_softReservedZoneSizeInRegisters; + + // If we have already committed enough memory to satisfy this request, + // just update the end pointer and return. + if (newTopOfStackWithReservedZone >= m_commitTop) { + setCLoopStackLimit(newTopOfStack); + return true; + } + + // Compute the chunk size of additional memory to commit, and see if we + // have it still within our budget. If not, we'll fail to grow and + // return false. + ptrdiff_t delta = reinterpret_cast(m_commitTop) - reinterpret_cast(newTopOfStackWithReservedZone); + delta = WTF::roundUpToMultipleOf(commitSize(), delta); + Register* newCommitTop = m_commitTop - (delta / sizeof(Register)); + if (newCommitTop < reservationTop()) + return false; + + // Otherwise, the growth is still within our budget. Commit it and return true. + m_reservation.commit(newCommitTop, delta); + addToCommittedByteCount(delta); + m_commitTop = newCommitTop; + setCLoopStackLimit(newTopOfStack); + return true; +} + +void CLoopStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks) +{ + conservativeRoots.add(topOfStack() + 1, highAddress(), jitStubRoutines, codeBlocks); +} + +void CLoopStack::sanitizeStack() +{ +#if !ASAN_ENABLED + ASSERT(topOfStack() <= baseOfStack()); + + if (m_lastStackTop < topOfStack()) { + char* begin = reinterpret_cast(m_lastStackTop + 1); + char* end = reinterpret_cast(topOfStack() + 1); + memset(begin, 0, end - begin); + } + + m_lastStackTop = topOfStack(); +#endif +} + +void CLoopStack::releaseExcessCapacity() +{ + Register* highAddressWithReservedZone = highAddress() - m_softReservedZoneSizeInRegisters; + ptrdiff_t delta = reinterpret_cast(highAddressWithReservedZone) - reinterpret_cast(m_commitTop); + m_reservation.decommit(m_commitTop, delta); + addToCommittedByteCount(-delta); + m_commitTop = highAddressWithReservedZone; +} + +void CLoopStack::addToCommittedByteCount(long byteCount) +{ + LockHolder locker(stackStatisticsMutex); + ASSERT(static_cast(committedBytesCount) + byteCount > -1); + committedBytesCount += byteCount; +} + +void CLoopStack::setSoftReservedZoneSize(size_t reservedZoneSize) +{ + m_softReservedZoneSizeInRegisters = reservedZoneSize / sizeof(Register); + if (m_commitTop >= (m_end + 1) - m_softReservedZoneSizeInRegisters) + grow(m_end + 1); +} + +bool CLoopStack::isSafeToRecurse() const +{ + void* reservationLimit = reinterpret_cast(reservationTop() + m_softReservedZoneSizeInRegisters); + return !m_topCallFrame || (m_topCallFrame->topOfFrame() > reservationLimit); +} + +size_t CLoopStack::committedByteCount() +{ + LockHolder locker(stackStatisticsMutex); + return committedBytesCount; +} + +} // namespace JSC + +#endif // !ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CLoopStack.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CLoopStack.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CLoopStack.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CLoopStack.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008-2009, 2013-2014, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if !ENABLE(JIT) + +#include "Register.h" +#include +#include +#include + +namespace JSC { + + class CodeBlockSet; + class ConservativeRoots; + class JITStubRoutineSet; + class VM; + class LLIntOffsetsExtractor; + + class CLoopStack { + WTF_MAKE_NONCOPYABLE(CLoopStack); + public: + // Allow 8k of excess registers before we start trying to reap the stack + static const ptrdiff_t maxExcessCapacity = 8 * 1024; + + CLoopStack(VM&); + ~CLoopStack(); + + bool ensureCapacityFor(Register* newTopOfStack); + + bool containsAddress(Register* address) { return (lowAddress() <= address && address < highAddress()); } + static size_t committedByteCount(); + + void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&); + void sanitizeStack(); + + Register* baseOfStack() const + { + return highAddress() - 1; + } + + size_t size() const { return highAddress() - lowAddress(); } + + void setSoftReservedZoneSize(size_t); + bool isSafeToRecurse() const; + inline Register* topOfStack(); + + private: + + Register* lowAddress() const + { + return m_end + 1; + } + + Register* highAddress() const + { + return reinterpret_cast_ptr(static_cast(m_reservation.base()) + m_reservation.size()); + } + + inline Register* topOfFrameFor(CallFrame*); + + Register* reservationTop() const + { + char* reservationTop = static_cast(m_reservation.base()); + return reinterpret_cast_ptr(reservationTop); + } + + bool grow(Register* newTopOfStack); + void shrink(Register* newTopOfStack); + void releaseExcessCapacity(); + void addToCommittedByteCount(long); + + void setCLoopStackLimit(Register* newTopOfStack); + + VM& m_vm; + CallFrame*& m_topCallFrame; + Register* m_end; + Register* m_commitTop; + PageReservation m_reservation; + Register* m_lastStackTop; + ptrdiff_t m_softReservedZoneSizeInRegisters; + + friend class LLIntOffsetsExtractor; + }; + +} // namespace JSC + +#endif // !ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CLoopStackInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CLoopStackInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/CLoopStackInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/CLoopStackInlines.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012-2014, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if !ENABLE(JIT) + +#include "CLoopStack.h" +#include "CallFrame.h" +#include "CodeBlock.h" +#include "VM.h" + +namespace JSC { + +inline bool CLoopStack::ensureCapacityFor(Register* newTopOfStack) +{ + Register* newEnd = newTopOfStack - 1; + if (newEnd >= m_end) + return true; + return grow(newTopOfStack); +} + +inline Register* CLoopStack::topOfFrameFor(CallFrame* frame) +{ + if (UNLIKELY(!frame)) + return baseOfStack(); + return frame->topOfFrame() - 1; +} + +inline Register* CLoopStack::topOfStack() +{ + return topOfFrameFor(m_topCallFrame); +} + +inline void CLoopStack::shrink(Register* newTopOfStack) +{ + Register* newEnd = newTopOfStack - 1; + if (newEnd >= m_end) + return; + setCLoopStackLimit(newTopOfStack); + // Note: Clang complains of an unresolved linkage to maxExcessCapacity if + // invoke std::max() with it as an argument. To work around this, we first + // assign the constant to a local variable, and use the local instead. + ptrdiff_t maxExcessCapacity = CLoopStack::maxExcessCapacity; + ptrdiff_t maxExcessInRegisters = std::max(maxExcessCapacity, m_softReservedZoneSizeInRegisters); + if (m_end == baseOfStack() && (highAddress() - m_commitTop) >= maxExcessInRegisters) + releaseExcessCapacity(); +} + +inline void CLoopStack::setCLoopStackLimit(Register* newTopOfStack) +{ + Register* newEnd = newTopOfStack - 1; + m_end = newEnd; + m_vm.setCLoopStackLimit(newTopOfStack); +} + +} // namespace JSC + +#endif // !ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/Interpreter.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/Interpreter.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/Interpreter.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/Interpreter.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2010, 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008-2010, 2012-2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich * * Redistribution and use in source and binary forms, with or without @@ -43,18 +43,16 @@ #include "Exception.h" #include "ExceptionHelpers.h" #include "GetterSetter.h" -#include "JSArray.h" +#include "JSArrayInlines.h" #include "JSBoundFunction.h" #include "JSCInlines.h" #include "JSLexicalEnvironment.h" #include "JSModuleEnvironment.h" -#include "JSNotAnObject.h" -#include "JSStackInlines.h" #include "JSString.h" #include "JSWithScope.h" #include "LLIntCLoop.h" +#include "LLIntData.h" #include "LLIntThunks.h" -#include "LegacyProfiler.h" #include "LiteralParser.h" #include "ObjectPrototype.h" #include "Parser.h" @@ -62,7 +60,6 @@ #include "RegExpObject.h" #include "RegExpPrototype.h" #include "Register.h" -#include "SamplingTool.h" #include "ScopedArguments.h" #include "StackAlignment.h" #include "StackVisitor.h" @@ -79,7 +76,6 @@ #include #include #include -#include #include #if ENABLE(JIT) @@ -90,53 +86,11 @@ namespace JSC { -String StackFrame::friendlySourceURL() const -{ - String traceLine; - - switch (codeType) { - case StackFrameEvalCode: - case StackFrameModuleCode: - case StackFrameFunctionCode: - case StackFrameGlobalCode: - if (!sourceURL.isEmpty()) - traceLine = sourceURL.impl(); - break; - case StackFrameNativeCode: - traceLine = "[native code]"; - break; - } - return traceLine.isNull() ? emptyString() : traceLine; -} - -String StackFrame::friendlyFunctionName(CallFrame* callFrame) const -{ - String traceLine; - JSObject* stackFrameCallee = callee.get(); - - switch (codeType) { - case StackFrameEvalCode: - traceLine = "eval code"; - break; - case StackFrameModuleCode: - traceLine = "module code"; - break; - case StackFrameNativeCode: - if (callee) - traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); - break; - case StackFrameFunctionCode: - traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl(); - break; - case StackFrameGlobalCode: - traceLine = "global code"; - break; - } - return traceLine.isNull() ? emptyString() : traceLine; -} - JSValue eval(CallFrame* callFrame) { + VM& vm = callFrame->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (!callFrame->argumentCount()) return jsUndefined(); @@ -144,10 +98,10 @@ if (!program.isString()) return program; - TopCallFrameSetter topCallFrame(callFrame->vm(), callFrame); + TopCallFrameSetter topCallFrame(vm, callFrame); JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(); if (!globalObject->evalEnabled()) { - callFrame->vm().throwException(callFrame, createEvalError(callFrame, globalObject->evalDisabledErrorMessage())); + throwException(callFrame, scope, createEvalError(callFrame, globalObject->evalDisabledErrorMessage())); return jsUndefined(); } String programSource = asString(program)->value(callFrame); @@ -160,8 +114,23 @@ UnlinkedCodeBlock* callerUnlinkedCodeBlock = callerCodeBlock->unlinkedCodeBlock(); bool isArrowFunctionContext = callerUnlinkedCodeBlock->isArrowFunction() || callerUnlinkedCodeBlock->isArrowFunctionContext(); - EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, isArrowFunctionContext, callerScopeChain); + DerivedContextType derivedContextType = callerUnlinkedCodeBlock->derivedContextType(); + if (!isArrowFunctionContext && callerUnlinkedCodeBlock->isClassContext()) { + derivedContextType = callerUnlinkedCodeBlock->isConstructor() + ? DerivedContextType::DerivedConstructorContext + : DerivedContextType::DerivedMethodContext; + } + + EvalContextType evalContextType; + if (isFunctionParseMode(callerUnlinkedCodeBlock->parseMode())) + evalContextType = EvalContextType::FunctionEvalContext; + else if (callerUnlinkedCodeBlock->codeType() == EvalCode) + evalContextType = callerUnlinkedCodeBlock->evalContextType(); + else + evalContextType = EvalContextType::None; + + EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, derivedContextType, evalContextType, isArrowFunctionContext, callerScopeChain); if (!eval) { if (!callerCodeBlock->isStrictMode()) { if (programSource.is8Bit()) { @@ -176,29 +145,29 @@ } // If the literal parser bailed, it should not have thrown exceptions. - ASSERT(!callFrame->vm().exception()); + ASSERT(!vm.exception()); - ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded; - if (callerUnlinkedCodeBlock->constructorKind() == ConstructorKind::Derived) - thisTDZMode = ThisTDZMode::AlwaysCheck; + eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), derivedContextType, evalContextType, isArrowFunctionContext, programSource, callerScopeChain); - eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), thisTDZMode, callerCodeBlock->unlinkedCodeBlock()->derivedContextType(), callerCodeBlock->unlinkedCodeBlock()->isArrowFunction(), programSource, callerScopeChain); if (!eval) return jsUndefined(); } JSValue thisValue = callerFrame->thisValue(); - Interpreter* interpreter = callFrame->vm().interpreter; + Interpreter* interpreter = vm.interpreter; return interpreter->execute(eval, callFrame, thisValue, callerScopeChain); } unsigned sizeOfVarargs(CallFrame* callFrame, JSValue arguments, uint32_t firstVarArgOffset) { + VM& vm = callFrame->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (UNLIKELY(!arguments.isCell())) { if (arguments.isUndefinedOrNull()) return 0; - callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame, arguments)); + throwException(callFrame, scope, createInvalidFunctionApplyParameterError(callFrame, arguments)); return 0; } @@ -209,19 +178,21 @@ length = jsCast(cell)->length(callFrame); break; case ScopedArgumentsType: - length =jsCast(cell)->length(callFrame); + length = jsCast(cell)->length(callFrame); break; case StringType: - callFrame->vm().throwException(callFrame, createInvalidFunctionApplyParameterError(callFrame, arguments)); + case SymbolType: + throwException(callFrame, scope, createInvalidFunctionApplyParameterError(callFrame, arguments)); return 0; + default: - ASSERT(arguments.isObject()); - if (isJSArray(cell)) - length = jsCast(cell)->length(); - else - length = jsCast(cell)->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); + RELEASE_ASSERT(arguments.isObject()); + length = getLength(callFrame, jsCast(cell)); + if (UNLIKELY(callFrame->hadException())) + return 0; break; } + if (length >= firstVarArgOffset) length -= firstVarArgOffset; @@ -231,13 +202,27 @@ return length; } -unsigned sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset) +unsigned sizeFrameForForwardArguments(CallFrame* callFrame, VM& vm, unsigned numUsedStackSlots) +{ + auto scope = DECLARE_THROW_SCOPE(vm); + + unsigned length = callFrame->argumentCount(); + CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1); + if (UNLIKELY(!vm.ensureStackCapacityFor(calleeFrame->registers()))) + throwStackOverflowError(callFrame, scope); + + return length; +} + +unsigned sizeFrameForVarargs(CallFrame* callFrame, VM& vm, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset) { + auto scope = DECLARE_THROW_SCOPE(vm); + unsigned length = sizeOfVarargs(callFrame, arguments, firstVarArgOffset); CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1); - if (length > maxArguments || !stack->ensureCapacityFor(calleeFrame->registers())) { - throwStackOverflowError(callFrame); + if (UNLIKELY(length > maxArguments || !vm.ensureStackCapacityFor(calleeFrame->registers()))) { + throwStackOverflowError(callFrame, scope); return 0; } @@ -250,6 +235,7 @@ return; JSCell* cell = arguments.asCell(); + switch (cell->type()) { case DirectArgumentsType: jsCast(cell)->copyToArguments(callFrame, firstElementDest, offset, length); @@ -291,10 +277,27 @@ newCallFrame->setThisValue(thisValue); } +void setupForwardArgumentsFrame(CallFrame* execCaller, CallFrame* execCallee, uint32_t length) +{ + ASSERT(length == execCaller->argumentCount()); + unsigned offset = execCaller->argumentOffset(0) * sizeof(Register); + memcpy(reinterpret_cast(execCallee) + offset, reinterpret_cast(execCaller) + offset, length * sizeof(Register)); + execCallee->setArgumentCountIncludingThis(length + 1); +} + +void setupForwardArgumentsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length) +{ + setupForwardArgumentsFrame(execCaller, execCallee, length); + execCallee->setThisValue(thisValue); +} + + + Interpreter::Interpreter(VM& vm) - : m_sampleEntryDepth(0) - , m_vm(vm) - , m_stack(vm) + : m_vm(vm) +#if !ENABLE(JIT) + , m_cloopStack(vm) +#endif , m_errorHandlingModeReentry(0) #if !ASSERT_DISABLED , m_initialized(false) @@ -317,10 +320,6 @@ #if !ASSERT_DISABLED m_initialized = true; #endif - -#if ENABLE(OPCODE_SAMPLING) - enableSampler(); -#endif } #ifdef NDEBUG @@ -345,7 +344,7 @@ { } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { if (!m_hasSkippedFirstFrame) { m_hasSkippedFirstFrame = true; @@ -361,7 +360,7 @@ } private: - bool m_hasSkippedFirstFrame; + mutable bool m_hasSkippedFirstFrame; const Register*& m_it; }; @@ -376,8 +375,8 @@ const Register* it; const Register* end; - it = callFrame->registers() + JSStack::ThisArgument + callFrame->argumentCount(); - end = callFrame->registers() + JSStack::ThisArgument - 1; + it = callFrame->registers() + CallFrameSlot::thisArgument + callFrame->argumentCount(); + end = callFrame->registers() + CallFrameSlot::thisArgument - 1; while (it > end) { JSValue v = it->jsValue(); int registerNumber = it - callFrame->registers(); @@ -445,77 +444,6 @@ #endif } -static StackFrameCodeType getStackFrameCodeType(StackVisitor& visitor) -{ - switch (visitor->codeType()) { - case StackVisitor::Frame::Eval: - return StackFrameEvalCode; - case StackVisitor::Frame::Module: - return StackFrameModuleCode; - case StackVisitor::Frame::Function: - return StackFrameFunctionCode; - case StackVisitor::Frame::Global: - return StackFrameGlobalCode; - case StackVisitor::Frame::Native: - ASSERT_NOT_REACHED(); - return StackFrameNativeCode; - } - RELEASE_ASSERT_NOT_REACHED(); - return StackFrameGlobalCode; -} - -void StackFrame::computeLineAndColumn(unsigned& line, unsigned& column) -{ - if (!codeBlock) { - line = 0; - column = 0; - return; - } - - int divot = 0; - int unusedStartOffset = 0; - int unusedEndOffset = 0; - unsigned divotLine = 0; - unsigned divotColumn = 0; - expressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn); - - line = divotLine + lineOffset; - column = divotColumn + (divotLine ? 1 : firstLineColumnOffset); - - if (executable->hasOverrideLineNumber()) - line = executable->overrideLineNumber(); -} - -void StackFrame::expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) -{ - codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column); - divot += characterOffset; -} - -String StackFrame::toString(CallFrame* callFrame) -{ - StringBuilder traceBuild; - String functionName = friendlyFunctionName(callFrame); - String sourceURL = friendlySourceURL(); - traceBuild.append(functionName); - if (!sourceURL.isEmpty()) { - if (!functionName.isEmpty()) - traceBuild.append('@'); - traceBuild.append(sourceURL); - if (codeType != StackFrameNativeCode) { - unsigned line; - unsigned column; - computeLineAndColumn(line, column); - - traceBuild.append(':'); - traceBuild.appendNumber(line); - traceBuild.append(':'); - traceBuild.appendNumber(column); - } - } - return traceBuild.toString().impl(); -} - static inline bool isWebAssemblyExecutable(ExecutableBase* executable) { #if !ENABLE(WEBASSEMBLY) @@ -528,36 +456,38 @@ class GetStackTraceFunctor { public: - GetStackTraceFunctor(VM& vm, Vector& results, size_t remainingCapacity) + GetStackTraceFunctor(VM& vm, Vector& results, size_t framesToSkip, size_t capacity) : m_vm(vm) , m_results(results) - , m_remainingCapacityForFrameCapture(remainingCapacity) + , m_framesToSkip(framesToSkip) + , m_remainingCapacityForFrameCapture(capacity) { + m_results.reserveInitialCapacity(capacity); } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { - VM& vm = m_vm; + if (m_framesToSkip > 0) { + m_framesToSkip--; + return StackVisitor::Continue; + } + if (m_remainingCapacityForFrameCapture) { if (visitor->isJSFrame() && !isWebAssemblyExecutable(visitor->codeBlock()->ownerExecutable()) && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) { - CodeBlock* codeBlock = visitor->codeBlock(); StackFrame s = { - Strong(vm, visitor->callee()), - getStackFrameCodeType(visitor), - Strong(vm, codeBlock->ownerScriptExecutable()), - Strong(vm, codeBlock->unlinkedCodeBlock()), - codeBlock->source(), - codeBlock->ownerScriptExecutable()->firstLine(), - codeBlock->firstLineColumnOffset(), - codeBlock->sourceOffset(), - visitor->bytecodeOffset(), - visitor->sourceURL() + Strong(m_vm, visitor->callee()), + Strong(m_vm, visitor->codeBlock()), + visitor->bytecodeOffset() }; m_results.append(s); } else { - StackFrame s = { Strong(vm, visitor->callee()), StackFrameNativeCode, Strong(), Strong(), 0, 0, 0, 0, 0, String()}; + StackFrame s = { + Strong(m_vm, visitor->callee()), + Strong(), + 0 // unused value because codeBlock is null. + }; m_results.append(s); } @@ -570,33 +500,46 @@ private: VM& m_vm; Vector& m_results; - size_t m_remainingCapacityForFrameCapture; + mutable size_t m_framesToSkip; + mutable size_t m_remainingCapacityForFrameCapture; }; -void Interpreter::getStackTrace(Vector& results, size_t maxStackSize) +void Interpreter::getStackTrace(Vector& results, size_t framesToSkip, size_t maxStackSize) { VM& vm = m_vm; CallFrame* callFrame = vm.topCallFrame; if (!callFrame) return; - GetStackTraceFunctor functor(vm, results, maxStackSize); + size_t framesCount = 0; + callFrame->iterate([&] (StackVisitor&) -> StackVisitor::Status { + framesCount++; + return StackVisitor::Continue; + }); + if (framesCount <= framesToSkip) + return; + + framesCount -= framesToSkip; + framesCount = std::min(maxStackSize, framesCount); + + GetStackTraceFunctor functor(vm, results, framesToSkip, framesCount); callFrame->iterate(functor); + ASSERT(results.size() == results.capacity()); } -JSString* Interpreter::stackTraceAsString(ExecState* exec, Vector stackTrace) +JSString* Interpreter::stackTraceAsString(VM& vm, const Vector& stackTrace) { // FIXME: JSStringJoiner could be more efficient than StringBuilder here. StringBuilder builder; for (unsigned i = 0; i < stackTrace.size(); i++) { - builder.append(String(stackTrace[i].toString(exec))); + builder.append(String(stackTrace[i].toString(vm))); if (i != stackTrace.size() - 1) builder.append('\n'); } - return jsString(&exec->vm(), builder.toString()); + return jsString(&vm, builder.toString()); } -ALWAYS_INLINE static HandlerInfo* findExceptionHandler(StackVisitor& visitor, CodeBlock* codeBlock, CodeBlock::RequiredHandler requiredHandler) +ALWAYS_INLINE static HandlerInfo* findExceptionHandler(StackVisitor& visitor, CodeBlock* codeBlock, RequiredHandler requiredHandler) { ASSERT(codeBlock); #if ENABLE(DFG_JIT) @@ -622,7 +565,7 @@ HandlerInfo* handler() { return m_handler; } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { visitor.unwindToMachineCodeBlockFrame(); @@ -630,7 +573,7 @@ if (!codeBlock) return StackVisitor::Continue; - m_handler = findExceptionHandler(visitor, codeBlock, CodeBlock::RequiredHandler::CatchHandler); + m_handler = findExceptionHandler(visitor, codeBlock, RequiredHandler::CatchHandler); if (m_handler) return StackVisitor::Done; @@ -638,7 +581,7 @@ } private: - HandlerInfo* m_handler; + mutable HandlerInfo* m_handler; }; ALWAYS_INLINE static void notifyDebuggerOfUnwinding(CallFrame* callFrame) @@ -663,17 +606,16 @@ { } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { visitor.unwindToMachineCodeBlockFrame(); - VM& vm = m_callFrame->vm(); m_callFrame = visitor->callFrame(); m_codeBlock = visitor->codeBlock(); m_handler = nullptr; if (!m_isTermination) { if (m_codeBlock && !isWebAssemblyExecutable(m_codeBlock->ownerExecutable())) - m_handler = findExceptionHandler(visitor, m_codeBlock, CodeBlock::RequiredHandler::AnyHandler); + m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler); } if (m_handler) @@ -683,21 +625,18 @@ bool shouldStopUnwinding = visitor->callerIsVMEntryFrame(); if (shouldStopUnwinding) { - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->exceptionUnwind(m_callFrame); - - copyCalleeSavesToVMCalleeSavesBuffer(visitor); + copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor); return StackVisitor::Done; } - copyCalleeSavesToVMCalleeSavesBuffer(visitor); + copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor); return StackVisitor::Continue; } private: - void copyCalleeSavesToVMCalleeSavesBuffer(StackVisitor& visitor) + void copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(StackVisitor& visitor) const { #if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 @@ -719,13 +658,14 @@ intptr_t* frame = reinterpret_cast(m_callFrame->registers()); unsigned registerCount = currentCalleeSaves->size(); + VMEntryRecord* record = vmEntryRecord(vm.topVMEntryFrame); for (unsigned i = 0; i < registerCount; i++) { RegisterAtOffset currentEntry = currentCalleeSaves->at(i); if (dontCopyRegisters.get(currentEntry.reg())) continue; - RegisterAtOffset* vmCalleeSavesEntry = allCalleeSaves->find(currentEntry.reg()); + RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg()); - vm.calleeSaveRegistersBuffer[vmCalleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex()); + record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()] = *(frame + currentEntry.offsetAsIndex()); } #else UNUSED_PARAM(visitor); @@ -808,36 +748,20 @@ return returnValue; } -class SamplingScope { -public: - SamplingScope(Interpreter* interpreter) - : m_interpreter(interpreter) - { - interpreter->startSampling(); - } - ~SamplingScope() - { - m_interpreter->stopSampling(); - } -private: - Interpreter* m_interpreter; -}; - JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj) { - SamplingScope samplingScope(this); - JSScope* scope = thisObj->globalObject()->globalScope(); VM& vm = *scope->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); - ASSERT(!vm.exception()); + ASSERT(!throwScope.exception()); ASSERT(!vm.isCollectorBusy()); RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); if (vm.isCollectorBusy()) return jsNull(); - if (!vm.isSafeToRecurse()) - return checkedReturn(throwStackOverflowError(callFrame)); + if (UNLIKELY(!vm.isSafeToRecurseSoft())) + return checkedReturn(throwStackOverflowError(callFrame, throwScope)); // First check if the "program" is actually just a JSON object. If so, // we'll handle the JSON object here. Else, we'll handle real JS code @@ -878,20 +802,22 @@ if (i == 0) { PropertySlot slot(globalObject, PropertySlot::InternalMethodType::Get); if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) { + if (throwScope.exception()) + return jsUndefined(); if (entry) - return callFrame->vm().throwException(callFrame, createUndefinedVariableError(callFrame, JSONPPath[i].m_pathEntryName)); + return throwException(callFrame, throwScope, createUndefinedVariableError(callFrame, JSONPPath[i].m_pathEntryName)); goto failedJSONP; } baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName); } else baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName); - if (callFrame->hadException()) + if (throwScope.exception()) return jsUndefined(); continue; } case JSONPPathEntryTypeLookup: { - baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex); - if (callFrame->hadException()) + baseObject = baseObject.get(callFrame, static_cast(JSONPPath[i].m_pathIndex)); + if (throwScope.exception()) return jsUndefined(); continue; } @@ -904,29 +830,29 @@ switch (JSONPPath.last().m_type) { case JSONPPathEntryTypeCall: { JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName); - if (callFrame->hadException()) + if (throwScope.exception()) return jsUndefined(); CallData callData; CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return callFrame->vm().throwException(callFrame, createNotAFunctionError(callFrame, function)); + if (callType == CallType::None) + return throwException(callFrame, throwScope, createNotAFunctionError(callFrame, function)); MarkedArgumentBuffer jsonArg; jsonArg.append(JSONPValue); JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject; JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg); - if (callFrame->hadException()) + if (throwScope.exception()) return jsUndefined(); break; } case JSONPPathEntryTypeDot: { baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot); - if (callFrame->hadException()) + if (throwScope.exception()) return jsUndefined(); break; } case JSONPPathEntryTypeLookup: { baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode()); - if (callFrame->hadException()) + if (throwScope.exception()) return jsUndefined(); break; } @@ -946,33 +872,31 @@ // Compile source to bytecode if necessary: if (JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope)) - return checkedReturn(callFrame->vm().throwException(callFrame, error)); + return checkedReturn(throwException(callFrame, throwScope, error)); - if (JSObject* error = program->prepareForExecution(callFrame, nullptr, scope, CodeForCall)) - return checkedReturn(callFrame->vm().throwException(callFrame, error)); - - ProgramCodeBlock* codeBlock = program->codeBlock(); + ProgramCodeBlock* codeBlock; + { + CodeBlock* tempCodeBlock; + JSObject* error = program->prepareForExecution(callFrame, nullptr, scope, CodeForCall, tempCodeBlock); + ASSERT(!throwScope.exception() || throwScope.exception() == jsDynamicCast(error)); + if (error) + return checkedReturn(throwException(callFrame, throwScope, error)); + codeBlock = jsCast(tempCodeBlock); + } if (UNLIKELY(vm.shouldTriggerTermination(callFrame))) - return throwTerminatedExecutionException(callFrame); + return throwTerminatedExecutionException(callFrame, throwScope); + + if (scope->structure()->isUncacheableDictionary()) + scope->flattenDictionaryObject(vm); ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'. ProtoCallFrame protoCallFrame; protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisObj, 1); - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->willExecute(callFrame, program->sourceURL(), program->firstLine(), program->startColumn()); - // Execute the code: - JSValue result; - { - SamplingTool::CallRecord callRecord(m_sampler.get()); - result = program->generatedJITCode()->execute(&vm, &protoCallFrame); - } - - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->didExecute(callFrame, program->sourceURL(), program->firstLine(), program->startColumn()); + JSValue result = program->generatedJITCode()->execute(&vm, &protoCallFrame); return checkedReturn(result); } @@ -980,12 +904,14 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args) { VM& vm = callFrame->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + ASSERT(!callFrame->hadException()); ASSERT(!vm.isCollectorBusy()); if (vm.isCollectorBusy()) return jsNull(); - bool isJSCall = (callType == CallTypeJS); + bool isJSCall = (callType == CallType::JS); JSScope* scope = nullptr; CodeBlock* newCodeBlock; size_t argsCount = 1 + args.size(); // implicit "this" parameter @@ -996,66 +922,61 @@ scope = callData.js.scope; globalObject = scope->globalObject(); } else { - ASSERT(callType == CallTypeHost); + ASSERT(callType == CallType::Host); globalObject = function->globalObject(); } VMEntryScope entryScope(vm, globalObject); - if (!vm.isSafeToRecurse()) - return checkedReturn(throwStackOverflowError(callFrame)); + if (UNLIKELY(!vm.isSafeToRecurseSoft())) + return checkedReturn(throwStackOverflowError(callFrame, throwScope)); if (isJSCall) { // Compile the callee: - JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast(function), scope, CodeForCall); - if (UNLIKELY(!!compileError)) { - return checkedReturn(callFrame->vm().throwException(callFrame, compileError)); - } - newCodeBlock = callData.js.functionExecutable->codeBlockForCall(); + JSObject* compileError = callData.js.functionExecutable->prepareForExecution(callFrame, jsCast(function), scope, CodeForCall, newCodeBlock); + ASSERT(throwScope.exception() == reinterpret_cast(compileError)); + if (UNLIKELY(!!compileError)) + return checkedReturn(throwException(callFrame, throwScope, compileError)); + ASSERT(!!newCodeBlock); newCodeBlock->m_shouldAlwaysBeInlined = false; } else newCodeBlock = 0; if (UNLIKELY(vm.shouldTriggerTermination(callFrame))) - return throwTerminatedExecutionException(callFrame); + return throwTerminatedExecutionException(callFrame, throwScope); ProtoCallFrame protoCallFrame; protoCallFrame.init(newCodeBlock, function, thisValue, argsCount, args.data()); - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->willExecute(callFrame, function); - JSValue result; { - SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall); - // Execute the code: - if (isJSCall) + if (isJSCall) { result = callData.js.functionExecutable->generatedJITCodeForCall()->execute(&vm, &protoCallFrame); - else { + throwScope.release(); + } else { result = JSValue::decode(vmEntryToNative(reinterpret_cast(callData.native.function), &vm, &protoCallFrame)); - if (callFrame->hadException()) + if (throwScope.exception()) result = jsNull(); } } - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->didExecute(callFrame, function); - return checkedReturn(result); } JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args, JSValue newTarget) { VM& vm = callFrame->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + ASSERT(!callFrame->hadException()); ASSERT(!vm.isCollectorBusy()); // We throw in this case because we have to return something "valid" but we're // already in an invalid state. if (vm.isCollectorBusy()) - return checkedReturn(throwStackOverflowError(callFrame)); + return checkedReturn(throwStackOverflowError(callFrame, throwScope)); - bool isJSConstruct = (constructType == ConstructTypeJS); + bool isJSConstruct = (constructType == ConstructType::JS); JSScope* scope = nullptr; CodeBlock* newCodeBlock; size_t argsCount = 1 + args.size(); // implicit "this" parameter @@ -1066,39 +987,33 @@ scope = constructData.js.scope; globalObject = scope->globalObject(); } else { - ASSERT(constructType == ConstructTypeHost); + ASSERT(constructType == ConstructType::Host); globalObject = constructor->globalObject(); } VMEntryScope entryScope(vm, globalObject); - if (!vm.isSafeToRecurse()) - return checkedReturn(throwStackOverflowError(callFrame)); + if (UNLIKELY(!vm.isSafeToRecurseSoft())) + return checkedReturn(throwStackOverflowError(callFrame, throwScope)); if (isJSConstruct) { // Compile the callee: - JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast(constructor), scope, CodeForConstruct); - if (UNLIKELY(!!compileError)) { - return checkedReturn(callFrame->vm().throwException(callFrame, compileError)); - } - newCodeBlock = constructData.js.functionExecutable->codeBlockForConstruct(); + JSObject* compileError = constructData.js.functionExecutable->prepareForExecution(callFrame, jsCast(constructor), scope, CodeForConstruct, newCodeBlock); + if (UNLIKELY(!!compileError)) + return checkedReturn(throwException(callFrame, throwScope, compileError)); + ASSERT(!!newCodeBlock); newCodeBlock->m_shouldAlwaysBeInlined = false; } else newCodeBlock = 0; if (UNLIKELY(vm.shouldTriggerTermination(callFrame))) - return throwTerminatedExecutionException(callFrame); + return throwTerminatedExecutionException(callFrame, throwScope); ProtoCallFrame protoCallFrame; protoCallFrame.init(newCodeBlock, constructor, newTarget, argsCount, args.data()); - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->willExecute(callFrame, constructor); - JSValue result; { - SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct); - // Execute the code. if (isJSConstruct) result = constructData.js.functionExecutable->generatedJITCodeForConstruct()->execute(&vm, &protoCallFrame); @@ -1110,9 +1025,6 @@ } } - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->didExecute(callFrame, constructor); - if (callFrame->hadException()) return 0; ASSERT(result.isObject()); @@ -1122,18 +1034,19 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, ProtoCallFrame* protoCallFrame, JSFunction* function, int argumentCountIncludingThis, JSScope* scope, JSValue* args) { VM& vm = *scope->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); ASSERT(!vm.exception()); if (vm.isCollectorBusy()) return CallFrameClosure(); // Compile the callee: - JSObject* error = functionExecutable->prepareForExecution(callFrame, function, scope, CodeForCall); + CodeBlock* newCodeBlock; + JSObject* error = functionExecutable->prepareForExecution(callFrame, function, scope, CodeForCall, newCodeBlock); if (error) { - callFrame->vm().throwException(callFrame, error); + throwException(callFrame, throwScope, error); return CallFrameClosure(); } - CodeBlock* newCodeBlock = functionExecutable->codeBlockForCall(); newCodeBlock->m_shouldAlwaysBeInlined = false; size_t argsCount = argumentCountIncludingThis; @@ -1147,8 +1060,8 @@ JSValue Interpreter::execute(CallFrameClosure& closure) { VM& vm = *closure.vm; - SamplingScope samplingScope(this); - + auto throwScope = DECLARE_THROW_SCOPE(vm); + ASSERT(!vm.isCollectorBusy()); RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); if (vm.isCollectorBusy()) @@ -1156,21 +1069,11 @@ StackStats::CheckPoint stackCheckPoint; - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->willExecute(closure.oldCallFrame, closure.function); - if (UNLIKELY(vm.shouldTriggerTermination(closure.oldCallFrame))) - return throwTerminatedExecutionException(closure.oldCallFrame); + return throwTerminatedExecutionException(closure.oldCallFrame, throwScope); // Execute the code: - JSValue result; - { - SamplingTool::CallRecord callRecord(m_sampler.get()); - result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame); - } - - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->didExecute(closure.oldCallFrame, closure.function); + JSValue result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame); return checkedReturn(result); } @@ -1178,8 +1081,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope) { VM& vm = *scope->vm(); - SamplingScope samplingScope(this); - + auto throwScope = DECLARE_THROW_SCOPE(vm); + ASSERT(scope->vm() == &callFrame->vm()); ASSERT(!vm.exception()); ASSERT(!vm.isCollectorBusy()); @@ -1188,8 +1091,8 @@ return jsNull(); VMEntryScope entryScope(vm, scope->globalObject()); - if (!vm.isSafeToRecurse()) - return checkedReturn(throwStackOverflowError(callFrame)); + if (UNLIKELY(!vm.isSafeToRecurseSoft())) + return checkedReturn(throwStackOverflowError(callFrame, throwScope)); unsigned numVariables = eval->numVariables(); int numFunctions = eval->numberOfFunctionDecls(); @@ -1205,7 +1108,8 @@ variableObject = node; break; } - if (JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast(node)) { + if (node->isJSLexicalEnvironment()) { + JSLexicalEnvironment* lexicalEnvironment = jsCast(node); if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) { variableObject = node; break; @@ -1214,10 +1118,14 @@ } } - JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, scope, CodeForCall); - if (UNLIKELY(!!compileError)) - return checkedReturn(callFrame->vm().throwException(callFrame, compileError)); - EvalCodeBlock* codeBlock = eval->codeBlock(); + EvalCodeBlock* codeBlock; + { + CodeBlock* tempCodeBlock; + JSObject* compileError = eval->prepareForExecution(callFrame, nullptr, scope, CodeForCall, tempCodeBlock); + if (UNLIKELY(!!compileError)) + return checkedReturn(throwException(callFrame, throwScope, compileError)); + codeBlock = jsCast(tempCodeBlock); + } // We can't declare a "var"/"function" that overwrites a global "let"/"const"/"class" in a sloppy-mode eval. if (variableObject->isGlobalObject() && !eval->isStrictMode() && (numVariables || numFunctions)) { @@ -1226,8 +1134,7 @@ const Identifier& ident = codeBlock->variable(i); PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry); if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, ident, slot)) { - return checkedReturn(callFrame->vm().throwException(callFrame, - createTypeError(callFrame, makeString("Can't create duplicate global variable in eval: '", String(ident.impl()), "'")))); + return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(ident.impl()), "'"))); } } @@ -1235,16 +1142,18 @@ FunctionExecutable* function = codeBlock->functionDecl(i); PropertySlot slot(globalLexicalEnvironment, PropertySlot::InternalMethodType::VMInquiry); if (JSGlobalLexicalEnvironment::getOwnPropertySlot(globalLexicalEnvironment, callFrame, function->name(), slot)) { - return checkedReturn(callFrame->vm().throwException(callFrame, - createTypeError(callFrame, makeString("Can't create duplicate global variable in eval: '", String(function->name().impl()), "'")))); + return checkedReturn(throwTypeError(callFrame, throwScope, makeString("Can't create duplicate global variable in eval: '", String(function->name().impl()), "'"))); } } } + if (variableObject->structure()->isUncacheableDictionary()) + variableObject->flattenDictionaryObject(vm); + if (numVariables || numFunctions) { BatchedTransitionOptimizer optimizer(vm, variableObject); - if (variableObject->next()) - variableObject->globalObject()->varInjectionWatchpoint()->fireAll("Executed eval, fired VarInjection watchpoint"); + if (variableObject->next() && !eval->isStrictMode()) + variableObject->globalObject()->varInjectionWatchpoint()->fireAll(vm, "Executed eval, fired VarInjection watchpoint"); for (unsigned i = 0; i < numVariables; ++i) { const Identifier& ident = codeBlock->variable(i); @@ -1262,25 +1171,15 @@ } if (UNLIKELY(vm.shouldTriggerTermination(callFrame))) - return throwTerminatedExecutionException(callFrame); + return throwTerminatedExecutionException(callFrame, throwScope); ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'. ProtoCallFrame protoCallFrame; protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), thisValue, 1); - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->willExecute(callFrame, eval->sourceURL(), eval->firstLine(), eval->startColumn()); - // Execute the code: - JSValue result; - { - SamplingTool::CallRecord callRecord(m_sampler.get()); - result = eval->generatedJITCode()->execute(&vm, &protoCallFrame); - } - - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->didExecute(callFrame, eval->sourceURL(), eval->firstLine(), eval->startColumn()); + JSValue result = eval->generatedJITCode()->execute(&vm, &protoCallFrame); return checkedReturn(result); } @@ -1288,7 +1187,7 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* callFrame, JSModuleEnvironment* scope) { VM& vm = *scope->vm(); - SamplingScope samplingScope(this); + auto throwScope = DECLARE_THROW_SCOPE(vm); ASSERT(scope->vm() == &callFrame->vm()); ASSERT(!vm.exception()); @@ -1298,16 +1197,23 @@ return jsNull(); VMEntryScope entryScope(vm, scope->globalObject()); - if (!vm.isSafeToRecurse()) - return checkedReturn(throwStackOverflowError(callFrame)); + if (UNLIKELY(!vm.isSafeToRecurseSoft())) + return checkedReturn(throwStackOverflowError(callFrame, throwScope)); - JSObject* compileError = executable->prepareForExecution(callFrame, nullptr, scope, CodeForCall); - if (UNLIKELY(!!compileError)) - return checkedReturn(callFrame->vm().throwException(callFrame, compileError)); - ModuleProgramCodeBlock* codeBlock = executable->codeBlock(); + ModuleProgramCodeBlock* codeBlock; + { + CodeBlock* tempCodeBlock; + JSObject* compileError = executable->prepareForExecution(callFrame, nullptr, scope, CodeForCall, tempCodeBlock); + if (UNLIKELY(!!compileError)) + return checkedReturn(throwException(callFrame, throwScope, compileError)); + codeBlock = jsCast(tempCodeBlock); + } if (UNLIKELY(vm.shouldTriggerTermination(callFrame))) - return throwTerminatedExecutionException(callFrame); + return throwTerminatedExecutionException(callFrame, throwScope); + + if (scope->structure()->isUncacheableDictionary()) + scope->flattenDictionaryObject(vm); ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'. @@ -1317,18 +1223,8 @@ ProtoCallFrame protoCallFrame; protoCallFrame.init(codeBlock, JSCallee::create(vm, scope->globalObject(), scope), jsUndefined(), 1); - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->willExecute(callFrame, executable->sourceURL(), executable->firstLine(), executable->startColumn()); - // Execute the code: - JSValue result; - { - SamplingTool::CallRecord callRecord(m_sampler.get()); - result = executable->generatedJITCode()->execute(&vm, &protoCallFrame); - } - - if (LegacyProfiler* profiler = vm.enabledProfiler()) - profiler->didExecute(callFrame, executable->sourceURL(), executable->firstLine(), executable->startColumn()); + JSValue result = executable->generatedJITCode()->execute(&vm, &protoCallFrame); return checkedReturn(result); } @@ -1365,40 +1261,4 @@ ASSERT(!callFrame->hadException()); } -void Interpreter::enableSampler() -{ -#if ENABLE(OPCODE_SAMPLING) - if (!m_sampler) { - m_sampler = std::make_unique(this); - m_sampler->setup(); - } -#endif -} -void Interpreter::dumpSampleData(ExecState* exec) -{ -#if ENABLE(OPCODE_SAMPLING) - if (m_sampler) - m_sampler->dump(exec); -#else - UNUSED_PARAM(exec); -#endif -} -void Interpreter::startSampling() -{ -#if ENABLE(SAMPLING_THREAD) - if (!m_sampleEntryDepth) - SamplingThread::start(); - - m_sampleEntryDepth++; -#endif -} -void Interpreter::stopSampling() -{ -#if ENABLE(SAMPLING_THREAD) - m_sampleEntryDepth--; - if (!m_sampleEntryDepth) - SamplingThread::stop(); -#endif -} - } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/Interpreter.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/Interpreter.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/Interpreter.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/Interpreter.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2013, 2015-2016 Apple Inc. All rights reserved. * Copyright (C) 2012 Research In Motion Limited. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,15 +34,18 @@ #include "JSCJSValue.h" #include "JSCell.h" #include "JSObject.h" -#include "JSStack.h" -#include "LLIntData.h" #include "Opcode.h" #include "SourceProvider.h" #include "StackAlignment.h" - +#include "StackFrame.h" #include #include +#if !ENABLE(JIT) +#include "CLoopStack.h" +#endif + + namespace JSC { class CodeBlock; @@ -59,13 +62,13 @@ class ModuleProgramExecutable; class Register; class JSScope; - class SamplingTool; struct CallFrameClosure; struct HandlerInfo; struct Instruction; struct ProtoCallFrame; + struct UnlinkedInstruction; - enum UnwindStart { UnwindFromCurrentFrame, UnwindFromCallerFrame }; + enum UnwindStart : uint8_t { UnwindFromCurrentFrame, UnwindFromCallerFrame }; enum DebugHookID { WillExecuteProgram, @@ -84,26 +87,6 @@ StackFrameNativeCode }; - struct StackFrame { - Strong callee; - StackFrameCodeType codeType; - Strong executable; - Strong codeBlock; - RefPtr code; - int lineOffset; - unsigned firstLineColumnOffset; - unsigned characterOffset; - unsigned bytecodeOffset; - String sourceURL; - JS_EXPORT_PRIVATE String toString(CallFrame*); - String friendlySourceURL() const; - String friendlyFunctionName(CallFrame*) const; - JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column); - - private: - void expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column); - }; - class SuspendExceptionScope { public: SuspendExceptionScope(VM* vm) @@ -145,7 +128,7 @@ { ASSERT(vm); ASSERT(callFrame); - ASSERT(callFrame < vm->topVMEntryFrame); + ASSERT(reinterpret_cast(callFrame) < reinterpret_cast(vm->topVMEntryFrame)); vm->topCallFrame = callFrame; } }; @@ -188,7 +171,9 @@ void initialize(); - JSStack& stack() { return m_stack; } +#if !ENABLE(JIT) + CLoopStack& cloopStack() { return m_cloopStack; } +#endif Opcode getOpcode(OpcodeID id) { @@ -210,7 +195,10 @@ return opcode; #endif } - + + OpcodeID getOpcodeID(const Instruction&); + OpcodeID getOpcodeID(const UnlinkedInstruction&); + bool isOpcode(Opcode); JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj); @@ -221,25 +209,19 @@ void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); - SamplingTool* sampler() { return m_sampler.get(); } - NEVER_INLINE HandlerInfo* unwind(VM&, CallFrame*&, Exception*, UnwindStart); void notifyDebuggerOfExceptionToBeThrown(CallFrame*, Exception*); NEVER_INLINE void debug(CallFrame*, DebugHookID); - JSString* stackTraceAsString(ExecState*, Vector); + static JSString* stackTraceAsString(VM&, const Vector&); static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState*); static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState*); static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState*); static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState*); - void dumpSampleData(ExecState* exec); - void startSampling(); - void stopSampling(); - JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*); - void getStackTrace(Vector& results, size_t maxStackSize = std::numeric_limits::max()); + void getStackTrace(Vector& results, size_t framesToSkip = 0, size_t maxStackSize = std::numeric_limits::max()); private: enum ExecutionFlag { Normal, InitializeAndReturn }; @@ -254,12 +236,10 @@ bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval) || opcode == getOpcode(op_tail_call); } - void enableSampler(); - int m_sampleEntryDepth; - std::unique_ptr m_sampler; - VM& m_vm; - JSStack m_stack; +#if !ENABLE(JIT) + CLoopStack m_cloopStack; +#endif int m_errorHandlingModeReentry; #if ENABLE(COMPUTED_GOTO_OPCODES) @@ -280,21 +260,24 @@ // aligned size. Align the size here. argumentCountIncludingThis = WTF::roundUpToMultipleOf( stackAlignmentRegisters(), - argumentCountIncludingThis + JSStack::CallFrameHeaderSize) - JSStack::CallFrameHeaderSize; + argumentCountIncludingThis + CallFrame::headerSizeInRegisters) - CallFrame::headerSizeInRegisters; // Align the frame offset here. unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf( stackAlignmentRegisters(), - numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize); + numUsedStackSlots + argumentCountIncludingThis + CallFrame::headerSizeInRegisters); return CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset); } unsigned sizeOfVarargs(CallFrame* exec, JSValue arguments, uint32_t firstVarArgOffset); static const unsigned maxArguments = 0x10000; - unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset); + unsigned sizeFrameForVarargs(CallFrame* exec, VM&, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset); + unsigned sizeFrameForForwardArguments(CallFrame* exec, VM&, unsigned numUsedStackSlots); void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length); void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length); void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length); + void setupForwardArgumentsFrame(CallFrame* execCaller, CallFrame* execCallee, uint32_t length); + void setupForwardArgumentsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length); } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/InterpreterInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/InterpreterInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/InterpreterInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/InterpreterInlines.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Yusuke Suzuki + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Instruction.h" +#include "Interpreter.h" +#include "UnlinkedCodeBlock.h" + +namespace JSC { + +inline OpcodeID Interpreter::getOpcodeID(const Instruction& instruction) +{ + return getOpcodeID(instruction.u.opcode); +} + +inline OpcodeID Interpreter::getOpcodeID(const UnlinkedInstruction& instruction) +{ + return instruction.u.opcode; +} + +} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/JSStack.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/JSStack.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/JSStack.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/JSStack.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2008, 2013, 2014, 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSStackInlines.h" - -#include "ConservativeRoots.h" -#include "Interpreter.h" -#include "JSCInlines.h" -#include "Options.h" -#include - -namespace JSC { - -#if !ENABLE(JIT) -static size_t committedBytesCount = 0; - -static size_t commitSize() -{ - static size_t size = std::max(16 * 1024, pageSize()); - return size; -} - -static StaticLock stackStatisticsMutex; -#endif // !ENABLE(JIT) - -JSStack::JSStack(VM& vm) - : m_vm(vm) - , m_topCallFrame(vm.topCallFrame) -#if !ENABLE(JIT) - , m_end(0) - , m_reservedZoneSizeInRegisters(0) -#endif -{ -#if !ENABLE(JIT) - size_t capacity = Options::maxPerThreadStackUsage(); - ASSERT(capacity && isPageAligned(capacity)); - - m_reservation = PageReservation::reserve(WTF::roundUpToMultipleOf(commitSize(), capacity), OSAllocator::JSVMStackPages); - setStackLimit(highAddress()); - m_commitTop = highAddress(); - - m_lastStackTop = baseOfStack(); -#endif // !ENABLE(JIT) - - m_topCallFrame = 0; -} - -#if !ENABLE(JIT) -JSStack::~JSStack() -{ - ptrdiff_t sizeToDecommit = reinterpret_cast(highAddress()) - reinterpret_cast(m_commitTop); - m_reservation.decommit(reinterpret_cast(m_commitTop), sizeToDecommit); - addToCommittedByteCount(-sizeToDecommit); - m_reservation.deallocate(); -} - -bool JSStack::growSlowCase(Register* newTopOfStack) -{ - Register* newTopOfStackWithReservedZone = newTopOfStack - m_reservedZoneSizeInRegisters; - - // If we have already committed enough memory to satisfy this request, - // just update the end pointer and return. - if (newTopOfStackWithReservedZone >= m_commitTop) { - setStackLimit(newTopOfStack); - return true; - } - - // Compute the chunk size of additional memory to commit, and see if we - // have it is still within our budget. If not, we'll fail to grow and - // return false. - ptrdiff_t delta = reinterpret_cast(m_commitTop) - reinterpret_cast(newTopOfStackWithReservedZone); - delta = WTF::roundUpToMultipleOf(commitSize(), delta); - Register* newCommitTop = m_commitTop - (delta / sizeof(Register)); - if (newCommitTop < reservationTop()) - return false; - - // Otherwise, the growth is still within our budget. Commit it and return true. - m_reservation.commit(newCommitTop, delta); - addToCommittedByteCount(delta); - m_commitTop = newCommitTop; - setStackLimit(newTopOfStack); - return true; -} - -void JSStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks) -{ - conservativeRoots.add(topOfStack() + 1, highAddress(), jitStubRoutines, codeBlocks); -} - -void JSStack::sanitizeStack() -{ -#if !ASAN_ENABLED - ASSERT(topOfStack() <= baseOfStack()); - - if (m_lastStackTop < topOfStack()) { - char* begin = reinterpret_cast(m_lastStackTop + 1); - char* end = reinterpret_cast(topOfStack() + 1); - memset(begin, 0, end - begin); - } - - m_lastStackTop = topOfStack(); -#endif -} - -void JSStack::releaseExcessCapacity() -{ - Register* highAddressWithReservedZone = highAddress() - m_reservedZoneSizeInRegisters; - ptrdiff_t delta = reinterpret_cast(highAddressWithReservedZone) - reinterpret_cast(m_commitTop); - m_reservation.decommit(m_commitTop, delta); - addToCommittedByteCount(-delta); - m_commitTop = highAddressWithReservedZone; -} - -void JSStack::addToCommittedByteCount(long byteCount) -{ - LockHolder locker(stackStatisticsMutex); - ASSERT(static_cast(committedBytesCount) + byteCount > -1); - committedBytesCount += byteCount; -} - -void JSStack::setReservedZoneSize(size_t reservedZoneSize) -{ - m_reservedZoneSizeInRegisters = reservedZoneSize / sizeof(Register); - if (m_commitTop >= (m_end + 1) - m_reservedZoneSizeInRegisters) - growSlowCase(m_end + 1); -} -#endif // !ENABLE(JIT) - -#if ENABLE(JIT) -Register* JSStack::lowAddress() const -{ - ASSERT(wtfThreadData().stack().isGrowingDownward()); - return reinterpret_cast(m_vm.stackLimit()); -} - -Register* JSStack::highAddress() const -{ - ASSERT(wtfThreadData().stack().isGrowingDownward()); - return reinterpret_cast(wtfThreadData().stack().origin()); -} -#endif // ENABLE(JIT) - -size_t JSStack::committedByteCount() -{ -#if !ENABLE(JIT) - LockHolder locker(stackStatisticsMutex); - return committedBytesCount; -#else - // When using the C stack, we don't know how many stack pages are actually - // committed. So, we use the current stack usage as an estimate. - ASSERT(wtfThreadData().stack().isGrowingDownward()); - int8_t* current = reinterpret_cast(¤t); - int8_t* high = reinterpret_cast(wtfThreadData().stack().origin()); - return high - current; -#endif -} - -} // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/JSStack.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/JSStack.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/JSStack.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/JSStack.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSStack_h -#define JSStack_h - -#include "ExecutableAllocator.h" -#include "Register.h" -#include -#include -#include - -namespace JSC { - - class CodeBlockSet; - class ConservativeRoots; - class ExecState; - class JITStubRoutineSet; - class VM; - class LLIntOffsetsExtractor; - - struct Instruction; - typedef ExecState CallFrame; - - struct CallerFrameAndPC { - CallFrame* callerFrame; - Instruction* pc; - }; - - class JSStack { - WTF_MAKE_NONCOPYABLE(JSStack); - public: - enum CallFrameHeaderEntry { - CallerFrameAndPCSize = sizeof(CallerFrameAndPC) / sizeof(Register), - CodeBlock = CallerFrameAndPCSize, - Callee, - ArgumentCount, - CallFrameHeaderSize, - - // The following entries are not part of the CallFrameHeader but are provided here as a convenience: - ThisArgument = CallFrameHeaderSize, - FirstArgument, - }; - - // Allow 8k of excess registers before we start trying to reap the stack - static const ptrdiff_t maxExcessCapacity = 8 * 1024; - - JSStack(VM&); - - bool ensureCapacityFor(Register* newTopOfStack); - - bool containsAddress(Register* address) { return (lowAddress() <= address && address < highAddress()); } - static size_t committedByteCount(); - -#if ENABLE(JIT) - void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&) { } - void sanitizeStack() { } -#else - ~JSStack(); - - void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&); - void sanitizeStack(); - - Register* baseOfStack() const - { - return highAddress() - 1; - } - - size_t size() const { return highAddress() - lowAddress(); } - - void setReservedZoneSize(size_t); - - inline Register* topOfStack(); -#endif // ENABLE(JIT) - - private: - -#if !ENABLE(JIT) - Register* lowAddress() const - { - return m_end + 1; - } - - Register* highAddress() const - { - return reinterpret_cast_ptr(static_cast(m_reservation.base()) + m_reservation.size()); - } -#else - Register* lowAddress() const; - Register* highAddress() const; -#endif // !ENABLE(JIT) - -#if !ENABLE(JIT) - inline Register* topOfFrameFor(CallFrame*); - - Register* reservationTop() const - { - char* reservationTop = static_cast(m_reservation.base()); - return reinterpret_cast_ptr(reservationTop); - } - - bool grow(Register* newTopOfStack); - bool growSlowCase(Register* newTopOfStack); - void shrink(Register* newTopOfStack); - void releaseExcessCapacity(); - void addToCommittedByteCount(long); - - void setStackLimit(Register* newTopOfStack); -#endif // !ENABLE(JIT) - - VM& m_vm; - CallFrame*& m_topCallFrame; -#if !ENABLE(JIT) - Register* m_end; - Register* m_commitTop; - PageReservation m_reservation; - Register* m_lastStackTop; - ptrdiff_t m_reservedZoneSizeInRegisters; -#endif // !ENABLE(JIT) - - friend class LLIntOffsetsExtractor; - }; - -} // namespace JSC - -#endif // JSStack_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/JSStackInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/JSStackInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/JSStackInlines.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/JSStackInlines.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSStackInlines_h -#define JSStackInlines_h - -#include "CallFrame.h" -#include "CodeBlock.h" -#include "JSStack.h" -#include "VM.h" - -namespace JSC { - -inline bool JSStack::ensureCapacityFor(Register* newTopOfStack) -{ -#if !ENABLE(JIT) - return grow(newTopOfStack); -#else - ASSERT(wtfThreadData().stack().isGrowingDownward()); - return newTopOfStack >= m_vm.stackLimit(); -#endif -} - -#if !ENABLE(JIT) - -inline Register* JSStack::topOfFrameFor(CallFrame* frame) -{ - if (UNLIKELY(!frame)) - return baseOfStack(); - return frame->topOfFrame() - 1; -} - -inline Register* JSStack::topOfStack() -{ - return topOfFrameFor(m_topCallFrame); -} - -inline void JSStack::shrink(Register* newTopOfStack) -{ - Register* newEnd = newTopOfStack - 1; - if (newEnd >= m_end) - return; - setStackLimit(newTopOfStack); - // Note: Clang complains of an unresolved linkage to maxExcessCapacity if - // invoke std::max() with it as an argument. To work around this, we first - // assign the constant to a local variable, and use the local instead. - ptrdiff_t maxExcessCapacity = JSStack::maxExcessCapacity; - ptrdiff_t maxExcessInRegisters = std::max(maxExcessCapacity, m_reservedZoneSizeInRegisters); - if (m_end == baseOfStack() && (highAddress() - m_commitTop) >= maxExcessInRegisters) - releaseExcessCapacity(); -} - -inline bool JSStack::grow(Register* newTopOfStack) -{ - Register* newEnd = newTopOfStack - 1; - if (newEnd >= m_end) - return true; - return growSlowCase(newTopOfStack); -} - -inline void JSStack::setStackLimit(Register* newTopOfStack) -{ - Register* newEnd = newTopOfStack - 1; - m_end = newEnd; - m_vm.setJSStackLimit(newTopOfStack); -} - -#endif // !ENABLE(JIT) - -} // namespace JSC - -#endif // JSStackInlines_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/ShadowChicken.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/ShadowChicken.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/ShadowChicken.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/ShadowChicken.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ShadowChicken.h" + +#include "CodeBlock.h" +#include "JSCInlines.h" +#include "ShadowChickenInlines.h" +#include + +namespace JSC { + +static const bool verbose = false; + +void ShadowChicken::Packet::dump(PrintStream& out) const +{ + if (!*this) { + out.print("empty"); + return; + } + + if (isPrologue()) { + out.print( + "{callee = ", RawPointer(callee), ", frame = ", RawPointer(frame), ", callerFrame = ", + RawPointer(callerFrame), "}"); + return; + } + + if (isTail()) { + out.print("tail-packet:{frame = ", RawPointer(frame), "}"); + return; + } + + ASSERT(isThrow()); + out.print("throw"); +} + +void ShadowChicken::Frame::dump(PrintStream& out) const +{ + out.print( + "{callee = ", RawPointer(callee), ", frame = ", RawPointer(frame), ", isTailDeleted = ", + isTailDeleted, "}"); +} + +ShadowChicken::ShadowChicken() + : m_logSize(Options::shadowChickenLogSize()) +{ + m_log = static_cast(fastZeroedMalloc(sizeof(Packet) * m_logSize)); + m_logCursor = m_log; + m_logEnd = m_log + m_logSize; +} + +ShadowChicken::~ShadowChicken() +{ + fastFree(m_log); +} + +void ShadowChicken::log(VM& vm, ExecState* exec, const Packet& packet) +{ + update(vm, exec); + *m_logCursor++ = packet; +} + +void ShadowChicken::update(VM&, ExecState* exec) +{ + if (verbose) { + dataLog("Running update on: ", *this, "\n"); + WTFReportBacktrace(); + } + + const unsigned logCursorIndex = m_logCursor - m_log; + + // We need to figure out how to reconcile the current machine stack with our shadow stack. We do + // that by figuring out how much of the shadow stack to pop. We apply three different rules. The + // precise rule relies on the log. The log contains caller frames, which means that we know + // where we bottomed out after making any call. If we bottomed out but made no calls then 'exec' + // will tell us. That's why "highestPointSinceLastTime" will go no lower than exec. The third + // rule, based on comparing to the current real stack, is executed in a later loop. + CallFrame* highestPointSinceLastTime = exec; + for (unsigned i = logCursorIndex; i--;) { + Packet packet = m_log[i]; + if (packet.isPrologue()) { + CallFrame* watermark; + if (i && m_log[i - 1].isTail()) + watermark = packet.frame; + else + watermark = packet.callerFrame; + highestPointSinceLastTime = std::max(highestPointSinceLastTime, watermark); + } + } + + if (verbose) + dataLog("Highest point since last time: ", RawPointer(highestPointSinceLastTime), "\n"); + + while (!m_stack.isEmpty() && (m_stack.last().frame < highestPointSinceLastTime || m_stack.last().isTailDeleted)) + m_stack.removeLast(); + + if (verbose) + dataLog(" Revised stack: ", listDump(m_stack), "\n"); + + // It's possible that the top of stack is now tail-deleted. The stack no longer contains any + // frames below the log's high watermark. That means that we just need to look for the first + // occurence of a tail packet for the current stack top. + if (!m_stack.isEmpty()) { + ASSERT(!m_stack.last().isTailDeleted); + for (unsigned i = 0; i < logCursorIndex; ++i) { + Packet& packet = m_log[i]; + if (packet.isTail() && packet.frame == m_stack.last().frame) { + Frame& frame = m_stack.last(); + frame.thisValue = packet.thisValue; + frame.scope = packet.scope; + frame.codeBlock = packet.codeBlock; + frame.callSiteIndex = packet.callSiteIndex; + frame.isTailDeleted = true; + break; + } + } + } + + + if (verbose) + dataLog(" Revised stack: ", listDump(m_stack), "\n"); + + // The log-based and exec-based rules require that ShadowChicken was enabled. The point of + // ShadowChicken is to give sensible-looking results even if we had not logged. This means that + // we need to reconcile the shadow stack and the real stack by actually looking at the real + // stack. This reconciliation allows the shadow stack to have extra tail-deleted frames, but it + // forbids it from diverging from the real stack on normal frames. + if (!m_stack.isEmpty()) { + Vector stackRightNow; + StackVisitor::visit( + exec, [&] (StackVisitor& visitor) -> StackVisitor::Status { + if (visitor->isInlinedFrame()) + return StackVisitor::Continue; + bool isTailDeleted = false; + stackRightNow.append(Frame(visitor->callee(), visitor->callFrame(), isTailDeleted)); + return StackVisitor::Continue; + }); + stackRightNow.reverse(); + + if (verbose) + dataLog(" Stack right now: ", listDump(stackRightNow), "\n"); + + unsigned shadowIndex = 0; + unsigned rightNowIndex = 0; + while (shadowIndex < m_stack.size() && rightNowIndex < stackRightNow.size()) { + if (m_stack[shadowIndex].isTailDeleted) { + shadowIndex++; + continue; + } + + // We specifically don't use operator== here because we are using a less + // strict filter on equality of frames. For example, the scope pointer + // could change, but we wouldn't want to consider the frames different entities + // because of that because it's natural for the program to change scopes. + if (m_stack[shadowIndex].frame == stackRightNow[rightNowIndex].frame + && m_stack[shadowIndex].callee == stackRightNow[rightNowIndex].callee) { + shadowIndex++; + rightNowIndex++; + continue; + } + break; + } + m_stack.resize(shadowIndex); + + if (verbose) + dataLog(" Revised stack: ", listDump(m_stack), "\n"); + } + + // It's possible that the top stack frame is actually lower than highestPointSinceLastTime. + // Account for that here. + highestPointSinceLastTime = nullptr; + for (unsigned i = m_stack.size(); i--;) { + if (!m_stack[i].isTailDeleted) { + highestPointSinceLastTime = m_stack[i].frame; + break; + } + } + + if (verbose) + dataLog(" Highest point since last time: ", RawPointer(highestPointSinceLastTime), "\n"); + + // Set everything up so that we know where the top frame is in the log. + unsigned indexInLog = logCursorIndex; + + auto advanceIndexInLogTo = [&] (CallFrame* frame, JSObject* callee, CallFrame* callerFrame) -> bool { + if (verbose) + dataLog(" Advancing to frame = ", RawPointer(frame), " from indexInLog = ", indexInLog, "\n"); + if (indexInLog > logCursorIndex) { + if (verbose) + dataLog(" Bailing.\n"); + return false; + } + + unsigned oldIndexInLog = indexInLog; + + while (indexInLog--) { + Packet packet = m_log[indexInLog]; + + // If all callees opt into ShadowChicken, then this search will rapidly terminate when + // we find our frame. But if our frame's callee didn't emit a prologue packet because it + // didn't opt in, then we will keep looking backwards until we *might* find a different + // frame. If we've been given the callee and callerFrame as a filter, then it's unlikely + // that we will hit the wrong frame. But we don't always have that information. + // + // This means it's worth adding other filters. For example, we could track changes in + // stack size. Once we've seen a frame at some height, we're no longer interested in + // frames below that height. Also, we can break as soon as we see a frame higher than + // the one we're looking for. + // FIXME: Add more filters. + // https://bugs.webkit.org/show_bug.cgi?id=155685 + + if (packet.isPrologue() && packet.frame == frame + && (!callee || packet.callee == callee) + && (!callerFrame || packet.callerFrame == callerFrame)) { + if (verbose) + dataLog(" Found at indexInLog = ", indexInLog, "\n"); + return true; + } + } + + // This is an interesting eventuality. We will see this if ShadowChicken was not + // consistently enabled. We have a choice between: + // + // - Leaving the log index at -1, which will prevent the log from being considered. This is + // the most conservative. It means that we will not be able to recover tail-deleted frames + // from anything that sits above a frame that didn't log a prologue packet. This means + // that everyone who creates prologues must log prologue packets. + // + // - Restoring the log index to what it was before. This prevents us from considering + // whether this frame has tail-deleted frames behind it, but that's about it. The problem + // with this approach is that it might recover tail-deleted frames that aren't relevant. + // I haven't thought about this too deeply, though. + // + // It seems like the latter option is less harmful, so that's what we do. + indexInLog = oldIndexInLog; + + if (verbose) + dataLog(" Didn't find it.\n"); + return false; + }; + + Vector toPush; + StackVisitor::visit( + exec, [&] (StackVisitor& visitor) -> StackVisitor::Status { + if (visitor->isInlinedFrame()) { + // FIXME: Handle inlining. + // https://bugs.webkit.org/show_bug.cgi?id=155686 + return StackVisitor::Continue; + } + + CallFrame* callFrame = visitor->callFrame(); + if (verbose) + dataLog(" Examining ", RawPointer(callFrame), "\n"); + if (callFrame == highestPointSinceLastTime) { + if (verbose) + dataLog(" Bailing at ", RawPointer(callFrame), " because it's the highest point since last time.\n"); + return StackVisitor::Done; + } + + bool foundFrame = advanceIndexInLogTo(callFrame, callFrame->callee(), callFrame->callerFrame()); + bool isTailDeleted = false; + JSScope* scope = nullptr; + CodeBlock* codeBlock = callFrame->codeBlock(); + if (codeBlock && codeBlock->wasCompiledWithDebuggingOpcodes() && codeBlock->scopeRegister().isValid()) { + scope = callFrame->scope(codeBlock->scopeRegister().offset()); + RELEASE_ASSERT(scope->inherits(JSScope::info())); + } else if (foundFrame) { + scope = m_log[indexInLog].scope; + if (scope) + RELEASE_ASSERT(scope->inherits(JSScope::info())); + } + toPush.append(Frame(visitor->callee(), callFrame, isTailDeleted, callFrame->thisValue(), scope, codeBlock, callFrame->callSiteIndex())); + + if (indexInLog < logCursorIndex + // This condition protects us from the case where advanceIndexInLogTo didn't find + // anything. + && m_log[indexInLog].frame == toPush.last().frame) { + if (verbose) + dataLog(" Going to loop through to find tail deleted frames with indexInLog = ", indexInLog, " and push-stack top = ", toPush.last(), "\n"); + for (;;) { + ASSERT(m_log[indexInLog].frame == toPush.last().frame); + + // Right now the index is pointing at a prologue packet of the last frame that + // we pushed. Peek behind that packet to see if there is a tail packet. If there + // is one then we know that there is a corresponding prologue packet that will + // tell us about a tail-deleted frame. + + if (!indexInLog) + break; + Packet tailPacket = m_log[indexInLog - 1]; + if (!tailPacket.isTail()) { + // Last frame that we recorded was not the outcome of a tail call. So, there + // will not be any more deleted frames. + // FIXME: We might want to have a filter here. Consider that this was a tail + // marker for a tail call to something that didn't log anything. It should + // be sufficient to give the tail marker a copy of the caller frame. + // https://bugs.webkit.org/show_bug.cgi?id=155687 + break; + } + indexInLog--; // Skip over the tail packet. + + if (!advanceIndexInLogTo(tailPacket.frame, nullptr, nullptr)) { + if (verbose) + dataLog("Can't find prologue packet for tail: ", RawPointer(tailPacket.frame), "\n"); + // We were unable to locate the prologue packet for this tail packet. + // This is rare but can happen in a situation like: + // function foo() { + // ... call some deeply tail-recursive function, causing a random number of log processings. + // return bar(); // tail call + // } + break; + } + Packet packet = m_log[indexInLog]; + bool isTailDeleted = true; + RELEASE_ASSERT(tailPacket.scope->inherits(JSScope::info())); + toPush.append(Frame(packet.callee, packet.frame, isTailDeleted, tailPacket.thisValue, tailPacket.scope, tailPacket.codeBlock, tailPacket.callSiteIndex)); + } + } + + return StackVisitor::Continue; + }); + + if (verbose) + dataLog(" Pushing: ", listDump(toPush), "\n"); + + for (unsigned i = toPush.size(); i--;) + m_stack.append(toPush[i]); + + // We want to reset the log. There is a fun corner-case: there could be a tail marker at the end + // of this log. We could make that work by setting isTailDeleted on the top of stack, but that + // would require more corner cases in the complicated reconciliation code above. That code + // already knows how to handle a tail packet at the beginning, so we just leverage that here. + if (logCursorIndex && m_log[logCursorIndex - 1].isTail()) { + m_log[0] = m_log[logCursorIndex - 1]; + m_logCursor = m_log + 1; + } else + m_logCursor = m_log; + + if (verbose) + dataLog(" After pushing: ", *this, "\n"); + + // Remove tail frames until the number of tail deleted frames is small enough. + const unsigned maxTailDeletedFrames = Options::shadowChickenMaxTailDeletedFramesSize(); + if (m_stack.size() > maxTailDeletedFrames) { + unsigned numberOfTailDeletedFrames = 0; + for (const Frame& frame : m_stack) { + if (frame.isTailDeleted) + numberOfTailDeletedFrames++; + } + if (numberOfTailDeletedFrames > maxTailDeletedFrames) { + unsigned dstIndex = 0; + unsigned srcIndex = 0; + while (srcIndex < m_stack.size()) { + Frame frame = m_stack[srcIndex++]; + if (numberOfTailDeletedFrames > maxTailDeletedFrames && frame.isTailDeleted) { + numberOfTailDeletedFrames--; + continue; + } + m_stack[dstIndex++] = frame; + } + m_stack.resize(dstIndex); + } + } + + if (verbose) + dataLog(" After clean-up: ", *this, "\n"); +} + +void ShadowChicken::visitChildren(SlotVisitor& visitor) +{ + for (unsigned i = m_logCursor - m_log; i--;) { + JSObject* callee = m_log[i].callee; + if (callee != Packet::tailMarker() && callee != Packet::throwMarker()) + visitor.appendUnbarrieredReadOnlyPointer(callee); + if (callee != Packet::throwMarker()) + visitor.appendUnbarrieredReadOnlyPointer(m_log[i].scope); + if (callee == Packet::tailMarker()) { + visitor.appendUnbarrieredValue(&m_log[i].thisValue); + visitor.appendUnbarrieredReadOnlyPointer(m_log[i].codeBlock); + } + } + + for (unsigned i = m_stack.size(); i--; ) { + Frame& frame = m_stack[i]; + visitor.appendUnbarrieredValue(&frame.thisValue); + visitor.appendUnbarrieredReadOnlyPointer(frame.callee); + if (frame.scope) + visitor.appendUnbarrieredReadOnlyPointer(frame.scope); + if (frame.codeBlock) + visitor.appendUnbarrieredReadOnlyPointer(frame.codeBlock); + } +} + +void ShadowChicken::reset() +{ + m_logCursor = m_log; + m_stack.clear(); +} + +void ShadowChicken::dump(PrintStream& out) const +{ + out.print("{stack = [", listDump(m_stack), "], log = ["); + + CommaPrinter comma; + unsigned limit = static_cast(m_logCursor - m_log); + out.print("\n"); + for (unsigned i = 0; i < limit; ++i) + out.print("\t", comma, m_log[i], "\n"); + out.print("]}"); +} + +JSArray* ShadowChicken::functionsOnStack(ExecState* exec) +{ + VM& vm = exec->vm(); + JSArray* result = constructEmptyArray(exec, 0); + if (UNLIKELY(vm.exception())) + return nullptr; + + iterate( + vm, exec, + [&] (const Frame& frame) -> bool { + result->push(exec, frame.callee); + return true; + }); + + return result; +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/ShadowChicken.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/ShadowChicken.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/ShadowChicken.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/ShadowChicken.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CallFrame.h" +#include "JSCJSValue.h" +#include +#include +#include +#include +#include + +namespace JSC { + +class CodeBlock; +class ExecState; +class JSArray; +class JSObject; +class JSScope; +class LLIntOffsetsExtractor; +class SlotVisitor; +class VM; + +typedef ExecState CallFrame; + +// ShadowChicken is a log that can be used to produce a shadow stack of CHICKEN-style stack frames. +// This enables the debugger to almost always see the tail-deleted stack frames, so long as we have +// memory inside ShadowChicken to remember them. +// +// The ShadowChicken log comprises packets that have one of two shapes: +// +// Prologue Packet, which has: +// - Callee object. +// - Frame pointer. +// - Caller frame pointer. +// +// Tail Call Packet, which has just: +// - Frame pointer. +// +// Prologue Packets are placed into the log in any JS function's prologue. Tail Call Packets are +// placed into the log just before making a proper tail call. We never log returns, since that would +// require a lot of infrastructure (unwinding, multiple ways of returning, etc). We don't need to +// see the returns because the prologue packets have a frame pointer. The tail call packets tell us +// when there was a tail call, and record the FP *before* the tail call. +// +// At any time it is possible to construct a shadow stack from the log and the actual machine stack. + +class ShadowChicken { + WTF_MAKE_NONCOPYABLE(ShadowChicken); + WTF_MAKE_FAST_ALLOCATED; +public: + struct Packet { + Packet() + { + } + + static const unsigned unlikelyValue = 0x7a11; + + static JSObject* tailMarker() + { + return bitwise_cast(static_cast(unlikelyValue)); + } + + static JSObject* throwMarker() + { + return bitwise_cast(static_cast(unlikelyValue + 1)); + } + + static Packet prologue(JSObject* callee, CallFrame* frame, CallFrame* callerFrame, JSScope* scope) + { + Packet result; + result.callee = callee; + result.frame = frame; + result.callerFrame = callerFrame; + result.scope = scope; + return result; + } + + static Packet tail(CallFrame* frame, JSValue thisValue, JSScope* scope, CodeBlock* codeBlock, CallSiteIndex callSiteIndex) + { + Packet result; + result.callee = tailMarker(); + result.frame = frame; + result.thisValue = thisValue; + result.scope = scope; + result.codeBlock = codeBlock; + result.callSiteIndex = callSiteIndex; + return result; + } + + static Packet throwPacket() + { + Packet result; + result.callee = throwMarker(); + return result; + } + + explicit operator bool() const { return !!callee; } + + bool isPrologue() const { return *this && callee != tailMarker() && callee != throwMarker(); } + bool isTail() const { return *this && callee == tailMarker(); } + bool isThrow() const { return *this && callee == throwMarker(); } + + void dump(PrintStream&) const; + + // Only tail packets have a valid thisValue, CodeBlock*, and CallSiteIndex. We grab 'this' and CodeBlock* from non tail-deleted frames from the machine frame. + JSValue thisValue { JSValue() }; + JSObject* callee { nullptr }; + CallFrame* frame { nullptr }; + CallFrame* callerFrame { nullptr }; + JSScope* scope { nullptr }; + CodeBlock* codeBlock { nullptr }; + CallSiteIndex callSiteIndex; + }; + + struct Frame { + Frame() + { + } + + Frame(JSObject* callee, CallFrame* frame, bool isTailDeleted, JSValue thisValue = JSValue(), JSScope* scope = nullptr, CodeBlock* codeBlock = nullptr, CallSiteIndex callSiteIndex = CallSiteIndex()) + : callee(callee) + , frame(frame) + , thisValue(thisValue) + , scope(scope) + , codeBlock(codeBlock) + , callSiteIndex(callSiteIndex) + , isTailDeleted(isTailDeleted) + { + } + + bool operator==(const Frame& other) const + { + return callee == other.callee + && frame == other.frame + && thisValue == other.thisValue + && scope == other.scope + && codeBlock == other.codeBlock + && callSiteIndex.bits() == other.callSiteIndex.bits() + && isTailDeleted == other.isTailDeleted; + } + + bool operator!=(const Frame& other) const + { + return !(*this == other); + } + + void dump(PrintStream&) const; + + // FIXME: This should be able to hold the moral equivalent of StackVisitor::Frame, so that + // we can support inlining. + // https://bugs.webkit.org/show_bug.cgi?id=155686 + JSObject* callee { nullptr }; + CallFrame* frame { nullptr }; + JSValue thisValue { JSValue() }; + JSScope* scope { nullptr }; + CodeBlock* codeBlock { nullptr }; + CallSiteIndex callSiteIndex; + bool isTailDeleted { false }; + }; + + ShadowChicken(); + ~ShadowChicken(); + + void log(VM& vm, ExecState* exec, const Packet&); + + void update(VM&, ExecState*); + + // Expects this signature: (const Frame& frame) -> bool. Return true to keep iterating. Return false to stop iterating. + // Note that this only works right with inlining disabled, but that's OK since for now we + // disable inlining when the inspector is attached. It would be easy to make this work with + // inlining, and would mostly require that we can request that StackVisitor doesn't skip tail + // frames. + template + void iterate(VM&, ExecState*, const Functor&); + + void visitChildren(SlotVisitor&); + void reset(); + + // JIT support. + Packet* log() const { return m_log; } + unsigned logSize() const { return m_logSize; } + Packet** addressOfLogCursor() { return &m_logCursor; } + Packet* logEnd() { return m_logEnd; } + + void dump(PrintStream&) const; + + JS_EXPORT_PRIVATE JSArray* functionsOnStack(ExecState*); + +private: + friend class LLIntOffsetsExtractor; + + Packet* m_log { nullptr }; + unsigned m_logSize { 0 }; + Packet* m_logCursor { nullptr }; + Packet* m_logEnd { nullptr }; + + Vector m_stack; +}; + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/ShadowChickenInlines.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/ShadowChickenInlines.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/ShadowChickenInlines.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/ShadowChickenInlines.h 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSCInlines.h" +#include "ShadowChicken.h" + +namespace JSC { + +template +void ShadowChicken::iterate(VM& vm, ExecState* exec, const Functor& functor) +{ + DeferGC deferGC(exec->vm().heap); + + update(vm, exec); + + for (unsigned i = m_stack.size(); i--;) { + if (!functor(m_stack[i])) + break; + } +} + +} // namespace JSC + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/StackVisitor.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/StackVisitor.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/StackVisitor.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/StackVisitor.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,7 @@ #include "StackVisitor.h" #include "ClonedArguments.h" +#include "DebuggerPrimitives.h" #include "Executable.h" #include "InlineCallFrame.h" #include "Interpreter.h" @@ -42,6 +43,11 @@ if (startFrame) { m_frame.m_VMEntryFrame = startFrame->vm().topVMEntryFrame; topFrame = startFrame->vm().topCallFrame; + + if (topFrame && static_cast(m_frame.m_VMEntryFrame) == static_cast(topFrame)) { + topFrame = vmEntryRecord(m_frame.m_VMEntryFrame)->m_prevTopCallFrame; + m_frame.m_VMEntryFrame = vmEntryRecord(m_frame.m_VMEntryFrame)->m_prevTopVMEntryFrame; + } } else { m_frame.m_VMEntryFrame = 0; topFrame = 0; @@ -56,6 +62,7 @@ void StackVisitor::gotoNextFrame() { + m_frame.m_index++; #if ENABLE(DFG_JIT) if (m_frame.isInlinedFrame()) { InlineCallFrame* inlineCallFrame = m_frame.inlineCallFrame(); @@ -79,8 +86,12 @@ void StackVisitor::unwindToMachineCodeBlockFrame() { #if ENABLE(DFG_JIT) - while (m_frame.isInlinedFrame()) - gotoNextFrame(); + if (m_frame.isInlinedFrame()) { + CodeOrigin codeOrigin = m_frame.inlineCallFrame()->directCaller; + while (codeOrigin.inlineCallFrame) + codeOrigin = codeOrigin.inlineCallFrame->directCaller; + readNonInlinedFrame(m_frame.callFrame(), &codeOrigin); + } #endif } @@ -207,7 +218,7 @@ return CodeType::Global; } -String StackVisitor::Frame::functionName() +String StackVisitor::Frame::functionName() const { String traceLine; JSObject* callee = this->callee(); @@ -221,10 +232,10 @@ break; case CodeType::Native: if (callee) - traceLine = getCalculatedDisplayName(callFrame(), callee).impl(); + traceLine = getCalculatedDisplayName(callFrame()->vm(), callee).impl(); break; case CodeType::Function: - traceLine = getCalculatedDisplayName(callFrame(), callee).impl(); + traceLine = getCalculatedDisplayName(callFrame()->vm(), callee).impl(); break; case CodeType::Global: traceLine = ASCIILiteral("global code"); @@ -233,7 +244,7 @@ return traceLine.isNull() ? emptyString() : traceLine; } -String StackVisitor::Frame::sourceURL() +String StackVisitor::Frame::sourceURL() const { String traceLine; @@ -254,7 +265,7 @@ return traceLine.isNull() ? emptyString() : traceLine; } -String StackVisitor::Frame::toString() +String StackVisitor::Frame::toString() const { StringBuilder traceBuild; String functionName = this->functionName(); @@ -277,6 +288,13 @@ return traceBuild.toString().impl(); } +intptr_t StackVisitor::Frame::sourceID() +{ + if (CodeBlock* codeBlock = this->codeBlock()) + return codeBlock->ownerScriptExecutable()->sourceID(); + return noSourceID; +} + ClonedArguments* StackVisitor::Frame::createArguments() { ASSERT(m_callFrame); @@ -297,7 +315,7 @@ return arguments; } -void StackVisitor::Frame::computeLineAndColumn(unsigned& line, unsigned& column) +void StackVisitor::Frame::computeLineAndColumn(unsigned& line, unsigned& column) const { CodeBlock* codeBlock = this->codeBlock(); if (!codeBlock) { @@ -320,7 +338,7 @@ line = codeBlock->ownerScriptExecutable()->overrideLineNumber(); } -void StackVisitor::Frame::retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) +void StackVisitor::Frame::retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const { CodeBlock* codeBlock = this->codeBlock(); codeBlock->unlinkedCodeBlock()->expressionRangeForBytecodeOffset(bytecodeOffset(), divot, startOffset, endOffset, line, column); @@ -335,46 +353,22 @@ #endif } -static void printIndents(int levels) -{ - while (levels--) - dataLogFString(" "); -} - -template -void log(unsigned indent, const Types&... values) +void StackVisitor::Frame::dump(PrintStream& out, Indenter indent) const { - printIndents(indent); - dataLog(values...); -} - -template -void logF(unsigned indent, const char* format, const Types&... values) -{ - printIndents(indent); - -#if COMPILER(GCC_OR_CLANG) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" -#pragma GCC diagnostic ignored "-Wmissing-format-attribute" -#endif - - dataLogF(format, values...); - -#if COMPILER(GCC_OR_CLANG) -#pragma GCC diagnostic pop -#endif + dump(out, indent, [] (PrintStream&) { }); } -void StackVisitor::Frame::print(int indent) +void StackVisitor::Frame::dump(PrintStream& out, Indenter indent, std::function prefix) const { if (!this->callFrame()) { - log(indent, "frame 0x0\n"); + out.print(indent, "frame 0x0\n"); return; } CodeBlock* codeBlock = this->codeBlock(); - logF(indent, "frame %p {\n", this->callFrame()); + out.print(indent); + prefix(out); + out.print("frame ", RawPointer(this->callFrame()), " {\n"); { indent++; @@ -383,43 +377,46 @@ CallFrame* callerFrame = this->callerFrame(); void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : nullptr; - log(indent, "name: ", functionName(), "\n"); - log(indent, "sourceURL: ", sourceURL(), "\n"); + out.print(indent, "name: ", functionName(), "\n"); + out.print(indent, "sourceURL: ", sourceURL(), "\n"); bool isInlined = false; #if ENABLE(DFG_JIT) isInlined = isInlinedFrame(); - log(indent, "isInlinedFrame: ", isInlinedFrame(), "\n"); + out.print(indent, "isInlinedFrame: ", isInlinedFrame(), "\n"); if (isInlinedFrame()) - logF(indent, "InlineCallFrame: %p\n", m_inlineCallFrame); + out.print(indent, "InlineCallFrame: ", RawPointer(m_inlineCallFrame), "\n"); #endif - logF(indent, "callee: %p\n", callee()); - logF(indent, "returnPC: %p\n", returnPC); - logF(indent, "callerFrame: %p\n", callerFrame); + out.print(indent, "callee: ", RawPointer(callee()), "\n"); + out.print(indent, "returnPC: ", RawPointer(returnPC), "\n"); + out.print(indent, "callerFrame: ", RawPointer(callerFrame), "\n"); unsigned locationRawBits = callFrame->callSiteAsRawBits(); - logF(indent, "rawLocationBits: %u 0x%x\n", locationRawBits, locationRawBits); - logF(indent, "codeBlock: %p ", codeBlock); + out.print(indent, "rawLocationBits: ", static_cast(locationRawBits), + " ", RawPointer(reinterpret_cast(locationRawBits)), "\n"); + out.print(indent, "codeBlock: ", RawPointer(codeBlock)); if (codeBlock) - dataLog(*codeBlock); - dataLog("\n"); + out.print(*codeBlock); + out.print("\n"); if (codeBlock && !isInlined) { indent++; if (callFrame->callSiteBitsAreBytecodeOffset()) { unsigned bytecodeOffset = callFrame->bytecodeOffset(); - log(indent, "bytecodeOffset: ", bytecodeOffset, " of ", codeBlock->instructions().size(), "\n"); + out.print(indent, "bytecodeOffset: ", bytecodeOffset, " of ", codeBlock->instructions().size(), "\n"); #if ENABLE(DFG_JIT) } else { - log(indent, "hasCodeOrigins: ", codeBlock->hasCodeOrigins(), "\n"); + out.print(indent, "hasCodeOrigins: ", codeBlock->hasCodeOrigins(), "\n"); if (codeBlock->hasCodeOrigins()) { CallSiteIndex callSiteIndex = callFrame->callSiteIndex(); - log(indent, "callSiteIndex: ", callSiteIndex.bits(), " of ", codeBlock->codeOrigins().size(), "\n"); + out.print(indent, "callSiteIndex: ", callSiteIndex.bits(), " of ", codeBlock->codeOrigins().size(), "\n"); JITCode::JITType jitType = codeBlock->jitType(); if (jitType != JITCode::FTLJIT) { JITCode* jitCode = codeBlock->jitCode().get(); - logF(indent, "jitCode: %p start %p end %p\n", jitCode, jitCode->start(), jitCode->end()); + out.print(indent, "jitCode: ", RawPointer(jitCode), + " start ", RawPointer(jitCode->start()), + " end ", RawPointer(jitCode->end()), "\n"); } } #endif @@ -427,14 +424,15 @@ unsigned line = 0; unsigned column = 0; computeLineAndColumn(line, column); - log(indent, "line: ", line, "\n"); - log(indent, "column: ", column, "\n"); + out.print(indent, "line: ", line, "\n"); + out.print(indent, "column: ", column, "\n"); indent--; } + out.print(indent, "vmEntryFrame: ", RawPointer(vmEntryFrame()), "\n"); indent--; } - log(indent, "}\n"); + out.print(indent, "}\n"); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/StackVisitor.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/StackVisitor.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/StackVisitor.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/StackVisitor.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,8 @@ #define StackVisitor_h #include "VMEntryRecord.h" +#include +#include #include namespace JSC { @@ -63,33 +65,38 @@ JSObject* callee() const { return m_callee; } CodeBlock* codeBlock() const { return m_codeBlock; } unsigned bytecodeOffset() const { return m_bytecodeOffset; } + InlineCallFrame* inlineCallFrame() const { #if ENABLE(DFG_JIT) - InlineCallFrame* inlineCallFrame() const { return m_inlineCallFrame; } + return m_inlineCallFrame; +#else + return nullptr; #endif + } bool isJSFrame() const { return !!codeBlock(); } -#if ENABLE(DFG_JIT) - bool isInlinedFrame() const { return !!m_inlineCallFrame; } -#endif + bool isInlinedFrame() const { return !!inlineCallFrame(); } + + JS_EXPORT_PRIVATE String functionName() const; + JS_EXPORT_PRIVATE String sourceURL() const; + JS_EXPORT_PRIVATE String toString() const; - JS_EXPORT_PRIVATE String functionName(); - JS_EXPORT_PRIVATE String sourceURL(); - JS_EXPORT_PRIVATE String toString(); + intptr_t sourceID(); CodeType codeType() const; - JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column); + JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column) const; ClonedArguments* createArguments(); VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; } CallFrame* callFrame() const { return m_callFrame; } - JS_EXPORT_PRIVATE void print(int indentLevel); + void dump(PrintStream&, Indenter = Indenter()) const; + void dump(PrintStream&, Indenter, std::function prefix) const; private: Frame() { } ~Frame() { } - void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column); + void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const; void setToEnd(); size_t m_index; @@ -115,10 +122,10 @@ }; // StackVisitor::visit() expects a Functor that implements the following method: - // Status operator()(StackVisitor&); + // Status operator()(StackVisitor&) const; template - static void visit(CallFrame* startFrame, Functor& functor) + static void visit(CallFrame* startFrame, const Functor& functor) { StackVisitor visitor(startFrame); while (visitor->callFrame()) { @@ -157,7 +164,7 @@ CallFrame* callerFrame() const { return m_callerFrame; } - StackVisitor::Status operator()(StackVisitor& visitor) + StackVisitor::Status operator()(StackVisitor& visitor) const { if (!m_hasSkippedFirstFrame) { m_hasSkippedFirstFrame = true; @@ -169,8 +176,8 @@ } private: - bool m_hasSkippedFirstFrame; - CallFrame* m_callerFrame; + mutable bool m_hasSkippedFirstFrame; + mutable CallFrame* m_callerFrame; }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/VMEntryRecord.h webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/VMEntryRecord.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/interpreter/VMEntryRecord.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/interpreter/VMEntryRecord.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,10 +26,11 @@ #ifndef VMEntryRecord_h #define VMEntryRecord_h -namespace JSC { +#include "GPRInfo.h" -typedef void VMEntryFrame; +namespace JSC { +struct VMEntryFrame; class ExecState; class VM; @@ -42,6 +43,10 @@ ExecState* m_prevTopCallFrame; VMEntryFrame* m_prevTopVMEntryFrame; +#if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 + intptr_t calleeSaveRegistersBuffer[NUMBER_OF_CALLEE_SAVES_REGISTERS]; +#endif + ExecState* prevTopCallFrame() { return m_prevTopCallFrame; } SUPPRESS_ASAN ExecState* unsafePrevTopCallFrame() { return m_prevTopCallFrame; } @@ -51,6 +56,23 @@ extern "C" VMEntryRecord* vmEntryRecord(VMEntryFrame*); +struct VMEntryFrame { +#if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 + static ptrdiff_t vmEntryRecordOffset() + { + VMEntryFrame* fakeVMEntryFrame = reinterpret_cast(0x1000); + VMEntryRecord* record = vmEntryRecord(fakeVMEntryFrame); + return static_cast( + reinterpret_cast(record) - reinterpret_cast(fakeVMEntryFrame)); + } + + static ptrdiff_t calleeSaveRegistersBufferOffset() + { + return vmEntryRecordOffset() + OBJECT_OFFSETOF(VMEntryRecord, calleeSaveRegistersBuffer); + } +#endif +}; + } // namespace JSC #endif // VMEntryRecord_h diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/AssemblyHelpers.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/AssemblyHelpers.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/AssemblyHelpers.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/AssemblyHelpers.cpp 2016-10-13 08:26:50.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,7 @@ #include "JITOperations.h" #include "JSCInlines.h" +#include "LinkBuffer.h" namespace JSC { @@ -148,17 +149,16 @@ TrustedImm32(FastTypedArray)); } -AssemblyHelpers::Jump AssemblyHelpers::loadTypedArrayVector(GPRReg baseGPR, GPRReg resultGPR) +void AssemblyHelpers::incrementSuperSamplerCount() { - RELEASE_ASSERT(baseGPR != resultGPR); - - loadPtr(Address(baseGPR, JSArrayBufferView::offsetOfVector()), resultGPR); - Jump ok = branchIfToSpace(resultGPR); - Jump result = branchIfFastTypedArray(baseGPR); - ok.link(this); - return result; + add32(TrustedImm32(1), AbsoluteAddress(bitwise_cast(&g_superSamplerCount))); } +void AssemblyHelpers::decrementSuperSamplerCount() +{ + sub32(TrustedImm32(1), AbsoluteAddress(bitwise_cast(&g_superSamplerCount))); +} + void AssemblyHelpers::purifyNaN(FPRReg fpr) { MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr); @@ -294,7 +294,7 @@ void AssemblyHelpers::jitAssertArgumentCountSane() { - Jump ok = branch32(Below, payloadFor(JSStack::ArgumentCount), TrustedImm32(10000000)); + Jump ok = branch32(Below, payloadFor(CallFrameSlot::argumentCount), TrustedImm32(10000000)); abortWithReason(AHInsaneArgumentCount); ok.link(this); } @@ -420,6 +420,56 @@ #endif } +void AssemblyHelpers::loadProperty(GPRReg object, GPRReg offset, JSValueRegs result) +{ + Jump isInline = branch32(LessThan, offset, TrustedImm32(firstOutOfLineOffset)); + + loadPtr(Address(object, JSObject::butterflyOffset()), result.payloadGPR()); + neg32(offset); + signExtend32ToPtr(offset, offset); + Jump ready = jump(); + + isInline.link(this); + addPtr( + TrustedImm32( + static_cast(sizeof(JSObject)) - + (static_cast(firstOutOfLineOffset) - 2) * static_cast(sizeof(EncodedJSValue))), + object, result.payloadGPR()); + + ready.link(this); + + loadValue( + BaseIndex( + result.payloadGPR(), offset, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), + result); +} + +void AssemblyHelpers::emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch) +{ +#if USE(JSVALUE64) + load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); + loadPtr(vm()->heap.structureIDTable().base(), scratch); + loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest); +#else + UNUSED_PARAM(scratch); + loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); +#endif +} + +void AssemblyHelpers::makeSpaceOnStackForCCall() +{ + unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall); + if (stackOffset) + subPtr(TrustedImm32(stackOffset), stackPointerRegister); +} + +void AssemblyHelpers::reclaimSpaceOnStackForCCall() +{ + unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall); + if (stackOffset) + addPtr(TrustedImm32(stackOffset), stackPointerRegister); +} + #if USE(JSVALUE64) template void emitRandomThunkImpl(AssemblyHelpers& jit, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result, const LoadFromHigh& loadFromHigh, const StoreToHigh& storeToHigh, const LoadFromLow& loadFromLow, const StoreToLow& storeToLow) @@ -495,7 +545,7 @@ void AssemblyHelpers::emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result) { - emitGetFromCallFrameHeaderPtr(JSStack::Callee, scratch3); + emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, scratch3); emitLoadStructure(scratch3, scratch3, scratch0); loadPtr(Address(scratch3, Structure::globalObjectOffset()), scratch3); // Now, scratch3 holds JSGlobalObject*. @@ -517,27 +567,199 @@ } #endif -void AssemblyHelpers::restoreCalleeSavesFromVMCalleeSavesBuffer() +void AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer() { #if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 - char* sourceBuffer = bitwise_cast(m_vm->calleeSaveRegistersBuffer); - RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets(); RegisterSet dontRestoreRegisters = RegisterSet::stackRegisters(); unsigned registerCount = allCalleeSaves->size(); - + + GPRReg scratch = InvalidGPRReg; + unsigned scratchGPREntryIndex = 0; + + // Use the first GPR entry's register as our scratch. for (unsigned i = 0; i < registerCount; i++) { RegisterAtOffset entry = allCalleeSaves->at(i); if (dontRestoreRegisters.get(entry.reg())) continue; - if (entry.reg().isGPR()) - loadPtr(static_cast(sourceBuffer + entry.offset()), entry.reg().gpr()); - else - loadDouble(TrustedImmPtr(sourceBuffer + entry.offset()), entry.reg().fpr()); + if (entry.reg().isGPR()) { + scratchGPREntryIndex = i; + scratch = entry.reg().gpr(); + break; + } } + ASSERT(scratch != InvalidGPRReg); + + loadPtr(&m_vm->topVMEntryFrame, scratch); + addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), scratch); + + // Restore all callee saves except for the scratch. + for (unsigned i = 0; i < registerCount; i++) { + RegisterAtOffset entry = allCalleeSaves->at(i); + if (dontRestoreRegisters.get(entry.reg())) + continue; + if (entry.reg().isGPR()) { + if (i != scratchGPREntryIndex) + loadPtr(Address(scratch, entry.offset()), entry.reg().gpr()); + } else + loadDouble(Address(scratch, entry.offset()), entry.reg().fpr()); + } + + // Restore the callee save value of the scratch. + RegisterAtOffset entry = allCalleeSaves->at(scratchGPREntryIndex); + ASSERT(!dontRestoreRegisters.get(entry.reg())); + ASSERT(entry.reg().isGPR()); + ASSERT(scratch == entry.reg().gpr()); + loadPtr(Address(scratch, entry.offset()), scratch); #endif } +void AssemblyHelpers::emitDumbVirtualCall(CallLinkInfo* info) +{ + move(TrustedImmPtr(info), GPRInfo::regT2); + Call call = nearCall(); + addLinkTask( + [=] (LinkBuffer& linkBuffer) { + MacroAssemblerCodeRef virtualThunk = virtualThunkFor(&linkBuffer.vm(), *info); + info->setSlowStub(createJITStubRoutine(virtualThunk, linkBuffer.vm(), nullptr, true)); + linkBuffer.link(call, CodeLocationLabel(virtualThunk.code())); + }); +} + +#if USE(JSVALUE64) +void AssemblyHelpers::wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch) +{ + GPRReg input = inputAndResult; + // key += ~(key << 32); + move(input, scratch); + lshift64(TrustedImm32(32), scratch); + not64(scratch); + add64(scratch, input); + // key ^= (key >> 22); + move(input, scratch); + urshift64(TrustedImm32(22), scratch); + xor64(scratch, input); + // key += ~(key << 13); + move(input, scratch); + lshift64(TrustedImm32(13), scratch); + not64(scratch); + add64(scratch, input); + // key ^= (key >> 8); + move(input, scratch); + urshift64(TrustedImm32(8), scratch); + xor64(scratch, input); + // key += (key << 3); + move(input, scratch); + lshift64(TrustedImm32(3), scratch); + add64(scratch, input); + // key ^= (key >> 15); + move(input, scratch); + urshift64(TrustedImm32(15), scratch); + xor64(scratch, input); + // key += ~(key << 27); + move(input, scratch); + lshift64(TrustedImm32(27), scratch); + not64(scratch); + add64(scratch, input); + // key ^= (key >> 31); + move(input, scratch); + urshift64(TrustedImm32(31), scratch); + xor64(scratch, input); + + // return static_cast(result) + void* mask = bitwise_cast(static_cast(UINT_MAX)); + and64(TrustedImmPtr(mask), inputAndResult); +} +#endif // USE(JSVALUE64) + +void AssemblyHelpers::emitConvertValueToBoolean(JSValueRegs value, GPRReg result, GPRReg scratch, FPRReg valueAsFPR, FPRReg tempFPR, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject, bool negateResult) +{ + // Implements the following control flow structure: + // if (value is boolean) { + // result = value === true + // } else if (value is integer) { + // result = value !== 0 + // } else if (value is double) { + // result = value !== 0.0 && !isNaN(value); + // } else if (value is cell) { + // if (value is string) { + // result = value.length() !== 0; + // } else { + // do crazy things for masquerades as undefined + // } + // } else { + // result = false; + // } + // + // if (negateResult) + // result = !result; + + JumpList done; + auto notBoolean = branchIfNotBoolean(value, result); +#if USE(JSVALUE64) + compare32(negateResult ? NotEqual : Equal, value.gpr(), TrustedImm32(ValueTrue), result); +#else + compare32(negateResult ? Equal : NotEqual, value.payloadGPR(), TrustedImm32(0), result); +#endif + done.append(jump()); + + notBoolean.link(this); +#if USE(JSVALUE64) + auto isNotNumber = branchIfNotNumber(value.gpr()); +#else + ASSERT(scratch != InvalidGPRReg); + auto isNotNumber = branchIfNotNumber(value, scratch); +#endif + auto isDouble = branchIfNotInt32(value); + + // It's an int32. + compare32(negateResult ? Equal : NotEqual, value.payloadGPR(), TrustedImm32(0), result); + done.append(jump()); + + isDouble.link(this); +#if USE(JSVALUE64) + unboxDouble(value.gpr(), result, valueAsFPR); +#else + unboxDouble(value, valueAsFPR, tempFPR); +#endif + auto isZeroOrNaN = branchDoubleZeroOrNaN(valueAsFPR, tempFPR); + move(negateResult ? TrustedImm32(0) : TrustedImm32(1), result); + done.append(jump()); + isZeroOrNaN.link(this); + move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result); + done.append(jump()); + + isNotNumber.link(this); + auto isNotCellAndIsNotNumberAndIsNotBoolean = branchIfNotCell(value); + auto isCellButNotString = branch8(NotEqual, + Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)); + load32(Address(value.payloadGPR(), JSString::offsetOfLength()), result); + compare32(negateResult ? Equal : NotEqual, result, TrustedImm32(0), result); + done.append(jump()); + + isCellButNotString.link(this); + if (shouldCheckMasqueradesAsUndefined) { + ASSERT(scratch != InvalidGPRReg); + JumpList isNotMasqueradesAsUndefined; + isNotMasqueradesAsUndefined.append(branchTest8(Zero, Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined))); + emitLoadStructure(value.payloadGPR(), result, scratch); + move(TrustedImmPtr(globalObject), scratch); + isNotMasqueradesAsUndefined.append(branchPtr(NotEqual, Address(result, Structure::globalObjectOffset()), scratch)); + // We act like we are "undefined" here. + move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result); + done.append(jump()); + isNotMasqueradesAsUndefined.link(this); + } + move(negateResult ? TrustedImm32(0) : TrustedImm32(1), result); + done.append(jump()); + + // null or undefined. + isNotCellAndIsNotNumberAndIsNotBoolean.link(this); + move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result); + + done.link(this); +} + } // namespace JSC #endif // ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/AssemblyHelpers.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/AssemblyHelpers.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/AssemblyHelpers.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/AssemblyHelpers.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,12 +32,15 @@ #include "CopyBarrier.h" #include "FPRInfo.h" #include "GPRInfo.h" +#include "Heap.h" #include "InlineCallFrame.h" #include "JITCode.h" #include "MacroAssembler.h" +#include "MarkedSpace.h" #include "MaxFrameExtentForSlowPathCall.h" #include "RegisterAtOffsetList.h" #include "RegisterSet.h" +#include "SuperSampler.h" #include "TypeofType.h" #include "VM.h" @@ -58,7 +61,7 @@ ASSERT(m_baselineCodeBlock->jitType() == JITCode::None || JITCode::isBaselineCode(m_baselineCodeBlock->jitType())); } } - + CodeBlock* codeBlock() { return m_codeBlock; } VM* vm() { return m_vm; } AssemblerType_T& assembler() { return m_assembler; } @@ -84,6 +87,15 @@ #endif } + void loadCell(Address address, GPRReg gpr) + { +#if USE(JSVALUE64) + load64(address, gpr); +#else + load32(address.withOffset(PayloadOffset), gpr); +#endif + } + void storeValue(JSValueRegs regs, Address address) { #if USE(JSVALUE64) @@ -148,13 +160,27 @@ } #endif } + + // Note that this clobbers offset. + void loadProperty(GPRReg object, GPRReg offset, JSValueRegs result); void moveValueRegs(JSValueRegs srcRegs, JSValueRegs destRegs) { #if USE(JSVALUE32_64) + if (destRegs.tagGPR() == srcRegs.payloadGPR()) { + if (destRegs.payloadGPR() == srcRegs.tagGPR()) { + swap(srcRegs.payloadGPR(), srcRegs.tagGPR()); + return; + } + move(srcRegs.payloadGPR(), destRegs.payloadGPR()); + move(srcRegs.tagGPR(), destRegs.tagGPR()); + return; + } move(srcRegs.tagGPR(), destRegs.tagGPR()); -#endif move(srcRegs.payloadGPR(), destRegs.payloadGPR()); +#else + move(srcRegs.gpr(), destRegs.gpr()); +#endif } void moveValue(JSValue value, JSValueRegs regs) @@ -270,17 +296,43 @@ emitSaveCalleeSavesFor(codeBlock()); } + void emitSaveThenMaterializeTagRegisters() + { +#if USE(JSVALUE64) +#if CPU(ARM64) + pushPair(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister); +#else + push(GPRInfo::tagTypeNumberRegister); + push(GPRInfo::tagMaskRegister); +#endif + emitMaterializeTagCheckRegisters(); +#endif + } + void emitRestoreCalleeSaves() { emitRestoreCalleeSavesFor(codeBlock()); } - void copyCalleeSavesToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() }) + void emitRestoreSavedTagRegisters() + { +#if USE(JSVALUE64) +#if CPU(ARM64) + popPair(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister); +#else + pop(GPRInfo::tagMaskRegister); + pop(GPRInfo::tagTypeNumberRegister); +#endif +#endif + } + + void copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() }) { #if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 GPRReg temp1 = usedRegisters.getFreeGPR(0); - move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1); + loadPtr(&m_vm->topVMEntryFrame, temp1); + addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), temp1); RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets(); RegisterSet dontCopyRegisters = RegisterSet::stackRegisters(); @@ -300,9 +352,9 @@ #endif } - void restoreCalleeSavesFromVMCalleeSavesBuffer(); + void restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(); - void copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() }) + void copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::stubUnavailableRegisters() }) { #if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0 GPRReg temp1 = usedRegisters.getFreeGPR(0); @@ -313,7 +365,8 @@ ASSERT(codeBlock()); // Copy saved calleeSaves on stack or unsaved calleeSaves in register to vm calleeSave buffer - move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1); + loadPtr(&m_vm->topVMEntryFrame, temp1); + addPtr(TrustedImm32(VMEntryFrame::calleeSaveRegistersBufferOffset()), temp1); RegisterAtOffsetList* allCalleeSaves = m_vm->getAllCalleeSaveRegisterOffsets(); RegisterAtOffsetList* currentCalleeSaves = codeBlock()->calleeSaveRegisters(); @@ -520,26 +573,26 @@ } #endif - void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister) + void emitGetFromCallFrameHeaderPtr(int entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister) { loadPtr(Address(from, entry * sizeof(Register)), to); } - void emitGetFromCallFrameHeader32(JSStack::CallFrameHeaderEntry entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister) + void emitGetFromCallFrameHeader32(int entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister) { load32(Address(from, entry * sizeof(Register)), to); } #if USE(JSVALUE64) - void emitGetFromCallFrameHeader64(JSStack::CallFrameHeaderEntry entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister) + void emitGetFromCallFrameHeader64(int entry, GPRReg to, GPRReg from = GPRInfo::callFrameRegister) { load64(Address(from, entry * sizeof(Register)), to); } #endif // USE(JSVALUE64) - void emitPutToCallFrameHeader(GPRReg from, JSStack::CallFrameHeaderEntry entry) + void emitPutToCallFrameHeader(GPRReg from, int entry) { storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register))); } - void emitPutToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry) + void emitPutToCallFrameHeader(void* value, int entry) { storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register))); } @@ -569,17 +622,17 @@ // caller's frame pointer. On some platforms, the callee is responsible for pushing the // "link register" containing the return address in the function prologue. #if USE(JSVALUE64) - void emitPutToCallFrameHeaderBeforePrologue(GPRReg from, JSStack::CallFrameHeaderEntry entry) + void emitPutToCallFrameHeaderBeforePrologue(GPRReg from, int entry) { storePtr(from, Address(stackPointerRegister, entry * static_cast(sizeof(Register)) - prologueStackPointerDelta())); } #else - void emitPutPayloadToCallFrameHeaderBeforePrologue(GPRReg from, JSStack::CallFrameHeaderEntry entry) + void emitPutPayloadToCallFrameHeaderBeforePrologue(GPRReg from, int entry) { storePtr(from, Address(stackPointerRegister, entry * static_cast(sizeof(Register)) - prologueStackPointerDelta() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); } - void emitPutTagToCallFrameHeaderBeforePrologue(TrustedImm32 tag, JSStack::CallFrameHeaderEntry entry) + void emitPutTagToCallFrameHeaderBeforePrologue(TrustedImm32 tag, int entry) { storePtr(tag, Address(stackPointerRegister, entry * static_cast(sizeof(Register)) - prologueStackPointerDelta() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); } @@ -615,11 +668,6 @@ #endif } - enum TagRegistersMode { - DoNotHaveTagRegisters, - HaveTagRegisters - }; - Jump branchIfNotCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters) { #if USE(JSVALUE64) @@ -720,28 +768,54 @@ { #if USE(JSVALUE64) UNUSED_PARAM(tempGPR); - if (mode == HaveTagRegisters) - return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister); - return branchTest64(NonZero, regs.gpr(), TrustedImm64(TagTypeNumber)); + return branchIfNumber(regs.gpr(), mode); #else UNUSED_PARAM(mode); add32(TrustedImm32(1), regs.tagGPR(), tempGPR); return branch32(Below, tempGPR, TrustedImm32(JSValue::LowestTag + 1)); #endif } + +#if USE(JSVALUE64) + Jump branchIfNumber(GPRReg reg, TagRegistersMode mode = HaveTagRegisters) + { + if (mode == HaveTagRegisters) + return branchTest64(NonZero, reg, GPRInfo::tagTypeNumberRegister); + return branchTest64(NonZero, reg, TrustedImm64(TagTypeNumber)); + } +#endif // Note that the tempGPR is not used in 64-bit mode. Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters) { #if USE(JSVALUE64) UNUSED_PARAM(tempGPR); + return branchIfNotNumber(regs.gpr(), mode); +#else + UNUSED_PARAM(mode); + add32(TrustedImm32(1), regs.tagGPR(), tempGPR); + return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1)); +#endif + } + +#if USE(JSVALUE64) + Jump branchIfNotNumber(GPRReg reg, TagRegistersMode mode = HaveTagRegisters) + { + if (mode == HaveTagRegisters) + return branchTest64(Zero, reg, GPRInfo::tagTypeNumberRegister); + return branchTest64(Zero, reg, TrustedImm64(TagTypeNumber)); + } +#endif + + Jump branchIfNotDoubleKnownNotInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters) + { +#if USE(JSVALUE64) if (mode == HaveTagRegisters) return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister); return branchTest64(Zero, regs.gpr(), TrustedImm64(TagTypeNumber)); #else UNUSED_PARAM(mode); - add32(TrustedImm32(1), regs.tagGPR(), tempGPR); - return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1)); + return branch32(AboveOrEqual, regs.tagGPR(), TrustedImm32(JSValue::LowestTag)); #endif } @@ -810,7 +884,8 @@ } JumpList branchIfNotType( - JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&, TagRegistersMode); + JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&, + TagRegistersMode = HaveTagRegisters); template Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure) @@ -822,28 +897,9 @@ #endif } - Jump branchIfToSpace(GPRReg storageGPR) - { - return branchTest32(Zero, storageGPR, TrustedImm32(CopyBarrierBase::spaceBits)); - } - - Jump branchIfNotToSpace(GPRReg storageGPR) - { - return branchTest32(NonZero, storageGPR, TrustedImm32(CopyBarrierBase::spaceBits)); - } - - void removeSpaceBits(GPRReg storageGPR) - { - andPtr(TrustedImmPtr(~static_cast(CopyBarrierBase::spaceBits)), storageGPR); - } - Jump branchIfFastTypedArray(GPRReg baseGPR); Jump branchIfNotFastTypedArray(GPRReg baseGPR); - // Returns a jump to slow path for when we need to execute the barrier. Note that baseGPR and - // resultGPR must be different. - Jump loadTypedArrayVector(GPRReg baseGPR, GPRReg resultGPR); - static Address addressForByteOffset(ptrdiff_t byteOffset) { return Address(GPRInfo::callFrameRegister, byteOffset); @@ -890,8 +946,8 @@ // Access to our fixed callee CallFrame. static Address calleeFrameSlot(int slot) { - ASSERT(slot >= JSStack::CallerFrameAndPCSize); - return Address(stackPointerRegister, sizeof(Register) * (slot - JSStack::CallerFrameAndPCSize)); + ASSERT(slot >= CallerFrameAndPC::sizeInRegisters); + return Address(stackPointerRegister, sizeof(Register) * (slot - CallerFrameAndPC::sizeInRegisters)); } // Access to our fixed callee CallFrame. @@ -1025,6 +1081,9 @@ #endif void jitReleaseAssertNoException(); + + void incrementSuperSamplerCount(); + void decrementSuperSamplerCount(); void purifyNaN(FPRReg); @@ -1224,29 +1283,7 @@ return argumentsStart(codeOrigin.inlineCallFrame); } - void emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch) - { -#if USE(JSVALUE64) - load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); - loadPtr(vm()->heap.structureIDTable().base(), scratch); - loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest); -#else - UNUSED_PARAM(scratch); - loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); -#endif - } - - static void emitLoadStructure(AssemblyHelpers& jit, RegisterID base, RegisterID dest, RegisterID scratch) - { -#if USE(JSVALUE64) - jit.load32(MacroAssembler::Address(base, JSCell::structureIDOffset()), dest); - jit.loadPtr(jit.vm()->heap.structureIDTable().base(), scratch); - jit.loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest); -#else - UNUSED_PARAM(scratch); - jit.loadPtr(MacroAssembler::Address(base, JSCell::structureIDOffset()), dest); -#endif - } + void emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch); void emitStoreStructureWithTypeInfo(TrustedImmPtr structure, RegisterID dest, RegisterID) { @@ -1356,26 +1393,151 @@ functor(TypeofType::Undefined, true); } - + + void emitDumbVirtualCall(CallLinkInfo*); + Vector& decodedCodeMapFor(CodeBlock*); - void makeSpaceOnStackForCCall() + void makeSpaceOnStackForCCall(); + void reclaimSpaceOnStackForCCall(); + +#if USE(JSVALUE64) + void emitRandomThunk(JSGlobalObject*, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result); + void emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result); +#endif + + // Call this if you know that the value held in allocatorGPR is non-null. This DOES NOT mean + // that allocator is non-null; allocator can be null as a signal that we don't know what the + // value of allocatorGPR is. + void emitAllocateWithNonNullAllocator(GPRReg resultGPR, MarkedAllocator* allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath) { - unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall); - if (stackOffset) - subPtr(TrustedImm32(stackOffset), stackPointerRegister); + // NOTE: This is carefully written so that we can call it while we disallow scratch + // register usage. + + if (Options::forceGCSlowPaths()) { + slowPath.append(jump()); + return; + } + + Jump popPath; + Jump done; + + load32(Address(allocatorGPR, MarkedAllocator::offsetOfFreeList() + OBJECT_OFFSETOF(FreeList, remaining)), resultGPR); + popPath = branchTest32(Zero, resultGPR); + if (allocator) + add32(TrustedImm32(-allocator->cellSize()), resultGPR, scratchGPR); + else { + if (isX86()) { + move(resultGPR, scratchGPR); + sub32(Address(allocatorGPR, MarkedAllocator::offsetOfCellSize()), scratchGPR); + } else { + load32(Address(allocatorGPR, MarkedAllocator::offsetOfCellSize()), scratchGPR); + sub32(resultGPR, scratchGPR, scratchGPR); + } + } + negPtr(resultGPR); + store32(scratchGPR, Address(allocatorGPR, MarkedAllocator::offsetOfFreeList() + OBJECT_OFFSETOF(FreeList, remaining))); + Address payloadEndAddr = Address(allocatorGPR, MarkedAllocator::offsetOfFreeList() + OBJECT_OFFSETOF(FreeList, payloadEnd)); + if (isX86()) + addPtr(payloadEndAddr, resultGPR); + else { + loadPtr(payloadEndAddr, scratchGPR); + addPtr(scratchGPR, resultGPR); + } + + done = jump(); + + popPath.link(this); + + loadPtr(Address(allocatorGPR, MarkedAllocator::offsetOfFreeList() + OBJECT_OFFSETOF(FreeList, head)), resultGPR); + slowPath.append(branchTestPtr(Zero, resultGPR)); + + // The object is half-allocated: we have what we know is a fresh object, but + // it's still on the GC's free list. + loadPtr(Address(resultGPR), scratchGPR); + storePtr(scratchGPR, Address(allocatorGPR, MarkedAllocator::offsetOfFreeList() + OBJECT_OFFSETOF(FreeList, head))); + + done.link(this); + } + + void emitAllocate(GPRReg resultGPR, MarkedAllocator* allocator, GPRReg allocatorGPR, GPRReg scratchGPR, JumpList& slowPath) + { + if (!allocator) + slowPath.append(branchTestPtr(Zero, allocatorGPR)); + emitAllocateWithNonNullAllocator(resultGPR, allocator, allocatorGPR, scratchGPR, slowPath); + } + + template + void emitAllocateJSCell(GPRReg resultGPR, MarkedAllocator* allocator, GPRReg allocatorGPR, StructureType structure, GPRReg scratchGPR, JumpList& slowPath) + { + emitAllocate(resultGPR, allocator, allocatorGPR, scratchGPR, slowPath); + emitStoreStructureWithTypeInfo(structure, resultGPR, scratchGPR); + } + + template + void emitAllocateJSObject(GPRReg resultGPR, MarkedAllocator* allocator, GPRReg allocatorGPR, StructureType structure, StorageType storage, GPRReg scratchGPR, JumpList& slowPath) + { + emitAllocateJSCell(resultGPR, allocator, allocatorGPR, structure, scratchGPR, slowPath); + storePtr(storage, Address(resultGPR, JSObject::butterflyOffset())); + } + + template + void emitAllocateJSObjectWithKnownSize( + GPRReg resultGPR, StructureType structure, StorageType storage, GPRReg scratchGPR1, + GPRReg scratchGPR2, JumpList& slowPath, size_t size) + { + MarkedAllocator* allocator = vm()->heap.allocatorForObjectOfType(size); + if (!allocator) { + slowPath.append(jump()); + return; + } + move(TrustedImmPtr(allocator), scratchGPR1); + emitAllocateJSObject(resultGPR, allocator, scratchGPR1, structure, storage, scratchGPR2, slowPath); + } + + template + void emitAllocateJSObject(GPRReg resultGPR, StructureType structure, StorageType storage, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath) + { + emitAllocateJSObjectWithKnownSize(resultGPR, structure, storage, scratchGPR1, scratchGPR2, slowPath, ClassType::allocationSize(0)); + } + + // allocationSize can be aliased with any of the other input GPRs. If it's not aliased then it + // won't be clobbered. + void emitAllocateVariableSized(GPRReg resultGPR, MarkedSpace::Subspace& subspace, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath) + { + static_assert(!(MarkedSpace::sizeStep & (MarkedSpace::sizeStep - 1)), "MarkedSpace::sizeStep must be a power of two."); + + unsigned stepShift = getLSBSet(MarkedSpace::sizeStep); + + add32(TrustedImm32(MarkedSpace::sizeStep - 1), allocationSize, scratchGPR1); + urshift32(TrustedImm32(stepShift), scratchGPR1); + slowPath.append(branch32(Above, scratchGPR1, TrustedImm32(MarkedSpace::largeCutoff >> stepShift))); + move(TrustedImmPtr(&subspace.allocatorForSizeStep[0] - 1), scratchGPR2); + loadPtr(BaseIndex(scratchGPR2, scratchGPR1, timesPtr()), scratchGPR1); + + emitAllocate(resultGPR, nullptr, scratchGPR1, scratchGPR2, slowPath); + } + + template + void emitAllocateVariableSizedJSObject(GPRReg resultGPR, StructureType structure, GPRReg allocationSize, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath) + { + MarkedSpace::Subspace& subspace = vm()->heap.template subspaceForObjectOfType(); + emitAllocateVariableSized(resultGPR, subspace, allocationSize, scratchGPR1, scratchGPR2, slowPath); + emitStoreStructureWithTypeInfo(structure, resultGPR, scratchGPR2); + storePtr(TrustedImmPtr(0), Address(resultGPR, JSObject::butterflyOffset())); } - void reclaimSpaceOnStackForCCall() + void emitConvertValueToBoolean(JSValueRegs value, GPRReg result, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult = false); + + template + void emitAllocateDestructibleObject(GPRReg resultGPR, Structure* structure, GPRReg scratchGPR1, GPRReg scratchGPR2, JumpList& slowPath) { - unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), maxFrameExtentForSlowPathCall); - if (stackOffset) - addPtr(TrustedImm32(stackOffset), stackPointerRegister); + emitAllocateJSObject(resultGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR1, scratchGPR2, slowPath); + storePtr(TrustedImmPtr(structure->classInfo()), Address(resultGPR, JSDestructibleObject::classInfoOffset())); } #if USE(JSVALUE64) - void emitRandomThunk(JSGlobalObject*, GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, FPRReg result); - void emitRandomThunk(GPRReg scratch0, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, FPRReg result); + void wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch); #endif protected: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CallFrameShuffler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CallFrameShuffler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CallFrameShuffler.cpp 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CallFrameShuffler.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -36,11 +36,11 @@ CallFrameShuffler::CallFrameShuffler(CCallHelpers& jit, const CallFrameShuffleData& data) : m_jit(jit) - , m_oldFrame(data.numLocals + JSStack::CallerFrameAndPCSize, nullptr) - , m_newFrame(data.args.size() + JSStack::CallFrameHeaderSize, nullptr) - , m_alignedOldFrameSize(JSStack::CallFrameHeaderSize + , m_oldFrame(data.numLocals + CallerFrameAndPC::sizeInRegisters, nullptr) + , m_newFrame(data.args.size() + CallFrame::headerSizeInRegisters, nullptr) + , m_alignedOldFrameSize(CallFrame::headerSizeInRegisters + roundArgumentCountToAlignFrame(jit.codeBlock()->numParameters())) - , m_alignedNewFrameSize(JSStack::CallFrameHeaderSize + , m_alignedNewFrameSize(CallFrame::headerSizeInRegisters + roundArgumentCountToAlignFrame(data.args.size())) , m_frameDelta(m_alignedNewFrameSize - m_alignedOldFrameSize) , m_lockedRegisters(RegisterSet::allRegisters()) @@ -54,7 +54,7 @@ m_lockedRegisters.exclude(RegisterSet::vmCalleeSaveRegisters()); ASSERT(!data.callee.isInJSStack() || data.callee.virtualRegister().isLocal()); - addNew(VirtualRegister(JSStack::Callee), data.callee); + addNew(VirtualRegister(CallFrameSlot::callee), data.callee); for (size_t i = 0; i < data.args.size(); ++i) { ASSERT(!data.args[i].isInJSStack() || data.args[i].virtualRegister().isLocal()); @@ -145,7 +145,7 @@ out.printf(" %c%8s <- %18s %c ", d, str.data(), recoveryStr.data(), d); } - } else if (newReg == VirtualRegister { JSStack::ArgumentCount }) + } else if (newReg == VirtualRegister { CallFrameSlot::argumentCount }) out.printf(" %c%8s <- %18zu %c ", d, str.data(), argCount(), d); else out.printf(" %c%30s %c ", d, "", d); @@ -323,7 +323,7 @@ m_jit.subPtr(MacroAssembler::TrustedImm32(delta * sizeof(Register)), MacroAssembler::stackPointerRegister); if (isSlowPath()) - m_frameDelta = numLocals() + JSStack::CallerFrameAndPCSize; + m_frameDelta = numLocals() + CallerFrameAndPC::sizeInRegisters; else m_oldFrameOffset = numLocals(); @@ -339,9 +339,9 @@ ASSERT(isUndecided()); emitDeltaCheck(); - m_frameDelta = numLocals() + JSStack::CallerFrameAndPCSize; + m_frameDelta = numLocals() + CallerFrameAndPC::sizeInRegisters; m_newFrameBase = MacroAssembler::stackPointerRegister; - m_newFrameOffset = -JSStack::CallerFrameAndPCSize; + m_newFrameOffset = -CallerFrameAndPC::sizeInRegisters; if (verbose) dataLog("\n\nPreparing frame for slow path call:\n"); @@ -423,11 +423,11 @@ // old frame (taking into account an argument count higher than // the number of parameters), then substracting to it the aligned // new frame size (adjusted). - m_jit.load32(MacroAssembler::Address(GPRInfo::callFrameRegister, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset), m_newFrameBase); + m_jit.load32(MacroAssembler::Address(GPRInfo::callFrameRegister, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset), m_newFrameBase); MacroAssembler::Jump argumentCountOK = m_jit.branch32(MacroAssembler::BelowOrEqual, m_newFrameBase, MacroAssembler::TrustedImm32(m_jit.codeBlock()->numParameters())); - m_jit.add32(MacroAssembler::TrustedImm32(stackAlignmentRegisters() - 1 + JSStack::CallFrameHeaderSize), m_newFrameBase); + m_jit.add32(MacroAssembler::TrustedImm32(stackAlignmentRegisters() - 1 + CallFrame::headerSizeInRegisters), m_newFrameBase); m_jit.and32(MacroAssembler::TrustedImm32(-stackAlignmentRegisters()), m_newFrameBase); m_jit.mul32(MacroAssembler::TrustedImm32(sizeof(Register)), m_newFrameBase, m_newFrameBase); MacroAssembler::Jump done = m_jit.jump(); @@ -743,11 +743,11 @@ // We need to handle 4) first because it implies releasing // m_newFrameBase, which could be a wanted register. if (verbose) - dataLog(" * Storing the argument count into ", VirtualRegister { JSStack::ArgumentCount }, "\n"); + dataLog(" * Storing the argument count into ", VirtualRegister { CallFrameSlot::argumentCount }, "\n"); m_jit.store32(MacroAssembler::TrustedImm32(0), - addressForNew(VirtualRegister { JSStack::ArgumentCount }).withOffset(TagOffset)); + addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(TagOffset)); m_jit.store32(MacroAssembler::TrustedImm32(argCount()), - addressForNew(VirtualRegister { JSStack::ArgumentCount }).withOffset(PayloadOffset)); + addressForNew(VirtualRegister { CallFrameSlot::argumentCount }).withOffset(PayloadOffset)); if (!isSlowPath()) { ASSERT(m_newFrameBase != MacroAssembler::stackPointerRegister); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CallFrameShuffler.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CallFrameShuffler.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CallFrameShuffler.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CallFrameShuffler.h 2016-11-03 07:04:20.000000000 +0000 @@ -103,7 +103,7 @@ CallFrameShuffleData data; data.numLocals = numLocals(); - data.callee = getNew(VirtualRegister { JSStack::Callee })->recovery(); + data.callee = getNew(VirtualRegister { CallFrameSlot::callee })->recovery(); data.args.resize(argCount()); for (size_t i = 0; i < argCount(); ++i) data.args[i] = getNew(virtualRegisterForArgument(i))->recovery(); @@ -129,7 +129,7 @@ { ASSERT(isUndecided()); ASSERT(!getNew(jsValueRegs)); - CachedRecovery* cachedRecovery { getNew(VirtualRegister(JSStack::Callee)) }; + CachedRecovery* cachedRecovery { getNew(VirtualRegister(CallFrameSlot::callee)) }; ASSERT(cachedRecovery); addNew(jsValueRegs, cachedRecovery->recovery()); } @@ -142,7 +142,7 @@ void assumeCalleeIsCell() { #if USE(JSVALUE32_64) - CachedRecovery& calleeCachedRecovery = *getNew(VirtualRegister(JSStack::Callee)); + CachedRecovery& calleeCachedRecovery = *getNew(VirtualRegister(CallFrameSlot::callee)); switch (calleeCachedRecovery.recovery().technique()) { case InPair: updateRecovery( @@ -297,17 +297,17 @@ int numLocals() const { - return m_oldFrame.size() - JSStack::CallerFrameAndPCSize; + return m_oldFrame.size() - CallerFrameAndPC::sizeInRegisters; } CachedRecovery* getOld(VirtualRegister reg) const { - return m_oldFrame[JSStack::CallerFrameAndPCSize - reg.offset() - 1]; + return m_oldFrame[CallerFrameAndPC::sizeInRegisters - reg.offset() - 1]; } void setOld(VirtualRegister reg, CachedRecovery* cachedRecovery) { - m_oldFrame[JSStack::CallerFrameAndPCSize - reg.offset() - 1] = cachedRecovery; + m_oldFrame[CallerFrameAndPC::sizeInRegisters - reg.offset() - 1] = cachedRecovery; } VirtualRegister firstOld() const @@ -317,7 +317,7 @@ VirtualRegister lastOld() const { - return VirtualRegister { JSStack::CallerFrameAndPCSize - 1 }; + return VirtualRegister { CallerFrameAndPC::sizeInRegisters - 1 }; } bool isValidOld(VirtualRegister reg) const @@ -339,7 +339,7 @@ size_t argCount() const { - return m_newFrame.size() - JSStack::CallFrameHeaderSize; + return m_newFrame.size() - CallFrame::headerSizeInRegisters; } CachedRecovery* getNew(VirtualRegister newRegister) const diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CCallHelpers.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CCallHelpers.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CCallHelpers.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CCallHelpers.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CCallHelpers.h" + +#if ENABLE(JIT) + +#include "ShadowChicken.h" + +namespace JSC { + +void CCallHelpers::logShadowChickenProloguePacket(GPRReg shadowPacket, GPRReg scratch1, GPRReg scope) +{ + storePtr(GPRInfo::callFrameRegister, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, frame))); + loadPtr(Address(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame)), scratch1); + storePtr(scratch1, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callerFrame))); + loadPtr(addressFor(CallFrameSlot::callee), scratch1); + storePtr(scratch1, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callee))); + storePtr(scope, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, scope))); +} + +void CCallHelpers::logShadowChickenTailPacket(GPRReg shadowPacket, JSValueRegs thisRegs, GPRReg scope, CodeBlock* codeBlock, CallSiteIndex callSiteIndex) +{ + storePtr(GPRInfo::callFrameRegister, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, frame))); + storePtr(TrustedImmPtr(ShadowChicken::Packet::tailMarker()), Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callee))); + storeValue(thisRegs, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, thisValue))); + storePtr(scope, Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, scope))); + storePtr(TrustedImmPtr(codeBlock), Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, codeBlock))); + store32(TrustedImm32(callSiteIndex.bits()), Address(shadowPacket, OBJECT_OFFSETOF(ShadowChicken::Packet, callSiteIndex))); +} + +void CCallHelpers::ensureShadowChickenPacket(GPRReg shadowPacket, GPRReg scratch1NonArgGPR, GPRReg scratch2) +{ + ASSERT(!RegisterSet::argumentGPRS().get(scratch1NonArgGPR)); + move(TrustedImmPtr(vm()->shadowChicken().addressOfLogCursor()), scratch1NonArgGPR); + loadPtr(Address(scratch1NonArgGPR), shadowPacket); + Jump ok = branchPtr(Below, shadowPacket, TrustedImmPtr(vm()->shadowChicken().logEnd())); + setupArgumentsExecState(); + move(TrustedImmPtr(bitwise_cast(operationProcessShadowChickenLog)), scratch1NonArgGPR); + call(scratch1NonArgGPR); + move(TrustedImmPtr(vm()->shadowChicken().addressOfLogCursor()), scratch1NonArgGPR); + loadPtr(Address(scratch1NonArgGPR), shadowPacket); + ok.link(this); + addPtr(TrustedImm32(sizeof(ShadowChicken::Packet)), shadowPacket, scratch2); + storePtr(scratch2, Address(scratch1NonArgGPR)); +} + +#if NUMBER_OF_ARGUMENT_REGISTERS >= 4 +void CCallHelpers::setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD) +{ + if (!ASSERT_DISABLED) { + RegisterSet destinations(destA, destB, destC, destD); + ASSERT_WITH_MESSAGE(destinations.numberOfSetGPRs() == 4, "Destinations should not be aliased."); + } + + typedef std::pair RegPair; + Vector pairs; + + if (srcA != destA) + pairs.append(std::make_pair(srcA, destA)); + if (srcB != destB) + pairs.append(std::make_pair(srcB, destB)); + if (srcC != destC) + pairs.append(std::make_pair(srcC, destC)); + if (srcD != destD) + pairs.append(std::make_pair(srcD, destD)); + + +#if !ASSERT_DISABLED + auto numUniqueSources = [&] () -> unsigned { + RegisterSet set; + for (auto& pair : pairs) { + GPRReg source = pair.first; + set.set(source); + } + return set.numberOfSetGPRs(); + }; + + auto numUniqueDests = [&] () -> unsigned { + RegisterSet set; + for (auto& pair : pairs) { + GPRReg dest = pair.second; + set.set(dest); + } + return set.numberOfSetGPRs(); + }; +#endif + + while (pairs.size()) { + RegisterSet freeDestinations; + for (auto& pair : pairs) { + GPRReg dest = pair.second; + freeDestinations.set(dest); + } + for (auto& pair : pairs) { + GPRReg source = pair.first; + freeDestinations.clear(source); + } + + if (freeDestinations.numberOfSetGPRs()) { + bool madeMove = false; + for (unsigned i = 0; i < pairs.size(); i++) { + auto& pair = pairs[i]; + GPRReg source = pair.first; + GPRReg dest = pair.second; + if (freeDestinations.get(dest)) { + move(source, dest); + pairs.remove(i); + madeMove = true; + break; + } + } + ASSERT_UNUSED(madeMove, madeMove); + continue; + } + + ASSERT(numUniqueDests() == numUniqueSources()); + ASSERT(numUniqueDests() == pairs.size()); + // The set of source and destination registers are equivalent sets. This means we don't have + // any free destination registers that won't also clobber a source. We get around this by + // exchanging registers. + + GPRReg source = pairs[0].first; + GPRReg dest = pairs[0].second; + swap(source, dest); + pairs.remove(0); + + GPRReg newSource = source; + for (auto& pair : pairs) { + GPRReg source = pair.first; + if (source == dest) { + pair.first = newSource; + break; + } + } + + // We may have introduced pairs that have the same source and destination. Remove those now. + for (unsigned i = 0; i < pairs.size(); i++) { + auto& pair = pairs[i]; + if (pair.first == pair.second) { + pairs.remove(i); + i--; + } + } + } +} +#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4 + +} // namespace JSC + +#endif // ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CCallHelpers.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CCallHelpers.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/CCallHelpers.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/CCallHelpers.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,7 @@ #include "AssemblyHelpers.h" #include "GPRInfo.h" +#include "RegisterMap.h" #include "StackAlignment.h" namespace JSC { @@ -40,6 +41,23 @@ #define POKE_ARGUMENT_OFFSET 0 #endif +// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]). +// To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary. +#if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS) +#define EABI_32BIT_DUMMY_ARG CCallHelpers::TrustedImm32(0), +#else +#define EABI_32BIT_DUMMY_ARG +#endif + +// JSVALUE32_64 is a 64-bit integer that cannot be put half in an argument register and half on stack when using SH4 architecture. +// To avoid this, let's occupy the 4th argument register (r7) with a dummy argument when necessary. This must only be done when there +// is no other 32-bit value argument behind this 64-bit JSValue. +#if CPU(SH4) +#define SH4_32BIT_DUMMY_ARG CCallHelpers::TrustedImm32(0), +#else +#define SH4_32BIT_DUMMY_ARG +#endif + class CCallHelpers : public AssemblyHelpers { public: CCallHelpers(VM* vm, CodeBlock* codeBlock = 0) @@ -278,6 +296,15 @@ addCallArgument(arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2, GPRReg arg3) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3) { resetCallArguments(); @@ -324,6 +351,16 @@ addCallArgument(arg4); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImm32 arg4) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3) { resetCallArguments(); @@ -480,6 +517,26 @@ addCallArgument(arg5); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4, TrustedImm32 arg5) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + addCallArgument(arg5); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5) { resetCallArguments(); @@ -668,6 +725,16 @@ addCallArgument(arg4); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3, GPRReg arg4) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, GPRReg arg3, GPRReg arg4) { resetCallArguments(); @@ -768,6 +835,18 @@ addCallArgument(arg6); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5, TrustedImmPtr arg6) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + addCallArgument(arg5); + addCallArgument(arg6); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, TrustedImmPtr arg7) { resetCallArguments(); @@ -797,6 +876,21 @@ addCallArgument(arg2); addCallArgument(arg3); } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, GPRReg arg7, GPRReg arg8) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + addCallArgument(arg5); + addCallArgument(arg6); + addCallArgument(arg7); + addCallArgument(arg8); + } + #endif // !NUMBER_OF_ARGUMENT_REGISTERS // These methods are suitable for any calling convention that provides for // at least 4 argument registers, e.g. X86_64, ARMv7. @@ -883,6 +977,8 @@ swap(destB, destC); } + void setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD); + #if CPU(X86_64) || CPU(ARM64) template void setupTwoStubArgsFPR(FPRReg srcA, FPRReg srcB) @@ -1321,6 +1417,14 @@ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2, GPRReg arg3) + { + move(arg3, GPRInfo::argumentGPR3); + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImm32 arg2, TrustedImm32 arg3) { move(arg1, GPRInfo::argumentGPR1); @@ -1500,6 +1604,12 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImm32 arg4) + { + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4) { poke(arg4, POKE_ARGUMENT_OFFSET); @@ -1513,6 +1623,14 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5, TrustedImmPtr arg6) + { + poke(arg6, POKE_ARGUMENT_OFFSET + 2); + poke(arg5, POKE_ARGUMENT_OFFSET + 1); + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5) { poke(arg5, POKE_ARGUMENT_OFFSET + 1); @@ -1613,6 +1731,12 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3, GPRReg arg4) + { + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4, TrustedImm32 arg5) { poke(arg5, POKE_ARGUMENT_OFFSET + 1); @@ -1682,6 +1806,12 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImmPtr arg4) + { + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4) { poke(arg4, POKE_ARGUMENT_OFFSET); @@ -1736,6 +1866,13 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4, TrustedImm32 arg5) + { + poke(arg5, POKE_ARGUMENT_OFFSET + 1); + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3, GPRReg arg4) { poke(arg4, POKE_ARGUMENT_OFFSET); @@ -1898,6 +2035,15 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, TrustedImmPtr arg6, TrustedImmPtr arg7) + { + poke(arg7, POKE_ARGUMENT_OFFSET + 3); + poke(arg6, POKE_ARGUMENT_OFFSET + 2); + poke(arg5, POKE_ARGUMENT_OFFSET + 1); + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, GPRReg arg7, TrustedImmPtr arg8) { poke(arg8, POKE_ARGUMENT_OFFSET + 4); @@ -1908,6 +2054,27 @@ setupArgumentsWithExecState(arg1, arg2, arg3); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, GPRReg arg7, GPRReg arg8) + { + poke(arg8, POKE_ARGUMENT_OFFSET + 4); + poke(arg7, POKE_ARGUMENT_OFFSET + 3); + poke(arg6, POKE_ARGUMENT_OFFSET + 2); + poke(arg5, POKE_ARGUMENT_OFFSET + 1); + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5, GPRReg arg6, GPRReg arg7, GPRReg arg8, GPRReg arg9) + { + poke(arg9, POKE_ARGUMENT_OFFSET + 5); + poke(arg8, POKE_ARGUMENT_OFFSET + 4); + poke(arg7, POKE_ARGUMENT_OFFSET + 3); + poke(arg6, POKE_ARGUMENT_OFFSET + 2); + poke(arg5, POKE_ARGUMENT_OFFSET + 1); + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, TrustedImm32 arg5, GPRReg arg6, GPRReg arg7) { poke(arg7, POKE_ARGUMENT_OFFSET + 3); @@ -1940,9 +2107,22 @@ poke(arg4, POKE_ARGUMENT_OFFSET); setupArgumentsWithExecState(arg1, arg2, arg3); } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImmPtr arg4, GPRReg arg5) + { + poke(arg5, POKE_ARGUMENT_OFFSET + 1); + poke(arg4, POKE_ARGUMENT_OFFSET); + setupArgumentsWithExecState(arg1, arg2, arg3); + } #endif // NUMBER_OF_ARGUMENT_REGISTERS == 4 #if NUMBER_OF_ARGUMENT_REGISTERS >= 5 + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4) + { + setupFourStubArgsGPR(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, GPRInfo::argumentGPR4, arg1, arg2, arg3, arg4); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + void setupStubArguments134(GPRReg arg1, GPRReg arg3, GPRReg arg4) { setupThreeStubArgsGPR(arg1, arg3, arg4); @@ -1963,6 +2143,22 @@ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImm32 arg4) + { + setupTwoStubArgsGPR(arg1, arg2); + move(arg3, GPRInfo::argumentGPR3); + move(arg4, GPRInfo::argumentGPR4); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImmPtr arg4) + { + setupTwoStubArgsGPR(arg1, arg2); + move(arg3, GPRInfo::argumentGPR3); + move(arg4, GPRInfo::argumentGPR4); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5) { setupThreeStubArgsGPR(arg1, arg4, arg5); @@ -1985,7 +2181,7 @@ move(arg4, GPRInfo::argumentGPR4); move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); } - + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4) { move(arg2, GPRInfo::argumentGPR2); // In case arg2 is argumentGPR1. @@ -2071,6 +2267,33 @@ } #endif + void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2) + { +#if USE(JSVALUE64) + setupArgumentsWithExecState(arg1.gpr(), arg2.gpr()); +#else + setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR()); +#endif + } + + void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3) + { +#if USE(JSVALUE64) + setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), arg3); +#else + setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3); +#endif + } + + void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3, TrustedImmPtr arg4) + { +#if USE(JSVALUE64) + setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), arg3, arg4); +#else + setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3, arg4); +#endif + } + void setupArguments(JSValueRegs arg1) { #if USE(JSVALUE64) @@ -2133,13 +2356,13 @@ GPRReg oldFrameSizeGPR = temp2; { GPRReg argCountGPR = oldFrameSizeGPR; - load32(Address(framePointerRegister, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset), argCountGPR); + load32(Address(framePointerRegister, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset), argCountGPR); { GPRReg numParametersGPR = temp1; { GPRReg codeBlockGPR = numParametersGPR; - loadPtr(Address(framePointerRegister, JSStack::CodeBlock * static_cast(sizeof(Register))), codeBlockGPR); + loadPtr(Address(framePointerRegister, CallFrameSlot::codeBlock * static_cast(sizeof(Register))), codeBlockGPR); load32(Address(codeBlockGPR, CodeBlock::offsetOfNumParameters()), numParametersGPR); } @@ -2149,7 +2372,7 @@ argumentCountWasNotFixedUp.link(this); } - add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), argCountGPR, oldFrameSizeGPR); + add32(TrustedImm32(stackAlignmentRegisters() + CallFrame::headerSizeInRegisters - 1), argCountGPR, oldFrameSizeGPR); and32(TrustedImm32(-stackAlignmentRegisters()), oldFrameSizeGPR); // We assume < 2^28 arguments mul32(TrustedImm32(sizeof(Register)), oldFrameSizeGPR, oldFrameSizeGPR); @@ -2162,9 +2385,9 @@ // The new frame size is just the number of arguments plus the // frame header size, aligned ASSERT(newFrameSizeGPR != newFramePointer); - load32(Address(stackPointerRegister, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)), + load32(Address(stackPointerRegister, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC)), newFrameSizeGPR); - add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), newFrameSizeGPR); + add32(TrustedImm32(stackAlignmentRegisters() + CallFrame::headerSizeInRegisters - 1), newFrameSizeGPR); and32(TrustedImm32(-stackAlignmentRegisters()), newFrameSizeGPR); // We assume < 2^28 arguments mul32(TrustedImm32(sizeof(Register)), newFrameSizeGPR, newFrameSizeGPR); @@ -2205,6 +2428,13 @@ // Ready for a jump! move(newFramePointer, stackPointerRegister); } + + // These operations clobber all volatile registers. They assume that there is room on the top of + // stack to marshall call arguments. + void logShadowChickenProloguePacket(GPRReg shadowPacket, GPRReg scratch1, GPRReg scope); + void logShadowChickenTailPacket(GPRReg shadowPacket, JSValueRegs thisRegs, GPRReg scope, CodeBlock*, CallSiteIndex); + // Leaves behind a pointer to the Packet we should write to in shadowPacket. + void ensureShadowChickenPacket(GPRReg shadowPacket, GPRReg scratch1NonArgGPR, GPRReg scratch2); }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -32,27 +32,65 @@ #include "CodeProfiling.h" #include "ExecutableAllocationFuzz.h" -#include -#if !PLATFORM(WIN) -#include -#endif #include #include -#include #if OS(DARWIN) #include #endif -#if OS(LINUX) -#include +#include "LinkBuffer.h" +#include "MacroAssembler.h" + +#if PLATFORM(MAC) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) +#define HAVE_REMAP_JIT 1 +#endif + +#if HAVE(REMAP_JIT) +#if CPU(ARM64) && PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 +#define USE_EXECUTE_ONLY_JIT_WRITE_FUNCTION 1 +#endif +#endif + +#if OS(DARWIN) +#include +extern "C" { + /* Routine mach_vm_remap */ +#ifdef mig_external + mig_external +#else + extern +#endif /* mig_external */ + kern_return_t mach_vm_remap + ( + vm_map_t target_task, + mach_vm_address_t *target_address, + mach_vm_size_t size, + mach_vm_offset_t mask, + int flags, + vm_map_t src_task, + mach_vm_address_t src_address, + boolean_t copy, + vm_prot_t *cur_protection, + vm_prot_t *max_protection, + vm_inherit_t inheritance + ); +} + #endif using namespace WTF; namespace JSC { - -uintptr_t startOfFixedExecutableMemoryPool; + +JS_EXPORTDATA uintptr_t startOfFixedExecutableMemoryPool; +JS_EXPORTDATA uintptr_t endOfFixedExecutableMemoryPool; + +JS_EXPORTDATA JITWriteFunction jitWriteFunction; + +#if !USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION) && HAVE(REMAP_JIT) +static uintptr_t startOfFixedWritableMemoryPool; +#endif class FixedVMPoolExecutableAllocator : public MetaAllocator { WTF_MAKE_FAST_ALLOCATED; @@ -69,22 +107,33 @@ m_reservation = PageReservation::reserveWithGuardPages(reservationSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true); if (m_reservation) { ASSERT(m_reservation.size() == reservationSize); - addFreshFreeSpace(m_reservation.base(), m_reservation.size()); - - startOfFixedExecutableMemoryPool = reinterpret_cast(m_reservation.base()); + void* reservationBase = m_reservation.base(); + + if (Options::useSeparatedWXHeap()) { + // First page of our JIT allocation is reserved. + ASSERT(reservationSize >= pageSize() * 2); + reservationBase = (void*)((uintptr_t)reservationBase + pageSize()); + reservationSize -= pageSize(); + initializeSeparatedWXHeaps(m_reservation.base(), pageSize(), reservationBase, reservationSize); + } + + addFreshFreeSpace(reservationBase, reservationSize); + + startOfFixedExecutableMemoryPool = reinterpret_cast(reservationBase); + endOfFixedExecutableMemoryPool = startOfFixedExecutableMemoryPool + reservationSize; } } virtual ~FixedVMPoolExecutableAllocator(); protected: - virtual void* allocateNewSpace(size_t&) override + void* allocateNewSpace(size_t&) override { // We're operating in a fixed pool, so new allocation is always prohibited. return 0; } - virtual void notifyNeedPage(void* page) override + void notifyNeedPage(void* page) override { #if USE(MADV_FREE_FOR_JIT_MEMORY) UNUSED_PARAM(page); @@ -93,7 +142,7 @@ #endif } - virtual void notifyPageIsFree(void* page) override + void notifyPageIsFree(void* page) override { #if USE(MADV_FREE_FOR_JIT_MEMORY) for (;;) { @@ -112,6 +161,141 @@ } private: +#if OS(DARWIN) && HAVE(REMAP_JIT) + void initializeSeparatedWXHeaps(void* stubBase, size_t stubSize, void* jitBase, size_t jitSize) + { + mach_vm_address_t writableAddr = 0; + + // Create a second mapping of the JIT region at a random address. + vm_prot_t cur, max; + int remapFlags = VM_FLAGS_ANYWHERE; +#if defined(VM_FLAGS_RANDOM_ADDR) + remapFlags |= VM_FLAGS_RANDOM_ADDR; +#endif + kern_return_t ret = mach_vm_remap(mach_task_self(), &writableAddr, jitSize, 0, + remapFlags, + mach_task_self(), (mach_vm_address_t)jitBase, FALSE, + &cur, &max, VM_INHERIT_DEFAULT); + + bool remapSucceeded = (ret == KERN_SUCCESS); + if (!remapSucceeded) + return; + + // Assemble a thunk that will serve as the means for writing into the JIT region. + MacroAssemblerCodeRef writeThunk = jitWriteThunkGenerator(reinterpret_cast(writableAddr), stubBase, stubSize); + + int result = 0; + +#if USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION) + // Prevent reading the write thunk code. + result = mprotect(stubBase, stubSize, VM_PROT_EXECUTE_ONLY); + RELEASE_ASSERT(!result); +#endif + + // Prevent writing into the executable JIT mapping. + result = mprotect(jitBase, jitSize, VM_PROT_READ | VM_PROT_EXECUTE); + RELEASE_ASSERT(!result); + + // Prevent execution in the writable JIT mapping. + result = mprotect((void*)writableAddr, jitSize, VM_PROT_READ | VM_PROT_WRITE); + RELEASE_ASSERT(!result); + + // Zero out writableAddr to avoid leaking the address of the writable mapping. + memset_s(&writableAddr, sizeof(writableAddr), 0, sizeof(writableAddr)); + + jitWriteFunction = reinterpret_cast(writeThunk.code().executableAddress()); + } + +#if CPU(ARM64) && USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION) + MacroAssemblerCodeRef jitWriteThunkGenerator(void* writableAddr, void* stubBase, size_t stubSize) + { + using namespace ARM64Registers; + using TrustedImm32 = MacroAssembler::TrustedImm32; + + MacroAssembler jit; + + jit.move(MacroAssembler::TrustedImmPtr(writableAddr), x7); + jit.addPtr(x7, x0); + + jit.move(x0, x3); + MacroAssembler::Jump smallCopy = jit.branch64(MacroAssembler::Below, x2, MacroAssembler::TrustedImm64(64)); + + jit.add64(TrustedImm32(32), x3); + jit.and64(TrustedImm32(-32), x3); + jit.loadPair64(x1, x12, x13); + jit.loadPair64(x1, TrustedImm32(16), x14, x15); + jit.sub64(x3, x0, x5); + jit.addPtr(x5, x1); + + jit.loadPair64(x1, x8, x9); + jit.loadPair64(x1, TrustedImm32(16), x10, x11); + jit.add64(TrustedImm32(32), x1); + jit.sub64(x5, x2); + jit.storePair64(x12, x13, x0); + jit.storePair64(x14, x15, x0, TrustedImm32(16)); + MacroAssembler::Jump cleanup = jit.branchSub64(MacroAssembler::BelowOrEqual, TrustedImm32(64), x2); + + MacroAssembler::Label copyLoop = jit.label(); + jit.storePair64WithNonTemporalAccess(x8, x9, x3); + jit.storePair64WithNonTemporalAccess(x10, x11, x3, TrustedImm32(16)); + jit.add64(TrustedImm32(32), x3); + jit.loadPair64WithNonTemporalAccess(x1, x8, x9); + jit.loadPair64WithNonTemporalAccess(x1, TrustedImm32(16), x10, x11); + jit.add64(TrustedImm32(32), x1); + jit.branchSub64(MacroAssembler::Above, TrustedImm32(32), x2).linkTo(copyLoop, &jit); + + cleanup.link(&jit); + jit.add64(x2, x1); + jit.loadPair64(x1, x12, x13); + jit.loadPair64(x1, TrustedImm32(16), x14, x15); + jit.storePair64(x8, x9, x3); + jit.storePair64(x10, x11, x3, TrustedImm32(16)); + jit.addPtr(x2, x3); + jit.storePair64(x12, x13, x3, TrustedImm32(32)); + jit.storePair64(x14, x15, x3, TrustedImm32(48)); + jit.ret(); + + MacroAssembler::Label local0 = jit.label(); + jit.load64(x1, PostIndex(8), x6); + jit.store64(x6, x3, PostIndex(8)); + smallCopy.link(&jit); + jit.branchSub64(MacroAssembler::AboveOrEqual, TrustedImm32(8), x2).linkTo(local0, &jit); + MacroAssembler::Jump local2 = jit.branchAdd64(MacroAssembler::Equal, TrustedImm32(8), x2); + MacroAssembler::Label local1 = jit.label(); + jit.load8(x1, PostIndex(1), x6); + jit.store8(x6, x3, PostIndex(1)); + jit.branchSub64(MacroAssembler::NotEqual, TrustedImm32(1), x2).linkTo(local1, &jit); + local2.link(&jit); + jit.ret(); + + LinkBuffer linkBuffer(jit, stubBase, stubSize); + return FINALIZE_CODE(linkBuffer, ("Bulletproof JIT write thunk")); + } +#else // CPU(ARM64) && USE(EXECUTE_ONLY_JIT_WRITE_FUNCTION) + static void genericWriteToJITRegion(off_t offset, const void* data, size_t dataSize) + { + memcpy((void*)(startOfFixedWritableMemoryPool + offset), data, dataSize); + } + + MacroAssemblerCodeRef jitWriteThunkGenerator(void* address, void*, size_t) + { + startOfFixedWritableMemoryPool = reinterpret_cast(address); + uintptr_t function = (uintptr_t)((void*)&genericWriteToJITRegion); +#if CPU(ARM_THUMB2) + // Handle thumb offset + function -= 1; +#endif + return MacroAssemblerCodeRef::createSelfManagedCodeRef(MacroAssemblerCodePtr((void*)function)); + } +#endif + +#else // OS(DARWIN) && HAVE(REMAP_JIT) + void initializeSeparatedWXHeaps(void*, size_t, void*, size_t) + { + } +#endif + +private: PageReservation m_reservation; }; @@ -169,6 +353,11 @@ RefPtr ExecutableAllocator::allocate(VM&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort) { + if (Options::logExecutableAllocation()) { + MetaAllocator::Statistics stats = allocator->currentStatistics(); + dataLog("Allocating ", sizeInBytes, " bytes of executable memory with ", stats.bytesAllocated, " bytes allocated, ", stats.bytesReserved, " bytes reserved, and ", stats.bytesCommitted, " committed.\n"); + } + if (effort != JITCompilationCanFail && Options::reportMustSucceedExecutableAllocations()) { dataLog("Allocating ", sizeInBytes, " bytes of executable memory with JITCompilationMustSucceed.\n"); WTFReportBacktrace(); diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ExecutableAllocator.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ExecutableAllocator.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ExecutableAllocator.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ExecutableAllocator.h 2016-11-03 07:04:20.000000000 +0000 @@ -33,8 +33,6 @@ #include #include #include -#include -#include #if OS(IOS) #include @@ -89,7 +87,31 @@ static const double executablePoolReservationFraction = 0.25; #endif -extern uintptr_t startOfFixedExecutableMemoryPool; +extern JS_EXPORTDATA uintptr_t startOfFixedExecutableMemoryPool; +extern JS_EXPORTDATA uintptr_t endOfFixedExecutableMemoryPool; + +typedef void (*JITWriteFunction)(off_t, const void*, size_t); +extern JS_EXPORTDATA JITWriteFunction jitWriteFunction; + +static inline void* performJITMemcpy(void *dst, const void *src, size_t n) +{ + // Use execute-only write thunk for writes inside the JIT region. This is a variant of + // memcpy that takes an offset into the JIT region as its destination (first) parameter. + if (jitWriteFunction && (uintptr_t)dst >= startOfFixedExecutableMemoryPool && (uintptr_t)dst <= endOfFixedExecutableMemoryPool) { + off_t offset = (off_t)((uintptr_t)dst - startOfFixedExecutableMemoryPool); + jitWriteFunction(offset, src, n); + return dst; + } + + // Use regular memcpy for writes outside the JIT region. + return memcpy(dst, src, n); +} + +#else // ENABLE(EXECUTABLE_ALLOCATOR_FIXED) +static inline void* performJITMemcpy(void *dst, const void *src, size_t n) +{ + return memcpy(dst, src, n); +} #endif class ExecutableAllocator { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,9 +32,11 @@ #include "DFGCommonData.h" #include "Heap.h" #include "VM.h" +#include "JITStubRoutineSet.h" #include "JSCInlines.h" #include "SlotVisitor.h" #include "Structure.h" +#include namespace JSC { @@ -44,7 +46,7 @@ , m_mayBeExecuting(false) , m_isJettisoned(false) { - vm.heap.m_jitStubRoutines.add(this); + vm.heap.m_jitStubRoutines->add(this); } GCAwareJITStubRoutine::~GCAwareJITStubRoutine() { } @@ -79,28 +81,31 @@ { } -MarkingGCAwareJITStubRoutineWithOneObject::MarkingGCAwareJITStubRoutineWithOneObject( +MarkingGCAwareJITStubRoutine::MarkingGCAwareJITStubRoutine( const MacroAssemblerCodeRef& code, VM& vm, const JSCell* owner, - JSCell* object) + const Vector& cells) : GCAwareJITStubRoutine(code, vm) - , m_object(vm, owner, object) + , m_cells(cells.size()) { + for (unsigned i = cells.size(); i--;) + m_cells[i].set(vm, owner, cells[i]); } -MarkingGCAwareJITStubRoutineWithOneObject::~MarkingGCAwareJITStubRoutineWithOneObject() +MarkingGCAwareJITStubRoutine::~MarkingGCAwareJITStubRoutine() { } -void MarkingGCAwareJITStubRoutineWithOneObject::markRequiredObjectsInternal(SlotVisitor& visitor) +void MarkingGCAwareJITStubRoutine::markRequiredObjectsInternal(SlotVisitor& visitor) { - visitor.append(&m_object); + for (auto& entry : m_cells) + visitor.append(&entry); } GCAwareJITStubRoutineWithExceptionHandler::GCAwareJITStubRoutineWithExceptionHandler( - const MacroAssemblerCodeRef& code, VM& vm, + const MacroAssemblerCodeRef& code, VM& vm, const JSCell* owner, const Vector& cells, CodeBlock* codeBlockForExceptionHandlers, CallSiteIndex exceptionHandlerCallSiteIndex) - : GCAwareJITStubRoutine(code, vm) + : MarkingGCAwareJITStubRoutine(code, vm, owner, cells) , m_codeBlockWithExceptionHandler(codeBlockForExceptionHandlers) , m_exceptionHandlerCallSiteIndex(exceptionHandlerCallSiteIndex) { @@ -132,7 +137,7 @@ VM& vm, const JSCell* owner, bool makesCalls, - JSCell* object, + const Vector& cells, CodeBlock* codeBlockForExceptionHandlers, CallSiteIndex exceptionHandlerCallSiteIndex) { @@ -140,19 +145,14 @@ return adoptRef(new JITStubRoutine(code)); if (codeBlockForExceptionHandlers) { - RELEASE_ASSERT(!object); // We're not a marking stub routine. RELEASE_ASSERT(JITCode::isOptimizingJIT(codeBlockForExceptionHandlers->jitType())); - return static_pointer_cast( - adoptRef(new GCAwareJITStubRoutineWithExceptionHandler(code, vm, codeBlockForExceptionHandlers, exceptionHandlerCallSiteIndex))); + return adoptRef(new GCAwareJITStubRoutineWithExceptionHandler(code, vm, owner, cells, codeBlockForExceptionHandlers, exceptionHandlerCallSiteIndex)); } - if (!object) { - return static_pointer_cast( - adoptRef(new GCAwareJITStubRoutine(code, vm))); - } + if (cells.isEmpty()) + return adoptRef(new GCAwareJITStubRoutine(code, vm)); - return static_pointer_cast( - adoptRef(new MarkingGCAwareJITStubRoutineWithOneObject(code, vm, owner, object))); + return adoptRef(new MarkingGCAwareJITStubRoutine(code, vm, owner, cells)); } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GCAwareJITStubRoutine.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,7 +32,6 @@ #include "JSObject.h" #include "JSString.h" #include "WriteBarrier.h" -#include #include namespace JSC { @@ -63,7 +62,7 @@ void deleteFromGC(); protected: - virtual void observeZeroRefCount() override; + void observeZeroRefCount() override; virtual void markRequiredObjectsInternal(SlotVisitor&); @@ -76,28 +75,28 @@ // Use this if you want to mark one additional object during GC if your stub // routine is known to be executing. -class MarkingGCAwareJITStubRoutineWithOneObject : public GCAwareJITStubRoutine { +class MarkingGCAwareJITStubRoutine : public GCAwareJITStubRoutine { public: - MarkingGCAwareJITStubRoutineWithOneObject( - const MacroAssemblerCodeRef&, VM&, const JSCell* owner, JSCell*); - virtual ~MarkingGCAwareJITStubRoutineWithOneObject(); + MarkingGCAwareJITStubRoutine( + const MacroAssemblerCodeRef&, VM&, const JSCell* owner, const Vector&); + virtual ~MarkingGCAwareJITStubRoutine(); protected: - virtual void markRequiredObjectsInternal(SlotVisitor&) override; + void markRequiredObjectsInternal(SlotVisitor&) override; private: - WriteBarrier m_object; + Vector> m_cells; }; // The stub has exception handlers in it. So it clears itself from exception // handling table when it dies. It also frees space in CodeOrigin table // for new exception handlers to use the same CallSiteIndex. -class GCAwareJITStubRoutineWithExceptionHandler : public GCAwareJITStubRoutine { +class GCAwareJITStubRoutineWithExceptionHandler : public MarkingGCAwareJITStubRoutine { public: typedef GCAwareJITStubRoutine Base; - GCAwareJITStubRoutineWithExceptionHandler(const MacroAssemblerCodeRef&, VM&, CodeBlock*, CallSiteIndex); + GCAwareJITStubRoutineWithExceptionHandler(const MacroAssemblerCodeRef&, VM&, const JSCell* owner, const Vector&, CodeBlock*, CallSiteIndex); void aboutToDie() override; void observeZeroRefCount() override; @@ -128,14 +127,9 @@ PassRefPtr createJITStubRoutine( const MacroAssemblerCodeRef&, VM&, const JSCell* owner, bool makesCalls, - JSCell* = nullptr, + const Vector& = { }, CodeBlock* codeBlockForExceptionHandlers = nullptr, CallSiteIndex exceptionHandlingCallSiteIndex = CallSiteIndex(std::numeric_limits::max())); -// Helper for the creation of simple stub routines that need no help from the GC. Note -// that codeBlock gets "executed" more than once. -#define FINALIZE_CODE_FOR_GC_AWARE_STUB(codeBlock, patchBuffer, makesCalls, cell, dataLogFArguments) \ - (createJITStubRoutine(FINALIZE_CODE_FOR((codeBlock), (patchBuffer), dataLogFArguments), *(codeBlock)->vm(), (codeBlock), (makesCalls), (cell))) - } // namespace JSC #endif // ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GPRInfo.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GPRInfo.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GPRInfo.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GPRInfo.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -30,6 +30,15 @@ namespace JSC { +void JSValueRegs::dump(PrintStream& out) const +{ +#if USE(JSVALUE64) + out.print(m_gpr); +#else + out.print("(tag:", tagGPR(), ", payload:", payloadGPR(), ")"); +#endif +} + // This is in the .cpp file to work around clang issues. #if CPU(X86_64) const GPRReg GPRInfo::patchpointScratchRegister = MacroAssembler::s_scratchRegister; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GPRInfo.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GPRInfo.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/GPRInfo.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/GPRInfo.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -77,6 +77,8 @@ bool uses(GPRReg gpr) const { return m_gpr == gpr; } + void dump(PrintStream&) const; + private: GPRReg m_gpr; }; @@ -137,6 +139,11 @@ return m_base; } + JSValueRegs regs() const + { + return JSValueRegs(gpr()); + } + MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); } private: @@ -202,6 +209,8 @@ bool uses(GPRReg gpr) const { return m_tagGPR == gpr || m_payloadGPR == gpr; } + void dump(PrintStream&) const; + private: int8_t m_tagGPR; int8_t m_payloadGPR; @@ -302,6 +311,11 @@ return static_cast(m_tagType); } + JSValueRegs regs() const + { + return JSValueRegs(tagGPR(), payloadGPR()); + } + MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); } private: @@ -757,7 +771,7 @@ static const GPRReg argumentGPR1 = MIPSRegisters::a1; static const GPRReg argumentGPR2 = MIPSRegisters::a2; static const GPRReg argumentGPR3 = MIPSRegisters::a3; - static const GPRReg nonArgGPR0 = regT0; + static const GPRReg nonArgGPR0 = regT4; static const GPRReg returnValueGPR = regT0; static const GPRReg returnValueGPR2 = regT1; static const GPRReg nonPreservedNonReturnGPR = regT2; @@ -876,20 +890,6 @@ #endif // CPU(SH4) -inline GPRReg argumentRegisterFor(unsigned argumentIndex) -{ -#if USE(JSVALUE64) - if (argumentIndex >= NUMBER_OF_ARGUMENT_REGISTERS) - return InvalidGPRReg; - - return GPRInfo::toArgumentRegister(argumentIndex); -#else - UNUSED_PARAM(argumentIndex); - - return InvalidGPRReg; -#endif -} - // The baseline JIT uses "accumulator" style execution with regT0 (for 64-bit) // and regT0 + regT1 (for 32-bit) serving as the accumulator register(s) for // passing results of one opcode to the next. Hence: diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ICStats.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ICStats.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ICStats.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ICStats.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ICStats.h" + +namespace JSC { + +bool ICEvent::operator<(const ICEvent& other) const +{ + if (m_classInfo != other.m_classInfo) { + if (!m_classInfo) + return true; + if (!other.m_classInfo) + return false; + return strcmp(m_classInfo->className, other.m_classInfo->className) < 0; + } + + if (m_propertyName != other.m_propertyName) + return codePointCompare(m_propertyName.string(), other.m_propertyName.string()) < 0; + + return m_kind < other.m_kind; +} + +void ICEvent::dump(PrintStream& out) const +{ + out.print(m_kind, "(", m_classInfo ? m_classInfo->className : "", ", ", m_propertyName, ")"); +} + +void ICEvent::log() const +{ + ICStats::instance().add(*this); +} + +Atomic ICStats::s_instance; + +ICStats::ICStats() +{ + m_thread = createThread( + "JSC ICStats", + [this] () { + LockHolder locker(m_lock); + for (;;) { + m_condition.waitForSeconds(m_lock, 1, [this] () -> bool { return m_shouldStop; }); + if (m_shouldStop) + break; + + dataLog("ICStats:\n"); + auto list = m_spectrum.buildList(); + for (unsigned i = list.size(); i--;) + dataLog(" ", list[i].key, ": ", list[i].count, "\n"); + } + }); +} + +ICStats::~ICStats() +{ + { + LockHolder locker(m_lock); + m_shouldStop = true; + m_condition.notifyAll(); + } + + waitForThreadCompletion(m_thread); +} + +void ICStats::add(const ICEvent& event) +{ + m_spectrum.add(event); +} + +ICStats& ICStats::instance() +{ + for (;;) { + ICStats* result = s_instance.load(); + if (result) + return *result; + + ICStats* newStats = new ICStats(); + if (s_instance.compareExchangeWeak(nullptr, newStats)) + return *newStats; + + delete newStats; + } +} + +} // namespace JSC + +namespace WTF { + +using namespace JSC; + +void printInternal(PrintStream& out, ICEvent::Kind kind) +{ + switch (kind) { +#define ICEVENT_KIND_DUMP(name) case ICEvent::name: out.print(#name); return; + FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DUMP); +#undef ICEVENT_KIND_DUMP + } + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF + + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ICStats.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ICStats.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/ICStats.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/ICStats.h 2016-11-03 07:04:20.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ICStats_h +#define ICStats_h + +#include "ClassInfo.h" +#include "Identifier.h" +#include +#include +#include +#include +#include +#include +#include + +namespace JSC { + +#define FOR_EACH_ICEVENT_KIND(macro) \ + macro(InvalidKind) \ + macro(GetByIdAddAccessCase) \ + macro(GetByIdReplaceWithJump) \ + macro(GetByIdSelfPatch) \ + macro(InAddAccessCase) \ + macro(InReplaceWithJump) \ + macro(OperationGetById) \ + macro(OperationGetByIdGeneric) \ + macro(OperationGetByIdBuildList) \ + macro(OperationGetByIdOptimize) \ + macro(OperationInOptimize) \ + macro(OperationIn) \ + macro(OperationGenericIn) \ + macro(OperationPutByIdStrict) \ + macro(OperationPutByIdNonStrict) \ + macro(OperationPutByIdDirectStrict) \ + macro(OperationPutByIdDirectNonStrict) \ + macro(OperationPutByIdStrictOptimize) \ + macro(OperationPutByIdNonStrictOptimize) \ + macro(OperationPutByIdDirectStrictOptimize) \ + macro(OperationPutByIdDirectNonStrictOptimize) \ + macro(OperationPutByIdStrictBuildList) \ + macro(OperationPutByIdNonStrictBuildList) \ + macro(OperationPutByIdDirectStrictBuildList) \ + macro(OperationPutByIdDirectNonStrictBuildList) \ + macro(PutByIdAddAccessCase) \ + macro(PutByIdReplaceWithJump) \ + macro(PutByIdSelfPatch) + +class ICEvent { +public: + enum Kind { +#define ICEVENT_KIND_DECLARATION(name) name, + FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DECLARATION) +#undef ICEVENT_KIND_DECLARATION + }; + + ICEvent() + { + } + + ICEvent(Kind kind, const ClassInfo* classInfo, const Identifier propertyName) + : m_kind(kind) + , m_classInfo(classInfo) + , m_propertyName(propertyName) + { + } + + ICEvent(WTF::HashTableDeletedValueType) + : m_kind(OperationGetById) + { + } + + bool operator==(const ICEvent& other) const + { + return m_kind == other.m_kind + && m_classInfo == other.m_classInfo + && m_propertyName == other.m_propertyName; + } + + bool operator!=(const ICEvent& other) const + { + return !(*this == other); + } + + bool operator<(const ICEvent& other) const; + bool operator>(const ICEvent& other) const { return other < *this; } + bool operator<=(const ICEvent& other) const { return !(*this > other); } + bool operator>=(const ICEvent& other) const { return !(*this < other); } + + explicit operator bool() const + { + return *this != ICEvent(); + } + + Kind kind() const { return m_kind; } + const ClassInfo* classInfo() const { return m_classInfo; } + const Identifier& propertyName() const { return m_propertyName; } + + unsigned hash() const + { + return m_kind + WTF::PtrHash::hash(m_classInfo) + StringHash::hash(m_propertyName.string()); + } + + bool isHashTableDeletedValue() const + { + return *this == ICEvent(WTF::HashTableDeletedValue); + } + + void dump(PrintStream&) const; + + void log() const; + +private: + + Kind m_kind { InvalidKind }; + const ClassInfo* m_classInfo { nullptr }; + Identifier m_propertyName; +}; + +struct ICEventHash { + static unsigned hash(const ICEvent& key) { return key.hash(); } + static bool equal(const ICEvent& a, const ICEvent& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} // namespace JSC + +namespace WTF { + +void printInternal(PrintStream&, JSC::ICEvent::Kind); + +template struct DefaultHash; +template<> struct DefaultHash { + typedef JSC::ICEventHash Hash; +}; + +template struct HashTraits; +template<> struct HashTraits : SimpleClassHashTraits { + static const bool emptyValueIsZero = false; +}; + +} // namespace WTF + +namespace JSC { + +class ICStats { + WTF_MAKE_NONCOPYABLE(ICStats); + WTF_MAKE_FAST_ALLOCATED; +public: + ICStats(); + ~ICStats(); + + void add(const ICEvent& event); + + static ICStats& instance(); + +private: + + Spectrum m_spectrum; + ThreadIdentifier m_thread; + Lock m_lock; + Condition m_condition; + bool m_shouldStop { false }; + + static Atomic s_instance; +}; + +#define LOG_IC(arguments) do { \ + if (Options::useICStats()) \ + (ICEvent arguments).log(); \ + } while (false) + +} // namespace JSC + +#endif // ICStats_h + diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,7 @@ #include "JSCJSValueInlines.h" #include "JSCellInlines.h" #include "PolymorphicAccess.h" +#include "StructureStubInfo.h" namespace JSC { @@ -77,7 +78,7 @@ switch (intrinsic()) { case TypedArrayLengthIntrinsic: { jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR); - jit.boxInt32(valueGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters); + jit.boxInt32(valueGPR, valueRegs); state.succeed(); return; } @@ -92,7 +93,7 @@ jit.lshift32(valueGPR, Imm32(logElementSize(type)), valueGPR); } - jit.boxInt32(valueGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters); + jit.boxInt32(valueGPR, valueRegs); state.succeed(); return; } @@ -118,7 +119,7 @@ done.link(&jit); - jit.boxInt32(valueGPR, valueRegs, CCallHelpers::DoNotHaveTagRegisters); + jit.boxInt32(valueGPR, valueRegs); state.succeed(); return; } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITAddGenerator.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITAddGenerator.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITAddGenerator.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITAddGenerator.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,11 +26,48 @@ #include "config.h" #include "JITAddGenerator.h" +#include "ArithProfile.h" +#include "JITMathIC.h" +#include "LinkBuffer.h" + #if ENABLE(JIT) namespace JSC { -void JITAddGenerator::generateFastPath(CCallHelpers& jit) +JITMathICInlineResult JITAddGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state) +{ + // We default to speculating int32. + ObservedType lhs = ObservedType().withInt32(); + ObservedType rhs = ObservedType().withInt32(); + if (m_arithProfile) { + lhs = m_arithProfile->lhsObservedType(); + rhs = m_arithProfile->rhsObservedType(); + } + + if (lhs.isOnlyNonNumber() && rhs.isOnlyNonNumber()) + return JITMathICInlineResult::DontGenerate; + + if ((lhs.isOnlyInt32() || m_leftOperand.isConstInt32()) && (rhs.isOnlyInt32() || m_rightOperand.isConstInt32())) { + ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); + if (!m_leftOperand.isConstInt32()) + state.slowPathJumps.append(jit.branchIfNotInt32(m_left)); + if (!m_rightOperand.isConstInt32()) + state.slowPathJumps.append(jit.branchIfNotInt32(m_right)); + + if (m_leftOperand.isConstInt32() || m_rightOperand.isConstInt32()) { + JSValueRegs var = m_leftOperand.isConstInt32() ? m_right : m_left; + int32_t constValue = m_leftOperand.isConstInt32() ? m_leftOperand.asConstInt32() : m_rightOperand.asConstInt32(); + state.slowPathJumps.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constValue), m_scratchGPR)); + } else + state.slowPathJumps.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR)); + jit.boxInt32(m_scratchGPR, m_result); + return JITMathICInlineResult::GeneratedFastPath; + } + + return JITMathICInlineResult::GenerateFullSnippet; +} + +bool JITAddGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, bool shouldEmitProfiling) { ASSERT(m_scratchGPR != InvalidGPRReg); ASSERT(m_scratchGPR != m_left.payloadGPR()); @@ -43,12 +80,8 @@ ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); - if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber()) { - ASSERT(!m_didEmitFastPath); - return; - } - - m_didEmitFastPath = true; + if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber()) + return false; if (m_leftOperand.isConstInt32() || m_rightOperand.isConstInt32()) { JSValueRegs var = m_leftOperand.isConstInt32() ? m_right : m_left; @@ -58,20 +91,20 @@ // Try to do intVar + intConstant. CCallHelpers::Jump notInt32 = jit.branchIfNotInt32(var); - m_slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), m_scratchGPR)); + slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), m_scratchGPR)); jit.boxInt32(m_scratchGPR, m_result); - m_endJumpList.append(jit.jump()); + endJumpList.append(jit.jump()); if (!jit.supportsFloatingPoint()) { - m_slowPathJumpList.append(notInt32); - return; + slowPathJumpList.append(notInt32); + return true; } // Try to do doubleVar + double(intConstant). notInt32.link(&jit); if (!varOpr.definitelyIsNumber()) - m_slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR)); + slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR)); jit.unboxDoubleNonDestructive(var, m_leftFPR, m_scratchGPR, m_scratchFPR); @@ -89,22 +122,23 @@ leftNotInt = jit.branchIfNotInt32(m_left); rightNotInt = jit.branchIfNotInt32(m_right); - m_slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR)); + slowPathJumpList.append(jit.branchAdd32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR)); jit.boxInt32(m_scratchGPR, m_result); - m_endJumpList.append(jit.jump()); + endJumpList.append(jit.jump()); + if (!jit.supportsFloatingPoint()) { - m_slowPathJumpList.append(leftNotInt); - m_slowPathJumpList.append(rightNotInt); - return; + slowPathJumpList.append(leftNotInt); + slowPathJumpList.append(rightNotInt); + return true; } leftNotInt.link(&jit); if (!m_leftOperand.definitelyIsNumber()) - m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR)); + slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR)); if (!m_rightOperand.definitelyIsNumber()) - m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR)); + slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR)); jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR); CCallHelpers::Jump rightIsDouble = jit.branchIfNotInt32(m_right); @@ -114,7 +148,7 @@ rightNotInt.link(&jit); if (!m_rightOperand.definitelyIsNumber()) - m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR)); + slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR)); jit.convertInt32ToDouble(m_left.payloadGPR(), m_leftFPR); @@ -128,7 +162,12 @@ // Do doubleVar + doubleVar. jit.addDouble(m_rightFPR, m_leftFPR); + if (m_arithProfile && shouldEmitProfiling) + m_arithProfile->emitSetDouble(jit); + jit.boxDouble(m_leftFPR, m_result); + + return true; } } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITAddGenerator.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITAddGenerator.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITAddGenerator.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITAddGenerator.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,15 +29,22 @@ #if ENABLE(JIT) #include "CCallHelpers.h" +#include "JITMathICInlineResult.h" +#include "JITOperations.h" #include "SnippetOperand.h" namespace JSC { +struct MathICGenerationState; + class JITAddGenerator { public: + JITAddGenerator() { } + JITAddGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand, JSValueRegs result, JSValueRegs left, JSValueRegs right, - FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR) + FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR, + ArithProfile* arithProfile = nullptr) : m_leftOperand(leftOperand) , m_rightOperand(rightOperand) , m_result(result) @@ -47,15 +54,18 @@ , m_rightFPR(rightFPR) , m_scratchGPR(scratchGPR) , m_scratchFPR(scratchFPR) + , m_arithProfile(arithProfile) { ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); } - void generateFastPath(CCallHelpers&); + JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&); + bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, bool shouldEmitProfiling); - bool didEmitFastPath() const { return m_didEmitFastPath; } - CCallHelpers::JumpList& endJumpList() { return m_endJumpList; } - CCallHelpers::JumpList& slowPathJumpList() { return m_slowPathJumpList; } + static bool isLeftOperandValidConstant(SnippetOperand leftOperand) { return leftOperand.isPositiveConstInt32(); } + static bool isRightOperandValidConstant(SnippetOperand rightOperand) { return rightOperand.isPositiveConstInt32(); } + + ArithProfile* arithProfile() const { return m_arithProfile; } private: SnippetOperand m_leftOperand; @@ -67,10 +77,7 @@ FPRReg m_rightFPR; GPRReg m_scratchGPR; FPRReg m_scratchFPR; - bool m_didEmitFastPath { false }; - - CCallHelpers::JumpList m_endJumpList; - CCallHelpers::JumpList m_slowPathJumpList; + ArithProfile* m_arithProfile; }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -36,7 +36,6 @@ #include "Interpreter.h" #include "JSCInlines.h" #include "ResultType.h" -#include "SamplingTool.h" #include "SlowPathCall.h" diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITArithmetic.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITArithmetic.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITArithmetic.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITArithmetic.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,7 @@ #if ENABLE(JIT) #include "JIT.h" +#include "ArithProfile.h" #include "CodeBlock.h" #include "JITAddGenerator.h" #include "JITBitAndGenerator.h" @@ -36,6 +37,7 @@ #include "JITDivGenerator.h" #include "JITInlines.h" #include "JITLeftShiftGenerator.h" +#include "JITMathIC.h" #include "JITMulGenerator.h" #include "JITNegGenerator.h" #include "JITOperations.h" @@ -45,11 +47,10 @@ #include "JSFunction.h" #include "Interpreter.h" #include "JSCInlines.h" +#include "LinkBuffer.h" #include "ResultType.h" -#include "SamplingTool.h" #include "SlowPathCall.h" - namespace JSC { void JIT::emit_op_jless(Instruction* currentInstruction) @@ -676,20 +677,42 @@ slowPathCall.call(); } +ALWAYS_INLINE static OperandTypes getOperandTypes(Instruction* instruction) +{ + return OperandTypes(ArithProfile::fromInt(instruction[4].u.operand).lhsResultType(), ArithProfile::fromInt(instruction[4].u.operand).rhsResultType()); +} + void JIT::emit_op_add(Instruction* currentInstruction) { + JITAddIC* addIC = m_codeBlock->addJITAddIC(); + m_instructionToMathIC.add(currentInstruction, addIC); + emitMathICFast(addIC, currentInstruction, operationValueAddProfiled, operationValueAdd); +} + +void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector::iterator& iter) +{ + linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); + + JITAddIC* addIC = bitwise_cast(m_instructionToMathIC.get(currentInstruction)); + emitMathICSlow(addIC, currentInstruction, operationValueAddProfiledOptimize, operationValueAddProfiled, operationValueAddOptimize); +} + +template +void JIT::emitMathICFast(JITMathIC* mathIC, Instruction* currentInstruction, ProfiledFunction profiledFunction, NonProfiledFunction nonProfiledFunction) +{ int result = currentInstruction[1].u.operand; int op1 = currentInstruction[2].u.operand; int op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); #if USE(JSVALUE64) + OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction)); JSValueRegs leftRegs = JSValueRegs(regT0); JSValueRegs rightRegs = JSValueRegs(regT1); - JSValueRegs resultRegs = leftRegs; - GPRReg scratchGPR = regT2; - FPRReg scratchFPR = InvalidFPRReg; + JSValueRegs resultRegs = JSValueRegs(regT2); + GPRReg scratchGPR = regT3; + FPRReg scratchFPR = fpRegT2; #else + OperandTypes types = getOperandTypes(currentInstruction); JSValueRegs leftRegs = JSValueRegs(regT1, regT0); JSValueRegs rightRegs = JSValueRegs(regT3, regT2); JSValueRegs resultRegs = leftRegs; @@ -697,6 +720,10 @@ FPRReg scratchFPR = fpRegT2; #endif + ArithProfile* arithProfile = nullptr; + if (shouldEmitProfiling()) + arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction); + SnippetOperand leftOperand(types.first()); SnippetOperand rightOperand(types.second()); @@ -707,153 +734,161 @@ RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst()); - if (!leftOperand.isConst()) + mathIC->m_generator = Generator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile); + + ASSERT(!(Generator::isLeftOperandValidConstant(leftOperand) && Generator::isRightOperandValidConstant(rightOperand))); + + if (!Generator::isLeftOperandValidConstant(leftOperand)) emitGetVirtualRegister(op1, leftRegs); - if (!rightOperand.isConst()) + if (!Generator::isRightOperandValidConstant(rightOperand)) emitGetVirtualRegister(op2, rightRegs); - JITAddGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, - fpRegT0, fpRegT1, scratchGPR, scratchFPR); +#if ENABLE(MATH_IC_STATS) + auto inlineStart = label(); +#endif - gen.generateFastPath(*this); + MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.add(currentInstruction, MathICGenerationState()).iterator->value; - if (gen.didEmitFastPath()) { - gen.endJumpList().link(this); - emitPutVirtualRegister(result, resultRegs); - - addSlowCase(gen.slowPathJumpList()); - } else { - ASSERT(gen.endJumpList().empty()); - ASSERT(gen.slowPathJumpList().empty()); - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add); - slowPathCall.call(); - } -} - -void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector::iterator& iter) -{ - linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); + bool generatedInlineCode = mathIC->generateInline(*this, mathICGenerationState); + if (!generatedInlineCode) { + if (leftOperand.isConst()) + emitGetVirtualRegister(op1, leftRegs); + else if (rightOperand.isConst()) + emitGetVirtualRegister(op2, rightRegs); + if (arithProfile) + callOperation(profiledFunction, resultRegs, leftRegs, rightRegs, arithProfile); + else + callOperation(nonProfiledFunction, resultRegs, leftRegs, rightRegs); + } else + addSlowCase(mathICGenerationState.slowPathJumps); + +#if ENABLE(MATH_IC_STATS) + auto inlineEnd = label(); + addLinkTask([=] (LinkBuffer& linkBuffer) { + size_t size = static_cast(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast(linkBuffer.locationOf(inlineStart).executableAddress()); + mathIC->m_generatedCodeSize += size; + }); +#endif - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_add); - slowPathCall.call(); + emitPutVirtualRegister(result, resultRegs); } -void JIT::emit_op_div(Instruction* currentInstruction) +template +void JIT::emitMathICSlow(JITMathIC* mathIC, Instruction* currentInstruction, ProfiledRepatchFunction profiledRepatchFunction, ProfiledFunction profiledFunction, RepatchFunction repatchFunction) { + MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)->value; + mathICGenerationState.slowPathStart = label(); + int result = currentInstruction[1].u.operand; int op1 = currentInstruction[2].u.operand; int op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); #if USE(JSVALUE64) + OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction)); JSValueRegs leftRegs = JSValueRegs(regT0); JSValueRegs rightRegs = JSValueRegs(regT1); - JSValueRegs resultRegs = leftRegs; - GPRReg scratchGPR = regT2; + JSValueRegs resultRegs = JSValueRegs(regT2); #else + OperandTypes types = getOperandTypes(currentInstruction); JSValueRegs leftRegs = JSValueRegs(regT1, regT0); JSValueRegs rightRegs = JSValueRegs(regT3, regT2); JSValueRegs resultRegs = leftRegs; - GPRReg scratchGPR = regT4; #endif - FPRReg scratchFPR = fpRegT2; - - ResultProfile* resultProfile = nullptr; - if (shouldEmitProfiling()) - resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset); - + SnippetOperand leftOperand(types.first()); SnippetOperand rightOperand(types.second()); if (isOperandConstantInt(op1)) leftOperand.setConstInt32(getOperandConstantInt(op1)); -#if USE(JSVALUE64) - else if (isOperandConstantDouble(op1)) - leftOperand.setConstDouble(getOperandConstantDouble(op1)); -#endif - - if (isOperandConstantInt(op2)) + else if (isOperandConstantInt(op2)) rightOperand.setConstInt32(getOperandConstantInt(op2)); -#if USE(JSVALUE64) - else if (isOperandConstantDouble(op2)) - rightOperand.setConstDouble(getOperandConstantDouble(op2)); -#endif - RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst()); + ASSERT(!(Generator::isLeftOperandValidConstant(leftOperand) && Generator::isRightOperandValidConstant(rightOperand))); - if (!leftOperand.isConst()) + if (Generator::isLeftOperandValidConstant(leftOperand)) emitGetVirtualRegister(op1, leftRegs); - if (!rightOperand.isConst()) + else if (Generator::isRightOperandValidConstant(rightOperand)) emitGetVirtualRegister(op2, rightRegs); - JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, - fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile); - - gen.generateFastPath(*this); - - if (gen.didEmitFastPath()) { - gen.endJumpList().link(this); - emitPutVirtualRegister(result, resultRegs); +#if ENABLE(MATH_IC_STATS) + auto slowPathStart = label(); +#endif - addSlowCase(gen.slowPathJumpList()); - } else { - ASSERT(gen.endJumpList().empty()); - ASSERT(gen.slowPathJumpList().empty()); - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); - slowPathCall.call(); - } -} + if (shouldEmitProfiling()) { + ArithProfile& arithProfile = m_codeBlock->arithProfileForPC(currentInstruction); + if (mathICGenerationState.shouldSlowPathRepatch) + mathICGenerationState.slowPathCall = callOperation(bitwise_cast(profiledRepatchFunction), resultRegs, leftRegs, rightRegs, &arithProfile, TrustedImmPtr(mathIC)); + else + mathICGenerationState.slowPathCall = callOperation(profiledFunction, resultRegs, leftRegs, rightRegs, &arithProfile); + } else + mathICGenerationState.slowPathCall = callOperation(bitwise_cast(repatchFunction), resultRegs, leftRegs, rightRegs, TrustedImmPtr(mathIC)); + +#if ENABLE(MATH_IC_STATS) + auto slowPathEnd = label(); + addLinkTask([=] (LinkBuffer& linkBuffer) { + size_t size = static_cast(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast(linkBuffer.locationOf(slowPathStart).executableAddress()); + mathIC->m_generatedCodeSize += size; + }); +#endif -void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector::iterator& iter) -{ - linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); + emitPutVirtualRegister(result, resultRegs); - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); - slowPathCall.call(); + addLinkTask([=] (LinkBuffer& linkBuffer) { + MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)->value; + mathIC->finalizeInlineCode(mathICGenerationState, linkBuffer); + }); } -void JIT::emit_op_mul(Instruction* currentInstruction) +void JIT::emit_op_div(Instruction* currentInstruction) { int result = currentInstruction[1].u.operand; int op1 = currentInstruction[2].u.operand; int op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); #if USE(JSVALUE64) + OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction)); JSValueRegs leftRegs = JSValueRegs(regT0); JSValueRegs rightRegs = JSValueRegs(regT1); - JSValueRegs resultRegs = JSValueRegs(regT2); - GPRReg scratchGPR = regT3; - FPRReg scratchFPR = InvalidFPRReg; + JSValueRegs resultRegs = leftRegs; + GPRReg scratchGPR = regT2; #else + OperandTypes types = getOperandTypes(currentInstruction); JSValueRegs leftRegs = JSValueRegs(regT1, regT0); JSValueRegs rightRegs = JSValueRegs(regT3, regT2); JSValueRegs resultRegs = leftRegs; GPRReg scratchGPR = regT4; - FPRReg scratchFPR = fpRegT2; #endif + FPRReg scratchFPR = fpRegT2; - ResultProfile* resultProfile = nullptr; + ArithProfile* arithProfile = nullptr; if (shouldEmitProfiling()) - resultProfile = m_codeBlock->ensureResultProfile(m_bytecodeOffset); + arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction); SnippetOperand leftOperand(types.first()); SnippetOperand rightOperand(types.second()); if (isOperandConstantInt(op1)) leftOperand.setConstInt32(getOperandConstantInt(op1)); +#if USE(JSVALUE64) + else if (isOperandConstantDouble(op1)) + leftOperand.setConstDouble(getOperandConstantDouble(op1)); +#endif else if (isOperandConstantInt(op2)) rightOperand.setConstInt32(getOperandConstantInt(op2)); +#if USE(JSVALUE64) + else if (isOperandConstantDouble(op2)) + rightOperand.setConstDouble(getOperandConstantDouble(op2)); +#endif RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst()); - if (!leftOperand.isPositiveConstInt32()) + if (!leftOperand.isConst()) emitGetVirtualRegister(op1, leftRegs); - if (!rightOperand.isPositiveConstInt32()) + if (!rightOperand.isConst()) emitGetVirtualRegister(op2, rightRegs); - JITMulGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, - fpRegT0, fpRegT1, scratchGPR, scratchFPR, resultProfile); + JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, + fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile); gen.generateFastPath(*this); @@ -865,67 +900,55 @@ } else { ASSERT(gen.endJumpList().empty()); ASSERT(gen.slowPathJumpList().empty()); - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); + JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); slowPathCall.call(); } } -void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector::iterator& iter) +void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector::iterator& iter) { linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); - - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); + + JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); slowPathCall.call(); } -void JIT::emit_op_sub(Instruction* currentInstruction) +void JIT::emit_op_mul(Instruction* currentInstruction) { - int result = currentInstruction[1].u.operand; - int op1 = currentInstruction[2].u.operand; - int op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - -#if USE(JSVALUE64) - JSValueRegs leftRegs = JSValueRegs(regT0); - JSValueRegs rightRegs = JSValueRegs(regT1); - JSValueRegs resultRegs = leftRegs; - GPRReg scratchGPR = regT2; - FPRReg scratchFPR = InvalidFPRReg; -#else - JSValueRegs leftRegs = JSValueRegs(regT1, regT0); - JSValueRegs rightRegs = JSValueRegs(regT3, regT2); - JSValueRegs resultRegs = leftRegs; - GPRReg scratchGPR = regT4; - FPRReg scratchFPR = fpRegT2; -#endif - - SnippetOperand leftOperand(types.first()); - SnippetOperand rightOperand(types.second()); - - emitGetVirtualRegister(op1, leftRegs); - emitGetVirtualRegister(op2, rightRegs); - - JITSubGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, - fpRegT0, fpRegT1, scratchGPR, scratchFPR); + JITMulIC* mulIC = m_codeBlock->addJITMulIC(); + m_instructionToMathIC.add(currentInstruction, mulIC); + emitMathICFast(mulIC, currentInstruction, operationValueMulProfiled, operationValueMul); +} - gen.generateFastPath(*this); +void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector::iterator& iter) +{ + linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); - ASSERT(gen.didEmitFastPath()); - gen.endJumpList().link(this); - emitPutVirtualRegister(result, resultRegs); + JITMulIC* mulIC = bitwise_cast(m_instructionToMathIC.get(currentInstruction)); + emitMathICSlow(mulIC, currentInstruction, operationValueMulProfiledOptimize, operationValueMulProfiled, operationValueMulOptimize); +} - addSlowCase(gen.slowPathJumpList()); +void JIT::emit_op_sub(Instruction* currentInstruction) +{ + JITSubIC* subIC = m_codeBlock->addJITSubIC(); + m_instructionToMathIC.add(currentInstruction, subIC); + emitMathICFast(subIC, currentInstruction, operationValueSubProfiled, operationValueSub); } void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector::iterator& iter) { linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); + JITSubIC* subIC = bitwise_cast(m_instructionToMathIC.get(currentInstruction)); + emitMathICSlow(subIC, currentInstruction, operationValueSubProfiledOptimize, operationValueSubProfiled, operationValueSubOptimize); +} - JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub); +void JIT::emit_op_pow(Instruction* currentInstruction) +{ + JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_pow); slowPathCall.call(); } -/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */ +/* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL, OP_POW ------------------------------ */ } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITCall32_64.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITCall32_64.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITCall32_64.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITCall32_64.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -37,7 +37,6 @@ #include "JSCInlines.h" #include "LinkBuffer.h" #include "ResultType.h" -#include "SamplingTool.h" #include "SetupVarargsFrame.h" #include "StackAlignment.h" #include @@ -88,6 +87,11 @@ { compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++); } + +void JIT::emitSlow_op_tail_call_forward_arguments(Instruction* currentInstruction, Vector::iterator& iter) +{ + compileOpCallSlowCase(op_tail_call_forward_arguments, currentInstruction, iter, m_callLinkInfoIndex++); +} void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector::iterator& iter) { @@ -123,6 +127,11 @@ { compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++); } + +void JIT::emit_op_tail_call_forward_arguments(Instruction* currentInstruction) +{ + compileOpCall(op_tail_call_forward_arguments, currentInstruction, m_callLinkInfoIndex++); +} void JIT::emit_op_construct_varargs(Instruction* currentInstruction) { @@ -134,7 +143,7 @@ compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++); } -void JIT::compileSetupVarargsFrame(Instruction* instruction, CallLinkInfo* info) +void JIT::compileSetupVarargsFrame(OpcodeID opcode, Instruction* instruction, CallLinkInfo* info) { int thisValue = instruction[3].u.operand; int arguments = instruction[4].u.operand; @@ -142,16 +151,26 @@ int firstVarArgOffset = instruction[6].u.operand; emitLoad(arguments, regT1, regT0); - callOperation(operationSizeFrameForVarargs, regT1, regT0, -firstFreeRegister, firstVarArgOffset); + Z_JITOperation_EJZZ sizeOperation; + if (opcode == op_tail_call_forward_arguments) + sizeOperation = operationSizeFrameForForwardArguments; + else + sizeOperation = operationSizeFrameForVarargs; + callOperation(sizeOperation, regT1, regT0, -firstFreeRegister, firstVarArgOffset); move(TrustedImm32(-firstFreeRegister), regT1); emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1); addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), regT1, stackPointerRegister); emitLoad(arguments, regT2, regT4); - callOperation(operationSetupVarargsFrame, regT1, regT2, regT4, firstVarArgOffset, regT0); + F_JITOperation_EFJZZ setupOperation; + if (opcode == op_tail_call_forward_arguments) + setupOperation = operationSetupForwardArgumentsFrame; + else + setupOperation = operationSetupVarargsFrame; + callOperation(setupOperation, regT1, regT2, regT4, firstVarArgOffset, regT0); move(returnValueGPR, regT1); // Profile the argument count. - load32(Address(regT1, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset), regT2); + load32(Address(regT1, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset), regT2); load8(info->addressOfMaxNumArguments(), regT0); Jump notBiggest = branch32(Above, regT0, regT2); Jump notSaturated = branch32(BelowOrEqual, regT2, TrustedImm32(255)); @@ -195,11 +214,9 @@ addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister); - loadPtr(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0); - loadPtr(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT1); move(TrustedImmPtr(info), regT2); - emitLoad(JSStack::Callee, regT1, regT0); + emitLoad(CallFrameSlot::callee, regT1, regT0); MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info); info->setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true)); emitNakedCall(virtualThunk.code()); @@ -227,11 +244,11 @@ - Caller initializes ReturnPC; CodeBlock. - Caller restores callFrameRegister after return. */ - CallLinkInfo* info; + CallLinkInfo* info = nullptr; if (opcodeID != op_call_eval) info = m_codeBlock->addCallLinkInfo(); - if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs) - compileSetupVarargsFrame(instruction, info); + if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) + compileSetupVarargsFrame(opcodeID, instruction, info); else { int argCount = instruction[3].u.operand; int registerOffset = -instruction[4].u.operand; @@ -246,15 +263,15 @@ addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister); - store32(TrustedImm32(argCount), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); + store32(TrustedImm32(argCount), Address(stackPointerRegister, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); } // SP holds newCallFrame + sizeof(CallerFrameAndPC), with ArgumentCount initialized. uint32_t locationBits = CallSiteIndex(instruction).bits(); - store32(TrustedImm32(locationBits), tagFor(JSStack::ArgumentCount, callFrameRegister)); + store32(TrustedImm32(locationBits), tagFor(CallFrameSlot::argumentCount, callFrameRegister)); emitLoad(callee, regT1, regT0); // regT1, regT0 holds callee. - store32(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); - store32(regT1, Address(stackPointerRegister, JSStack::Callee * static_cast(sizeof(Register)) + TagOffset - sizeof(CallerFrameAndPC))); + store32(regT0, Address(stackPointerRegister, CallFrameSlot::callee * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); + store32(regT1, Address(stackPointerRegister, CallFrameSlot::callee * static_cast(sizeof(Register)) + TagOffset - sizeof(CallerFrameAndPC))); if (opcodeID == op_call_eval) { compileCallEval(instruction); @@ -278,7 +295,7 @@ m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info; checkStackPointerAlignment(); - if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) { + if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) { prepareForTailCallSlow(); m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall(); return; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITCall.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITCall.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITCall.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITCall.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2013-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,7 +38,6 @@ #include "JSCInlines.h" #include "LinkBuffer.h" #include "ResultType.h" -#include "SamplingTool.h" #include "SetupVarargsFrame.h" #include "StackAlignment.h" #include "ThunkGenerators.h" @@ -54,7 +53,7 @@ emitPutVirtualRegister(dst); } -void JIT::compileSetupVarargsFrame(Instruction* instruction, CallLinkInfo* info) +void JIT::compileSetupVarargsFrame(OpcodeID opcode, Instruction* instruction, CallLinkInfo* info) { int thisValue = instruction[3].u.operand; int arguments = instruction[4].u.operand; @@ -62,16 +61,26 @@ int firstVarArgOffset = instruction[6].u.operand; emitGetVirtualRegister(arguments, regT1); - callOperation(operationSizeFrameForVarargs, regT1, -firstFreeRegister, firstVarArgOffset); + Z_JITOperation_EJZZ sizeOperation; + if (opcode == op_tail_call_forward_arguments) + sizeOperation = operationSizeFrameForForwardArguments; + else + sizeOperation = operationSizeFrameForVarargs; + callOperation(sizeOperation, regT1, -firstFreeRegister, firstVarArgOffset); move(TrustedImm32(-firstFreeRegister), regT1); emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1); addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), regT1, stackPointerRegister); emitGetVirtualRegister(arguments, regT2); - callOperation(operationSetupVarargsFrame, regT1, regT2, firstVarArgOffset, regT0); + F_JITOperation_EFJZZ setupOperation; + if (opcode == op_tail_call_forward_arguments) + setupOperation = operationSetupForwardArgumentsFrame; + else + setupOperation = operationSetupVarargsFrame; + callOperation(setupOperation, regT1, regT2, firstVarArgOffset, regT0); move(returnValueGPR, regT1); // Profile the argument count. - load32(Address(regT1, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset), regT2); + load32(Address(regT1, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset), regT2); load8(info->addressOfMaxNumArguments(), regT0); Jump notBiggest = branch32(Above, regT0, regT2); Jump notSaturated = branch32(BelowOrEqual, regT2, TrustedImm32(255)); @@ -114,11 +123,8 @@ addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister); - load64(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0); - move(TrustedImmPtr(info), regT2); - MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info); - info->setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true)); - emitNakedCall(virtualThunk.code()); + load64(Address(stackPointerRegister, sizeof(Register) * CallFrameSlot::callee - sizeof(CallerFrameAndPC)), regT0); + emitDumbVirtualCall(info); addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister); checkStackPointerAlignment(); @@ -148,11 +154,13 @@ COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length); COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call), call_and_tail_call_opcodes_must_be_same_length); COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_varargs), call_and_tail_call_varargs_opcodes_must_be_same_length); + COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_forward_arguments), call_and_tail_call_forward_arguments_opcodes_must_be_same_length); + CallLinkInfo* info; if (opcodeID != op_call_eval) info = m_codeBlock->addCallLinkInfo(); - if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs) - compileSetupVarargsFrame(instruction, info); + if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) + compileSetupVarargsFrame(opcodeID, instruction, info); else { int argCount = instruction[3].u.operand; int registerOffset = -instruction[4].u.operand; @@ -166,15 +174,15 @@ } addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister); - store32(TrustedImm32(argCount), Address(stackPointerRegister, JSStack::ArgumentCount * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); + store32(TrustedImm32(argCount), Address(stackPointerRegister, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + PayloadOffset - sizeof(CallerFrameAndPC))); } // SP holds newCallFrame + sizeof(CallerFrameAndPC), with ArgumentCount initialized. uint32_t bytecodeOffset = instruction - m_codeBlock->instructions().begin(); uint32_t locationBits = CallSiteIndex(bytecodeOffset).bits(); - store32(TrustedImm32(locationBits), Address(callFrameRegister, JSStack::ArgumentCount * static_cast(sizeof(Register)) + TagOffset)); - emitGetVirtualRegister(callee, regT0); // regT0 holds callee. + store32(TrustedImm32(locationBits), Address(callFrameRegister, CallFrameSlot::argumentCount * static_cast(sizeof(Register)) + TagOffset)); - store64(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast(sizeof(Register)) - sizeof(CallerFrameAndPC))); + emitGetVirtualRegister(callee, regT0); // regT0 holds callee. + store64(regT0, Address(stackPointerRegister, CallFrameSlot::callee * static_cast(sizeof(Register)) - sizeof(CallerFrameAndPC))); if (opcodeID == op_call_eval) { compileCallEval(instruction); @@ -212,7 +220,7 @@ return; } - if (opcodeID == op_tail_call_varargs) { + if (opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) { emitRestoreCalleeSaves(); prepareForTailCallSlow(); m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall(); @@ -238,7 +246,7 @@ linkSlowCase(iter); - if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) + if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) emitRestoreCalleeSaves(); move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2); @@ -283,6 +291,11 @@ compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++); } +void JIT::emit_op_tail_call_forward_arguments(Instruction* currentInstruction) +{ + compileOpCall(op_tail_call_forward_arguments, currentInstruction, m_callLinkInfoIndex++); +} + void JIT::emit_op_construct_varargs(Instruction* currentInstruction) { compileOpCall(op_construct_varargs, currentInstruction, m_callLinkInfoIndex++); @@ -317,6 +330,11 @@ { compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++); } + +void JIT::emitSlow_op_tail_call_forward_arguments(Instruction* currentInstruction, Vector::iterator& iter) +{ + compileOpCallSlowCase(op_tail_call_forward_arguments, currentInstruction, iter, m_callLinkInfoIndex++); +} void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector::iterator& iter) { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITCode.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITCode.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITCode.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITCode.h 2016-11-03 07:04:20.000000000 +0000 @@ -212,11 +212,11 @@ public: virtual ~JITCodeWithCodeRef(); - virtual void* executableAddressAtOffset(size_t offset) override; - virtual void* dataAddressAtOffset(size_t offset) override; - virtual unsigned offsetOf(void* pointerIntoCode) override; - virtual size_t size() override; - virtual bool contains(void*) override; + void* executableAddressAtOffset(size_t offset) override; + void* dataAddressAtOffset(size_t offset) override; + unsigned offsetOf(void* pointerIntoCode) override; + size_t size() override; + bool contains(void*) override; protected: CodeRef m_ref; @@ -230,7 +230,7 @@ void initializeCodeRef(CodeRef, CodePtr withArityCheck); - virtual CodePtr addressForCall(ArityCheckMode) override; + CodePtr addressForCall(ArityCheckMode) override; private: CodePtr m_withArityCheck; @@ -244,7 +244,7 @@ void initializeCodeRef(CodeRef); - virtual CodePtr addressForCall(ArityCheckMode) override; + CodePtr addressForCall(ArityCheckMode) override; }; } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JIT.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JIT.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JIT.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JIT.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,16 +43,23 @@ #include "PCToCodeOriginMap.h" #include "ProfilerDatabase.h" #include "ResultType.h" -#include "SamplingTool.h" #include "SlowPathCall.h" #include "StackAlignment.h" +#include "SuperSampler.h" #include "TypeProfilerLog.h" #include +#include using namespace std; namespace JSC { +double totalBaselineCompileTime; +double totalDFGCompileTime; +double totalFTLCompileTime; +double totalFTLDFGCompileTime; +double totalFTLB3CompileTime; + void ctiPatchCallByReturnAddress(ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction) { MacroAssembler::repatchCall( @@ -60,6 +67,14 @@ newCalleeFunction); } +JIT::CodeRef JIT::compileCTINativeCall(VM* vm, NativeFunction func) +{ + if (!vm->canUseJIT()) + return CodeRef::createLLIntCodeRef(llint_native_call_trampoline); + JIT jit(vm, 0); + return jit.privateCompileCTINativeCall(vm, func); +} + JIT::JIT(VM* vm, CodeBlock* codeBlock) : JSInterfaceJIT(vm, codeBlock) , m_interpreter(vm->interpreter) @@ -76,6 +91,10 @@ { } +JIT::~JIT() +{ +} + #if ENABLE(DFG_JIT) void JIT::emitEnterOptimizationCheck() { @@ -87,7 +106,7 @@ skipOptimize.append(branchAdd32(Signed, TrustedImm32(Options::executionCounterIncrementForEntry()), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()))); ASSERT(!m_bytecodeOffset); - copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(); + copyCalleeSavesFromFrameOrRegisterToVMEntryFrameCalleeSavesBuffer(); callOperation(operationOptimize, m_bytecodeOffset); skipOptimize.append(branchTestPtr(Zero, returnValueGPR)); @@ -99,8 +118,10 @@ void JIT::emitNotifyWrite(WatchpointSet* set) { - if (!set || set->state() == IsInvalidated) + if (!set || set->state() == IsInvalidated) { + addSlowCase(Jump()); return; + } addSlowCase(branch8(NotEqual, AbsoluteAddress(set->addressOfState()), TrustedImm32(IsInvalidated))); } @@ -146,11 +167,14 @@ void JIT::privateCompileMainPass() { + if (false) + dataLog("Compiling ", *m_codeBlock, "\n"); + jitAssertTagsInPlace(); jitAssertArgumentCountSane(); Instruction* instructionsBegin = m_codeBlock->instructions().begin(); - unsigned instructionCount = m_codeBlock->instructions().size(); + unsigned instructionCount = m_instructions.size(); m_callLinkInfoIndex = 0; @@ -186,9 +210,8 @@ updateTopCallFrame(); unsigned bytecodeOffset = m_bytecodeOffset; - + switch (opcodeID) { - DEFINE_SLOW_OP(del_by_val) DEFINE_SLOW_OP(in) DEFINE_SLOW_OP(less) DEFINE_SLOW_OP(lesseq) @@ -207,6 +230,7 @@ DEFINE_OP(op_call_eval) DEFINE_OP(op_call_varargs) DEFINE_OP(op_tail_call_varargs) + DEFINE_OP(op_tail_call_forward_arguments) DEFINE_OP(op_construct_varargs) DEFINE_OP(op_catch) DEFINE_OP(op_construct) @@ -214,31 +238,38 @@ DEFINE_OP(op_to_this) DEFINE_OP(op_create_direct_arguments) DEFINE_OP(op_create_scoped_arguments) - DEFINE_OP(op_create_out_of_band_arguments) - DEFINE_OP(op_copy_rest) + DEFINE_OP(op_create_cloned_arguments) + DEFINE_OP(op_argument_count) + DEFINE_OP(op_create_rest) DEFINE_OP(op_get_rest_length) DEFINE_OP(op_check_tdz) DEFINE_OP(op_assert) - DEFINE_OP(op_save) - DEFINE_OP(op_resume) DEFINE_OP(op_debug) DEFINE_OP(op_del_by_id) + DEFINE_OP(op_del_by_val) DEFINE_OP(op_div) DEFINE_OP(op_end) DEFINE_OP(op_enter) DEFINE_OP(op_get_scope) DEFINE_OP(op_eq) DEFINE_OP(op_eq_null) + DEFINE_OP(op_try_get_by_id) case op_get_array_length: + case op_get_by_id_proto_load: + case op_get_by_id_unset: DEFINE_OP(op_get_by_id) + DEFINE_OP(op_get_by_id_with_this) DEFINE_OP(op_get_by_val) + DEFINE_OP(op_get_by_val_with_this) DEFINE_OP(op_overrides_has_instance) DEFINE_OP(op_instanceof) DEFINE_OP(op_instanceof_custom) + DEFINE_OP(op_is_empty) DEFINE_OP(op_is_undefined) DEFINE_OP(op_is_boolean) DEFINE_OP(op_is_number) DEFINE_OP(op_is_string) + DEFINE_OP(op_is_jsarray) DEFINE_OP(op_is_object) DEFINE_OP(op_jeq_null) DEFINE_OP(op_jfalse) @@ -270,24 +301,24 @@ DEFINE_OP(op_new_func_exp) DEFINE_OP(op_new_generator_func) DEFINE_OP(op_new_generator_func_exp) - DEFINE_OP(op_new_arrow_func_exp) DEFINE_OP(op_new_object) DEFINE_OP(op_new_regexp) DEFINE_OP(op_not) DEFINE_OP(op_nstricteq) DEFINE_OP(op_dec) DEFINE_OP(op_inc) - DEFINE_OP(op_profile_did_call) - DEFINE_OP(op_profile_will_call) + DEFINE_OP(op_pow) DEFINE_OP(op_profile_type) DEFINE_OP(op_profile_control_flow) DEFINE_OP(op_push_with_scope) DEFINE_OP(op_create_lexical_environment) DEFINE_OP(op_get_parent_scope) DEFINE_OP(op_put_by_id) + DEFINE_OP(op_put_by_id_with_this) DEFINE_OP(op_put_by_index) case op_put_by_val_direct: DEFINE_OP(op_put_by_val) + DEFINE_OP(op_put_by_val_with_this) DEFINE_OP(op_put_getter_by_id) DEFINE_OP(op_put_setter_by_id) DEFINE_OP(op_put_getter_setter_by_id) @@ -298,6 +329,7 @@ DEFINE_OP(op_rshift) DEFINE_OP(op_unsigned) DEFINE_OP(op_urshift) + DEFINE_OP(op_set_function_name) DEFINE_OP(op_strcat) DEFINE_OP(op_stricteq) DEFINE_OP(op_sub) @@ -325,6 +357,9 @@ DEFINE_OP(op_enumerator_structure_pname) DEFINE_OP(op_enumerator_generic_pname) DEFINE_OP(op_to_index_string) + + DEFINE_OP(op_log_shadow_chicken_prologue) + DEFINE_OP(op_log_shadow_chicken_tail) default: RELEASE_ASSERT_NOT_REACHED(); } @@ -396,6 +431,7 @@ DEFINE_SLOWCASE_OP(op_call_eval) DEFINE_SLOWCASE_OP(op_call_varargs) DEFINE_SLOWCASE_OP(op_tail_call_varargs) + DEFINE_SLOWCASE_OP(op_tail_call_forward_arguments) DEFINE_SLOWCASE_OP(op_construct_varargs) DEFINE_SLOWCASE_OP(op_construct) DEFINE_SLOWCASE_OP(op_to_this) @@ -403,12 +439,14 @@ DEFINE_SLOWCASE_OP(op_create_this) DEFINE_SLOWCASE_OP(op_div) DEFINE_SLOWCASE_OP(op_eq) + DEFINE_SLOWCASE_OP(op_try_get_by_id) case op_get_array_length: + case op_get_by_id_proto_load: + case op_get_by_id_unset: DEFINE_SLOWCASE_OP(op_get_by_id) DEFINE_SLOWCASE_OP(op_get_by_val) DEFINE_SLOWCASE_OP(op_instanceof) DEFINE_SLOWCASE_OP(op_instanceof_custom) - DEFINE_SLOWCASE_OP(op_jfalse) DEFINE_SLOWCASE_OP(op_jless) DEFINE_SLOWCASE_OP(op_jlesseq) DEFINE_SLOWCASE_OP(op_jgreater) @@ -417,7 +455,6 @@ DEFINE_SLOWCASE_OP(op_jnlesseq) DEFINE_SLOWCASE_OP(op_jngreater) DEFINE_SLOWCASE_OP(op_jngreatereq) - DEFINE_SLOWCASE_OP(op_jtrue) DEFINE_SLOWCASE_OP(op_loop_hint) DEFINE_SLOWCASE_OP(op_watchdog) DEFINE_SLOWCASE_OP(op_lshift) @@ -476,8 +513,17 @@ #endif } -CompilationResult JIT::privateCompile(JITCompilationEffort effort) +void JIT::compileWithoutLinking(JITCompilationEffort effort) { + double before = 0; + if (UNLIKELY(computeCompileTimes())) + before = monotonicallyIncreasingTimeMS(); + + { + ConcurrentJITLocker locker(m_codeBlock->m_lock); + m_instructions = m_codeBlock->instructions().clone(); + } + DFG::CapabilityLevel level = m_codeBlock->capabilityLevel(); switch (level) { case DFG::CannotCompile: @@ -509,13 +555,7 @@ break; } - m_codeBlock->setCalleeSaveRegisters(RegisterSet::llintBaselineCalleeSaveRegisters()); // Might be able to remove as this is probably already set to this value. - - // This ensures that we have the most up to date type information when performing typecheck optimizations for op_profile_type. - if (m_vm->typeProfiler()) - m_vm->typeProfilerLog()->processLogEntries(ASCIILiteral("Preparing for JIT compilation.")); - - if (Options::dumpDisassembly() || m_vm->m_perBytecodeProfiler) + if (Options::dumpDisassembly() || (m_vm->m_perBytecodeProfiler && Options::disassembleBaselineForProfiler())) m_disassembler = std::make_unique(m_codeBlock); if (m_vm->m_perBytecodeProfiler) { m_compilation = adoptRef( @@ -535,7 +575,7 @@ nop(); emitFunctionPrologue(); - emitPutToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); + emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock); Label beginLabel(this); @@ -565,13 +605,15 @@ } addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, regT1); - Jump stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfStackLimit()), regT1); + Jump stackOverflow = branchPtr(Above, AbsoluteAddress(m_vm->addressOfSoftStackLimit()), regT1); move(regT1, stackPointerRegister); checkStackPointerAlignment(); emitSaveCalleeSaves(); emitMaterializeTagCheckRegisters(); + + RELEASE_ASSERT(!JITCode::isJIT(m_codeBlock->jitType())); privateCompileMainPass(); privateCompileLinkPass(); @@ -587,14 +629,13 @@ addPtr(TrustedImm32(-maxFrameExtentForSlowPathCall), stackPointerRegister); callOperationWithCallFrameRollbackOnException(operationThrowStackOverflowError, m_codeBlock); - Label arityCheck; if (m_codeBlock->codeType() == FunctionCode) { - arityCheck = label(); + m_arityCheck = label(); store8(TrustedImm32(0), &m_codeBlock->m_shouldAlwaysBeInlined); emitFunctionPrologue(); - emitPutToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); + emitPutToCallFrameHeader(m_codeBlock, CallFrameSlot::codeBlock); - load32(payloadFor(JSStack::ArgumentCount), regT1); + load32(payloadFor(CallFrameSlot::argumentCount), regT1); branch32(AboveOrEqual, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this); m_bytecodeOffset = 0; @@ -623,8 +664,26 @@ m_disassembler->setEndOfCode(label()); m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder::defaultCodeOrigin()); + m_linkBuffer = std::unique_ptr(new LinkBuffer(*m_vm, *this, m_codeBlock, effort)); + + double after = 0; + if (UNLIKELY(computeCompileTimes())) { + after = monotonicallyIncreasingTimeMS(); - LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock, effort); + if (Options::reportTotalCompileTimes()) + totalBaselineCompileTime += after - before; + } + if (UNLIKELY(reportCompileTimes())) { + CString codeBlockName = toCString(*m_codeBlock); + + dataLog("Optimized ", codeBlockName, " with Baseline JIT into ", m_linkBuffer->size(), " bytes in ", after - before, " ms.\n"); + } +} + +CompilationResult JIT::link() +{ + LinkBuffer& patchBuffer = *m_linkBuffer; + if (patchBuffer.didFailToAllocate()) return CompilationFailed; @@ -671,27 +730,33 @@ for (unsigned i = m_putByIds.size(); i--;) m_putByIds[i].finalize(patchBuffer); - for (const auto& byValCompilationInfo : m_byValCompilationInfo) { - PatchableJump patchableNotIndexJump = byValCompilationInfo.notIndexJump; - CodeLocationJump notIndexJump = CodeLocationJump(); - if (Jump(patchableNotIndexJump).isSet()) - notIndexJump = CodeLocationJump(patchBuffer.locationOf(patchableNotIndexJump)); - CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(byValCompilationInfo.badTypeJump)); - CodeLocationLabel doneTarget = patchBuffer.locationOf(byValCompilationInfo.doneTarget); - CodeLocationLabel nextHotPathTarget = patchBuffer.locationOf(byValCompilationInfo.nextHotPathTarget); - CodeLocationLabel slowPathTarget = patchBuffer.locationOf(byValCompilationInfo.slowPathTarget); - CodeLocationCall returnAddress = patchBuffer.locationOf(byValCompilationInfo.returnAddress); - - *byValCompilationInfo.byValInfo = ByValInfo( - byValCompilationInfo.bytecodeIndex, - notIndexJump, - badTypeJump, - byValCompilationInfo.arrayMode, - byValCompilationInfo.arrayProfile, - differenceBetweenCodePtr(badTypeJump, doneTarget), - differenceBetweenCodePtr(badTypeJump, nextHotPathTarget), - differenceBetweenCodePtr(returnAddress, slowPathTarget)); + if (m_byValCompilationInfo.size()) { + CodeLocationLabel exceptionHandler = patchBuffer.locationOf(m_exceptionHandler); + + for (const auto& byValCompilationInfo : m_byValCompilationInfo) { + PatchableJump patchableNotIndexJump = byValCompilationInfo.notIndexJump; + CodeLocationJump notIndexJump = CodeLocationJump(); + if (Jump(patchableNotIndexJump).isSet()) + notIndexJump = CodeLocationJump(patchBuffer.locationOf(patchableNotIndexJump)); + CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(byValCompilationInfo.badTypeJump)); + CodeLocationLabel doneTarget = patchBuffer.locationOf(byValCompilationInfo.doneTarget); + CodeLocationLabel nextHotPathTarget = patchBuffer.locationOf(byValCompilationInfo.nextHotPathTarget); + CodeLocationLabel slowPathTarget = patchBuffer.locationOf(byValCompilationInfo.slowPathTarget); + CodeLocationCall returnAddress = patchBuffer.locationOf(byValCompilationInfo.returnAddress); + + *byValCompilationInfo.byValInfo = ByValInfo( + byValCompilationInfo.bytecodeIndex, + notIndexJump, + badTypeJump, + exceptionHandler, + byValCompilationInfo.arrayMode, + byValCompilationInfo.arrayProfile, + differenceBetweenCodePtr(badTypeJump, doneTarget), + differenceBetweenCodePtr(badTypeJump, nextHotPathTarget), + differenceBetweenCodePtr(returnAddress, slowPathTarget)); + } } + for (unsigned i = 0; i < m_callCompilationInfo.size(); ++i) { CallCompilationInfo& compilationInfo = m_callCompilationInfo[i]; CallLinkInfo& info = *compilationInfo.callLinkInfo; @@ -709,15 +774,16 @@ MacroAssemblerCodePtr withArityCheck; if (m_codeBlock->codeType() == FunctionCode) - withArityCheck = patchBuffer.locationOf(arityCheck); + withArityCheck = patchBuffer.locationOf(m_arityCheck); if (Options::dumpDisassembly()) { m_disassembler->dump(patchBuffer); patchBuffer.didAlreadyDisassemble(); } if (m_compilation) { - m_disassembler->reportToProfiler(m_compilation.get(), patchBuffer); - m_vm->m_perBytecodeProfiler->addCompilation(m_compilation); + if (Options::disassembleBaselineForProfiler()) + m_disassembler->reportToProfiler(m_compilation.get(), patchBuffer); + m_vm->m_perBytecodeProfiler->addCompilation(m_codeBlock, m_compilation); } if (m_pcToCodeOriginMapBuilder.didBuildMapping()) @@ -727,14 +793,14 @@ patchBuffer, ("Baseline JIT code for %s", toCString(CodeBlockWithJITType(m_codeBlock, JITCode::BaselineJIT)).data())); - m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.add( + m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT->add( static_cast(result.size()) / - static_cast(m_codeBlock->instructions().size())); + static_cast(m_instructions.size())); m_codeBlock->shrinkToFit(CodeBlock::LateShrink); m_codeBlock->setJITCode( adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT))); - + #if ENABLE(JIT_VERBOSE) dataLogF("JIT generated code for %p at [%p, %p).\n", m_codeBlock, result.executableMemory()->start(), result.executableMemory()->end()); #endif @@ -742,12 +808,19 @@ return CompilationSuccessful; } +CompilationResult JIT::privateCompile(JITCompilationEffort effort) +{ + doMainThreadPreparationBeforeCompile(); + compileWithoutLinking(effort); + return link(); +} + void JIT::privateCompileExceptionHandlers() { if (!m_exceptionChecksWithCallFrameRollback.empty()) { m_exceptionChecksWithCallFrameRollback.link(this); - copyCalleeSavesToVMCalleeSavesBuffer(); + copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(); // lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*). @@ -763,10 +836,11 @@ jumpToExceptionHandler(); } - if (!m_exceptionChecks.empty()) { + if (!m_exceptionChecks.empty() || m_byValCompilationInfo.size()) { + m_exceptionHandler = label(); m_exceptionChecks.link(this); - copyCalleeSavesToVMCalleeSavesBuffer(); + copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(); // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*). move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0); @@ -782,6 +856,13 @@ } } +void JIT::doMainThreadPreparationBeforeCompile() +{ + // This ensures that we have the most up to date type information when performing typecheck optimizations for op_profile_type. + if (m_vm->typeProfiler()) + m_vm->typeProfilerLog()->processLogEntries(ASCIILiteral("Preparing for JIT compilation.")); +} + unsigned JIT::frameRegisterCountFor(CodeBlock* codeBlock) { ASSERT(static_cast(codeBlock->m_numCalleeLocals) == WTF::roundUpToMultipleOf(stackAlignmentRegisters(), static_cast(codeBlock->m_numCalleeLocals))); @@ -794,6 +875,34 @@ return virtualRegisterForLocal(frameRegisterCountFor(codeBlock) - 1).offset(); } +bool JIT::reportCompileTimes() +{ + return Options::reportCompileTimes() || Options::reportBaselineCompileTimes(); +} + +bool JIT::computeCompileTimes() +{ + return reportCompileTimes() || Options::reportTotalCompileTimes(); +} + +HashMap JIT::compileTimeStats() +{ + HashMap result; + if (Options::reportTotalCompileTimes()) { + result.add("Total Compile Time", totalBaselineCompileTime + totalDFGCompileTime + totalFTLCompileTime); + result.add("Baseline Compile Time", totalBaselineCompileTime); +#if ENABLE(DFG_JIT) + result.add("DFG Compile Time", totalDFGCompileTime); +#if ENABLE(FTL_JIT) + result.add("FTL Compile Time", totalFTLCompileTime); + result.add("FTL (DFG) Compile Time", totalFTLDFGCompileTime); + result.add("FTL (B3) Compile Time", totalFTLB3CompileTime); +#endif // ENABLE(FTL_JIT) +#endif // ENABLE(DFG_JIT) + } + return result; +} + } // namespace JSC #endif // ENABLE(JIT) diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITDisassembler.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITDisassembler.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITDisassembler.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITDisassembler.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012-2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,6 +33,7 @@ #include "JIT.h" #include "JSCInlines.h" #include "LinkBuffer.h" +#include "ProfilerCompilation.h" #include namespace JSC { diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITDivGenerator.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITDivGenerator.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITDivGenerator.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITDivGenerator.cpp 2016-09-16 09:56:47.000000000 +0000 @@ -28,13 +28,19 @@ #if ENABLE(JIT) +#include "ArithProfile.h" #include "JSCJSValueInlines.h" +#include "MathCommon.h" namespace JSC { void JITDivGenerator::loadOperand(CCallHelpers& jit, SnippetOperand& opr, JSValueRegs oprRegs, FPRReg destFPR) { if (opr.isConstInt32()) { + // FIXME: this does not looks right. + // -On x86_64, CVTSI2SD has partial register stall on its FPR. + // A move or load might be a tiny bit larger but safer. + // -On ARM64 we also have FMOV that can load small immediates. jit.move(CCallHelpers::Imm32(opr.asConstInt32()), m_scratchGPR); jit.convertInt32ToDouble(m_scratchGPR, destFPR); #if USE(JSVALUE64) @@ -74,14 +80,31 @@ ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); m_didEmitFastPath = true; loadOperand(jit, m_leftOperand, m_left, m_leftFPR); - loadOperand(jit, m_rightOperand, m_right, m_rightFPR); - jit.divDouble(m_rightFPR, m_leftFPR); +#if USE(JSVALUE64) + Optional safeReciprocal; + if (m_rightOperand.isConst()) { + double constant = m_rightOperand.asConstNumber(); + safeReciprocal = safeReciprocalForDivByConst(constant); + } + + if (safeReciprocal) { + jit.move(CCallHelpers::Imm64(bitwise_cast(*safeReciprocal)), m_scratchGPR); + jit.move64ToDouble(m_scratchGPR, m_rightFPR); + + jit.mulDouble(m_rightFPR, m_leftFPR); + } else +#endif + { + loadOperand(jit, m_rightOperand, m_right, m_rightFPR); + + jit.divDouble(m_rightFPR, m_leftFPR); + } // Is the result actually an integer? The DFG JIT would really like to know. If it's - // not an integer, we increment a count. If this together with the slow case counter - // are below threshold then the DFG JIT will compile this division with a speculation - // that the remainder is zero. + // not an integer, we set a bit. If this together with the slow case counter are below + // threshold then the DFG JIT will compile this division with a speculation that the + // remainder is zero. // As well, there are cases where a double result here would cause an important field // in the heap to sometimes have doubles in it, resulting in double predictions getting @@ -106,8 +129,8 @@ notDoubleZero.link(&jit); #endif - if (m_resultProfile) - jit.add32(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(m_resultProfile->addressOfSpecialFastPathCount())); + if (m_arithProfile) + jit.or32(CCallHelpers::TrustedImm32(ArithProfile::specialFastPathBit), CCallHelpers::AbsoluteAddress(m_arithProfile->addressOfBits())); jit.boxDouble(m_leftFPR, m_result); } diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITDivGenerator.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITDivGenerator.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITDivGenerator.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITDivGenerator.h 2016-11-03 07:04:20.000000000 +0000 @@ -38,7 +38,7 @@ JITDivGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand, JSValueRegs result, JSValueRegs left, JSValueRegs right, FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR, - ResultProfile* resultProfile = nullptr) + ArithProfile* arithProfile = nullptr) : m_leftOperand(leftOperand) , m_rightOperand(rightOperand) , m_result(result) @@ -48,7 +48,7 @@ , m_rightFPR(rightFPR) , m_scratchGPR(scratchGPR) , m_scratchFPR(scratchFPR) - , m_resultProfile(resultProfile) + , m_arithProfile(arithProfile) { ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32()); } @@ -71,7 +71,7 @@ FPRReg m_rightFPR; GPRReg m_scratchGPR; FPRReg m_scratchFPR; - ResultProfile* m_resultProfile; + ArithProfile* m_arithProfile; bool m_didEmitFastPath { false }; CCallHelpers::JumpList m_endJumpList; diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITExceptions.cpp webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITExceptions.cpp --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITExceptions.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITExceptions.cpp 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012-2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,12 +29,13 @@ #include "CallFrame.h" #include "CodeBlock.h" #include "Interpreter.h" +#include "JSCInlines.h" #include "JSCJSValue.h" #include "LLIntData.h" #include "LLIntOpcode.h" #include "LLIntThunks.h" #include "Opcode.h" -#include "JSCInlines.h" +#include "ShadowChicken.h" #include "VM.h" namespace JSC { @@ -50,6 +51,13 @@ CRASH(); } + ExecState* shadowChickenTopFrame = callFrame; + if (unwindStart == UnwindFromCallerFrame) { + VMEntryFrame* topVMEntryFrame = vm->topVMEntryFrame; + shadowChickenTopFrame = callFrame->callerFrame(topVMEntryFrame); + } + vm->shadowChicken().log(*vm, shadowChickenTopFrame, ShadowChicken::Packet::throwPacket()); + Exception* exception = vm->exception(); RELEASE_ASSERT(exception); HandlerInfo* handler = vm->interpreter->unwind(*vm, callFrame, exception, unwindStart); // This may update callFrame. @@ -73,6 +81,8 @@ } else catchRoutine = LLInt::getCodePtr(handleUncaughtException); + ASSERT(bitwise_cast(callFrame) < bitwise_cast(vm->topVMEntryFrame)); + vm->callFrameForCatch = callFrame; vm->targetMachinePCForThrow = catchRoutine; vm->targetInterpreterPCForThrow = catchPCForInterpreter; @@ -80,4 +90,9 @@ RELEASE_ASSERT(catchRoutine); } +void genericUnwind(VM* vm, ExecState* callFrame) +{ + genericUnwind(vm, callFrame, UnwindFromCurrentFrame); +} + } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITExceptions.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITExceptions.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JITExceptions.h 2016-04-11 06:18:43.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JITExceptions.h 2016-11-03 07:04:20.000000000 +0000 @@ -26,15 +26,15 @@ #ifndef JITExceptions_h #define JITExceptions_h -#include "Interpreter.h" -#include "JSCJSValue.h" - namespace JSC { +enum UnwindStart : uint8_t; + class ExecState; class VM; -void genericUnwind(VM*, ExecState*, UnwindStart = UnwindFromCurrentFrame); +void genericUnwind(VM*, ExecState*, UnwindStart); +void genericUnwind(VM*, ExecState*); } // namespace JSC diff -Nru webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JIT.h webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JIT.h --- webkit2gtk-2.12.3/Source/JavaScriptCore/jit/JIT.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Source/JavaScriptCore/jit/JIT.h 2016-11-03 07:04:20.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2012-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,18 +40,17 @@ #include "CodeBlock.h" #include "CompactJITCodeMap.h" -#include "Interpreter.h" #include "JITDisassembler.h" #include "JITInlineCacheGenerator.h" +#include "JITMathIC.h" #include "JSInterfaceJIT.h" -#include "Opcode.h" #include "PCToCodeOriginMap.h" -#include "ResultType.h" -#include "SamplingTool.h" #include "UnusedPointer.h" namespace JSC { + enum OpcodeID : unsigned; + class ArrayAllocationProfile; class CallLinkInfo; class CodeBlock; @@ -60,7 +59,6 @@ class Identifier; class Interpreter; class JSScope; - class JSStack; class MarkedAllocator; class Register; class StructureChain; @@ -102,12 +100,10 @@ struct SlowCaseEntry { MacroAssembler::Jump from; unsigned to; - unsigned hint; - SlowCaseEntry(MacroAssembler::Jump f, unsigned t, unsigned h = 0) + SlowCaseEntry(MacroAssembler::Jump f, unsigned t) : from(f) , to(t) - , hint(h) { } }; @@ -197,6 +193,14 @@ static const int patchPutByIdDefaultOffset = 256; public: + JIT(VM*, CodeBlock* = 0); + ~JIT(); + + void compileWithoutLinking(JITCompilationEffort); + CompilationResult link(); + + void doMainThreadPreparationBeforeCompile(); + static CompilationResult compile(VM* vm, CodeBlock* codeBlock, JITCompilationEffort effort) { return JIT(vm, codeBlock).privateCompile(effort); @@ -244,21 +248,14 @@ jit.privateCompileHasIndexedProperty(byValInfo, returnAddress, arrayMode); } - static CodeRef compileCTINativeCall(VM* vm, NativeFunction func) - { - if (!vm->canUseJIT()) { - return CodeRef::createLLIntCodeRef(llint_native_call_trampoline); - } - JIT jit(vm, 0); - return jit.privateCompileCTINativeCall(vm, func); - } + static CodeRef compileCTINativeCall(VM*, NativeFunction); static unsigned frameRegisterCountFor(CodeBlock*); static int stackPointerOffsetFor(CodeBlock*); - private: - JIT(VM*, CodeBlock* = 0); + JS_EXPORT_PRIVATE static HashMap compileTimeStats(); + private: void privateCompileMainPass(); void privateCompileLinkPass(); void privateCompileSlowCases(); @@ -310,14 +307,14 @@ void privateCompileExceptionHandlers(); void addSlowCase(Jump); - void addSlowCase(JumpList); + void addSlowCase(const JumpList&); void addSlowCase(); void addJump(Jump, int); void emitJumpSlowToHot(Jump, int); void compileOpCall(OpcodeID, Instruction*, unsigned callLinkInfoIndex); void compileOpCallSlowCase(OpcodeID, Instruction*, Vector::iterator&, unsigned callLinkInfoIndex); - void compileSetupVarargsFrame(Instruction*, CallLinkInfo*); + void compileSetupVarargsFrame(OpcodeID, Instruction*, CallLinkInfo*); void compileCallEval(Instruction*); void compileCallEvalSlowCase(Instruction*, Vector::iterator&); void emitPutCallResult(Instruction*); @@ -338,9 +335,6 @@ void emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode); void emitWriteBarrier(JSCell* owner); - template // StructureType can be RegisterID or ImmPtr. - void emitAllocateJSObject(RegisterID allocator, StructureType, RegisterID result, RegisterID scratch); - // This assumes that the value to profile is in regT0 and that regT3 is available for // scratch. void emitValueProfilingSite(ValueProfile*); @@ -394,10 +388,10 @@ JumpList emitFloatTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType); // Identifier check helper for GetByVal and PutByVal. - void emitIdentifierCheck(RegisterID cell, RegisterID scratch, const Identifier&, JumpList& slowCases); + void emitByValIdentifierCheck(ByValInfo*, RegisterID cell, RegisterID scratch, const Identifier&, JumpList& slowCases); - JITGetByIdGenerator emitGetByValWithCachedId(Instruction*, const Identifier&, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases); - JITPutByIdGenerator emitPutByValWithCachedId(Instruction*, PutKind, const Identifier&, JumpList& doneCases, JumpList& slowCases); + JITGetByIdGenerator emitGetByValWithCachedId(ByValInfo*, Instruction*, const Identifier&, Jump& fastDoneCase, Jump& slowDoneCase, JumpList& slowCases); + JITPutByIdGenerator emitPutByValWithCachedId(ByValInfo*, Instruction*, PutKind, const Identifier&, JumpList& doneCases, JumpList& slowCases); enum FinalObjectMode { MayBeFinal, KnownNotFinal }; @@ -431,7 +425,6 @@ void compileGetByIdHotPath(const Identifier*); // Arithmetic opcode helpers - void emitSub32Constant(int dst, int op, int32_t constant, ResultType opType); void emitBinaryDoubleOp(OpcodeID, int dst, int op1, int op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true); #else // USE(JSVALUE32_64) @@ -483,6 +476,7 @@ void emit_op_call_eval(Instruction*); void emit_op_call_varargs(Instruction*); void emit_op_tail_call_varargs(Instruction*); + void emit_op_tail_call_forward_arguments(Instruction*); void emit_op_construct_varargs(Instruction*); void emit_op_catch(Instruction*); void emit_op_construct(Instruction*); @@ -490,22 +484,25 @@ void emit_op_to_this(Instruction*); void emit_op_create_direct_arguments(Instruction*); void emit_op_create_scoped_arguments(Instruction*); - void emit_op_create_out_of_band_arguments(Instruction*); - void emit_op_copy_rest(Instruction*); + void emit_op_create_cloned_arguments(Instruction*); + void emit_op_argument_count(Instruction*); + void emit_op_create_rest(Instruction*); void emit_op_get_rest_length(Instruction*); void emit_op_check_tdz(Instruction*); void emit_op_assert(Instruction*); - void emit_op_save(Instruction*); - void emit_op_resume(Instruction*); void emit_op_debug(Instruction*); void emit_op_del_by_id(Instruction*); + void emit_op_del_by_val(Instruction*); void emit_op_div(Instruction*); void emit_op_end(Instruction*); void emit_op_enter(Instruction*); void emit_op_get_scope(Instruction*); void emit_op_eq(Instruction*); void emit_op_eq_null(Instruction*); + void emit_op_try_get_by_id(Instruction*); void emit_op_get_by_id(Instruction*); + void emit_op_get_by_id_with_this(Instruction*); + void emit_op_get_by_val_with_this(Instruction*); void emit_op_get_arguments_length(Instruction*); void emit_op_get_by_val(Instruction*); void emit_op_get_argument_by_val(Instruction*); @@ -513,10 +510,12 @@ void emit_op_overrides_has_instance(Instruction*); void emit_op_instanceof(Instruction*); void emit_op_instanceof_custom(Instruction*); + void emit_op_is_empty(Instruction*); void emit_op_is_undefined(Instruction*); void emit_op_is_boolean(Instruction*); void emit_op_is_number(Instruction*); void emit_op_is_string(Instruction*); + void emit_op_is_jsarray(Instruction*); void emit_op_is_object(Instruction*); void emit_op_jeq_null(Instruction*); void emit_op_jfalse(Instruction*); @@ -548,23 +547,23 @@ void emit_op_new_func_exp(Instruction*); void emit_op_new_generator_func(Instruction*); void emit_op_new_generator_func_exp(Instruction*); - void emit_op_new_arrow_func_exp(Instruction*); void emit_op_new_object(Instruction*); void emit_op_new_regexp(Instruction*); void emit_op_not(Instruction*); void emit_op_nstricteq(Instruction*); void emit_op_dec(Instruction*); void emit_op_inc(Instruction*); - void emit_op_profile_did_call(Instruction*); - void emit_op_profile_will_call(Instruction*); + void emit_op_pow(Instruction*); void emit_op_profile_type(Instruction*); void emit_op_profile_control_flow(Instruction*); void emit_op_push_with_scope(Instruction*); void emit_op_create_lexical_environment(Instruction*); void emit_op_get_parent_scope(Instruction*); void emit_op_put_by_id(Instruction*); + void emit_op_put_by_id_with_this(Instruction*); void emit_op_put_by_index(Instruction*); void emit_op_put_by_val(Instruction*); + void emit_op_put_by_val_with_this(Instruction*); void emit_op_put_getter_by_id(Instruction*); void emit_op_put_setter_by_id(Instruction*); void emit_op_put_getter_setter_by_id(Instruction*); @@ -572,6 +571,7 @@ void emit_op_put_setter_by_val(Instruction*); void emit_op_ret(Instruction*); void emit_op_rshift(Instruction*); + void emit_op_set_function_name(Instruction*); void emit_op_strcat(Instruction*); void emit_op_stricteq(Instruction*); void emit_op_sub(Instruction*); @@ -596,6 +596,8 @@ void emit_op_enumerator_structure_pname(Instruction*); void emit_op_enumerator_generic_pname(Instruction*); void emit_op_to_index_string(Instruction*); + void emit_op_log_shadow_chicken_prologue(Instruction*); + void emit_op_log_shadow_chicken_tail(Instruction*); void emitSlow_op_add(Instruction*, Vector::iterator&); void emitSlow_op_bitand(Instruction*, Vector::iterator&); @@ -606,6 +608,7 @@ void emitSlow_op_call_eval(Instruction*, Vector::iterator&); void emitSlow_op_call_varargs(Instruction*, Vector::iterator&); void emitSlow_op_tail_call_varargs(Instruction*, Vector::iterator&); + void emitSlow_op_tail_call_forward_arguments(Instruction*, Vector::iterator&); void emitSlow_op_construct_varargs(Instruction*, Vector::iterator&); void emitSlow_op_construct(Instruction*, Vector::iterator&); void emitSlow_op_to_this(Instruction*, Vector::iterator&); @@ -614,13 +617,13 @@ void emitSlow_op_div(Instruction*, Vector::iterator&); void emitSlow_op_eq(Instruction*, Vector::iterator&); void emitSlow_op_get_callee(Instruction*, Vector::iterator&); + void emitSlow_op_try_get_by_id(Instruction*, Vector::iterator&); void emitSlow_op_get_by_id(Instruction*, Vector::iterator&); void emitSlow_op_get_arguments_length(Instruction*, Vector::iterator&); void emitSlow_op_get_by_val(Instruction*, Vector::iterator&); void emitSlow_op_get_argument_by_val(Instruction*, Vector::iterator&); void emitSlow_op_instanceof(Instruction*, Vector::iterator&); void emitSlow_op_instanceof_custom(Instruction*, Vector::iterator&); - void emitSlow_op_jfalse(Instruction*, Vector::iterator&); void emitSlow_op_jless(Instruction*, Vector::iterator&); void emitSlow_op_jlesseq(Instruction*, Vector::iterator&); void emitSlow_op_jgreater(Instruction*, Vector::iterator&); @@ -689,19 +692,26 @@ void emitInitRegister(int dst); - void emitPutIntToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry); + void emitPutIntToCallFrameHeader(RegisterID from, int entry); JSValue getConstantOperand(int src); bool isOperandConstantInt(int src); bool isOperandConstantChar(int src); + template + void emitMathICFast(JITMathIC*, Instruction*, ProfiledFunction, NonProfiledFunction); + + template + void emitMathICSlow(JITMathIC*, Instruction*, ProfiledRepatchFunction, ProfiledFunction, RepatchFunction); + Jump getSlowCase(Vector::iterator& iter) { return iter++->from; } void linkSlowCase(Vector::iterator& iter) { - iter->from.link(this); + if (iter->from.isSet()) + iter->from.link(this); ++iter; } void linkDummySlowCase(Vector::iterator& iter) @@ -738,12 +748,18 @@ MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*); MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg); #if USE(JSVALUE64) + MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*); MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*); #else + MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*); MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, UniquedStringImpl*); #endif - MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, const Identifier*); + MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, UniquedStringImpl*); MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg); + MacroAssembler::Call callOperation(J_JITOperation_EJJArp, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*); + MacroAssembler::Call callOperation(J_JITOperation_EJJ, JSValueRegs, JSValueRegs, JSValueRegs); + MacroAssembler::Call callOperation(J_JITOperation_EJJArpMic, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*, TrustedImmPtr); + MacroAssembler::Call callOperation(J_JITOperation_EJJMic, JSValueRegs, JSValueRegs, JSValueRegs, TrustedImmPtr); MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*); MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*); MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg); @@ -766,6 +782,7 @@ MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, size_t); MacroAssembler::Call callOperation(S_JITOperation_ECC, RegisterID, RegisterID); MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID); + MacroAssembler::Call callOperation(S_JITOperation_EJI, GPRReg, UniquedStringImpl*); MacroAssembler::Call callOperation(S_JITOperation_EJJ, RegisterID, RegisterID); MacroAssembler::Call callOperation(S_JITOperation_EOJss, RegisterID, RegisterID); MacroAssembler::Call callOperation(Sprt_JITOperation_EZ, int32_t); @@ -793,8 +810,10 @@ MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, int32_t, RegisterID); MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, UniquedStringImpl*); MacroAssembler::Call callOperation(V_JITOperation_ECIZJJ, RegisterID, UniquedStringImpl*, int32_t, RegisterID, RegisterID); + MacroAssembler::Call callOperation(V_JITOperation_ECJ, RegisterID, RegisterID); #else MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, RegisterID, RegisterID, UniquedStringImpl*); + MacroAssembler::Call callOperation(V_JITOperation_ECJ, RegisterID, RegisterID, RegisterID); #endif MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID); MacroAssembler::Call callOperation(V_JITOperation_EJJJAp, RegisterID, RegisterID, RegisterID, ArrayProfile*); @@ -812,13 +831,14 @@ MacroAssembler::Call callOperation(Z_JITOperation_EJZZ, GPRReg, GPRReg, int32_t, int32_t); MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg, GPRReg); MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg, GPRReg); - MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, GPRReg, const Identifier*); + MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, GPRReg, UniquedStringImpl*); MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg, GPRReg, GPRReg); MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg, GPRReg, GPRReg); MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, GPRReg, GPRReg, ArrayProfile*); MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, GPRReg, GPRReg, ByValInfo*); MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, GPRReg, size_t); MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID, RegisterID); + MacroAssembler::Call callOperation(S_JITOperation_EJI, GPRReg, GPRReg, UniquedStringImpl*); MacroAssembler::Call callOperation(S_JITOperation_EJJ, RegisterID, RegisterID, RegisterID, RegisterID); MacroAssembler::Call callOperation(V_JITOperation_EZSymtabJ, int, SymbolTable*, RegisterID, RegisterID); MacroAssembler::Call callOperation(V_JITOperation_EJ, RegisterID, RegisterID); @@ -887,7 +907,17 @@ bool shouldEmitProfiling() { return false; } #endif + static bool reportCompileTimes(); + static bool computeCompileTimes(); + + // If you need to check the value of an instruction multiple times and the instruction is + // part of a LLInt inline cache, then you want to use this. It will give you the value of + // the instruction at the start of JITing. + Instruction* copiedInstruction(Instruction*); + Interpreter* m_interpreter; + + RefCountedArray m_instructions; Vector m_calls; Vector

    + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,4 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,10 @@ + + + +
    download + + + \ No newline at end of file diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,10 @@ + + + +download + + + \ No newline at end of file diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,7 @@ + + Lorem Ipsum Et Cetera + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,15 @@ + + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,31 @@ + + + + + + + +
    + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,31 @@ + + + + + + + +
    + + \ No newline at end of file diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,23 @@ + + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,14 @@ + Binary files /tmp/tmpNcyQ7s/uy0UchU8gO/webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3 and /tmp/tmpNcyQ7s/FMJ_tuanjO/webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3 differ Binary files /tmp/tmpNcyQ7s/uy0UchU8gO/webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm and /tmp/tmpNcyQ7s/FMJ_tuanjO/webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm differ Binary files /tmp/tmpNcyQ7s/uy0UchU8gO/webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal and /tmp/tmpNcyQ7s/FMJ_tuanjO/webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal differ diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,33 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html 2016-09-16 09:56:48.000000000 +0000 @@ -8,7 +8,7 @@ request.onerror = function(e) { // Unexpected error - window.webkit.messageHandlers.testHandler.postMessage('Error opening database'); + window.webkit.messageHandlers.testHandler.postMessage('Error deleting database'); } function continueTest() @@ -17,13 +17,13 @@ request.onsuccess = function() { - window.webkit.messageHandlers.testHandler.postMessage('Success'); + window.webkit.messageHandlers.testHandler.postMessage('Open success'); } request.onerror = function() { // Unexpected error - window.webkit.messageHandlers.testHandler.postMessage('Error'); + window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database'); } request.onupgradeneeded = function(event) diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html 2016-09-16 09:56:48.000000000 +0000 @@ -9,19 +9,20 @@ req.onsuccess = function(event) { window.webkit.messageHandlers.testHandler.postMessage('Value of foo: ' + req.result); + continueTest1(); } req.onerror = function(event) { // Unexpected error - window.webkit.messageHandlers.testHandler.postMessage('Unexpected error'); + window.webkit.messageHandlers.testHandler.postMessage('Unexpected error getting value'); } } request.onerror = function() { // Unexpected error - window.webkit.messageHandlers.testHandler.postMessage('Unexpected error'); + window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database'); } request.onupgradeneeded = function(event) @@ -29,4 +30,63 @@ // Unexpected upgrade needed window.webkit.messageHandlers.testHandler.postMessage('Unexpected UpgradeNeeded'); } + +function continueTest1() +{ + var request = window.indexedDB.deleteDatabase("ProcessCloseIDBCleanup"); + request.onsuccess = function(e) + { + continueTest2(); + } + request.onerror = function(e) + { + // Unexpected error + window.webkit.messageHandlers.testHandler.postMessage('Error deleting ProcessCloseIDBCleanup database'); + } +} + +function startGetLoop() +{ + var request = window.indexedDB.open("ProcessCloseIDBCleanup"); + request.onsuccess = function(e) + { + var req = e.target.result.transaction(["TestObjectStore"]).objectStore("TestObjectStore").get("foo"); + req.onsuccess = startGetLoop; + req.onerror = function(e) + { + // Unexpected error + window.webkit.messageHandlers.testHandler.postMessage('Error with a get loop'); + } + } + + request.onerror = function(e) + { + // Unexpected error + window.webkit.messageHandlers.testHandler.postMessage('Error with a get loop'); + } +} + +function continueTest2() +{ + var request = window.indexedDB.open("ProcessCloseIDBCleanup"); + request.onsuccess = function(e) + { + for (var i = 0; i < 75; ++i) + startGetLoop(); + + setTimeout("window.webkit.messageHandlers.testHandler.postMessage('Get loops started');", 0); + } + + request.onerror = function(e) + { + // Unexpected error + window.webkit.messageHandlers.testHandler.postMessage('Error opening ProcessCloseIDBCleanup database'); + } + + request.onupgradeneeded = function(e) + { + e.target.result.createObjectStore("TestObjectStore").put("bar", "foo"); + } +} + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,21 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,31 @@ + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,21 @@ + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,23 @@ + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,34 @@ + + + + + + + + Binary files /tmp/tmpNcyQ7s/uy0UchU8gO/webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4 and /tmp/tmpNcyQ7s/FMJ_tuanjO/webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4 differ diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,6 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html 2016-08-30 16:10:50.000000000 +0000 @@ -0,0 +1,6 @@ + Binary files /tmp/tmpNcyQ7s/uy0UchU8gO/webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage and /tmp/tmpNcyQ7s/FMJ_tuanjO/webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage differ Binary files /tmp/tmpNcyQ7s/uy0UchU8gO/webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shm and /tmp/tmpNcyQ7s/FMJ_tuanjO/webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shm differ diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,66 @@ + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h 2016-09-19 12:18:06.000000000 +0000 @@ -34,6 +34,8 @@ - (void)sayHello:(NSString *)hello; - (void)sayHello:(NSString *)hello completionHandler:(void (^)(NSString *))completionHandler; - (void)selectionAndClickInformationForClickAtPoint:(NSValue *)pointValue completionHandler:(void (^)(NSDictionary *))completionHandler; +- (void)takeRange:(NSRange)range completionHandler:(void (^)(NSUInteger location, NSUInteger length))completionHandler; +- (void)doNotCallCompletionHandler:(void (^)())completionHandler; @end @@ -41,7 +43,7 @@ { _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(RemoteObjectProtocol)]; - [interface setClasses:[NSSet setWithObjects:[NSDictionary class], [NSURL class], nil] forSelector:@selector(selectionAndClickInformationForClickAtPoint:completionHandler:) argumentIndex:0 ofReply:YES]; + [interface setClasses:[NSSet setWithObjects:[NSDictionary class], [NSString class], [NSURL class], nil] forSelector:@selector(selectionAndClickInformationForClickAtPoint:completionHandler:) argumentIndex:0 ofReply:YES]; return interface; } diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,23 @@ + + + + + + + + + + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,41 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#if WK_API_ENABLED + +@protocol UserContentWorldProtocol + +- (void)didObserveNormalWorld; +- (void)didObserveWorldWithName:(NSString *)name; + +@end + +#endif diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,67 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,25 @@ + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -57,8 +57,14 @@ WebViewTest::add("Autocleanups", "web-process-autocleanups", testWebProcessAutocleanups); } -void afterAll() +#else + +void beforeAll() { } #endif // G_DEFINE_AUTOPTR_CLEANUP_FUNC + +void afterAll() +{ +} diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp 2016-10-18 15:36:57.000000000 +0000 @@ -64,18 +64,15 @@ } ConsoleMessageTest() - : WebViewTest(webkit_user_content_manager_new()) { - WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView); - webkit_user_content_manager_register_script_message_handler(manager, "console"); - g_signal_connect(manager, "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), this); + webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "console"); + g_signal_connect(m_userContentManager.get(), "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), this); } ~ConsoleMessageTest() { - WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView); - g_signal_handlers_disconnect_matched(manager, G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); - webkit_user_content_manager_unregister_script_message_handler(manager, "console"); + g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); + webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "console"); } void waitUntilConsoleMessageReceived() diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -385,7 +385,7 @@ " " " " " " - " " + " " "

    Lorem ipsum.

    " ""; test->loadHtml(linksHTML, "file:///"); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp 2016-10-27 09:23:43.000000000 +0000 @@ -27,6 +27,7 @@ #include "WebViewTest.h" #include #include +#include #include static WebKitTestBus* bus; @@ -209,51 +210,100 @@ static void uriChanged(GObject*, GParamSpec*, ViewURITrackingTest* test) { - g_assert_cmpstr(test->m_activeURI.data(), !=, webkit_web_view_get_uri(test->m_webView)); - test->m_activeURI = webkit_web_view_get_uri(test->m_webView); + g_assert_cmpstr(test->m_currentURI.data(), !=, webkit_web_view_get_uri(test->m_webView)); + test->m_currentURI = webkit_web_view_get_uri(test->m_webView); } ViewURITrackingTest() - : m_activeURI(webkit_web_view_get_uri(m_webView)) + : m_currentURI(webkit_web_view_get_uri(m_webView)) { - g_assert(m_activeURI.isNull()); + g_assert(m_currentURI.isNull()); + m_currentURIList.grow(m_currentURIList.capacity()); g_signal_connect(m_webView, "notify::uri", G_CALLBACK(uriChanged), this); } + enum State { Provisional, ProvisionalAfterRedirect, Commited, Finished }; + + void loadURI(const char* uri) + { + reset(); + LoadTrackingTest::loadURI(uri); + } + void provisionalLoadStarted() { - checkActiveURI("/redirect"); + m_currentURIList[Provisional] = m_currentURI; } void provisionalLoadReceivedServerRedirect() { - checkActiveURI("/normal"); + m_currentURIList[ProvisionalAfterRedirect] = m_currentURI; } void loadCommitted() { - checkActiveURI("/normal"); + m_currentURIList[Commited] = m_currentURI; } void loadFinished() { - checkActiveURI("/normal"); + m_currentURIList[Finished] = m_currentURI; LoadTrackingTest::loadFinished(); } - CString m_activeURI; + void checkURIAtState(State state, const char* path) + { + if (path) + ASSERT_CMP_CSTRING(m_currentURIList[state], ==, kServer->getURIForPath(path)); + else + g_assert(m_currentURIList[state].isNull()); + } private: - void checkActiveURI(const char* uri) + void reset() { - ASSERT_CMP_CSTRING(m_activeURI, ==, kServer->getURIForPath(uri)); + m_currentURI = CString(); + m_currentURIList.clear(); + m_currentURIList.grow(m_currentURIList.capacity()); } + + CString m_currentURI; + Vector m_currentURIList; }; static void testWebViewActiveURI(ViewURITrackingTest* test, gconstpointer) { + // Normal load, the URL doesn't change. + test->loadURI(kServer->getURIForPath("/normal1").data()); + test->waitUntilLoadFinished(); + test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal1"); + test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); + test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal1"); + test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal1"); + + // Redirect, the URL changes after the redirect. test->loadURI(kServer->getURIForPath("/redirect").data()); test->waitUntilLoadFinished(); + test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect"); + test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal"); + test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal"); + test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal"); + + // Normal load, URL changed by WebKitPage::send-request. + test->loadURI(kServer->getURIForPath("/normal-change-request").data()); + test->waitUntilLoadFinished(); + test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal-change-request"); + test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); + test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed"); + test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed"); + + // Redirect, URL changed by WebKitPage::send-request. + test->loadURI(kServer->getURIForPath("/redirect-to-change-request").data()); + test->waitUntilLoadFinished(); + test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-to-change-request"); + test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal-change-request"); + test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed-on-redirect"); + test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed-on-redirect"); } class ViewIsLoadingTest: public LoadTrackingTest { @@ -355,6 +405,20 @@ g_dbus_connection_signal_unsubscribe(bus->connection(), m_uriChangedSignalID); } + void loadURI(const char* uri) + { + m_webPageURIs.clear(); + m_webViewURIs.clear(); + WebViewTest::loadURI(uri); + } + + void checkViewAndPageURIsMatch() const + { + g_assert_cmpint(m_webPageURIs.size(), ==, m_webViewURIs.size()); + for (size_t i = 0; i < m_webPageURIs.size(); ++i) + ASSERT_CMP_CSTRING(m_webPageURIs[i], ==, m_webViewURIs[i]); + } + unsigned m_uriChangedSignalID; Vector m_webPageURIs; Vector m_webViewURIs; @@ -362,17 +426,37 @@ static void testWebPageURI(WebPageURITest* test, gconstpointer) { - test->loadURI(kServer->getURIForPath("/redirect").data()); + // Normal load. + test->loadURI(kServer->getURIForPath("/normal1").data()); test->waitUntilLoadFinished(); + test->checkViewAndPageURIsMatch(); + g_assert_cmpint(test->m_webPageURIs.size(), ==, 1); + ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal1")); - g_assert_cmpint(test->m_webPageURIs.size(), ==, test->m_webViewURIs.size()); - for (size_t i = 0; i < test->m_webPageURIs.size(); ++i) - ASSERT_CMP_CSTRING(test->m_webPageURIs[i], ==, test->m_webViewURIs[i]); - + // Redirect + test->loadURI(kServer->getURIForPath("/redirect").data()); + test->waitUntilLoadFinished(); + test->checkViewAndPageURIsMatch(); g_assert_cmpint(test->m_webPageURIs.size(), ==, 2); ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect")); ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal")); + // Normal load, URL changed by WebKitPage::send-request. + test->loadURI(kServer->getURIForPath("/normal-change-request").data()); + test->waitUntilLoadFinished(); + test->checkViewAndPageURIsMatch(); + g_assert_cmpint(test->m_webPageURIs.size(), ==, 2); + ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal-change-request")); + ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/request-changed")); + + // Redirect, URL changed by WebKitPage::send-request. + test->loadURI(kServer->getURIForPath("/redirect-to-change-request").data()); + test->waitUntilLoadFinished(); + test->checkViewAndPageURIsMatch(); + g_assert_cmpint(test->m_webPageURIs.size(), ==, 3); + ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect-to-change-request")); + ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal-change-request")); + ASSERT_CMP_CSTRING(test->m_webPageURIs[2], ==, kServer->getURIForPath("/request-changed-on-redirect")); } static void testURIRequestHTTPHeaders(WebViewTest* test, gconstpointer) @@ -484,6 +568,9 @@ else if (g_str_equal(path, "/redirect")) { soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); soup_message_headers_append(message->response_headers, "Location", "/normal"); + } else if (g_str_equal(path, "/redirect-to-change-request")) { + soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); + soup_message_headers_append(message->response_headers, "Location", "/normal-change-request"); } else if (g_str_equal(path, "/cancelled")) { soup_message_headers_set_encoding(message->response_headers, SOUP_ENCODING_CHUNKED); soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp 2016-04-25 15:16:47.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp 2016-10-14 09:38:09.000000000 +0000 @@ -225,6 +225,12 @@ return TRUE; } + static void permissionResultMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, UIClientTest* test) + { + test->m_permissionResult.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_main_loop_quit(test->m_mainLoop); + } + UIClientTest() : m_scriptDialogType(WEBKIT_SCRIPT_DIALOG_ALERT) , m_scriptDialogConfirmed(true) @@ -239,11 +245,15 @@ g_signal_connect(m_webView, "script-dialog", G_CALLBACK(scriptDialog), this); g_signal_connect(m_webView, "mouse-target-changed", G_CALLBACK(mouseTargetChanged), this); g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequested), this); + webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "permission"); + g_signal_connect(m_userContentManager.get(), "script-message-received::permission", G_CALLBACK(permissionResultMessageReceivedCallback), this); } ~UIClientTest() { g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "permission"); } static void tryWebViewCloseCallback(UIClientTest* test) @@ -269,6 +279,13 @@ g_main_loop_run(m_mainLoop); } + const char* waitUntilPermissionResultMessageReceived() + { + m_permissionResult = nullptr; + g_main_loop_run(m_mainLoop); + return m_permissionResult.get(); + } + void setExpectedWindowProperties(const WindowProperties& windowProperties) { m_windowProperties = windowProperties; @@ -336,6 +353,7 @@ HashSet m_windowPropertiesChanged; GRefPtr m_mouseTargetHitTestResult; unsigned m_mouseTargetModifiers; + GUniquePtr m_permissionResult; }; static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer) @@ -722,31 +740,33 @@ " " " " ""; - // Test denying a permission request. + // Geolocation is not allowed from insecure connections like HTTP, + // POSITION_UNAVAILABLE ('2') is returned in that case without even + // asking the API layer. test->m_allowPermissionRequests = false; test->loadHtml(geolocationRequestHTML, "http://foo.com/bar"); - test->waitUntilTitleChanged(); + const gchar* result = test->waitUntilPermissionResultMessageReceived(); + g_assert_cmpstr(result, ==, "2"); - // According to the Geolocation API specification, '1' is the - // error code returned for the PERMISSION_DENIED error. - // http://dev.w3.org/geo/api/spec-source.html#position_error_interface - const gchar* result = webkit_web_view_get_title(test->m_webView); + // Test denying a permission request. PERMISSION_DENIED ('1') is + // returned in this case. + test->m_allowPermissionRequests = false; + test->loadHtml(geolocationRequestHTML, "https://foo.com/bar"); + result = test->waitUntilPermissionResultMessageReceived(); g_assert_cmpstr(result, ==, "1"); - // Test allowing a permission request. + // Test allowing a permission request. Result should be different + // to PERMISSION_DENIED ('1'). test->m_allowPermissionRequests = true; - test->loadHtml(geolocationRequestHTML, 0); - test->waitUntilTitleChanged(); - - // Check that we did not get the PERMISSION_DENIED error now. - result = webkit_web_view_get_title(test->m_webView); + test->loadHtml(geolocationRequestHTML, "https://foo.com/bar"); + result = test->waitUntilPermissionResultMessageReceived(); g_assert_cmpstr(result, !=, "1"); test->addLogFatalFlag(G_LOG_LEVEL_WARNING); } diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -278,6 +278,11 @@ webkit_settings_set_allow_file_access_from_file_urls(settings, TRUE); g_assert(webkit_settings_get_allow_file_access_from_file_urls(settings)); + // Universal access from file URLs is not allowed by default. + g_assert(!webkit_settings_get_allow_universal_access_from_file_urls(settings)); + webkit_settings_set_allow_universal_access_from_file_urls(settings, TRUE); + g_assert(webkit_settings_get_allow_universal_access_from_file_urls(settings)); + g_object_unref(G_OBJECT(settings)); } diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -27,23 +27,6 @@ #include #include -class UserContentManagerTest : public WebViewTest { -public: - MAKE_GLIB_TEST_FIXTURE(UserContentManagerTest); - - UserContentManagerTest() - : WebViewTest(webkit_user_content_manager_new()) - { - // A reference is leaked when passing the result of webkit_user_content_manager_new() - // directly to webkit_web_view_new_with_user_content_manager() above. Adopting the - // reference here avoids the leak. - m_userContentManager = adoptGRef(webkit_web_view_get_user_content_manager(m_webView)); - assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_userContentManager.get())); - } - - GRefPtr m_userContentManager; -}; - static WebKitTestServer* kServer; // These are all here so that they can be changed easily, if necessary. @@ -127,7 +110,7 @@ } } -static void testUserContentManagerInjectedStyleSheet(UserContentManagerTest* test, gconstpointer) +static void testUserContentManagerInjectedStyleSheet(WebViewTest* test, gconstpointer) { char* whitelist[3] = { 0, 0, 0 }; char* blacklist[3] = { 0, 0, 0 }; @@ -170,7 +153,7 @@ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); } -static void testUserContentManagerInjectedScript(UserContentManagerTest* test, gconstpointer) +static void testUserContentManagerInjectedScript(WebViewTest* test, gconstpointer) { char* whitelist[3] = { 0, 0, 0 }; char* blacklist[3] = { 0, 0, 0 }; @@ -213,13 +196,12 @@ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); } -class UserScriptMessageTest : public UserContentManagerTest { +class UserScriptMessageTest : public WebViewTest { public: MAKE_GLIB_TEST_FIXTURE(UserScriptMessageTest); UserScriptMessageTest() - : UserContentManagerTest() - , m_userScriptMessage(nullptr) + : m_userScriptMessage(nullptr) { } @@ -376,8 +358,8 @@ kServer->run(serverCallback); Test::add("WebKitWebView", "new-with-user-content-manager", testWebViewNewWithUserContentManager); - UserContentManagerTest::add("WebKitUserContentManager", "injected-style-sheet", testUserContentManagerInjectedStyleSheet); - UserContentManagerTest::add("WebKitUserContentManager", "injected-script", testUserContentManagerInjectedScript); + WebViewTest::add("WebKitUserContentManager", "injected-style-sheet", testUserContentManagerInjectedStyleSheet); + WebViewTest::add("WebKitUserContentManager", "injected-script", testUserContentManagerInjectedScript); UserScriptMessageTest::add("WebKitUserContentManager", "script-message-received", testUserContentManagerScriptMessageReceived); UserScriptMessageTest::add("WebKitUserContentManager", "script-message-from-dom-bindings", testUserContentManagerScriptMessageFromDOMBindings); } diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -280,7 +280,7 @@ webkit_web_context_register_uri_scheme(m_webContext.get(), scheme, uriSchemeRequestCallback, this, 0); } - virtual void loadCommitted() override + void loadCommitted() override { if (m_finishOnCommitted) { GUniquePtr error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, afterInitialChunkErrorMessage)); @@ -465,7 +465,7 @@ static void testWebContextLanguages(WebViewTest* test, gconstpointer) { - static const char* expectedDefaultLanguage = "en"; + static const char* expectedDefaultLanguage = "en-us"; test->loadURI(kServer->getURIForPath("/").data()); test->waitUntilLoadFinished(); size_t mainResourceDataSize = 0; @@ -487,6 +487,32 @@ mainResourceData = test->mainResourceData(mainResourceDataSize); g_assert_cmpuint(mainResourceDataSize, ==, strlen(expectedLanguages)); g_assert(!strncmp(mainResourceData, expectedLanguages, mainResourceDataSize)); + + // When using the C locale, en-US should be used as default. + const char* cLanguage[] = { "C", nullptr }; + webkit_web_context_set_preferred_languages(test->m_webContext.get(), cLanguage); + GUniqueOutPtr error; + WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().locale", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error); + GUniquePtr locale(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(locale.get(), ==, "en-US"); + + // When using the POSIX locale, en-US should be used as default. + const char* posixLanguage[] = { "POSIX", nullptr }; + webkit_web_context_set_preferred_languages(test->m_webContext.get(), posixLanguage); + javascriptResult = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().locale", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error); + locale.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(locale.get(), ==, "en-US"); + + // An invalid locale should throw an exception. + const char* invalidLanguage[] = { "A", nullptr }; + webkit_web_context_set_preferred_languages(test->m_webContext.get(), invalidLanguage); + javascriptResult = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().locale", &error.outPtr()); + g_assert(!javascriptResult); + g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); } static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) @@ -601,6 +627,13 @@ | SecurityPolicyTest::CORSEnabled | SecurityPolicyTest::EmptyDocument); } +static void consoleMessageReceivedCallback(WebKitUserContentManager*, WebKitJavascriptResult* message, WebKitJavascriptResult** result) +{ + g_assert(result); + g_assert(!*result); + *result = webkit_javascript_result_ref(message); +} + static void testWebContextSecurityFileXHR(WebViewTest* test, gconstpointer) { GUniquePtr fileURL(g_strdup_printf("file://%s/simple.html", Test::getResourcesDir(Test::WebKit2Resources).data())); @@ -610,11 +643,30 @@ GUniquePtr jsonURL(g_strdup_printf("file://%s/simple.json", Test::getResourcesDir().data())); GUniquePtr xhr(g_strdup_printf("var xhr = new XMLHttpRequest; xhr.open(\"GET\", \"%s\"); xhr.send();", jsonURL.get())); - // By default file access is not allowed, this will fail with a cross-origin error. + WebKitJavascriptResult* consoleMessage = nullptr; + webkit_user_content_manager_register_script_message_handler(test->m_userContentManager.get(), "console"); + g_signal_connect(test->m_userContentManager.get(), "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), &consoleMessage); + + // By default file access is not allowed, this will show a console message with a cross-origin error. GUniqueOutPtr error; WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr()); - g_assert(!javascriptResult); - g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); + g_assert(javascriptResult); + g_assert(!error); + g_assert(consoleMessage); + GUniquePtr messageString(WebViewTest::javascriptResultToCString(consoleMessage)); + GRefPtr variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr); + g_assert(variant.get()); + unsigned level; + const char* messageText; + g_variant_get(variant.get(), "(uu&su&s)", nullptr, &level, &messageText, nullptr, nullptr); + g_assert_cmpuint(level, ==, 3); // Console error message. + GUniquePtr expectedErrorMessage(g_strdup_printf("XMLHttpRequest cannot load %s. Cross origin requests are only supported for HTTP.", jsonURL.get())); + g_assert_cmpstr(messageText, ==, expectedErrorMessage.get()); + webkit_javascript_result_unref(consoleMessage); + consoleMessage = nullptr; + level = 0; + messageText = nullptr; + variant = nullptr; // Allow file access from file URLs. webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), TRUE); @@ -628,8 +680,18 @@ test->loadURI(kServer->getURIForPath("/").data()); test->waitUntilLoadFinished(); javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr()); - g_assert(!javascriptResult); - g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); + g_assert(javascriptResult); + g_assert(!error); + g_assert(consoleMessage); + variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr); + g_assert(variant.get()); + g_variant_get(variant.get(), "(uu&su&s)", nullptr, &level, &messageText, nullptr, nullptr); + g_assert_cmpuint(level, ==, 3); // Console error message. + g_assert_cmpstr(messageText, ==, expectedErrorMessage.get()); + webkit_javascript_result_unref(consoleMessage); + + g_signal_handlers_disconnect_matched(test->m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, &consoleMessage); + webkit_user_content_manager_unregister_script_message_handler(test->m_userContentManager.get(), "console"); webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), FALSE); } diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp 2016-10-14 09:38:09.000000000 +0000 @@ -699,23 +699,20 @@ } NotificationWebViewTest() - : WebViewTest(webkit_user_content_manager_new()) - , m_notification(nullptr) + : m_notification(nullptr) , m_event(None) { g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), this); g_signal_connect(m_webView, "show-notification", G_CALLBACK(showNotificationCallback), this); - WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView); - webkit_user_content_manager_register_script_message_handler(manager, "notifications"); - g_signal_connect(manager, "script-message-received::notifications", G_CALLBACK(notificationsMessageReceivedCallback), this); + webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "notifications"); + g_signal_connect(m_userContentManager.get(), "script-message-received::notifications", G_CALLBACK(notificationsMessageReceivedCallback), this); } ~NotificationWebViewTest() { g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); - WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView); - g_signal_handlers_disconnect_matched(manager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); - webkit_user_content_manager_unregister_script_message_handler(manager, "notifications"); + g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "notifications"); } void requestPermissionAndWaitUntilGiven() @@ -818,13 +815,15 @@ test->waitUntilLoadFinished(); g_assert(!webkit_web_view_is_playing_audio(test->m_webView)); - webkit_web_view_run_javascript(test->m_webView, "playVideo();", nullptr, nullptr, nullptr); - test->waitUntilIsPlayingAudioChanged(); + test->runJavaScriptAndWaitUntilFinished("playVideo();", nullptr); + if (!webkit_web_view_is_playing_audio(test->m_webView)) + test->waitUntilIsPlayingAudioChanged(); g_assert(webkit_web_view_is_playing_audio(test->m_webView)); // Pause the video, and check again. - webkit_web_view_run_javascript(test->m_webView, "document.getElementById('test-video').pause();", nullptr, nullptr, nullptr); - test->waitUntilIsPlayingAudioChanged(); + test->runJavaScriptAndWaitUntilFinished("document.getElementById('test-video').pause();", nullptr); + if (webkit_web_view_is_playing_audio(test->m_webView)) + test->waitUntilIsPlayingAudioChanged(); g_assert(!webkit_web_view_is_playing_audio(test->m_webView)); } @@ -853,6 +852,19 @@ // MiniBrowser --bg-color="" for manually testing this API. } +static void testWebViewPreferredSize(WebViewTest* test, gconstpointer) +{ + test->loadHtml("", nullptr); + test->waitUntilLoadFinished(); + test->showInWindowAndWaitUntilMapped(); + GtkRequisition minimunSize, naturalSize; + gtk_widget_get_preferred_size(GTK_WIDGET(test->m_webView), &minimunSize, &naturalSize); + g_assert_cmpint(minimunSize.width, ==, 0); + g_assert_cmpint(minimunSize.height, ==, 0); + g_assert_cmpint(naturalSize.width, ==, 325); + g_assert_cmpint(naturalSize.height, ==, 615); +} + static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) { if (message->method != SOUP_METHOD_GET) { @@ -887,6 +899,7 @@ NotificationWebViewTest::add("WebKitWebView", "notification", testWebViewNotification); IsPlayingAudioWebViewTest::add("WebKitWebView", "is-playing-audio", testWebViewIsPlayingAudio); WebViewTest::add("WebKitWebView", "background-color", testWebViewBackgroundColor); + WebViewTest::add("WebKitWebView", "preferred-size", testWebViewPreferredSize); } void afterAll() diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -166,6 +166,10 @@ SoupMessageHeaders* headers = webkit_uri_request_get_http_headers(request); g_assert(headers); soup_message_headers_append(headers, "DNT", "1"); + } else if (g_str_has_suffix(requestURI, "/normal-change-request")) { + GUniquePtr prefix(g_strndup(requestURI, strlen(requestURI) - strlen("/normal-change-request"))); + GUniquePtr newURI(g_strdup_printf("%s/request-changed%s", prefix.get(), redirectResponse ? "-on-redirect" : "")); + webkit_uri_request_set_uri(request, newURI.get()); } else if (g_str_has_suffix(requestURI, "/http-get-method")) { g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "GET"); g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_GET); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -47,7 +47,7 @@ } private: - virtual void didCreatePage(WKBundleRef, WKBundlePageRef bundlePage) override + void didCreatePage(WKBundleRef, WKBundlePageRef bundlePage) override { WKBundlePagePolicyClientV0 policyClient; memset(&policyClient, 0, sizeof(policyClient)); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#include + +namespace TestWebKitAPI { + +static size_t totalDestructorCalls; +static size_t totalIsolatedCopyCalls; + +static HashCountedSet defaultConstructorSet; +static HashCountedSet nameConstructorSet; +static HashCountedSet copyConstructorSet; +static HashCountedSet moveConstructorSet; + +struct LifetimeLogger { + LifetimeLogger() + { + defaultConstructorSet.add(fullName()); + } + + LifetimeLogger(const char* inputName) + : name(*inputName) + { + nameConstructorSet.add(fullName()); + } + + LifetimeLogger(const LifetimeLogger& other) + : name(other.name) + , copyGeneration(other.copyGeneration + 1) + , moveGeneration(other.moveGeneration) + { + copyConstructorSet.add(fullName()); + } + + LifetimeLogger(LifetimeLogger&& other) + : name(other.name) + , copyGeneration(other.copyGeneration) + , moveGeneration(other.moveGeneration + 1) + { + moveConstructorSet.add(fullName()); + } + + ~LifetimeLogger() + { + ++totalDestructorCalls; + } + + LifetimeLogger isolatedCopy() const + { + ++totalIsolatedCopyCalls; + return LifetimeLogger(*this); + } + + String fullName() + { + StringBuilder builder; + builder.append(&name); + builder.append("-"); + builder.append(String::number(copyGeneration)); + builder.append("-"); + builder.append(String::number(moveGeneration)); + + return builder.toString(); + } + + const char& name { *"" }; + int copyGeneration { 0 }; + int moveGeneration { 0 }; +}; + +void testFunction(const LifetimeLogger&, const LifetimeLogger&, const LifetimeLogger&) +{ + // Do nothing - Just need to check the side effects of the arguments getting in here. +} + +TEST(WTF_CrossThreadTask, Basic) +{ + { + LifetimeLogger logger1; + LifetimeLogger logger2(logger1); + LifetimeLogger logger3("logger"); + + auto task = createCrossThreadTask(testFunction, logger1, logger2, logger3); + task.performTask(); + } + + ASSERT_EQ(1u, defaultConstructorSet.size()); + ASSERT_EQ(1u, defaultConstructorSet.count("-0-0")); + + ASSERT_EQ(1u, nameConstructorSet.size()); + ASSERT_EQ(1u, nameConstructorSet.count("logger-0-0")); + + ASSERT_EQ(3u, copyConstructorSet.size()); + ASSERT_EQ(1u, copyConstructorSet.count("logger-1-0")); + ASSERT_EQ(2u, copyConstructorSet.count("-1-0")); + ASSERT_EQ(1u, copyConstructorSet.count("-2-0")); + +#if !COMPILER(MSVC) + ASSERT_EQ(6u, moveConstructorSet.size()); +#else + // The number of times the move constructor is called is different on Windows in this test. + // This seems to be caused by differences in MSVC's implementation of lambdas or std functions like std::make_tuple. + ASSERT_EQ(9u, moveConstructorSet.size()); +#endif + ASSERT_EQ(1u, moveConstructorSet.count("logger-1-1")); + ASSERT_EQ(1u, moveConstructorSet.count("logger-1-2")); + ASSERT_EQ(1u, moveConstructorSet.count("-2-1")); + ASSERT_EQ(1u, moveConstructorSet.count("-2-2")); + ASSERT_EQ(1u, moveConstructorSet.count("-1-1")); + ASSERT_EQ(1u, moveConstructorSet.count("-1-2")); + +#if !COMPILER(MSVC) + ASSERT_EQ(12u, totalDestructorCalls); +#else + // Since the move constructor is called 3 more times on Windows (see above), we will have 3 more destructor calls. + ASSERT_EQ(15u, totalDestructorCalls); +#endif + ASSERT_EQ(3u, totalIsolatedCopyCalls); + +} + +} // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +class DeletedAddressOfOperator { +public: + DeletedAddressOfOperator() + : m_value(0) + { + } + + DeletedAddressOfOperator(unsigned value) + : m_value(value) + { + } + + DeletedAddressOfOperator* operator&() = delete; + + unsigned value() const + { + return m_value; + } + + friend bool operator==(const DeletedAddressOfOperator& a, const DeletedAddressOfOperator& b) + { + return a.m_value == b.m_value; + } + +private: + unsigned m_value; +}; + +namespace WTF { + +template<> struct HashTraits : public GenericHashTraits { + static const bool emptyValueIsZero = true; + + static void constructDeletedValue(DeletedAddressOfOperator& slot) { slot = DeletedAddressOfOperator(std::numeric_limits::max()); } + static bool isDeletedValue(const DeletedAddressOfOperator& slot) { return slot.value() == std::numeric_limits::max(); } +}; + +template<> struct DefaultHash { + struct Hash { + static unsigned hash(const DeletedAddressOfOperator& key) + { + return intHash(key.value()); + } + + static bool equal(const DeletedAddressOfOperator& a, const DeletedAddressOfOperator& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = true; + }; +}; +} + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include + +enum class TestEnum { + A, + B, + C, +}; + +namespace WTF { +template<> struct EnumTraits { + using values = EnumValues; +}; +} + +namespace TestWebKitAPI { + +static_assert(WTF::isValidEnum(0), ""); +static_assert(!WTF::isValidEnum(-1), ""); +static_assert(!WTF::isValidEnum(3), ""); + +TEST(WTF_EnumTraits, IsValidEnum) +{ + EXPECT_TRUE(isValidEnum(0)); + EXPECT_FALSE(isValidEnum(-1)); + EXPECT_FALSE(isValidEnum(3)); +} + +} diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp 2013-08-03 16:10:41.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include -#include - -namespace TestWebKitAPI { - -static int returnFortyTwo() -{ - return 42; -} - -TEST(FunctionalTest, Basic) -{ - Function emptyFunction; - ASSERT_TRUE(emptyFunction.isNull()); - - Function returnFortyTwoFunction = bind(returnFortyTwo); - ASSERT_FALSE(returnFortyTwoFunction.isNull()); - ASSERT_EQ(42, returnFortyTwoFunction()); -} - -static int multiplyByTwo(int n) -{ - return n * 2; -} - -static double multiplyByOneAndAHalf(double d) -{ - return d * 1.5; -} - -TEST(FunctionalTest, UnaryBind) -{ - Function multiplyFourByTwoFunction = bind(multiplyByTwo, 4); - ASSERT_EQ(8, multiplyFourByTwoFunction()); - - Function multiplyByOneAndAHalfFunction = bind(multiplyByOneAndAHalf, 3); - ASSERT_EQ(4.5, multiplyByOneAndAHalfFunction()); -} - -static int multiply(int x, int y) -{ - return x * y; -} - -static int subtract(int x, int y) -{ - return x - y; -} - -TEST(FunctionalTest, BinaryBind) -{ - Function multiplyFourByTwoFunction = bind(multiply, 4, 2); - ASSERT_EQ(8, multiplyFourByTwoFunction()); - - Function subtractTwoFromFourFunction = bind(subtract, 4, 2); - ASSERT_EQ(2, subtractTwoFromFourFunction()); -} - -class A { -public: - explicit A(int i) - : m_i(i) - { - } - - int f() { return m_i; } - int addF(int j) { return m_i + j; } - -private: - int m_i; -}; - -TEST(FunctionalTest, MemberFunctionBind) -{ - A a(10); - Function function1 = bind(&A::f, &a); - ASSERT_EQ(10, function1()); - - Function function2 = bind(&A::addF, &a, 15); - ASSERT_EQ(25, function2()); -} - -class B { -public: - B() - : m_numRefCalls(0) - , m_numDerefCalls(0) - { - } - - ~B() - { - } - - void ref() - { - m_numRefCalls++; - } - - void deref() - { - m_numDerefCalls++; - } - - void f() { ASSERT_GT(m_numRefCalls, 0); } - void g(int) { ASSERT_GT(m_numRefCalls, 0); } - - int m_numRefCalls; - int m_numDerefCalls; -}; - -TEST(FunctionalTest, MemberFunctionBindRefDeref) -{ - B b; - - { - Function function1 = bind(&B::f, &b); - function1(); - - Function function2 = bind(&B::g, &b, 10); - function2(); - } - - ASSERT_TRUE(b.m_numRefCalls == b.m_numDerefCalls); - ASSERT_GT(b.m_numRefCalls, 0); - -} - -class Number : public RefCounted { -public: - static PassRefPtr create(int value) - { - return adoptRef(new Number(value)); - } - - ~Number() - { - m_value = 0; - } - - int value() const { return m_value; } - -private: - explicit Number(int value) - : m_value(value) - { - } - - int m_value; -}; - -static int multiplyNumberByTwo(Number* number) -{ - return number->value() * 2; -} - -TEST(FunctionalTest, RefCountedStorage) -{ - RefPtr five = Number::create(5); - Function multiplyFiveByTwoFunction = bind(multiplyNumberByTwo, five); - ASSERT_EQ(10, multiplyFiveByTwoFunction()); - - Function multiplyFourByTwoFunction = bind(multiplyNumberByTwo, Number::create(4)); - ASSERT_EQ(8, multiplyFourByTwoFunction()); - - RefPtr six = Number::create(6); - Function multiplySixByTwoFunction = bind(multiplyNumberByTwo, six.release()); - ASSERT_FALSE(six); - ASSERT_EQ(12, multiplySixByTwoFunction()); -} - -namespace RefAndDerefTests { - - template struct RefCounted { - void ref(); - void deref(); - }; - struct Connection : RefCounted { }; - COMPILE_ASSERT(WTF::HasRefAndDeref::value, class_has_ref_and_deref); - - struct NoRefOrDeref { }; - COMPILE_ASSERT(!WTF::HasRefAndDeref::value, class_has_no_ref_or_deref); - - struct RefOnly { void ref(); }; - COMPILE_ASSERT(!WTF::HasRefAndDeref::value, class_has_ref_only); - - struct DerefOnly { void deref(); }; - COMPILE_ASSERT(!WTF::HasRefAndDeref::value, class_has_deref_only); - -} - -} // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -370,7 +370,7 @@ DerivedRefLogger a("a"); RefPtr ptr(&a); - hashCountedSet.add(ptr.release()); + hashCountedSet.add(WTFMove(ptr)); EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); } @@ -436,7 +436,7 @@ { RefPtr ptr2(&a); - auto addResult = hashCountedSet.add(ptr2.release()); + auto addResult = hashCountedSet.add(WTFMove(ptr2)); EXPECT_FALSE(addResult.isNewEntry); } diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -26,10 +26,13 @@ #include "config.h" #include "Counters.h" +#include "DeletedAddressOfOperator.h" #include "MoveOnly.h" #include "RefLogger.h" +#include "Test.h" #include #include +#include #include namespace TestWebKitAPI { @@ -307,7 +310,7 @@ DerivedRefLogger a("a"); RefPtr ptr(&a); - map.add(ptr.release(), 0); + map.add(WTFMove(ptr), 0); EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); } @@ -371,7 +374,7 @@ { RefPtr ptr2(&a); - auto addResult = map.add(ptr2.release(), 0); + auto addResult = map.add(WTFMove(ptr2), 0); EXPECT_FALSE(addResult.isNewEntry); } @@ -417,7 +420,7 @@ DerivedRefLogger a("a"); RefPtr ptr(&a); - map.set(ptr.release(), 0); + map.set(WTFMove(ptr), 0); EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); } @@ -479,7 +482,7 @@ { RefPtr ptr2(&a); - auto addResult = map.set(ptr2.release(), 1); + auto addResult = map.set(WTFMove(ptr2), 1); EXPECT_FALSE(addResult.isNewEntry); EXPECT_EQ(1, map.get(ptr.get())); } @@ -699,4 +702,224 @@ EXPECT_EQ(observer->count, 0u); } +TEST(WTF_HashMap, Ref_Key) +{ + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.add(WTFMove(ref), 1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.set(WTFMove(ref), 1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref refA(a); + map.add(WTFMove(refA), 1); + + Ref refA2(a); + map.set(WTFMove(refA2), 1); + } + + ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.ensure(WTFMove(ref), []() { + return 1; + }); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.add(WTFMove(ref), 1); + + auto it = map.find(&a); + ASSERT_TRUE(it != map.end()); + + ASSERT_EQ(it->key.ptr(), &a); + ASSERT_EQ(it->value, 1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.add(WTFMove(ref), 1); + + map.remove(&a); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.add(WTFMove(ref), 1); + + int i = map.take(&a); + ASSERT_EQ(i, 1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + for (int i = 0; i < 64; ++i) { + Ref ref = adoptRef(*new RefLogger("a")); + auto* pointer = ref.ptr(); + map.add(WTFMove(ref), i + 1); + ASSERT_TRUE(map.contains(pointer)); + } + } + + ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, Ref_Value) +{ + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.set(1, WTFMove(ref)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + Ref refA(a); + map.add(1, WTFMove(refA)); + + RefLogger b("b"); + Ref refB(b); + map.set(1, WTFMove(refB)); + } + + ASSERT_STREQ("ref(a) ref(b) deref(a) deref(b) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + + auto aGet = map.get(1); + ASSERT_EQ(aGet, &a); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + auto emptyGet = map.get(1); + ASSERT_TRUE(emptyGet == nullptr); + } + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + + auto aOut = map.take(1); + ASSERT_TRUE(static_cast(aOut)); + ASSERT_EQ(&a, aOut.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + auto emptyTake = map.take(1); + ASSERT_FALSE(static_cast(emptyTake)); + } + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + map.remove(1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + map.ensure(1, [&]() { + Ref ref(a); + return ref; + }); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + for (int i = 0; i < 64; ++i) { + Ref ref = adoptRef(*new RefLogger("a")); + map.add(i + 1, WTFMove(ref)); + ASSERT_TRUE(map.contains(i + 1)); + } + } + + ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, DeletedAddressOfOperator) +{ + HashMap map1; + for (auto& value : map1.values()) + (void)value; +} + } // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp 2016-04-13 11:44:57.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp 2016-10-13 08:26:50.000000000 +0000 @@ -26,7 +26,9 @@ #include "config.h" #include "Counters.h" +#include "DeletedAddressOfOperator.h" #include "MoveOnly.h" +#include "RefLogger.h" #include #include @@ -348,5 +350,103 @@ EXPECT_TRUE(observedBucket == observerAddress || observedBucket == reinterpret_cast(-1)); } +TEST(WTF_HashSet, Ref) +{ + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(ref.copyRef()); + } + + ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + set.remove(&a); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + + auto aOut = set.take(&a); + ASSERT_TRUE(static_cast(aOut)); + ASSERT_EQ(&a, aOut.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + + auto aOut = set.takeAny(); + ASSERT_TRUE(static_cast(aOut)); + ASSERT_EQ(&a, aOut.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + auto emptyTake = set.takeAny(); + ASSERT_FALSE(static_cast(emptyTake)); + } + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + + ASSERT_TRUE(set.contains(&a)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + for (int i = 0; i < 64; ++i) { + Ref ref = adoptRef(*new RefLogger("a")); + auto* pointer = ref.ptr(); + set.add(WTFMove(ref)); + ASSERT_TRUE(set.contains(pointer)); + } + } + ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashSet, DeletedAddressOfOperator) +{ + HashSet set1; + set1.add(10); + + set1.remove(10); +} } // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -266,4 +266,86 @@ ASSERT_TRUE(list.isEmpty()); } +TEST(WTF_ListHashSet, MoveConstructor) +{ + ListHashSet list; + list.add(1); + list.add(2); + list.add(3); + + ASSERT_EQ(3U, list.size()); + auto iterator = list.begin(); + ASSERT_EQ(1, *iterator); + ++iterator; + ASSERT_EQ(2, *iterator); + ++iterator; + ASSERT_EQ(3, *iterator); + ++iterator; + + ListHashSet list2(WTFMove(list)); + ASSERT_EQ(3U, list2.size()); + auto iterator2 = list2.begin(); + ASSERT_EQ(1, *iterator2); + ++iterator2; + ASSERT_EQ(2, *iterator2); + ++iterator2; + ASSERT_EQ(3, *iterator2); + ++iterator2; + + ASSERT_EQ(0U, list.size()); + ASSERT_TRUE(list.begin() == list.end()); + list.add(4); + list.add(5); + list.add(6); + iterator = list.begin(); + ASSERT_EQ(4, *iterator); + ++iterator; + ASSERT_EQ(5, *iterator); + ++iterator; + ASSERT_EQ(6, *iterator); + ++iterator; +} + +TEST(WTF_ListHashSet, MoveAssignment) +{ + ListHashSet list; + list.add(1); + list.add(2); + list.add(3); + + ASSERT_EQ(3U, list.size()); + auto iterator = list.begin(); + ASSERT_EQ(1, *iterator); + ++iterator; + ASSERT_EQ(2, *iterator); + ++iterator; + ASSERT_EQ(3, *iterator); + ++iterator; + + ListHashSet list2; + list2.add(10); + list2 = (WTFMove(list)); + ASSERT_EQ(3U, list2.size()); + auto iterator2 = list2.begin(); + ASSERT_EQ(1, *iterator2); + ++iterator2; + ASSERT_EQ(2, *iterator2); + ++iterator2; + ASSERT_EQ(3, *iterator2); + ++iterator2; + + ASSERT_EQ(0U, list.size()); + ASSERT_TRUE(list.begin() == list.end()); + list.add(4); + list.add(5); + list.add(6); + iterator = list.begin(); + ASSERT_EQ(4, *iterator); + ++iterator; + ASSERT_EQ(5, *iterator); + ++iterator; + ASSERT_EQ(6, *iterator); + ++iterator; +} + } // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -148,7 +148,7 @@ } // We need to wait. - if (ParkingLot::compareAndPark(&semaphore, newSemaphoreValue)) { + if (ParkingLot::compareAndPark(&semaphore, newSemaphoreValue).wasUnparked) { // We did wait, and then got woken up. This means that someone who up'd the semaphore // passed ownership onto us. return; @@ -254,12 +254,10 @@ repeatParkingTest(1, 1, 10000, 50, 50); } -#if !PLATFORM(IOS) TEST(WTF_ParkingLot, UnparkOneFiftyThenFiftyAll) { repeatParkingTest(2, 1, 10000, 100, 50); } -#endif TEST(WTF_ParkingLot, HundredUnparkAllOneFast) { diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -31,11 +31,13 @@ namespace TestWebKitAPI { -static const int CallbackExpected = 0xC0FFEE; +static const int IncrementExpected = 0xC0FFEE1; +static const int DecrementExpected = 0xC0FFEE2; static const int CallbackNotExpected = 0xDECAF; -enum CounterType { }; -typedef RefCounter::Token TokenType; +enum TestCounterType { }; +typedef RefCounter TestCounter; +typedef TestCounter::Token TokenType; TEST(WTF, RefCounter) { @@ -77,56 +79,66 @@ { // Testing (1a) - Construction with a callback. - RefCounter* counterPtr = nullptr; - RefCounter counter([&](bool value) { + TestCounter* counterPtr = nullptr; + TestCounter counter([&](RefCounterEvent event) { // Check that the callback is called at the expected times, and the correct number of times. - EXPECT_EQ(callbackValue, CallbackExpected); - // Value provided should be equal to the counter value. - EXPECT_EQ(value, counterPtr->value()); + if (RefCounterEvent::Increment == event) + EXPECT_EQ(callbackValue, IncrementExpected); + if (RefCounterEvent::Decrement == event) + EXPECT_EQ(callbackValue, DecrementExpected); // return the value of the counter in the callback. - callbackValue = value; + callbackValue = counterPtr->value(); }); counterPtr = &counter; // Testing (4a) - after construction value() is 0. EXPECT_EQ(0, static_cast(counter.value())); // Testing (3a) - ref with callback from 0 -> 1. - callbackValue = CallbackExpected; - TokenType incTo1(counter.token()); + callbackValue = IncrementExpected; + TokenType incTo1(counter.count()); // Testing (4b) & (4c) - values within & after callback. - EXPECT_EQ(true, callbackValue); + EXPECT_EQ(1, callbackValue); EXPECT_EQ(1, static_cast(counter.value())); // Testing (3b) - ref with callback from 1 -> 2. + callbackValue = IncrementExpected; TokenType incTo2(incTo1); // Testing (4b) & (4c) - values within & after callback. + EXPECT_EQ(2, callbackValue); EXPECT_EQ(2, static_cast(counter.value())); // Testing (3c) - deref with callback from >1 -> 1. + callbackValue = DecrementExpected; incTo1 = nullptr; // Testing (4b) & (4c) - values within & after callback. + EXPECT_EQ(1, callbackValue); EXPECT_EQ(1, static_cast(counter.value())); { // Testing (3j) - ref using a Ref rather than a RefPtr. - TokenType incTo2Again(counter.token()); + callbackValue = IncrementExpected; + TokenType incTo2Again(counter.count()); // Testing (4b) & (4c) - values within & after callback. + EXPECT_EQ(2, callbackValue); EXPECT_EQ(2, static_cast(counter.value())); // Testing (3k) - deref using a Ref rather than a RefPtr. + + callbackValue = DecrementExpected; } + EXPECT_EQ(1, callbackValue); EXPECT_EQ(1, static_cast(counter.value())); // Testing (4b) & (4c) - values within & after callback. // Testing (3d) - deref with callback from 1 -> 0. - callbackValue = CallbackExpected; + callbackValue = DecrementExpected; incTo2 = nullptr; // Testing (4b) & (4c) - values within & after callback. EXPECT_EQ(0, callbackValue); EXPECT_EQ(0, static_cast(counter.value())); - // Testing (2a) - Destruction where the RefCounter::Count has a non-zero reference count. - callbackValue = CallbackExpected; - incTo1Again = counter.token(); + // Testing (2a) - Destruction where the TestCounter::Count has a non-zero reference count. + callbackValue = IncrementExpected; + incTo1Again = counter.count(); EXPECT_EQ(1, callbackValue); EXPECT_EQ(1, static_cast(counter.value())); callbackValue = CallbackNotExpected; @@ -140,11 +152,11 @@ incTo2Again = nullptr; // Testing (1b) - Construction without a callback. - RefCounter counter; + TestCounter counter; // Testing (4a) - after construction value() is 0. EXPECT_EQ(0, static_cast(counter.value())); // Testing (3h) - ref without callback - TokenType incTo1(counter.token()); + TokenType incTo1(counter.count()); // Testing (4c) - value as read after the ref. EXPECT_EQ(1, static_cast(counter.value())); // Testing (3i) - deref without callback diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "RefLogger.h" + +namespace TestWebKitAPI { + +std::ostringstream& log() +{ + static std::ostringstream log; + return log; +} + +} diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h 2016-09-16 09:56:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,11 +27,7 @@ namespace TestWebKitAPI { -inline std::ostringstream& log() -{ - static std::ostringstream log; - return log; -} +std::ostringstream& log(); inline std::string takeLogStr() { diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -26,6 +26,8 @@ #include "config.h" #include "RefLogger.h" +#include +#include #include namespace TestWebKitAPI { @@ -403,4 +405,34 @@ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); } + +struct ConstRefCounted : RefCounted { + static Ref create() { return adoptRef(*new ConstRefCounted); } +}; + +const ConstRefCounted& returnConstRefCountedRef() +{ + static NeverDestroyed instance; + return instance.get(); +} +ConstRefCounted& returnRefCountedRef() +{ + static NeverDestroyed instance; + return instance.get(); +} + +TEST(WTF_RefPtr, Const) +{ + // This test passes if it compiles without an error. + auto a = ConstRefCounted::create(); + Ref b = WTFMove(a); + RefPtr c = b.ptr(); + Ref d = returnConstRefCountedRef(); + RefPtr e = &returnConstRefCountedRef(); + RefPtr f = ConstRefCounted::create(); + RefPtr g = f; + RefPtr h(f); + Ref i(returnRefCountedRef()); +} + } // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -25,7 +25,7 @@ #include "config.h" -#include "PlatformUtilities.h" +#include "Utilities.h" #include namespace TestWebKitAPI { @@ -54,4 +54,113 @@ Util::run(&testFinished); } +TEST(WTF_RunLoop, NestedRunLoop) +{ + RunLoop::initializeMainRunLoop(); + + bool testFinished = false; + RunLoop::current().dispatch([&] { + RunLoop::current().dispatch([&] { + testFinished = true; + }); + Util::run(&testFinished); + }); + + Util::run(&testFinished); +} + +TEST(WTF_RunLoop, OneShotTimer) +{ + RunLoop::initializeMainRunLoop(); + + bool testFinished = false; + + class DerivedTimer : public RunLoop::Timer { + public: + DerivedTimer(bool& testFinished) + : RunLoop::Timer(RunLoop::current(), this, &DerivedTimer::fired) + , m_testFinished(testFinished) + { + } + + void fired() + { + m_testFinished = true; + stop(); + } + + private: + bool& m_testFinished; + }; + + { + DerivedTimer timer(testFinished); + timer.startOneShot(0.1); + Util::run(&testFinished); + } +} + +TEST(WTF_RunLoop, RepeatingTimer) +{ + RunLoop::initializeMainRunLoop(); + + bool testFinished = false; + + class DerivedTimer : public RunLoop::Timer { + public: + DerivedTimer(bool& testFinished) + : RunLoop::Timer(RunLoop::current(), this, &DerivedTimer::fired) + , m_testFinished(testFinished) + { + } + + void fired() + { + if (++m_count == 10) { + m_testFinished = true; + stop(); + } + } + + private: + unsigned m_count { 0 }; + bool& m_testFinished; + }; + + { + DerivedTimer timer(testFinished); + timer.startRepeating(0.01); + Util::run(&testFinished); + } +} + +TEST(WTF_RunLoop, ManyTimes) +{ + RunLoop::initializeMainRunLoop(); + + class Counter { + public: + void run() + { + if (++m_count == 100000) { + RunLoop::current().stop(); + return; + } + RunLoop::current().dispatch([this] { + run(); + }); + } + + private: + unsigned m_count { 0 }; + }; + + Counter counter; + + RunLoop::current().dispatch([&counter] { + counter.run(); + }); + RunLoop::run(); +} + } // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include + +namespace TestWebKitAPI { + +TEST(WTF_Scope, ScopeExit) +{ + bool isCalled = false; + { + auto scopeExit = makeScopeExit([&] { + EXPECT_FALSE(isCalled); + isCalled = true; + }); + EXPECT_FALSE(isCalled); + } + EXPECT_TRUE(isCalled); + + isCalled = false; + { + auto scopeExit = makeScopeExit([&] { + isCalled = true; + }); + scopeExit.release(); + } + EXPECT_FALSE(isCalled); +} + +} diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include +#include + +using namespace WTF; + +namespace TestWebKitAPI { + +// This test relies on this module being compiled with -fno-elide-constructors +TEST(WTF_ScopedLambda, NoRVOLivenessBug) +{ + Vector vector; + for (unsigned i = 0; i < 10; ++i) + vector.append(i); + + auto lambda = scopedLambda( + [=] (size_t i) -> int { + return vector[i]; + }); + + for (unsigned i = 0; i < 10; ++i) + EXPECT_EQ(i, static_cast(lambda(i))); +} + +} // namespace TestWebKitAPI + diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,14 +33,14 @@ TEST(WTF, StringImplCreationFromLiteral) { // Constructor using the template to determine the size. - RefPtr stringWithTemplate = StringImpl::createFromLiteral("Template Literal"); + auto stringWithTemplate = StringImpl::createFromLiteral("Template Literal"); ASSERT_EQ(strlen("Template Literal"), stringWithTemplate->length()); ASSERT_TRUE(equal(stringWithTemplate.get(), "Template Literal")); ASSERT_TRUE(stringWithTemplate->is8Bit()); // Constructor taking the size explicitely. const char* programmaticStringData = "Explicit Size Literal"; - RefPtr programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData)); + auto programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData)); ASSERT_EQ(strlen(programmaticStringData), programmaticString->length()); ASSERT_TRUE(equal(programmaticString.get(), programmaticStringData)); ASSERT_EQ(programmaticStringData, reinterpret_cast(programmaticString->characters8())); @@ -48,7 +48,7 @@ // Constructor without explicit size. const char* stringWithoutLengthLiteral = "No Size Literal"; - RefPtr programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral); + auto programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral); ASSERT_EQ(strlen(stringWithoutLengthLiteral), programmaticStringNoLength->length()); ASSERT_TRUE(equal(programmaticStringNoLength.get(), stringWithoutLengthLiteral)); ASSERT_EQ(stringWithoutLengthLiteral, reinterpret_cast(programmaticStringNoLength->characters8())); @@ -57,7 +57,7 @@ TEST(WTF, StringImplReplaceWithLiteral) { - RefPtr testStringImpl = StringImpl::createFromLiteral("1224"); + auto testStringImpl = StringImpl::createFromLiteral("1224"); ASSERT_TRUE(testStringImpl->is8Bit()); // Cases for 8Bit source. @@ -101,225 +101,225 @@ TEST(WTF, StringImplEqualIgnoringASCIICaseBasic) { - RefPtr a = StringImpl::createFromLiteral("aBcDeFG"); - RefPtr b = StringImpl::createFromLiteral("ABCDEFG"); - RefPtr c = StringImpl::createFromLiteral("abcdefg"); + auto a = StringImpl::createFromLiteral("aBcDeFG"); + auto b = StringImpl::createFromLiteral("ABCDEFG"); + auto c = StringImpl::createFromLiteral("abcdefg"); const char d[] = "aBcDeFG"; - RefPtr empty = StringImpl::create(reinterpret_cast("")); - RefPtr shorter = StringImpl::createFromLiteral("abcdef"); - RefPtr different = StringImpl::createFromLiteral("abcrefg"); + auto empty = StringImpl::create(reinterpret_cast("")); + auto shorter = StringImpl::createFromLiteral("abcdef"); + auto different = StringImpl::createFromLiteral("abcrefg"); // Identity. - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), a.get())); - ASSERT_TRUE(equalIgnoringASCIICase(b.get(), b.get())); - ASSERT_TRUE(equalIgnoringASCIICase(c.get(), c.get())); - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), d)); - ASSERT_TRUE(equalIgnoringASCIICase(b.get(), d)); - ASSERT_TRUE(equalIgnoringASCIICase(c.get(), d)); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d)); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), d)); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d)); // Transitivity. - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), b.get())); - ASSERT_TRUE(equalIgnoringASCIICase(b.get(), c.get())); - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), c.get())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr())); // Negative cases. - ASSERT_FALSE(equalIgnoringASCIICase(a.get(), empty.get())); - ASSERT_FALSE(equalIgnoringASCIICase(b.get(), empty.get())); - ASSERT_FALSE(equalIgnoringASCIICase(c.get(), empty.get())); - ASSERT_FALSE(equalIgnoringASCIICase(a.get(), shorter.get())); - ASSERT_FALSE(equalIgnoringASCIICase(b.get(), shorter.get())); - ASSERT_FALSE(equalIgnoringASCIICase(c.get(), shorter.get())); - ASSERT_FALSE(equalIgnoringASCIICase(a.get(), different.get())); - ASSERT_FALSE(equalIgnoringASCIICase(b.get(), different.get())); - ASSERT_FALSE(equalIgnoringASCIICase(c.get(), different.get())); - ASSERT_FALSE(equalIgnoringASCIICase(empty.get(), d)); - ASSERT_FALSE(equalIgnoringASCIICase(shorter.get(), d)); - ASSERT_FALSE(equalIgnoringASCIICase(different.get(), d)); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), empty.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), empty.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), empty.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), shorter.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), shorter.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), shorter.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), different.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), different.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), different.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(empty.ptr(), d)); + ASSERT_FALSE(equalIgnoringASCIICase(shorter.ptr(), d)); + ASSERT_FALSE(equalIgnoringASCIICase(different.ptr(), d)); } TEST(WTF, StringImplEqualIgnoringASCIICaseWithNull) { - RefPtr reference = StringImpl::createFromLiteral("aBcDeFG"); + auto reference = StringImpl::createFromLiteral("aBcDeFG"); StringImpl* nullStringImpl = nullptr; - ASSERT_FALSE(equalIgnoringASCIICase(nullStringImpl, reference.get())); - ASSERT_FALSE(equalIgnoringASCIICase(reference.get(), nullStringImpl)); + ASSERT_FALSE(equalIgnoringASCIICase(nullStringImpl, reference.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(reference.ptr(), nullStringImpl)); ASSERT_TRUE(equalIgnoringASCIICase(nullStringImpl, nullStringImpl)); } TEST(WTF, StringImplEqualIgnoringASCIICaseWithEmpty) { - RefPtr a = StringImpl::create(reinterpret_cast("")); - RefPtr b = StringImpl::create(reinterpret_cast("")); - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), b.get())); - ASSERT_TRUE(equalIgnoringASCIICase(b.get(), a.get())); + auto a = StringImpl::create(reinterpret_cast("")); + auto b = StringImpl::create(reinterpret_cast("")); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), a.ptr())); } -static RefPtr stringFromUTF8(const char* characters) +static Ref stringFromUTF8(const char* characters) { - return String::fromUTF8(characters).impl(); + return String::fromUTF8(characters).releaseImpl().releaseNonNull(); } TEST(WTF, StringImplEqualIgnoringASCIICaseWithLatin1Characters) { - RefPtr a = stringFromUTF8("aBcéeFG"); - RefPtr b = stringFromUTF8("ABCÉEFG"); - RefPtr c = stringFromUTF8("ABCéEFG"); - RefPtr d = stringFromUTF8("abcéefg"); + auto a = stringFromUTF8("aBcéeFG"); + auto b = stringFromUTF8("ABCÉEFG"); + auto c = stringFromUTF8("ABCéEFG"); + auto d = stringFromUTF8("abcéefg"); const char e[] = "aBcéeFG"; // Identity. - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), a.get())); - ASSERT_TRUE(equalIgnoringASCIICase(b.get(), b.get())); - ASSERT_TRUE(equalIgnoringASCIICase(c.get(), c.get())); - ASSERT_TRUE(equalIgnoringASCIICase(d.get(), d.get())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(d.ptr(), d.ptr())); // All combination. - ASSERT_FALSE(equalIgnoringASCIICase(a.get(), b.get())); - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), c.get())); - ASSERT_TRUE(equalIgnoringASCIICase(a.get(), d.get())); - ASSERT_FALSE(equalIgnoringASCIICase(b.get(), c.get())); - ASSERT_FALSE(equalIgnoringASCIICase(b.get(), d.get())); - ASSERT_TRUE(equalIgnoringASCIICase(c.get(), d.get())); - ASSERT_FALSE(equalIgnoringASCIICase(a.get(), e)); - ASSERT_FALSE(equalIgnoringASCIICase(b.get(), e)); - ASSERT_FALSE(equalIgnoringASCIICase(c.get(), e)); - ASSERT_FALSE(equalIgnoringASCIICase(d.get(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), c.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), d.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d.ptr())); + ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), e)); + ASSERT_FALSE(equalIgnoringASCIICase(d.ptr(), e)); } TEST(WTF, StringImplFindIgnoringASCIICaseBasic) { - RefPtr referenceA = stringFromUTF8("aBcéeFG"); - RefPtr referenceB = stringFromUTF8("ABCÉEFG"); + auto referenceA = stringFromUTF8("aBcéeFG"); + auto referenceB = stringFromUTF8("ABCÉEFG"); // Search the exact string. - EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(referenceA.get())); - EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(referenceB.get())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(referenceA.ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(referenceB.ptr())); // A and B are distinct by the non-ascii character é/É. - EXPECT_EQ(static_cast(notFound), referenceA->findIgnoringASCIICase(referenceB.get())); - EXPECT_EQ(static_cast(notFound), referenceB->findIgnoringASCIICase(referenceA.get())); + EXPECT_EQ(static_cast(notFound), referenceA->findIgnoringASCIICase(referenceB.ptr())); + EXPECT_EQ(static_cast(notFound), referenceB->findIgnoringASCIICase(referenceA.ptr())); // Find the prefix. - EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").get())); - EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").get())); - EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").get())); - EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").get())); - EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").get())); - EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").get())); - EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").get())); - EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").ptr())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr())); // Not a prefix. - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").get())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr())); // Find the infix. - EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").get())); - EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").get())); - EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").get())); - EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").get())); - EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").get())); - EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").get())); - EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").get())); - EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").get())); - EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").get())); - - EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").get())); - EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").get())); - EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").get())); - EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").get())); - EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").get())); - EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").get())); - EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").get())); - EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").get())); - EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").get())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").ptr())); + + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").ptr())); // Not an infix. - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").get())); - - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").get())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").ptr())); + + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").ptr())); // Find the suffix. - EXPECT_EQ(static_cast(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").get())); - EXPECT_EQ(static_cast(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").get())); - EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").get())); - EXPECT_EQ(static_cast(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").get())); - EXPECT_EQ(static_cast(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").get())); - EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").get())); - - EXPECT_EQ(static_cast(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").get())); - EXPECT_EQ(static_cast(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").get())); - EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").get())); - EXPECT_EQ(static_cast(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").get())); - EXPECT_EQ(static_cast(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").get())); - EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").get())); + EXPECT_EQ(static_cast(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr())); + EXPECT_EQ(static_cast(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").ptr())); + EXPECT_EQ(static_cast(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr())); + EXPECT_EQ(static_cast(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr())); + + EXPECT_EQ(static_cast(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr())); + EXPECT_EQ(static_cast(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr())); + EXPECT_EQ(static_cast(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr())); + EXPECT_EQ(static_cast(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr())); // Not a suffix. - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").get())); - - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").get())); - EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").get())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr())); + + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr())); } TEST(WTF, StringImplFindIgnoringASCIICaseWithValidOffset) { - RefPtr reference = stringFromUTF8("ABCÉEFGaBcéeFG"); - EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 0)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 1)); - EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 0)); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 1)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").get(), 0)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").get(), 1)); + auto reference = stringFromUTF8("ABCÉEFGaBcéeFG"); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 0)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 1)); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 0)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 1)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 0)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 1)); } TEST(WTF, StringImplFindIgnoringASCIICaseWithInvalidOffset) { - RefPtr reference = stringFromUTF8("ABCÉEFGaBcéeFG"); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 15)); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 16)); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 17)); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 42)); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), std::numeric_limits::max())); + auto reference = stringFromUTF8("ABCÉEFGaBcéeFG"); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 15)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 16)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 17)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 42)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), std::numeric_limits::max())); } TEST(WTF, StringImplFindIgnoringASCIICaseOnNull) { - RefPtr reference = stringFromUTF8("ABCÉEFG"); + auto reference = stringFromUTF8("ABCÉEFG"); EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr)); EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 0)); EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 3)); @@ -331,215 +331,243 @@ TEST(WTF, StringImplFindIgnoringASCIICaseOnEmpty) { - RefPtr reference = stringFromUTF8("ABCÉEFG"); - RefPtr empty = StringImpl::create(reinterpret_cast("")); - EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(empty.get())); - EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(empty.get(), 0)); - EXPECT_EQ(static_cast(3), reference->findIgnoringASCIICase(empty.get(), 3)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.get(), 7)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.get(), 8)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.get(), 42)); - EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.get(), std::numeric_limits::max())); + auto reference = stringFromUTF8("ABCÉEFG"); + auto empty = StringImpl::create(reinterpret_cast("")); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(empty.ptr())); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(empty.ptr(), 0)); + EXPECT_EQ(static_cast(3), reference->findIgnoringASCIICase(empty.ptr(), 3)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), 7)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), 8)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), 42)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), std::numeric_limits::max())); } TEST(WTF, StringImplFindIgnoringASCIICaseWithPatternLongerThanReference) { - RefPtr reference = stringFromUTF8("ABCÉEFG"); - RefPtr pattern = stringFromUTF8("XABCÉEFG"); - EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(pattern.get())); - EXPECT_EQ(static_cast(1), pattern->findIgnoringASCIICase(reference.get())); + auto reference = stringFromUTF8("ABCÉEFG"); + auto pattern = stringFromUTF8("XABCÉEFG"); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(pattern.ptr())); + EXPECT_EQ(static_cast(1), pattern->findIgnoringASCIICase(reference.ptr())); } TEST(WTF, StringImplStartsWithIgnoringASCIICaseBasic) { - RefPtr reference = stringFromUTF8("aBcéX"); - RefPtr referenceEquivalent = stringFromUTF8("AbCéx"); + auto reference = stringFromUTF8("aBcéX"); + auto referenceEquivalent = stringFromUTF8("AbCéx"); // Identity. - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(reference.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*reference.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(referenceEquivalent.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*referenceEquivalent.get())); - ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(reference.get())); - ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*reference.get())); - ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(referenceEquivalent.get())); - ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*referenceEquivalent.get())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*referenceEquivalent.ptr())); // Proper prefixes. - RefPtr aLower = StringImpl::createFromLiteral("a"); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aLower.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aLower.get())); - RefPtr aUpper = StringImpl::createFromLiteral("A"); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aUpper.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aUpper.get())); - - RefPtr abcLower = StringImpl::createFromLiteral("abc"); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcLower.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcLower.get())); - RefPtr abcUpper = StringImpl::createFromLiteral("ABC"); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcUpper.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcUpper.get())); - - RefPtr abcAccentLower = stringFromUTF8("abcé"); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentLower.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentLower.get())); - RefPtr abcAccentUpper = stringFromUTF8("ABCé"); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentUpper.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentUpper.get())); + auto aLower = StringImpl::createFromLiteral("a"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aLower.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aLower.ptr())); + auto aUpper = StringImpl::createFromLiteral("A"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aUpper.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aUpper.ptr())); + + auto abcLower = StringImpl::createFromLiteral("abc"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcLower.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcLower.ptr())); + auto abcUpper = StringImpl::createFromLiteral("ABC"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcUpper.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcUpper.ptr())); + + auto abcAccentLower = stringFromUTF8("abcé"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentLower.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentLower.ptr())); + auto abcAccentUpper = stringFromUTF8("ABCé"); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentUpper.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentUpper.ptr())); // Negative cases. - RefPtr differentFirstChar = stringFromUTF8("bBcéX"); - RefPtr differentFirstCharProperPrefix = stringFromUTF8("CBcé"); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstChar.get())); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstChar.get())); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstCharProperPrefix.get())); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstCharProperPrefix.get())); - - RefPtr uppercaseAccent = stringFromUTF8("aBcÉX"); - RefPtr uppercaseAccentProperPrefix = stringFromUTF8("aBcÉX"); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccent.get())); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccent.get())); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccentProperPrefix.get())); - ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccentProperPrefix.get())); + auto differentFirstChar = stringFromUTF8("bBcéX"); + auto differentFirstCharProperPrefix = stringFromUTF8("CBcé"); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstChar.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstChar.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstCharProperPrefix.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstCharProperPrefix.ptr())); + + auto uppercaseAccent = stringFromUTF8("aBcÉX"); + auto uppercaseAccentProperPrefix = stringFromUTF8("aBcÉX"); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccent.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccent.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccentProperPrefix.ptr())); + ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccentProperPrefix.ptr())); } TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithNull) { - RefPtr reference = StringImpl::createFromLiteral("aBcDeFG"); + auto reference = StringImpl::createFromLiteral("aBcDeFG"); ASSERT_FALSE(reference->startsWithIgnoringASCIICase(nullptr)); - RefPtr empty = StringImpl::create(reinterpret_cast("")); + auto empty = StringImpl::create(reinterpret_cast("")); ASSERT_FALSE(empty->startsWithIgnoringASCIICase(nullptr)); } TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithEmpty) { - RefPtr reference = StringImpl::createFromLiteral("aBcDeFG"); - RefPtr empty = StringImpl::create(reinterpret_cast("")); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(empty.get())); - ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*empty.get())); - ASSERT_TRUE(empty->startsWithIgnoringASCIICase(empty.get())); - ASSERT_TRUE(empty->startsWithIgnoringASCIICase(*empty.get())); - ASSERT_FALSE(empty->startsWithIgnoringASCIICase(reference.get())); - ASSERT_FALSE(empty->startsWithIgnoringASCIICase(*reference.get())); + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + auto empty = StringImpl::create(reinterpret_cast("")); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_TRUE(empty->startsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(empty->startsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_FALSE(empty->startsWithIgnoringASCIICase(reference.ptr())); + ASSERT_FALSE(empty->startsWithIgnoringASCIICase(*reference.ptr())); +} + +TEST(WTF, StartsWithLettersIgnoringASCIICase) +{ + String string("Test tEST"); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test t")); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test te")); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test test")); + ASSERT_FALSE(startsWithLettersIgnoringASCIICase(string, "test tex")); + + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "")); + ASSERT_TRUE(startsWithLettersIgnoringASCIICase(String(""), "")); + + ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), "t")); + ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), "")); } TEST(WTF, StringImplEndsWithIgnoringASCIICaseBasic) { - RefPtr reference = stringFromUTF8("XÉCbA"); - RefPtr referenceEquivalent = stringFromUTF8("xÉcBa"); + auto reference = stringFromUTF8("XÉCbA"); + auto referenceEquivalent = stringFromUTF8("xÉcBa"); // Identity. - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(reference.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*reference.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(referenceEquivalent.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*referenceEquivalent.get())); - ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(reference.get())); - ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*reference.get())); - ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(referenceEquivalent.get())); - ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*referenceEquivalent.get())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(reference.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*reference.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(referenceEquivalent.ptr())); + ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*referenceEquivalent.ptr())); // Proper suffixes. - RefPtr aLower = StringImpl::createFromLiteral("a"); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aLower.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aLower.get())); - RefPtr aUpper = StringImpl::createFromLiteral("a"); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aUpper.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aUpper.get())); - - RefPtr abcLower = StringImpl::createFromLiteral("cba"); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcLower.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcLower.get())); - RefPtr abcUpper = StringImpl::createFromLiteral("CBA"); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcUpper.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcUpper.get())); - - RefPtr abcAccentLower = stringFromUTF8("Écba"); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentLower.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentLower.get())); - RefPtr abcAccentUpper = stringFromUTF8("ÉCBA"); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentUpper.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentUpper.get())); + auto aLower = StringImpl::createFromLiteral("a"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aLower.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aLower.ptr())); + auto aUpper = StringImpl::createFromLiteral("a"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aUpper.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aUpper.ptr())); + + auto abcLower = StringImpl::createFromLiteral("cba"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcLower.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcLower.ptr())); + auto abcUpper = StringImpl::createFromLiteral("CBA"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcUpper.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcUpper.ptr())); + + auto abcAccentLower = stringFromUTF8("Écba"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentLower.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentLower.ptr())); + auto abcAccentUpper = stringFromUTF8("ÉCBA"); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentUpper.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentUpper.ptr())); // Negative cases. - RefPtr differentLastChar = stringFromUTF8("XÉCbB"); - RefPtr differentLastCharProperSuffix = stringFromUTF8("ÉCbb"); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastChar.get())); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastChar.get())); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastCharProperSuffix.get())); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastCharProperSuffix.get())); - - RefPtr lowercaseAccent = stringFromUTF8("aBcéX"); - RefPtr loweraseAccentProperSuffix = stringFromUTF8("aBcéX"); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(lowercaseAccent.get())); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*lowercaseAccent.get())); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(loweraseAccentProperSuffix.get())); - ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*loweraseAccentProperSuffix.get())); + auto differentLastChar = stringFromUTF8("XÉCbB"); + auto differentLastCharProperSuffix = stringFromUTF8("ÉCbb"); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastChar.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastChar.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastCharProperSuffix.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastCharProperSuffix.ptr())); + + auto lowercaseAccent = stringFromUTF8("aBcéX"); + auto loweraseAccentProperSuffix = stringFromUTF8("aBcéX"); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(lowercaseAccent.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*lowercaseAccent.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(loweraseAccentProperSuffix.ptr())); + ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*loweraseAccentProperSuffix.ptr())); } TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithNull) { - RefPtr reference = StringImpl::createFromLiteral("aBcDeFG"); + auto reference = StringImpl::createFromLiteral("aBcDeFG"); ASSERT_FALSE(reference->endsWithIgnoringASCIICase(nullptr)); - RefPtr empty = StringImpl::create(reinterpret_cast("")); + auto empty = StringImpl::create(reinterpret_cast("")); ASSERT_FALSE(empty->endsWithIgnoringASCIICase(nullptr)); } TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithEmpty) { - RefPtr reference = StringImpl::createFromLiteral("aBcDeFG"); - RefPtr empty = StringImpl::create(reinterpret_cast("")); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(empty.get())); - ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*empty.get())); - ASSERT_TRUE(empty->endsWithIgnoringASCIICase(empty.get())); - ASSERT_TRUE(empty->endsWithIgnoringASCIICase(*empty.get())); - ASSERT_FALSE(empty->endsWithIgnoringASCIICase(reference.get())); - ASSERT_FALSE(empty->endsWithIgnoringASCIICase(*reference.get())); + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + auto empty = StringImpl::create(reinterpret_cast("")); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_TRUE(empty->endsWithIgnoringASCIICase(empty.ptr())); + ASSERT_TRUE(empty->endsWithIgnoringASCIICase(*empty.ptr())); + ASSERT_FALSE(empty->endsWithIgnoringASCIICase(reference.ptr())); + ASSERT_FALSE(empty->endsWithIgnoringASCIICase(*reference.ptr())); } -TEST(WTF, StringImplCreateSymbolEmpty) +TEST(WTF, StringImplCreateNullSymbol) { - RefPtr reference = StringImpl::createSymbolEmpty(); + auto reference = StringImpl::createNullSymbol(); ASSERT_TRUE(reference->isSymbol()); + ASSERT_TRUE(reference->isNullSymbol()); ASSERT_FALSE(reference->isAtomic()); ASSERT_EQ(0u, reference->length()); - ASSERT_TRUE(equal(reference.get(), "")); + ASSERT_TRUE(equal(reference.ptr(), "")); } TEST(WTF, StringImplCreateSymbol) { - RefPtr original = stringFromUTF8("original"); - RefPtr reference = StringImpl::createSymbol(original); + auto original = stringFromUTF8("original"); + auto reference = StringImpl::createSymbol(original); ASSERT_TRUE(reference->isSymbol()); + ASSERT_FALSE(reference->isNullSymbol()); ASSERT_FALSE(reference->isAtomic()); ASSERT_FALSE(original->isSymbol()); ASSERT_FALSE(original->isAtomic()); ASSERT_EQ(original->length(), reference->length()); - ASSERT_TRUE(equal(reference.get(), "original")); + ASSERT_TRUE(equal(reference.ptr(), "original")); + + auto empty = stringFromUTF8(""); + auto emptyReference = StringImpl::createSymbol(empty); + ASSERT_TRUE(emptyReference->isSymbol()); + ASSERT_FALSE(emptyReference->isNullSymbol()); + ASSERT_FALSE(emptyReference->isAtomic()); + ASSERT_FALSE(empty->isSymbol()); + ASSERT_FALSE(empty->isNullSymbol()); + ASSERT_TRUE(empty->isAtomic()); + ASSERT_EQ(empty->length(), emptyReference->length()); + ASSERT_TRUE(equal(emptyReference.ptr(), "")); } TEST(WTF, StringImplSymbolToAtomicString) { - RefPtr original = stringFromUTF8("original"); - RefPtr reference = StringImpl::createSymbol(original); + auto original = stringFromUTF8("original"); + auto reference = StringImpl::createSymbol(original); ASSERT_TRUE(reference->isSymbol()); ASSERT_FALSE(reference->isAtomic()); - RefPtr atomic = AtomicStringImpl::add(reference.get()); + auto atomic = AtomicStringImpl::add(reference.ptr()); ASSERT_TRUE(atomic->isAtomic()); ASSERT_FALSE(atomic->isSymbol()); ASSERT_TRUE(reference->isSymbol()); ASSERT_FALSE(reference->isAtomic()); } -TEST(WTF, StringImplSymbolEmptyToAtomicString) +TEST(WTF, StringImplNullSymbolToAtomicString) { - RefPtr reference = StringImpl::createSymbolEmpty(); + auto reference = StringImpl::createNullSymbol(); ASSERT_TRUE(reference->isSymbol()); ASSERT_FALSE(reference->isAtomic()); - RefPtr atomic = AtomicStringImpl::add(reference.get()); + auto atomic = AtomicStringImpl::add(reference.ptr()); ASSERT_TRUE(atomic->isAtomic()); ASSERT_FALSE(atomic->isSymbol()); ASSERT_TRUE(reference->isSymbol()); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -78,6 +78,14 @@ SUCCEED(); } +bool compareLoopIterations(StringView::GraphemeClusters graphemeClusters, std::vector expected) +{ + std::vector actual; + for (auto graphemeCluster : graphemeClusters) + actual.push_back(graphemeCluster); + return actual == expected; +} + bool compareLoopIterations(StringView::CodePoints codePoints, std::vector expected) { std::vector actual; @@ -103,43 +111,107 @@ TEST(WTF, StringViewIterators) { - compareLoopIterations(StringView().codePoints(), { }); - compareLoopIterations(StringView().codeUnits(), { }); - - compareLoopIterations(StringView::empty().codePoints(), { }); - compareLoopIterations(StringView::empty().codeUnits(), { }); - - compareLoopIterations(StringView(String("hello")).codePoints(), {'h', 'e', 'l', 'l', 'o'}); - compareLoopIterations(StringView(String("hello")).codeUnits(), {'h', 'e', 'l', 'l', 'o'}); + EXPECT_TRUE(compareLoopIterations(StringView().codePoints(), { })); + EXPECT_TRUE(compareLoopIterations(StringView().codeUnits(), { })); + EXPECT_TRUE(compareLoopIterations(StringView().graphemeClusters(), { })); + + EXPECT_TRUE(compareLoopIterations(StringView::empty().codePoints(), { })); + EXPECT_TRUE(compareLoopIterations(StringView::empty().codeUnits(), { })); + EXPECT_TRUE(compareLoopIterations(StringView::empty().graphemeClusters(), { })); + + String helo("helo"); + StringView heloView(helo); + + auto codePoints = heloView.codePoints(); + auto codePointsIterator = codePoints.begin(); + EXPECT_EQ(*codePointsIterator, 'h'); + EXPECT_EQ(*codePointsIterator, 'h'); + ++codePointsIterator; + ++codePointsIterator; + EXPECT_EQ(*codePointsIterator, 'l'); + auto savedIterator = codePointsIterator; + codePointsIterator = codePoints.begin(); + EXPECT_EQ(*codePointsIterator, 'h'); + codePointsIterator = savedIterator; + EXPECT_EQ(*codePointsIterator, 'l'); + String webkit("webkit"); + auto webkitCodePoints = StringView(webkit).codePoints(); + codePointsIterator = webkitCodePoints.begin(); + ++codePointsIterator; + ++codePointsIterator; + EXPECT_EQ(*codePointsIterator, 'b'); + while (codePointsIterator != webkitCodePoints.end()) + ++codePointsIterator; + + EXPECT_TRUE(compareLoopIterations(heloView.codePoints(), {'h', 'e', 'l', 'o'})); + EXPECT_TRUE(compareLoopIterations(heloView.codeUnits(), {'h', 'e', 'l', 'o'})); + EXPECT_TRUE(compareLoopIterations(heloView.graphemeClusters(), { + StringView(heloView.characters8(), 1), + StringView(heloView.characters8() + 1, 1), + StringView(heloView.characters8() + 2, 1), + StringView(heloView.characters8() + 3, 1)})); StringBuilder b; build(b, {0xD800, 0xDD55}); // Surrogates for unicode code point U+10155 EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x10155})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xDD55})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())})); build(b, {0xD800}); // Leading surrogate only EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())})); build(b, {0xD800, 0xD801}); // Two leading surrogates EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 0xD801})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xD801})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.characters16(), 1), StringView(b.characters16() + 1, 1)})); build(b, {0xDD55}); // Trailing surrogate only EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xDD55})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xDD55})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())})); build(b, {0xD800, 'h'}); // Leading surrogate followed by non-surrogate EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 'h'})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 'h'})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.characters16(), 1), StringView(b.characters16() + 1, 1)})); build(b, {0x0306}); // "COMBINING BREVE" EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())})); build(b, {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}); // Mix of single code unit and multi code unit code points EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306, 0x10155, 'h', 'e', 'l', 'o'})); EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { + StringView(b.characters16(), 1), + StringView(b.characters16() + 1, 2), + StringView(b.characters16() + 3, 1), + StringView(b.characters16() + 4, 1), + StringView(b.characters16() + 5, 1), + StringView(b.characters16() + 6, 1)})); + + build(b, {'e', 0x0301}); // "COMBINING ACUTE" + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {'e', 0x0301})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {'e', 0x0301})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())})); + + build(b, {'e', 0x0301, 0x0306, 'a'}); // "COMBINING ACUTE" "COMBINING BREVE" + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {'e', 0x0301, 0x0306, 'a'})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {'e', 0x0301, 0x0306, 'a'})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { + StringView(b.characters16(), 3), + StringView(b.characters16() + 3, 1), + })); + + build(b, {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}); // Korean combining Jamo + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8})); + EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), { + StringView(b.characters16(), 3), + StringView(b.characters16() + 3, 3)})); } TEST(WTF, StringViewEqualIgnoringASCIICaseBasic) @@ -717,7 +789,6 @@ TEST(WTF, StringView8Bit) { StringView nullView; - StringView emptyView = StringView::empty(); EXPECT_TRUE(StringView().is8Bit()); EXPECT_TRUE(StringView::empty().is8Bit()); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +namespace TestWebKitAPI { + +class A { }; +class B { +public: + B(int a, int b, int c) + : a(a) + , b(b) + , c(c) + { }; + int a; + int b; + int c; +}; +class C { +public: + C(UniqueRef&& a) + : a(WTFMove(a)) + { } + UniqueRef a; +}; +class D : public A { }; + +void function(const UniqueRef a) +{ + const A& b = a.get(); + const A* c = &a; + UNUSED_PARAM(b); + UNUSED_PARAM(c); +} + +TEST(WTF, UniqueRef) +{ + UniqueRef a = makeUniqueRef(); + UniqueRef b = makeUniqueRef(1, 2, 3); + B& c = b.get(); + const B& d = b.get(); + B* e = &b; + const B* f = &b; + UniqueRef j = WTFMove(a); + + Vector> v; + v.append(makeUniqueRef(4, 5, 6)); + v.append(makeUniqueRef(7, 8, 9)); + UniqueRef g = v.takeLast(); + ASSERT_EQ(g->b, 8); + ASSERT_EQ(v.last()->b, 5); + + C h(makeUniqueRef()); + C i(makeUniqueRef()); + + UNUSED_PARAM(b); + UNUSED_PARAM(c); + UNUSED_PARAM(d); + UNUSED_PARAM(e); + UNUSED_PARAM(f); + UNUSED_PARAM(g); + UNUSED_PARAM(h); + UNUSED_PARAM(i); + UNUSED_PARAM(j); +} + +} // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "Counters.h" +#include "RefLogger.h" +#include +#include +#include +#include +#include + +namespace TestWebKitAPI { + +TEST(WTF_Variant, Initial) +{ + std::experimental::variant v1; + EXPECT_TRUE(v1.index() == 0); + EXPECT_TRUE(std::experimental::get(v1) == 0); + + struct T { + T() : value(15) { } + int value; + }; + + std::experimental::variant v2; + EXPECT_TRUE(v2.index() == 0); + EXPECT_TRUE(std::experimental::get(v2).value == 15); +} + +TEST(WTF_Variant, Basic) +{ + std::experimental::variant variant = 1; + EXPECT_TRUE(variant.index() == 0); + EXPECT_TRUE(std::experimental::get(variant) == 1); + EXPECT_TRUE(*std::experimental::get_if(variant) == 1); + EXPECT_TRUE(std::experimental::get_if(variant) == nullptr); + EXPECT_TRUE(std::experimental::holds_alternative(variant)); + EXPECT_FALSE(std::experimental::holds_alternative(variant)); + + variant = 1.0; + EXPECT_TRUE(variant.index() == 1); + EXPECT_TRUE(std::experimental::get(variant) == 1); + EXPECT_TRUE(*std::experimental::get_if(variant) == 1.0); + EXPECT_TRUE(std::experimental::get_if(variant) == nullptr); + EXPECT_TRUE(std::experimental::holds_alternative(variant)); + EXPECT_FALSE(std::experimental::holds_alternative(variant)); +} + +TEST(WTF_Variant, BasicVisitor) +{ + enum class Type { + None, + Int, + Float, + String, + }; + + struct Visitor { + Visitor(Type& t) + : type(t) + { + } + + Type& type; + + void operator()(int) const { type = Type::Int; } + void operator()(float) const { type = Type::Float; } + void operator()(String) const { type = Type::String; } + }; + + Type type = Type::None; + + std::experimental::variant variant = 8; + std::experimental::visit(Visitor(type), variant); + EXPECT_TRUE(Type::Int == type); + + + variant = 1.0f; + std::experimental::visit(Visitor(type), variant); + EXPECT_TRUE(Type::Float == type); + + + variant = "hello"; + std::experimental::visit(Visitor(type), variant); + EXPECT_TRUE(Type::String == type); +} + +TEST(WTF_Variant, VisitorUsingMakeVisitor) +{ + enum class Type { + None, + Int, + Float, + String, + }; + + Type type = Type::None; + + auto visitor = WTF::makeVisitor( + [&](int) { type = Type::Int; }, + [&](float) { type = Type::Float; }, + [&](String) { type = Type::String; } + ); + + std::experimental::variant variant = 8; + std::experimental::visit(visitor, variant); + EXPECT_TRUE(Type::Int == type); + + + variant = 1.0f; + std::experimental::visit(visitor, variant); + EXPECT_TRUE(Type::Float == type); + + + variant = "hello"; + std::experimental::visit(visitor, variant); + EXPECT_TRUE(Type::String == type); +} + +TEST(WTF_Variant, ConstructorDestructor) +{ + ConstructorDestructorCounter::TestingScope scope; + + { + auto uniquePtr = std::make_unique(); + std::experimental::variant, int> v = WTFMove(uniquePtr); + + EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount); + EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount); + } + + EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount); + EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount); +} + +TEST(WTF_Variant, RefPtr) +{ + { + RefLogger a("a"); + RefPtr ref(&a); + std::experimental::variant, int> v = ref; + } + + ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str()); + + { + RefLogger a("a"); + RefPtr ref(&a); + std::experimental::variant, int> v = WTFMove(ref); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_Variant, Ref) +{ + { + RefLogger a("a"); + Ref ref(a); + std::experimental::variant, int> v = WTFMove(ref); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); +} + +} diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -67,7 +67,7 @@ { struct Test { private: - Test* operator&(); + Test* operator&() = delete; }; Vector vector; diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -24,8 +24,8 @@ */ #include "config.h" -#include "test.h" +#include "Test.h" #include namespace TestWebKitAPI { @@ -43,6 +43,9 @@ EXPECT_TRUE(weakPtr1); EXPECT_TRUE(weakPtr2); EXPECT_TRUE(weakPtr3); + EXPECT_TRUE(weakPtr1 == weakPtr2); + EXPECT_TRUE(weakPtr1 == &dummy); + EXPECT_TRUE(&dummy == weakPtr2); delete factory; EXPECT_NULL(weakPtr1.get()); EXPECT_NULL(weakPtr2.get()); @@ -75,6 +78,9 @@ WeakPtr weakPtr2 = factory2->createWeakPtr(); EXPECT_EQ(weakPtr1.get(), &dummy1); EXPECT_EQ(weakPtr2.get(), &dummy2); + EXPECT_TRUE(weakPtr1 != weakPtr2); + EXPECT_TRUE(weakPtr1 != &dummy2); + EXPECT_TRUE(&dummy1 != weakPtr2); delete factory1; EXPECT_NULL(weakPtr1.get()); EXPECT_EQ(weakPtr2.get(), &dummy2); diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp 2016-09-19 12:18:06.000000000 +0000 @@ -162,7 +162,7 @@ TEST(WTF, StringToInt) { - bool ok; + bool ok = false; EXPECT_EQ(0, String().toInt()); EXPECT_EQ(0, String().toInt(&ok)); @@ -214,7 +214,7 @@ TEST(WTF, StringToDouble) { - bool ok; + bool ok = false; EXPECT_EQ(0.0, String().toDouble()); EXPECT_EQ(0.0, String().toDouble(&ok)); @@ -292,4 +292,25 @@ ASSERT_EQ(string2.existingHash(), 0u); } +TEST(WTF, StringUnicodeEqualUCharArray) +{ + String string1("abc"); + ASSERT_FALSE(string1.isNull()); + ASSERT_TRUE(string1.is8Bit()); + UChar ab[] = { 'a', 'b' }; + UChar abc[] = { 'a', 'b', 'c' }; + UChar abcd[] = { 'a', 'b', 'c', 'd' }; + UChar aBc[] = { 'a', 'B', 'c' }; + ASSERT_FALSE(equal(string1, ab)); + ASSERT_TRUE(equal(string1, abc)); + ASSERT_FALSE(equal(string1, abcd)); + ASSERT_FALSE(equal(string1, aBc)); + + String string2(abc, 3); + ASSERT_FALSE(equal(string2, ab)); + ASSERT_TRUE(equal(string2, abc)); + ASSERT_FALSE(equal(string2, abcd)); + ASSERT_FALSE(equal(string2, aBc)); +} + } // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/TestWebKitAPI/Utilities.h webkit2gtk-2.14.2/Tools/TestWebKitAPI/Utilities.h --- webkit2gtk-2.12.3/Tools/TestWebKitAPI/Utilities.h 1970-01-01 00:00:00.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/TestWebKitAPI/Utilities.h 2016-09-16 09:56:48.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace TestWebKitAPI { +namespace Util { + +// Runs a platform runloop until the 'done' is true. +void run(bool* done); +void sleep(double seconds); + +} // namespace Util +} // namespace TestWebKitAPI diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/CMakeLists.txt webkit2gtk-2.14.2/Tools/WebKitTestRunner/CMakeLists.txt --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/CMakeLists.txt 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/CMakeLists.txt 2016-11-03 07:04:21.000000000 +0000 @@ -1,6 +1,8 @@ set(WEBKIT_TESTRUNNER_DIR "${TOOLS_DIR}/WebKitTestRunner") set(WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR "${TOOLS_DIR}/WebKitTestRunner/InjectedBundle") -set(WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR "${TOOLS_DIR}/WebKitTestRunner/UIScriptContext") +set(WEBKIT_TESTRUNNER_SHARED_DIR "${TOOLS_DIR}/TestRunnerShared/") +set(WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR "${WEBKIT_TESTRUNNER_SHARED_DIR}/UIScriptContext") +set(WEBKIT_TESTRUNNER_BINDINGS_DIR "${WEBKIT_TESTRUNNER_SHARED_DIR}/Bindings") file(MAKE_DIRECTORY ${DERIVED_SOURCES_DIR}/InjectedBundle) file(MAKE_DIRECTORY ${DERIVED_SOURCES_DIR}/UIScriptContext) @@ -17,13 +19,11 @@ ${WEBKIT_TESTRUNNER_DIR}/WorkQueueManager.cpp ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/UIScriptContext.cpp ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/UIScriptController.cpp - - ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/JSWrapper.cpp + ${WEBKIT_TESTRUNNER_BINDINGS_DIR}/JSWrapper.cpp ) set(WebKitTestRunner_LIBRARIES JavaScriptCore - WebCore WebCoreTestSupport WebKit2 ) @@ -34,7 +34,7 @@ ${WEBKIT_TESTRUNNER_DIR}/InjectedBundle/Bindings ${WEBKIT_TESTRUNNER_DIR}/InjectedBundle/atk ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR} - ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/Bindings + ${WEBKIT_TESTRUNNER_BINDINGS_DIR} ${JAVASCRIPTCORE_DIR} ${JAVASCRIPTCORE_DIR}/ForwardingHeaders ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR} @@ -63,6 +63,7 @@ set(WebKitTestRunner_SYSTEM_INCLUDE_DIRECTORIES ${LIBSOUP_INCLUDE_DIRS} + ${ICU_INCLUDE_DIRS} ) set(WebKitTestRunnerInjectedBundle_SOURCES @@ -78,7 +79,7 @@ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/TestRunner.cpp ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/TextInputController.cpp - ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/JSWrapper.cpp + ${WEBKIT_TESTRUNNER_BINDINGS_DIR}/JSWrapper.cpp ) set(WebKitTestRunnerInjectedBundle_IDL_FILES @@ -93,7 +94,7 @@ ) set(WebKitTestRunner_IDL_FILES - "${WEBKIT_TESTRUNNER_DIR}/UIScriptContext/Bindings/UIScriptController.idl" + "${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/Bindings/UIScriptController.idl" ) GENERATE_BINDINGS(WebKitTestRunnerInjectedBundle_SOURCES @@ -123,4 +124,6 @@ add_executable(WebKitTestRunner ${WebKitTestRunner_SOURCES}) target_link_libraries(WebKitTestRunner ${WebKitTestRunner_LIBRARIES}) -add_dependencies(WebKit2 ${ForwardingHeadersForWebKitTestRunner_NAME}) +if (NOT APPLE) + add_dependencies(WebKit2 ${ForwardingHeadersForWebKitTestRunner_NAME}) +endif () \ No newline at end of file diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/config.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/config.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/config.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/config.h 2016-09-19 12:18:06.000000000 +0000 @@ -29,13 +29,10 @@ #include "cmakeconfig.h" #endif +#include #include #include #include #include -// This is needed because we include WebCore's headers. -// FIXME: We should include instead. -#define WEBCORE_EXPORT - #endif diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/DerivedSources.make webkit2gtk-2.14.2/Tools/WebKitTestRunner/DerivedSources.make --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/DerivedSources.make 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/DerivedSources.make 2016-09-19 12:18:06.000000000 +0000 @@ -23,7 +23,7 @@ VPATH = \ $(WebKitTestRunner)/InjectedBundle/Bindings \ - $(WebKitTestRunner)/UIScriptContext/Bindings \ + $(WebKitTestRunner)/../TestRunnerShared/UIScriptContext/Bindings \ # INJECTED_BUNDLE_INTERFACES = \ diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -140,6 +140,7 @@ void TestController::platformConfigureViewForTest(const TestInvocation&) { + WKPageSetApplicationNameForUserAgent(mainWebView()->page(), WKStringCreateWithUTF8CString("WebKitTestRunnerGTK")); } void TestController::platformResetPreferencesToConsistentValues() diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp 2016-05-23 10:59:50.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -81,6 +81,9 @@ } else if (!g_strcmp0(signalQuery.signal_name, "children-changed")) { const gchar* childrenChangedDetail = g_quark_to_string(signalHint->detail); notificationName = !g_strcmp0(childrenChangedDetail, "add") ? "AXChildrenAdded" : "AXChildrenRemoved"; + gpointer child = g_value_get_pointer(¶mValues[2]); + if (ATK_IS_OBJECT(child)) + extraArgs.append(toJS(jsContext, WTF::getPtr(WTR::AccessibilityUIElement::create(ATK_OBJECT(child))))); } else if (!g_strcmp0(signalQuery.signal_name, "property-change")) { if (!g_strcmp0(g_quark_to_string(signalHint->detail), "accessible-value")) notificationName = "AXValueChanged"; diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp 2016-05-23 13:29:15.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -105,6 +105,7 @@ const char* landmarkStringContentinfo = "AXLandmarkContentInfo"; const char* landmarkStringMain = "AXLandmarkMain"; const char* landmarkStringNavigation = "AXLandmarkNavigation"; +const char* landmarkStringRegion = "AXLandmarkRegion"; const char* landmarkStringSearch = "AXLandmarkSearch"; #endif @@ -331,6 +332,8 @@ return landmarkStringMain; if (equalLettersIgnoringASCIICase(xmlRolesValue, "navigation")) return landmarkStringNavigation; + if (equalLettersIgnoringASCIICase(xmlRolesValue, "region")) + return landmarkStringRegion; if (equalLettersIgnoringASCIICase(xmlRolesValue, "search")) return landmarkStringSearch; } @@ -379,6 +382,8 @@ return "AXInvalid"; case ATK_ROLE_LABEL: return "AXLabel"; + case ATK_ROLE_LEVEL_BAR: + return "AXProgressIndicator"; case ATK_ROLE_LINK: return "AXLink"; case ATK_ROLE_LIST: @@ -1025,7 +1030,19 @@ PassRefPtr AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const { - // FIXME: implement + if (!ATK_IS_OBJECT(m_element.get())) + return nullptr; + + // ATK does not have this API. So we're "faking it" here on a case-by-case basis. + String attributeString = jsStringToWTFString(attribute); + AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); + if (role == ATK_ROLE_SPIN_BUTTON && const_cast(this)->childrenCount() == 2) { + if (attributeString == "AXDecrementButton") + return const_cast(this)->childAtIndex(0); + if (attributeString == "AXIncrementButton") + return const_cast(this)->childAtIndex(1); + } + return nullptr; } @@ -1130,8 +1147,10 @@ JSRetainPtr AccessibilityUIElement::roleDescription() { - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); + String roleDescription = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "roledescription"); + GUniquePtr axRoleDescription(g_strdup_printf("AXRoleDescription: %s", roleDescription.utf8().data())); + + return JSStringCreateWithUTF8CString(axRoleDescription.get()); } JSRetainPtr AccessibilityUIElement::computedRoleString() @@ -1217,15 +1236,15 @@ AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element.get())); if (!relationSet) - return nullptr; + return JSStringCreateWithCharacters(0, 0); AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY); if (!relation) - return nullptr; + return JSStringCreateWithCharacters(0, 0); GPtrArray* targetList = atk_relation_get_target(relation); if (!targetList || !targetList->len) - return nullptr; + return JSStringCreateWithCharacters(0, 0); StringBuilder builder; builder.append("AXHelp: "); @@ -1400,8 +1419,9 @@ JSRetainPtr AccessibilityUIElement::valueDescription() { - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); + String valueText = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "valuetext"); + GUniquePtr valueDescription(g_strdup_printf("AXValueDescription: %s", valueText.utf8().data())); + return JSStringCreateWithUTF8CString(valueDescription.get()); } int AccessibilityUIElement::insertionPointLineNumber() @@ -1788,7 +1808,7 @@ return JSStringCreateWithCharacters(0, 0); AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); - if (role != ATK_ROLE_DOCUMENT_FRAME) + if (role != ATK_ROLE_DOCUMENT_WEB) return JSStringCreateWithCharacters(0, 0); return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "Encoding")); @@ -1800,7 +1820,7 @@ return JSStringCreateWithCharacters(0, 0); AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); - if (role != ATK_ROLE_DOCUMENT_FRAME) + if (role != ATK_ROLE_DOCUMENT_WEB) return JSStringCreateWithCharacters(0, 0); return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "URI")); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl 2016-09-16 09:56:48.000000000 +0000 @@ -30,7 +30,7 @@ readonly attribute DOMString platformName; readonly attribute AccessibilityUIElement rootElement; readonly attribute AccessibilityUIElement focusedElement; - AccessibilityUIElement elementAtPoint(int x, int y); + AccessibilityUIElement elementAtPoint(long x, long y); AccessibilityUIElement accessibleElementById(DOMString id); boolean addNotificationListener(object functionCallback); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl 2016-09-16 09:56:48.000000000 +0000 @@ -31,7 +31,7 @@ readonly attribute DOMString documentURI; // Element access. - AccessibilityUIElement elementAtPoint(int x, int y); + AccessibilityUIElement elementAtPoint(long x, long y); AccessibilityUIElement childAtIndex(unsigned long index); unsigned long indexOfChild(AccessibilityUIElement child); AccessibilityUIElement linkedUIElementAtIndex(unsigned long index); @@ -54,7 +54,7 @@ readonly attribute DOMString url; readonly attribute DOMString speak; readonly attribute DOMString orientation; - readonly attribute int insertionPointLineNumber; + readonly attribute long insertionPointLineNumber; readonly attribute DOMString selectedTextRange; DOMString stringAttributeValue(DOMString attr); @@ -70,9 +70,9 @@ boolean isDecrementActionSupported(); readonly attribute DOMString stringValue; - readonly attribute int intValue; - readonly attribute int minValue; - readonly attribute int maxValue; + readonly attribute long intValue; + readonly attribute long minValue; + readonly attribute long maxValue; readonly attribute boolean isEnabled; readonly attribute boolean isRequired; @@ -91,22 +91,22 @@ readonly attribute boolean isIgnored; readonly attribute boolean isOffScreen; readonly attribute boolean isValid; - readonly attribute int hierarchicalLevel; + readonly attribute long hierarchicalLevel; readonly attribute boolean ariaIsGrabbed; readonly attribute DOMString ariaDropEffects; readonly attribute DOMString classList; - readonly attribute int x; - readonly attribute int y; - readonly attribute int width; - readonly attribute int height; - readonly attribute int clickPointX; - readonly attribute int clickPointY; - - readonly attribute int childrenCount; - readonly attribute int selectedChildrenCount; - readonly attribute int rowCount; - readonly attribute int columnCount; + readonly attribute long x; + readonly attribute long y; + readonly attribute long width; + readonly attribute long height; + readonly attribute long clickPointX; + readonly attribute long clickPointY; + + readonly attribute long childrenCount; + readonly attribute long selectedChildrenCount; + readonly attribute long rowCount; + readonly attribute long columnCount; // Actions. void increment(); @@ -121,10 +121,10 @@ DOMString attributesOfDocumentLinks(); // Text info. - DOMString characterAtOffset(int offset); - DOMString wordAtOffset(int offset); - DOMString lineAtOffset(int offset); - DOMString sentenceAtOffset(int offset); + DOMString characterAtOffset(long offset); + DOMString wordAtOffset(long offset); + DOMString lineAtOffset(long offset); + DOMString sentenceAtOffset(long offset); // Table info. DOMString attributesOfColumnHeaders(); @@ -138,11 +138,11 @@ AccessibilityUIElement disclosedByRow(); AccessibilityUIElement disclosedRowAtIndex(unsigned long index); AccessibilityUIElement rowAtIndex(unsigned long index); - int indexInTable(); + long indexInTable(); DOMString rowIndexRange(); DOMString columnIndexRange(); - int rowCount(); - int columnCount(); + long rowCount(); + long columnCount(); object columnHeaders(); object rowHeaders(); @@ -152,14 +152,14 @@ // Paramaterized attributes. DOMString parameterizedAttributeNames(); - int lineForIndex(int index); - DOMString rangeForLine(int index); - DOMString rangeForPosition(int x, int y); + long lineForIndex(long index); + DOMString rangeForLine(long index); + DOMString rangeForPosition(long x, long y); DOMString boundsForRange(unsigned long location, unsigned long length); DOMString stringForRange(unsigned long location, unsigned long length); DOMString attributedStringForRange(unsigned long location, unsigned long length); boolean attributedStringRangeIsMisspelled(unsigned long location, unsigned long length); - [PassContext] unsigned int uiElementCountForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly); + [PassContext] unsigned long uiElementCountForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly); [PassContext] AccessibilityUIElement uiElementForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly); [PassContext] DOMString selectTextWithCriteria(DOMString ambiguityResolution, object searchStrings, DOMString replacementString, DOMString activity); boolean setSelectedTextRange(unsigned long location, unsigned long length); @@ -169,8 +169,8 @@ readonly attribute AccessibilityUIElement verticalScrollbar; void scrollToMakeVisible(); - void scrollToGlobalPoint(int x, int y); - void scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height); + void scrollToGlobalPoint(long x, long y); + void scrollToMakeVisibleWithSubFocus(long x, long y, long width, long height); void takeFocus(); boolean scrollPageDown(); @@ -186,18 +186,18 @@ void resetSelectedTextMarkerRange(); AccessibilityTextMarker startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange range); AccessibilityTextMarker endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange range); - AccessibilityTextMarker endTextMarkerForBounds(int x, int y, int width, int height); - AccessibilityTextMarker startTextMarkerForBounds(int x, int y, int width, int height); - AccessibilityTextMarker textMarkerForPoint(int x, int y); + AccessibilityTextMarker endTextMarkerForBounds(long x, long y, long width, long height); + AccessibilityTextMarker startTextMarkerForBounds(long x, long y, long width, long height); + AccessibilityTextMarker textMarkerForPoint(long x, long y); AccessibilityTextMarker previousTextMarker(AccessibilityTextMarker marker); AccessibilityTextMarker nextTextMarker(AccessibilityTextMarker marker); AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker marker); DOMString stringForTextMarkerRange(AccessibilityTextMarkerRange range); - int textMarkerRangeLength(AccessibilityTextMarkerRange range); + long textMarkerRangeLength(AccessibilityTextMarkerRange range); boolean attributedStringForTextMarkerRangeContainsAttribute(DOMString attr, AccessibilityTextMarkerRange range); - int indexForTextMarker(AccessibilityTextMarker marker); + long indexForTextMarker(AccessibilityTextMarker marker); boolean isTextMarkerValid(AccessibilityTextMarker marker); - AccessibilityTextMarker textMarkerForIndex(int textIndex); + AccessibilityTextMarker textMarkerForIndex(long textIndex); readonly attribute AccessibilityTextMarker startTextMarker; readonly attribute AccessibilityTextMarker endTextMarker; boolean setSelectedVisibleTextRange(AccessibilityTextMarkerRange range); @@ -222,8 +222,8 @@ // iOS specific accessibility methods. readonly attribute DOMString identifier; readonly attribute DOMString traits; - readonly attribute int elementTextPosition; - readonly attribute int elementTextLength; + readonly attribute long elementTextPosition; + readonly attribute long elementTextLength; readonly attribute DOMString stringForSelection; object elementsForRange(unsigned long location, unsigned long length); void increaseTextSelection(); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h 2013-08-03 16:10:41.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSWrappable_h -#define JSWrappable_h - -#include -#include - -namespace WTR { - -class JSWrappable : public RefCounted { -public: - virtual ~JSWrappable() { } - virtual JSClassRef wrapperClass() = 0; -}; - -inline JSValueRef JSValueMakeStringOrNull(JSContextRef context, JSStringRef stringOrNull) -{ - return stringOrNull ? JSValueMakeString(context, stringOrNull) : JSValueMakeNull(context); -} - -} // namespace WTR - -#endif // JSWrappable_h diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp 2013-08-03 16:10:41.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSWrapper.h" - -#include - -namespace WTR { - -JSValueRef JSWrapper::wrap(JSContextRef context, JSWrappable* object) -{ - ASSERT_ARG(context, context); - - if (!object) - return JSValueMakeNull(context); - - JSClassRef objectClass = object->wrapperClass(); - ASSERT(objectClass); - JSObjectRef wrapperObject = JSObjectMake(context, objectClass, object); - ASSERT(wrapperObject); - - return wrapperObject; -} - -JSWrappable* JSWrapper::unwrap(JSContextRef context, JSValueRef value) -{ - ASSERT_ARG(context, context); - ASSERT_ARG(value, value); - if (!context || !value) - return 0; - return static_cast(JSObjectGetPrivate(JSValueToObject(context, value, 0))); -} - -static JSWrappable* unwrapObject(JSObjectRef object) -{ - JSWrappable* wrappable = static_cast(JSObjectGetPrivate(object)); - ASSERT(wrappable); - return wrappable; -} - -void JSWrapper::initialize(JSContextRef ctx, JSObjectRef object) -{ - JSWrappable* wrappable = unwrapObject(object); - if (!wrappable) - return; - wrappable->ref(); -} - -void JSWrapper::finalize(JSObjectRef object) -{ - JSWrappable* wrappable = unwrapObject(object); - if (!wrappable) - return; - wrappable->deref(); -} - -} // namespace WTR diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h 2013-08-03 16:10:41.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSWrapper_h -#define JSWrapper_h - -#include "JSWrappable.h" -#include - -namespace WTR { - -// FIXME: If necessary, we can do wrapper caching here. -class JSWrapper { -public: - static JSValueRef wrap(JSContextRef context, JSWrappable* object); - static JSWrappable* unwrap(JSContextRef context, JSValueRef value); - - static void initialize(JSContextRef, JSObjectRef); - static void finalize(JSObjectRef); -}; - -inline JSValueRef toJS(JSContextRef context, JSWrappable* impl) -{ - return JSWrapper::wrap(context, impl); -} - -inline void setProperty(JSContextRef context, JSObjectRef object, const char* propertyName, JSWrappable* value, JSPropertyAttributes attributes, JSValueRef* exception) -{ - JSRetainPtr propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName)); - JSObjectSetProperty(context, object, propertyNameString.get(), JSWrapper::wrap(context, value), attributes, exception); -} - -} // namespace WTR - -#endif // JSWrapper_h diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,8 +29,10 @@ void dumpChildFramesAsText(); void waitForPolicyDelegate(); void waitUntilDone(); + void waitUntilDownloadFinished(); void notifyDone(); double preciseTime(); + readonly attribute double timeout; // Other dumping. void dumpBackForwardList(); @@ -60,6 +62,7 @@ void setAllowFileAccessFromFileURLs(boolean value); void setPluginsEnabled(boolean value); void setJavaScriptCanAccessClipboard(boolean value); + void setAutomaticLinkDetectionEnabled(boolean value); void setPrivateBrowsingEnabled(boolean value); void setPopupBlockingEnabled(boolean value); void setAuthorAndUserStylesEnabled(boolean value); @@ -72,11 +75,12 @@ void setTabKeyCyclesThroughElements(boolean enabled); void setSerializeHTTPLoads(); void dispatchPendingLoadRequests(); - void setCacheModel(int model); + void setCacheModel(long model); void setAsynchronousSpellCheckingEnabled(boolean value); void setPrinting(); void setShouldDecideNavigationPolicyAfterDelay(boolean value); void setNavigationGesturesEnabled(boolean value); + void setIgnoresViewportScaleLimits(boolean value); // Special DOM functions. void clearBackForwardList(); @@ -93,7 +97,7 @@ void display(); // Printing - boolean isPageBoxVisible(int pageIndex); + boolean isPageBoxVisible(long pageIndex); [PassContext] void setValueForUser(object element, DOMString value); @@ -147,11 +151,11 @@ void removeChromeInputField(object callback); void focusWebView(object callback); - void clearTestRunnerCallbacks(); - + // Window/view state void setBackingScaleFactor(double backingScaleFactor, object callback); void setWindowIsKey(boolean isKey); + void setViewSize(double width, double height); // Cookies testing void setAlwaysAcceptCookies(boolean accept); @@ -173,13 +177,13 @@ // Geolocation void setGeolocationPermission(boolean value); - void setMockGeolocationPosition(double latitude, double longitude, double accuracy, [Default=Undefined] optional object altitude, optional object altitudeAccuracy, optional object heading, optional object speed); + void setMockGeolocationPosition(double latitude, double longitude, double accuracy, optional object altitude, optional object altitudeAccuracy, optional object heading, optional object speed); void setMockGeolocationPositionUnavailableError(DOMString errorMessage); boolean isGeolocationProviderActive(); // MediaStream void setUserMediaPermission(boolean value); - void setUserMediaPermissionForOrigin(boolean permission, DOMString url); + void setUserMediaPermissionForOrigin(boolean permission, DOMString origin, DOMString parentOrigin); // Audio testing. [PassContext] void setAudioResult(object data); @@ -196,10 +200,14 @@ void queueNonLoadingScript(DOMString script); // Authentication + void setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(boolean value); void setHandlesAuthenticationChallenges(boolean value); + void setShouldLogCanAuthenticateAgainstProtectionSpace(boolean value); void setAuthenticationUsername(DOMString username); void setAuthenticationPassword(DOMString password); + void setAllowsAnySSLCertificate(boolean value); + // Secure text input mode (Mac only) readonly attribute boolean secureEventInputIsEnabled; @@ -217,7 +225,19 @@ void installDidEndSwipeCallback(object callback); void installDidRemoveSwipeSnapshotCallback(object callback); + unsigned long imageCountInGeneralPasteboard(); + // UI Process Testing void runUIScript(DOMString script, object callback); -}; + void clearTestRunnerCallbacks(); + + void accummulateLogsForChannel(DOMString channel); + + // Gamepad + void setMockGamepadDetails(unsigned long index, DOMString id, unsigned long axisCount, unsigned long buttonCount); + void setMockGamepadAxisValue(unsigned long index, unsigned long axisIndex, double value); + void setMockGamepadButtonValue(unsigned long index, unsigned long buttonIndex, double value); + void connectMockGamepad(unsigned long index); + void disconnectMockGamepad(unsigned long index); +}; diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +29,7 @@ #include "ActivateFonts.h" #include "InjectedBundlePage.h" #include "StringFunctions.h" +#include "WebCoreTestSupport.h" #include #include #include @@ -109,7 +110,7 @@ void InjectedBundle::willDestroyPage(WKBundlePageRef page) { - m_pages.removeFirstMatching([page] (const std::unique_ptr& current) { + m_pages.removeFirstMatching([page](auto& current) { return current->page() == page; }); } @@ -189,7 +190,7 @@ m_pixelResultIsPending = false; resetLocalSettings(); - m_testRunner->removeAllWebNotificationPermissions(); + TestRunner::removeAllWebNotificationPermissions(); InjectedBundle::page()->resetAfterTest(); @@ -236,6 +237,11 @@ return; } + if (WKStringIsEqualToUTF8CString(messageName, "NotifyDownloadDone")) { + m_testRunner->notifyDone(); + return; + } + if (WKStringIsEqualToUTF8CString(messageName, "CallUISideScriptCallback")) { WKDictionaryRef messageBodyDictionary = static_cast(messageBody); @@ -288,6 +294,7 @@ WKBundleSetAllowUniversalAccessFromFileURLs(m_bundle, m_pageGroup, true); WKBundleSetJavaScriptCanAccessClipboard(m_bundle, m_pageGroup, true); + WKBundleSetAutomaticLinkDetectionEnabled(m_bundle, m_pageGroup, false); WKBundleSetPrivateBrowsingEnabled(m_bundle, m_pageGroup, false); WKBundleSetAuthorAndUserStylesEnabled(m_bundle, m_pageGroup, true); WKBundleSetFrameFlatteningEnabled(m_bundle, m_pageGroup, false); @@ -304,6 +311,18 @@ m_testRunner->setShouldDumpFrameLoadCallbacks(booleanForKey(settings, "DumpFrameLoadDelegates")); m_testRunner->setUserStyleSheetEnabled(false); m_testRunner->setXSSAuditorEnabled(false); + + m_testRunner->setShadowDOMEnabled(true); + m_testRunner->setCustomElementsEnabled(true); + + m_testRunner->setDOMIteratorEnabled(true); + + m_testRunner->setWebGL2Enabled(true); + + m_testRunner->setFetchAPIEnabled(true); + + m_testRunner->setDownloadAttributeEnabled(true); + m_testRunner->setCloseRemainingWindowsWhenComplete(false); m_testRunner->setAcceptsEditing(true); m_testRunner->setTabKeyCyclesThroughElements(true); @@ -429,6 +448,24 @@ WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0); } +void InjectedBundle::postSetViewSize(double width, double height) +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetViewSize")); + + WKRetainPtr widthKey(AdoptWK, WKStringCreateWithUTF8CString("width")); + WKRetainPtr heightKey(AdoptWK, WKStringCreateWithUTF8CString("height")); + + WKRetainPtr messageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr widthWK(AdoptWK, WKDoubleCreate(width)); + WKDictionarySetItem(messageBody.get(), widthKey.get(), widthWK.get()); + + WKRetainPtr heightWK(AdoptWK, WKDoubleCreate(height)); + WKDictionarySetItem(messageBody.get(), heightKey.get(), heightWK.get()); + + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0); +} + void InjectedBundle::postSimulateWebNotificationClick(uint64_t notificationID) { WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SimulateWebNotificationClick")); @@ -519,6 +556,16 @@ return WKBooleanGetValue(isActive.get()); } +unsigned InjectedBundle::imageCountInGeneralPasteboard() const +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("ImageCountInGeneralPasteboard")); + WKTypeRef resultToPass = 0; + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass); + WKRetainPtr imageCount(AdoptWK, static_cast(resultToPass)); + + return static_cast(WKUInt64GetValue(imageCount.get())); +} + void InjectedBundle::setUserMediaPermission(bool enabled) { auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermission")); @@ -526,7 +573,7 @@ WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } -void InjectedBundle::setUserMediaPermissionForOrigin(bool permission, WKStringRef url) +void InjectedBundle::setUserMediaPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin) { auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermissionForOrigin")); WKRetainPtr messageBody(AdoptWK, WKMutableDictionaryCreate()); @@ -535,8 +582,11 @@ WKRetainPtr permissionWK(AdoptWK, WKBooleanCreate(permission)); WKDictionarySetItem(messageBody.get(), permissionKeyWK.get(), permissionWK.get()); - WKRetainPtr urlKeyWK(AdoptWK, WKStringCreateWithUTF8CString("url")); - WKDictionarySetItem(messageBody.get(), urlKeyWK.get(), url); + WKRetainPtr originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin")); + WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin); + + WKRetainPtr parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin")); + WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin); WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } @@ -690,4 +740,9 @@ return m_allowedHosts.contains(toWTFString(host)); } +void InjectedBundle::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate) +{ + WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate); +} + } // namespace WTR diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h 2016-09-16 09:56:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -85,6 +85,7 @@ void postFocusWebView(); void postSetBackingScaleFactor(double); void postSetWindowIsKey(bool); + void postSetViewSize(double width, double height); void postSimulateWebNotificationClick(uint64_t notificationID); void postSetAddsVisitedLinks(bool); @@ -96,7 +97,7 @@ // MediaStream. void setUserMediaPermission(bool); - void setUserMediaPermissionForOrigin(bool permission, WKStringRef url); + void setUserMediaPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin); // Policy delegate. void setCustomPolicyDelegate(bool enabled, bool permissive); @@ -120,6 +121,10 @@ bool isAllowedHost(WKStringRef); + unsigned imageCountInGeneralPasteboard() const; + + void setAllowsAnySSLCertificate(bool); + private: InjectedBundle(); ~InjectedBundle(); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -697,8 +697,11 @@ if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) { dumpLoadEvent(frame, "didFailProvisionalLoadWithError"); - if (WKErrorGetErrorCode(error) == kWKErrorCodeCannotShowURL) + auto code = WKErrorGetErrorCode(error); + if (code == kWKErrorCodeCannotShowURL) dumpLoadEvent(frame, "(kWKErrorCodeCannotShowURL)"); + else if (code == kWKErrorCodeFrameLoadBlockedByContentBlocker) + dumpLoadEvent(frame, "(kWKErrorCodeFrameLoadBlockedByContentBlocker)"); } frameDidChangeLocation(frame); @@ -892,12 +895,7 @@ injectedBundle.dumpBackForwardListsForAllPages(stringBuilder); if (injectedBundle.shouldDumpPixels() && injectedBundle.testRunner()->shouldDumpPixels()) { -#if PLATFORM(IOS) - // IOS doesn't implement PlatformWebView::windowSnapshotImage() yet, so we need to generate the snapshot in the web process. - bool shouldCreateSnapshot = true; -#else bool shouldCreateSnapshot = injectedBundle.testRunner()->isPrinting(); -#endif if (shouldCreateSnapshot) { WKSnapshotOptions options = kWKSnapshotOptionsShareable; WKRect snapshotRect = WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)); @@ -1317,8 +1315,11 @@ if (injectedBundle.testRunner()->shouldDecideNavigationPolicyAfterDelay()) return WKBundlePagePolicyActionPassThrough; - if (!injectedBundle.testRunner()->isPolicyDelegateEnabled()) - return WKBundlePagePolicyActionUse; + if (!injectedBundle.testRunner()->isPolicyDelegateEnabled()) { + WKRetainPtr downloadAttributeRef(AdoptWK, WKBundleNavigationActionCopyDownloadAttribute(navigationAction)); + String downloadAttribute = toWTFString(downloadAttributeRef); + return downloadAttribute.isNull() ? WKBundlePagePolicyActionUse : WKBundlePagePolicyActionPassThrough; + } WKRetainPtr url = adoptWK(WKURLRequestCopyURL(request)); WKRetainPtr urlScheme = adoptWK(WKURLCopyScheme(url.get())); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -141,6 +142,12 @@ waitUntilDone(); } +void TestRunner::waitUntilDownloadFinished() +{ + m_shouldFinishAfterDownload = true; + waitUntilDone(); +} + void TestRunner::waitUntilDone() { m_waitToDump = true; @@ -152,6 +159,11 @@ { invalidateWaitToDumpWatchdogTimer(); auto& injectedBundle = InjectedBundle::singleton(); +#if PLATFORM(COCOA) + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "#PID UNRESPONSIVE - %s (pid %d)\n", getprogname(), getpid()); + injectedBundle.outputText(buffer); +#endif injectedBundle.outputText("FAIL: Timed out waiting for notifyDone to be called\n\n"); injectedBundle.done(); } @@ -172,6 +184,11 @@ m_waitToDump = false; } +unsigned TestRunner::imageCountInGeneralPasteboard() const +{ + return InjectedBundle::singleton().imageCountInGeneralPasteboard(); +} + void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames) { WKRetainPtr sourceWK = toWK(source); @@ -241,6 +258,11 @@ void TestRunner::clearAllDatabases() { WKBundleClearAllDatabases(InjectedBundle::singleton().bundle()); + + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("DeleteAllIndexedDatabases")); + WKRetainPtr messageBody(AdoptWK, WKBooleanCreate(true)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); } void TestRunner::setDatabaseQuota(uint64_t quota) @@ -318,6 +340,53 @@ WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); } +void TestRunner::setShadowDOMEnabled(bool enabled) +{ + WKRetainPtr key(AdoptWK, WKStringCreateWithUTF8CString("WebKitShadowDOMEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setCustomElementsEnabled(bool enabled) +{ + WKRetainPtr key(AdoptWK, WKStringCreateWithUTF8CString("WebKitCustomElementsEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setDOMIteratorEnabled(bool enabled) +{ + WKRetainPtr key(AdoptWK, WKStringCreateWithUTF8CString("WebKitDOMIteratorEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setWebGL2Enabled(bool enabled) +{ + WKRetainPtr key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGL2Enabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setFetchAPIEnabled(bool enabled) +{ + WKRetainPtr key(AdoptWK, WKStringCreateWithUTF8CString("WebKitFetchAPIEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setDownloadAttributeEnabled(bool enabled) +{ + WKRetainPtr key(AdoptWK, WKStringCreateWithUTF8CString("WebKitDownloadAttributeEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setAllowsAnySSLCertificate(bool enabled) +{ + InjectedBundle::singleton().setAllowsAnySSLCertificate(enabled); +} + void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled) { auto& injectedBundle = InjectedBundle::singleton(); @@ -342,6 +411,12 @@ WKBundleSetJavaScriptCanAccessClipboard(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } +void TestRunner::setAutomaticLinkDetectionEnabled(bool enabled) +{ + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetAutomaticLinkDetectionEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); +} + void TestRunner::setPrivateBrowsingEnabled(bool enabled) { auto& injectedBundle = InjectedBundle::singleton(); @@ -560,6 +635,11 @@ callbackMap().clear(); } +void TestRunner::accummulateLogsForChannel(JSStringRef) +{ + // FIXME: Implement getting the call to all processes. +} + void TestRunner::addChromeInputField(JSValueRef callback) { cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback); @@ -589,6 +669,11 @@ InjectedBundle::singleton().postSetWindowIsKey(isKey); } +void TestRunner::setViewSize(double width, double height) +{ + InjectedBundle::singleton().postSetViewSize(width, height); +} + void TestRunner::callAddChromeInputFieldCallback() { callTestRunnerCallback(AddChromeInputFieldCallbackID); @@ -627,7 +712,7 @@ WKRetainPtr messageBody(AdoptWK, WKBooleanCreate(accept)); - WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), 0); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); } double TestRunner::preciseTime() @@ -775,10 +860,11 @@ InjectedBundle::singleton().setUserMediaPermission(enabled); } -void TestRunner::setUserMediaPermissionForOrigin(bool permission, JSStringRef url) +void TestRunner::setUserMediaPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin) { - WKRetainPtr urlWK = toWK(url); - InjectedBundle::singleton().setUserMediaPermissionForOrigin(permission, urlWK.get()); + WKRetainPtr originWK = toWK(origin); + WKRetainPtr parentOriginWK = toWK(parentOrigin); + InjectedBundle::singleton().setUserMediaPermissionForOrigin(permission, originWK.get(), parentOriginWK.get()); } bool TestRunner::callShouldCloseOnWebView() @@ -833,13 +919,27 @@ InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get()); } +void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value) +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges")); + WKRetainPtr messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges) { - WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenge")); + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges")); WKRetainPtr messageBody(AdoptWK, WKBooleanCreate(handlesAuthenticationChallenges)); WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); } +void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value) +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace")); + WKRetainPtr messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + void TestRunner::setAuthenticationUsername(JSStringRef username) { WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationUsername")); @@ -906,6 +1006,13 @@ WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); } +void TestRunner::setIgnoresViewportScaleLimits(bool value) +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits")); + WKRetainPtr messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + static unsigned nextUIScriptCallbackID() { static unsigned callbackID = FirstUIScriptCallbackID; @@ -982,4 +1089,135 @@ callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID); } +#if PLATFORM(MAC) +void TestRunner::connectMockGamepad(unsigned index) +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("ConnectMockGamepad")); + WKRetainPtr messageBody(AdoptWK, WKUInt64Create(index)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::disconnectMockGamepad(unsigned index) +{ + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("DisconnectMockGamepad")); + WKRetainPtr messageBody(AdoptWK, WKUInt64Create(index)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount) +{ + Vector> keys; + Vector> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadID") }); + values.append(toWK(gamepadID)); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") }); + values.append({ AdoptWK, WKUInt64Create(index) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisCount") }); + values.append({ AdoptWK, WKUInt64Create(axisCount) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonCount") }); + values.append({ AdoptWK, WKUInt64Create(buttonCount) }); + + Vector rawKeys; + Vector rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadDetails")); + WKRetainPtr messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value) +{ + Vector> keys; + Vector> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") }); + values.append({ AdoptWK, WKUInt64Create(index) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisIndex") }); + values.append({ AdoptWK, WKUInt64Create(axisIndex) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") }); + values.append({ AdoptWK, WKDoubleCreate(value) }); + + Vector rawKeys; + Vector rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadAxisValue")); + WKRetainPtr messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value) +{ + Vector> keys; + Vector> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") }); + values.append({ AdoptWK, WKUInt64Create(index) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex") }); + values.append({ AdoptWK, WKUInt64Create(buttonIndex) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") }); + values.append({ AdoptWK, WKDoubleCreate(value) }); + + Vector rawKeys; + Vector rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadButtonValue")); + WKRetainPtr messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} +#else +void TestRunner::connectMockGamepad(unsigned) +{ +} + +void TestRunner::disconnectMockGamepad(unsigned) +{ +} + +void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned) +{ +} + +void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double) +{ +} + +void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double) +{ +} +#endif // PLATFORM(MAC) + } // namespace WTR diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -67,9 +67,11 @@ void dumpAsText(bool dumpPixels); void waitForPolicyDelegate(); void dumpChildFramesAsText() { m_whatToDump = AllFramesText; } + void waitUntilDownloadFinished(); void waitUntilDone(); void notifyDone(); double preciseTime(); + double timeout() { return m_timeout; } // Other dumping. void dumpBackForwardList() { m_shouldDumpBackForwardListsForAllWindows = true; } @@ -98,10 +100,16 @@ void setCanOpenWindows(bool); void setCloseRemainingWindowsWhenComplete(bool value) { m_shouldCloseExtraWindows = value; } void setXSSAuditorEnabled(bool); + void setShadowDOMEnabled(bool); + void setCustomElementsEnabled(bool); + void setDOMIteratorEnabled(bool); + void setWebGL2Enabled(bool); + void setFetchAPIEnabled(bool); void setAllowUniversalAccessFromFileURLs(bool); void setAllowFileAccessFromFileURLs(bool); void setPluginsEnabled(bool); void setJavaScriptCanAccessClipboard(bool); + void setAutomaticLinkDetectionEnabled(bool); void setPrivateBrowsingEnabled(bool); void setPopupBlockingEnabled(bool); void setAuthorAndUserStylesEnabled(bool); @@ -116,6 +124,8 @@ void dispatchPendingLoadRequests(); void setCacheModel(int); void setAsynchronousSpellCheckingEnabled(bool); + void setDownloadAttributeEnabled(bool); + void setAllowsAnySSLCertificate(bool); // Special DOM functions. void clearBackForwardList(); @@ -155,7 +165,9 @@ void setPrinting() { m_isPrinting = true; } // Authentication + void setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool); void setHandlesAuthenticationChallenges(bool); + void setShouldLogCanAuthenticateAgainstProtectionSpace(bool); void setAuthenticationUsername(JSStringRef); void setAuthenticationPassword(JSStringRef); @@ -193,6 +205,7 @@ bool waitToDump() const { return m_waitToDump; } void waitToDumpWatchdogTimerFired(); void invalidateWaitToDumpWatchdogTimer(); + bool shouldFinishAfterDownload() const { return m_shouldFinishAfterDownload; } bool shouldAllowEditing() const { return m_shouldAllowEditing; } @@ -240,6 +253,8 @@ void setWindowIsKey(bool); + void setViewSize(double width, double height); + void callAddChromeInputFieldCallback(); void callRemoveChromeInputFieldCallback(); void callFocusWebViewCallback(); @@ -255,10 +270,10 @@ bool hasCustomFullScreenBehavior() const { return m_customFullScreenBehavior; } // Web notifications. - void grantWebNotificationPermission(JSStringRef origin); - void denyWebNotificationPermission(JSStringRef origin); - void removeAllWebNotificationPermissions(); - void simulateWebNotificationClick(JSValueRef notification); + static void grantWebNotificationPermission(JSStringRef origin); + static void denyWebNotificationPermission(JSStringRef origin); + static void removeAllWebNotificationPermissions(); + static void simulateWebNotificationClick(JSValueRef notification); // Geolocation. void setGeolocationPermission(bool); @@ -268,7 +283,7 @@ // MediaStream void setUserMediaPermission(bool); - void setUserMediaPermissionForOrigin(bool permission, JSStringRef url); + void setUserMediaPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin); void setPageVisibility(JSStringRef state); void resetPageVisibility(); @@ -287,7 +302,7 @@ void queueNonLoadingScript(JSStringRef script); bool secureEventInputIsEnabled() const; - + JSValueRef failNextNewCodeBlock(); JSValueRef numberOfDFGCompiles(JSValueRef theFunction); JSValueRef neverInlineFunction(JSValueRef theFunction); @@ -295,6 +310,7 @@ bool shouldDecideNavigationPolicyAfterDelay() const { return m_shouldDecideNavigationPolicyAfterDelay; } void setShouldDecideNavigationPolicyAfterDelay(bool); void setNavigationGesturesEnabled(bool); + void setIgnoresViewportScaleLimits(bool); void runUIScript(JSStringRef script, JSValueRef callback); void runUIScriptCallback(unsigned callbackID, JSStringRef result); @@ -310,6 +326,17 @@ void clearTestRunnerCallbacks(); + void accummulateLogsForChannel(JSStringRef channel); + + unsigned imageCountInGeneralPasteboard() const; + + // Gamepads + void connectMockGamepad(unsigned index); + void disconnectMockGamepad(unsigned index); + void setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount); + void setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value); + void setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value); + private: TestRunner(); @@ -362,6 +389,7 @@ double m_databaseMaxQuota; bool m_shouldDecideNavigationPolicyAfterDelay { false }; + bool m_shouldFinishAfterDownload { false }; bool m_userStyleSheetEnabled; WKRetainPtr m_userStyleSheetLocation; diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/PlatformGTK.cmake webkit2gtk-2.14.2/Tools/WebKitTestRunner/PlatformGTK.cmake --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/PlatformGTK.cmake 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/PlatformGTK.cmake 2016-09-19 12:18:06.000000000 +0000 @@ -1,5 +1,5 @@ add_custom_target(WebKitTestRunner-forwarding-headers - COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl --include-path ${WEBKIT_TESTRUNNER_DIR} --output ${FORWARDING_HEADERS_DIR} --platform gtk --platform soup + COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl --include-path ${WEBKIT_TESTRUNNER_DIR} --include-path ${WEBKIT_TESTRUNNER_SHARED_DIR} --output ${FORWARDING_HEADERS_DIR} --platform gtk --platform soup ) set(ForwardingHeadersForWebKitTestRunner_NAME WebKitTestRunner-forwarding-headers) @@ -31,6 +31,7 @@ ${GTK3_LIBRARIES} ${GLIB_LIBRARIES} WTF + WebCore WebCorePlatformGTK ) diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/PlatformWebView.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/PlatformWebView.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/PlatformWebView.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/PlatformWebView.h 2016-09-19 12:18:06.000000000 +0000 @@ -66,6 +66,7 @@ WKPageRef page(); PlatformWKView platformView() { return m_view; } PlatformWindow platformWindow() { return m_window; } + static PlatformWindow keyWindow(); void resizeTo(unsigned width, unsigned height); void focus(); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/StringFunctions.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/StringFunctions.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/StringFunctions.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/StringFunctions.h 2016-09-16 09:56:48.000000000 +0000 @@ -87,7 +87,7 @@ { size_t bufferSize = WKStringGetMaximumUTF8CStringSize(string); auto buffer = std::make_unique(bufferSize); - size_t stringLength = WKStringGetUTF8CString(string, buffer.get(), bufferSize); + size_t stringLength = WKStringGetUTF8CStringNonStrict(string, buffer.get(), bufferSize); return WTF::String::fromUTF8WithLatin1Fallback(buffer.get(), stringLength - 1); } diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestController.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestController.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestController.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestController.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2014-2015 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2014-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +31,8 @@ #include "PlatformWebView.h" #include "StringFunctions.h" #include "TestInvocation.h" +#include "WebCoreTestSupport.h" +#include #include #include #include @@ -38,12 +40,15 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -61,7 +66,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -113,29 +121,6 @@ } TestController::TestController(int argc, const char* argv[]) - : m_verbose(false) - , m_printSeparators(false) - , m_usingServerMode(false) - , m_gcBetweenTests(false) - , m_shouldDumpPixelsForAllTests(false) - , m_state(Initial) - , m_doneResetting(false) - , m_useWaitToDumpWatchdogTimer(true) - , m_forceNoTimeout(false) - , m_didPrintWebProcessCrashedMessage(false) - , m_shouldExitWhenWebProcessCrashes(true) - , m_beforeUnloadReturnValue(true) - , m_isGeolocationPermissionSet(false) - , m_isGeolocationPermissionAllowed(false) - , m_policyDelegateEnabled(false) - , m_policyDelegatePermissive(false) - , m_handlesAuthenticationChallenges(false) - , m_shouldBlockAllPlugins(false) - , m_forceComplexText(false) - , m_shouldUseAcceleratedDrawing(false) - , m_shouldUseRemoteLayerTree(false) - , m_shouldLogHistoryClientCallbacks(false) - , m_shouldShowWebView(false) { initialize(argc, argv); controller = this; @@ -170,6 +155,12 @@ return TestController::singleton().beforeUnloadReturnValue(); } +static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef resultListenerRef, const void*) +{ + printf("OPEN FILE PANEL\n"); + WKOpenPanelResultListenerCancel(resultListenerRef); +} + void TestController::runModal(WKPageRef page, const void* clientInfo) { PlatformWebView* view = static_cast(const_cast(clientInfo)); @@ -203,14 +194,14 @@ TestController::singleton().handleGeolocationPermissionRequest(permissionRequest); } -static void decidePolicyForUserMediaPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef origin, WKUserMediaPermissionRequestRef permissionRequest, const void* clientInfo) +static void decidePolicyForUserMediaPermissionRequest(WKPageRef, WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, WKUserMediaPermissionRequestRef permissionRequest, const void* clientInfo) { - TestController::singleton().handleUserMediaPermissionRequest(origin, permissionRequest); + TestController::singleton().handleUserMediaPermissionRequest(frame, userMediaDocumentOrigin, topLevelDocumentOrigin, permissionRequest); } -static void checkUserMediaPermissionForOrigin(WKPageRef, WKFrameRef, WKSecurityOriginRef origin, WKUserMediaPermissionCheckRef checkRequest, const void*) +static void checkUserMediaPermissionForOrigin(WKPageRef, WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, WKUserMediaPermissionCheckRef checkRequest, const void*) { - TestController::singleton().handleCheckOfUserMediaPermissionForOrigin(origin, checkRequest); + TestController::singleton().handleCheckOfUserMediaPermissionForOrigin(frame, userMediaDocumentOrigin, topLevelDocumentOrigin, checkRequest); } WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKPageConfigurationRef configuration, WKNavigationActionRef navigationAction, WKWindowFeaturesRef windowFeatures, const void *clientInfo) @@ -252,7 +243,7 @@ 0, // didDraw 0, // pageDidScroll 0, // exceededDatabaseQuota - 0, // runOpenPanel + runOpenPanel, decidePolicyForGeolocationPermissionRequest, 0, // headerHeight 0, // footerHeight @@ -380,6 +371,9 @@ initializeInjectedBundlePath(); initializeTestPluginDirectory(); +#if PLATFORM(MAC) + WebCoreTestSupport::installMockGamepadProvider(); +#endif WKRetainPtr pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup")); m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get())); } @@ -420,6 +414,7 @@ WKContextSetIconDatabasePath(m_context.get(), toWK(emptyString()).get()); } + WKContextSetDiskCacheSpeculativeValidationEnabled(m_context.get(), true); WKContextUseTestingNetworkSession(m_context.get()); WKContextSetCacheModel(m_context.get(), kWKCacheModelDocumentBrowser); @@ -429,16 +424,17 @@ { 1, this }, didReceiveMessageFromInjectedBundle, didReceiveSynchronousMessageFromInjectedBundle, - 0 // getInjectedBundleInitializationUserData + getInjectedBundleInitializationUserData, }; WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient.base); - WKContextClientV1 contextClient = { - { 1, this }, + WKContextClientV2 contextClient = { + { 2, this }, 0, // plugInAutoStartOriginHashesChanged networkProcessDidCrash, 0, // plugInInformationBecameAvailable 0, // copyWebCryptoMasterKey + databaseProcessDidCrash, }; WKContextSetClient(m_context.get(), &contextClient.base); @@ -482,7 +478,7 @@ // Some preferences (notably mock scroll bars setting) currently cannot be re-applied to an existing view, so we need to set them now. // FIXME: Migrate these preferences to WKContextConfigurationRef. - resetPreferencesToConsistentValues(); + resetPreferencesToConsistentValues(options); platformCreateWebView(configuration.get(), options); WKPageUIClientV6 pageUIClient = { @@ -515,7 +511,7 @@ 0, // didDraw 0, // pageDidScroll 0, // exceededDatabaseQuota, - 0, // runOpenPanel + runOpenPanel, decidePolicyForGeolocationPermissionRequest, 0, // headerHeight 0, // footerHeight @@ -578,7 +574,22 @@ }; WKPageSetPageNavigationClient(m_mainWebView->page(), &pageNavigationClient.base); - + WKContextDownloadClientV0 downloadClient = { + { 0, this }, + downloadDidStart, + 0, // didReceiveAuthenticationChallenge + 0, // didReceiveResponse + 0, // didReceiveData + 0, // shouldDecodeSourceDataOfMIMEType + decideDestinationWithSuggestedFilename, + 0, // didCreateDestination + downloadDidFinish, + downloadDidFail, + downloadDidCancel, + 0 // processDidCrash; + }; + WKContextSetDownloadClient(context(), &downloadClient.base); + // this should just be done on the page? WKPageInjectedBundleClientV0 injectedBundleClient = { { 0, this }, @@ -611,19 +622,19 @@ createWebViewWithOptions(options); - if (!resetStateToConsistentValues()) + if (!resetStateToConsistentValues(options)) TestInvocation::dumpWebProcessUnresponsiveness(" - TestController::run - Failed to reset state to consistent values\n"); } -void TestController::resetPreferencesToConsistentValues() +void TestController::resetPreferencesToConsistentValues(const TestOptions& options) { // Reset preferences WKPreferencesRef preferences = platformPreferences(); WKPreferencesResetTestRunnerOverrides(preferences); + WKPreferencesEnableAllExperimentalFeatures(preferences); WKPreferencesSetPageVisibilityBasedProcessSuppressionEnabled(preferences, false); WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true); WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing); - WKPreferencesSetAntialiasedFontDilationEnabled(preferences, false); WKPreferencesSetXSSAuditorEnabled(preferences, false); WKPreferencesSetWebAudioEnabled(preferences, true); WKPreferencesSetMediaStreamEnabled(preferences, true); @@ -643,7 +654,8 @@ WKPreferencesSetArtificialPluginInitializationDelayEnabled(preferences, false); WKPreferencesSetTabToLinksEnabled(preferences, false); WKPreferencesSetInteractiveFormValidationEnabled(preferences, true); - WKPreferencesSetMockScrollbarsEnabled(preferences, true); + WKPreferencesSetMockScrollbarsEnabled(preferences, options.useMockScrollbars); + WKPreferencesSetNeedsSiteSpecificQuirks(preferences, options.needsSiteSpecificQuirks); static WKStringRef defaultTextEncoding = WKStringCreateWithUTF8CString("ISO-8859-1"); WKPreferencesSetDefaultTextEncodingName(preferences, defaultTextEncoding); @@ -683,7 +695,7 @@ platformResetPreferencesToConsistentValues(); } -bool TestController::resetStateToConsistentValues() +bool TestController::resetStateToConsistentValues(const TestOptions& options) { TemporaryChange changeState(m_state, Resetting); m_beforeUnloadReturnValue = true; @@ -723,7 +735,7 @@ // FIXME: Is this needed? Nothing in TestController changes preferences during tests, and if there is // some other code doing this, it should probably be responsible for cleanup too. - resetPreferencesToConsistentValues(); + resetPreferencesToConsistentValues(options); #if !PLATFORM(COCOA) WKTextCheckerContinuousSpellCheckingEnabledStateChanged(true); @@ -755,7 +767,7 @@ // Reset UserMedia permissions. m_userMediaPermissionRequests.clear(); - m_userMediaOriginPermissions = nullptr; + m_cahcedUserMediaPermissions.clear(); m_isUserMediaPermissionSet = false; m_isUserMediaPermissionAllowed = false; @@ -764,6 +776,7 @@ m_workQueueManager.clearWorkQueue(); + m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges = false; m_handlesAuthenticationChallenges = false; m_authenticationUsername = String(); m_authenticationPassword = String(); @@ -771,6 +784,7 @@ m_shouldBlockAllPlugins = false; m_shouldLogHistoryClientCallbacks = false; + m_shouldLogCanAuthenticateAgainstProtectionSpace = false; setHidden(false); @@ -782,6 +796,8 @@ m_shouldDecideNavigationPolicyAfterDelay = false; setNavigationGesturesEnabled(false); + + setIgnoresViewportScaleLimits(options.ignoresViewportScaleLimits); WKPageLoadURL(m_mainWebView->page(), blankURL()); runUntil(m_doneResetting, shortTimeout); @@ -821,6 +837,16 @@ #endif } +const char* TestController::databaseProcessName() +{ + // FIXME: Find a way to not hardcode the process name. +#if PLATFORM(COCOA) + return "com.apple.WebKit.Databases.Development"; +#else + return "DatabaseProcess"; +#endif +} + static std::string testPath(WKURLRef url) { auto scheme = adoptWK(WKURLCopyScheme(url)); @@ -921,6 +947,12 @@ testOptions.useFlexibleViewport = parseBooleanTestHeaderValue(value); if (key == "useDataDetection") testOptions.useDataDetection = parseBooleanTestHeaderValue(value); + if (key == "useMockScrollbars") + testOptions.useMockScrollbars = parseBooleanTestHeaderValue(value); + if (key == "needsSiteSpecificQuirks") + testOptions.needsSiteSpecificQuirks = parseBooleanTestHeaderValue(value); + if (key == "ignoresViewportScaleLimits") + testOptions.ignoresViewportScaleLimits = parseBooleanTestHeaderValue(value); pairStart = pairEnd + 1; } } @@ -952,7 +984,7 @@ void TestController::updateWindowScaleForTest(PlatformWebView* view, const TestInvocation& test) { - view->changeWindowScaleIfNeeded(test.options().isHiDPITest ? 2 : 1); + view->changeWindowScaleIfNeeded(test.options().deviceScaleFactor); } void TestController::configureViewForTest(const TestInvocation& test) @@ -1121,6 +1153,11 @@ *returnData = static_cast(const_cast(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef(); } +WKTypeRef TestController::getInjectedBundleInitializationUserData(WKContextRef, const void* clientInfo) +{ + return static_cast(const_cast(clientInfo))->getInjectedBundleInitializationUserData().leakRef(); +} + // WKPageInjectedBundleClient void TestController::didReceivePageMessageFromInjectedBundle(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo) @@ -1138,6 +1175,11 @@ static_cast(const_cast(clientInfo))->networkProcessDidCrash(); } +void TestController::databaseProcessDidCrash(WKContextRef context, const void *clientInfo) +{ + static_cast(const_cast(clientInfo))->databaseProcessDidCrash(); +} + void TestController::didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef messageBodyDictionary, bool synchronous) { WKRetainPtr keyKey = adoptWK(WKStringCreateWithUTF8CString("Key")); @@ -1432,16 +1474,24 @@ return m_currentInvocation->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody); } +WKRetainPtr TestController::getInjectedBundleInitializationUserData() +{ + return nullptr; +} + // WKContextClient void TestController::networkProcessDidCrash() { -#if PLATFORM(COCOA) pid_t pid = WKContextGetNetworkProcessIdentifier(m_context.get()); fprintf(stderr, "#CRASHED - %s (pid %ld)\n", networkProcessName(), static_cast(pid)); -#else - fprintf(stderr, "#CRASHED - %s\n", networkProcessName()); -#endif + exit(1); +} + +void TestController::databaseProcessDidCrash() +{ + pid_t pid = WKContextGetDatabaseProcessIdentifier(m_context.get()); + fprintf(stderr, "#CRASHED - %s (pid %ld)\n", databaseProcessName(), static_cast(pid)); exit(1); } @@ -1457,16 +1507,9 @@ static_cast(const_cast(clientInfo))->didFinishNavigation(page, navigation); } -bool TestController::canAuthenticateAgainstProtectionSpace(WKPageRef, WKProtectionSpaceRef protectionSpace, const void*) +bool TestController::canAuthenticateAgainstProtectionSpace(WKPageRef page, WKProtectionSpaceRef protectionSpace, const void* clientInfo) { - WKProtectionSpaceAuthenticationScheme authenticationScheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace); - - if (authenticationScheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) { - std::string host = toSTD(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get()); - return host == "localhost" || host == "127.0.0.1"; - } - - return authenticationScheme <= kWKProtectionSpaceAuthenticationSchemeHTTPDigest; + return static_cast(const_cast(clientInfo))->canAuthenticateAgainstProtectionSpace(page, protectionSpace); } void TestController::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef authenticationChallenge, const void *clientInfo) @@ -1531,6 +1574,20 @@ mainWebView()->focus(); } +bool TestController::canAuthenticateAgainstProtectionSpace(WKPageRef page, WKProtectionSpaceRef protectionSpace) +{ + if (m_shouldLogCanAuthenticateAgainstProtectionSpace) + m_currentInvocation->outputText("canAuthenticateAgainstProtectionSpace\n"); + WKProtectionSpaceAuthenticationScheme authenticationScheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace); + + if (authenticationScheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) { + std::string host = toSTD(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get()); + return host == "localhost" || host == "127.0.0.1"; + } + + return authenticationScheme <= kWKProtectionSpaceAuthenticationSchemeHTTPDigest; +} + void TestController::didFinishNavigation(WKPageRef page, WKNavigationRef navigation) { if (m_state != Resetting) @@ -1558,6 +1615,12 @@ return; } + if (m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges) { + m_currentInvocation->outputText("Simulating reject protection space and continue for authentication challenge\n"); + WKAuthenticationDecisionListenerRejectProtectionSpaceAndContinue(decisionListener); + return; + } + std::string host = toSTD(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get()); int port = WKProtectionSpaceGetPort(protectionSpace); String message = String::format("%s:%d - didReceiveAuthenticationChallenge - ", host.c_str(), port); @@ -1577,17 +1640,92 @@ WKAuthenticationDecisionListenerUseCredential(decisionListener, credential.get()); } + +// WKContextDownloadClient + +void TestController::downloadDidStart(WKContextRef context, WKDownloadRef download, const void* clientInfo) +{ + static_cast(const_cast(clientInfo))->downloadDidStart(context, download); +} + +WKStringRef TestController::decideDestinationWithSuggestedFilename(WKContextRef context, WKDownloadRef download, WKStringRef filename, bool* allowOverwrite, const void* clientInfo) +{ + return static_cast(const_cast(clientInfo))->decideDestinationWithSuggestedFilename(context, download, filename, allowOverwrite); +} + +void TestController::downloadDidFinish(WKContextRef context, WKDownloadRef download, const void* clientInfo) +{ + static_cast(const_cast(clientInfo))->downloadDidFinish(context, download); +} + +void TestController::downloadDidFail(WKContextRef context, WKDownloadRef download, WKErrorRef error, const void* clientInfo) +{ + static_cast(const_cast(clientInfo))->downloadDidFail(context, download, error); +} + +void TestController::downloadDidCancel(WKContextRef context, WKDownloadRef download, const void* clientInfo) +{ + static_cast(const_cast(clientInfo))->downloadDidCancel(context, download); +} + +void TestController::downloadDidStart(WKContextRef context, WKDownloadRef download) +{ + m_currentInvocation->outputText("Download started.\n"); +} + +WKStringRef TestController::decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef, WKStringRef filename, bool*& allowOverwrite) +{ + StringBuilder builder; + builder.append("Downloading URL with suggested filename \""); + builder.append(toWTFString(filename)); + builder.append("\"\n"); + + m_currentInvocation->outputText(builder.toString()); + + return nullptr; +} + +void TestController::downloadDidFinish(WKContextRef, WKDownloadRef) +{ + m_currentInvocation->outputText("Download completed.\n"); + m_currentInvocation->notifyDownloadDone(); +} + +void TestController::downloadDidFail(WKContextRef, WKDownloadRef, WKErrorRef error) +{ + String message = String::format("Download failed.\n"); + m_currentInvocation->outputText(message); + + WKRetainPtr errorDomain = adoptWK(WKErrorCopyDomain(error)); + WKRetainPtr errorDescription = adoptWK(WKErrorCopyLocalizedDescription(error)); + int errorCode = WKErrorGetErrorCode(error); + + StringBuilder errorBuilder; + errorBuilder.append("Failed: "); + errorBuilder.append(toWTFString(errorDomain)); + errorBuilder.append(", code="); + errorBuilder.appendNumber(errorCode); + errorBuilder.append(", description="); + errorBuilder.append(toWTFString(errorDescription)); + errorBuilder.append("\n"); + + m_currentInvocation->outputText(errorBuilder.toString()); + m_currentInvocation->notifyDownloadDone(); +} + +void TestController::downloadDidCancel(WKContextRef, WKDownloadRef) +{ + m_currentInvocation->outputText("Download cancelled.\n"); + m_currentInvocation->notifyDownloadDone(); +} + void TestController::processDidCrash() { // This function can be called multiple times when crash logs are being saved on Windows, so // ensure we only print the crashed message once. if (!m_didPrintWebProcessCrashedMessage) { -#if PLATFORM(COCOA) pid_t pid = WKPageGetProcessIdentifier(m_mainWebView->page()); fprintf(stderr, "#CRASHED - %s (pid %ld)\n", webProcessName(), static_cast(pid)); -#else - fprintf(stderr, "#CRASHED - %s\n", webProcessName()); -#endif fflush(stderr); m_didPrintWebProcessCrashedMessage = true; } @@ -1618,7 +1756,7 @@ void TestController::simulateWebNotificationClick(uint64_t notificationID) { - m_webNotificationProvider.simulateWebNotificationClick(notificationID); + m_webNotificationProvider.simulateWebNotificationClick(mainWebView()->page(), notificationID); } void TestController::setGeolocationPermission(bool enabled) @@ -1649,19 +1787,43 @@ return m_geolocationProvider->isActive(); } -static WKStringRef originUserVisibleName(WKSecurityOriginRef origin) +static String originUserVisibleName(WKSecurityOriginRef origin) { + if (!origin) + return emptyString(); + std::string host = toSTD(adoptWK(WKSecurityOriginCopyHost(origin))).c_str(); std::string protocol = toSTD(adoptWK(WKSecurityOriginCopyProtocol(origin))).c_str(); - unsigned short port = WKSecurityOriginGetPort(origin); - String userVisibleName; + if (!host.length() || !protocol.length()) + return emptyString(); + + unsigned short port = WKSecurityOriginGetPort(origin); if (port) - userVisibleName = String::format("%s://%s:%d", protocol.c_str(), host.c_str(), port); - else - userVisibleName = String::format("%s://%s", protocol.c_str(), host.c_str()); + return String::format("%s://%s:%d", protocol.c_str(), host.c_str(), port); + + return String::format("%s://%s", protocol.c_str(), host.c_str()); +} + +static String userMediaOriginHash(WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin) +{ + String userMediaDocumentOriginString = originUserVisibleName(userMediaDocumentOrigin); + String topLevelDocumentOriginString = originUserVisibleName(topLevelDocumentOrigin); + + if (topLevelDocumentOriginString.isEmpty()) + return userMediaDocumentOriginString; + + return String::format("%s-%s", userMediaDocumentOriginString.utf8().data(), topLevelDocumentOriginString.utf8().data()); +} + +static String userMediaOriginHash(WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString) +{ + auto userMediaDocumentOrigin = adoptWK(WKSecurityOriginCreateFromString(userMediaDocumentOriginString)); + if (!WKStringGetLength(topLevelDocumentOriginString)) + return userMediaOriginHash(userMediaDocumentOrigin.get(), nullptr); - return WKStringCreateWithUTF8CString(userVisibleName.utf8().data()); + auto topLevelDocumentOrigin = adoptWK(WKSecurityOriginCreateFromString(topLevelDocumentOriginString)); + return userMediaOriginHash(userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get()); } void TestController::setUserMediaPermission(bool enabled) @@ -1671,32 +1833,104 @@ decidePolicyForUserMediaPermissionRequestIfPossible(); } -void TestController::setUserMediaPermissionForOrigin(bool permission, WKStringRef originString) +static String createCanonicalUUIDString() { - if (!m_userMediaOriginPermissions) - m_userMediaOriginPermissions = adoptWK(WKMutableDictionaryCreate()); - WKRetainPtr allowed = adoptWK(WKBooleanCreate(permission)); - WKRetainPtr origin = adoptWK(WKSecurityOriginCreateFromString(originString)); - WKDictionarySetItem(m_userMediaOriginPermissions.get(), originUserVisibleName(origin.get()), allowed.get()); + unsigned randomData[4]; + cryptographicallyRandomValues(reinterpret_cast(randomData), sizeof(randomData)); + + // Format as Version 4 UUID. + StringBuilder builder; + builder.reserveCapacity(36); + appendUnsignedAsHexFixedSize(randomData[0], builder, 8, Lowercase); + builder.append('-'); + appendUnsignedAsHexFixedSize(randomData[1] >> 16, builder, 4, Lowercase); + builder.appendLiteral("-4"); + appendUnsignedAsHexFixedSize(randomData[1] & 0x00000fff, builder, 3, Lowercase); + builder.append('-'); + appendUnsignedAsHexFixedSize((randomData[2] >> 30) | 0x8, builder, 1, Lowercase); + appendUnsignedAsHexFixedSize((randomData[2] >> 16) & 0x00000fff, builder, 3, Lowercase); + builder.append('-'); + appendUnsignedAsHexFixedSize(randomData[2] & 0x0000ffff, builder, 4, Lowercase); + appendUnsignedAsHexFixedSize(randomData[3], builder, 8, Lowercase); + return builder.toString(); } -void TestController::handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginRef origin, const WKUserMediaPermissionCheckRef& checkRequest) +class OriginSettings : public RefCounted { +public: + explicit OriginSettings() + { + } + + bool persistentPermission() const { return m_persistentPermission; } + void setPersistentPermission(bool permission) { m_persistentPermission = permission; } + + String persistentSalt() const { return m_persistentSalt; } + void setPersistentSalt(const String& salt) { m_persistentSalt = salt; } + + HashMap& ephemeralSalts() { return m_ephemeralSalts; } + +private: + HashMap m_ephemeralSalts; + String m_persistentSalt; + bool m_persistentPermission { false }; +}; + +String TestController::saltForOrigin(WKFrameRef frame, String originHash) { - bool allowed = false; + RefPtr settings = m_cahcedUserMediaPermissions.get(originHash); + if (!settings) { + settings = adoptRef(*new OriginSettings()); + m_cahcedUserMediaPermissions.add(originHash, settings); + } + + auto& ephemeralSalts = settings->ephemeralSalts(); + auto frameInfo = adoptWK(WKFrameCreateFrameInfo(frame)); + auto frameHandle = WKFrameInfoGetFrameHandleRef(frameInfo.get()); + uint64_t frameIdentifier = WKFrameHandleGetFrameID(frameHandle); + String frameSalt = ephemeralSalts.get(frameIdentifier); + + if (settings->persistentPermission()) { + if (frameSalt.length()) + return frameSalt; + + if (!settings->persistentSalt().length()) + settings->setPersistentSalt(createCanonicalUUIDString()); + + return settings->persistentSalt(); + } - if (m_userMediaOriginPermissions) { - WKRetainPtr originString = originUserVisibleName(origin); - WKBooleanRef value = static_cast(WKDictionaryGetItemForKey(m_userMediaOriginPermissions.get(), originString.get())); - if (value && WKGetTypeID(value) == WKBooleanGetTypeID()) - allowed = WKBooleanGetValue(value); + if (!frameSalt.length()) { + frameSalt = createCanonicalUUIDString(); + ephemeralSalts.add(frameIdentifier, frameSalt); } - WKUserMediaPermissionCheckSetHasPersistentPermission(checkRequest, allowed); + return frameSalt; } -void TestController::handleUserMediaPermissionRequest(WKSecurityOriginRef origin, WKUserMediaPermissionRequestRef request) +void TestController::setUserMediaPermissionForOrigin(bool permission, WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString) { - m_userMediaPermissionRequests.append(std::make_pair(origin, request)); + auto originHash = userMediaOriginHash(userMediaDocumentOriginString, topLevelDocumentOriginString); + RefPtr settings = m_cahcedUserMediaPermissions.get(originHash); + if (!settings) { + settings = adoptRef(*new OriginSettings()); + m_cahcedUserMediaPermissions.add(originHash, settings); + } + + settings->setPersistentPermission(permission); +} + +void TestController::handleCheckOfUserMediaPermissionForOrigin(WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, const WKUserMediaPermissionCheckRef& checkRequest) +{ + auto originHash = userMediaOriginHash(userMediaDocumentOrigin, topLevelDocumentOrigin); + auto salt = saltForOrigin(frame, originHash); + + WKUserMediaPermissionCheckSetUserMediaAccessInfo(checkRequest, WKStringCreateWithUTF8CString(salt.utf8().data()), m_cahcedUserMediaPermissions.get(originHash)->persistentPermission()); +} + +void TestController::handleUserMediaPermissionRequest(WKFrameRef frame, WKSecurityOriginRef userMediaDocumentOrigin, WKSecurityOriginRef topLevelDocumentOrigin, WKUserMediaPermissionRequestRef request) +{ + auto originHash = userMediaOriginHash(userMediaDocumentOrigin, topLevelDocumentOrigin); + m_userMediaPermissionRequests.append(std::make_pair(originHash, request)); decidePolicyForUserMediaPermissionRequestIfPossible(); } @@ -1706,11 +1940,18 @@ return; for (auto& pair : m_userMediaPermissionRequests) { + auto originHash = pair.first; auto request = pair.second.get(); + + bool persistentPermission = false; + RefPtr settings = m_cahcedUserMediaPermissions.get(originHash); + if (settings) + persistentPermission = settings->persistentPermission(); + WKRetainPtr audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(request); WKRetainPtr videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(request); - if (m_isUserMediaPermissionAllowed && (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get()))) { + if ((m_isUserMediaPermissionAllowed || persistentPermission) && (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get()))) { WKRetainPtr videoDeviceUID; if (WKArrayGetSize(videoDeviceUIDs.get())) videoDeviceUID = reinterpret_cast(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0)); @@ -1776,7 +2017,7 @@ { WKRetainPtr retainedListener { listener }; const bool shouldIgnore { m_policyDelegateEnabled && !m_policyDelegatePermissive }; - std::function decisionFunction = [shouldIgnore, retainedListener]() { + auto decisionFunction = [shouldIgnore, retainedListener]() { if (shouldIgnore) WKFramePolicyListenerIgnore(retainedListener.get()); else @@ -1784,7 +2025,7 @@ }; if (m_shouldDecideNavigationPolicyAfterDelay) - RunLoop::main().dispatch(decisionFunction); + RunLoop::main().dispatch(WTFMove(decisionFunction)); else decisionFunction(); } @@ -1893,6 +2134,11 @@ m_mainWebView->setNavigationGesturesEnabled(value); } +void TestController::setIgnoresViewportScaleLimits(bool ignoresViewportScaleLimits) +{ + WKPageSetIgnoresViewportScaleLimits(m_mainWebView->page(), ignoresViewportScaleLimits); +} + #if !PLATFORM(COCOA) void TestController::platformWillRunTest(const TestInvocation&) { @@ -1917,6 +2163,12 @@ { } + +unsigned TestController::imageCountInGeneralPasteboard() const +{ + return 0; +} + #endif } // namespace WTR diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestController.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestController.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestController.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestController.h 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2015 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,12 +34,14 @@ #include #include #include +#include OBJC_CLASS WKWebViewConfiguration; namespace WTR { class TestInvocation; +class OriginSettings; class PlatformWebView; class EventSenderProxy; struct TestOptions; @@ -79,7 +81,7 @@ void notifyDone(); bool shouldShowWebView() const { return m_shouldShowWebView; } - + bool usingServerMode() const { return m_usingServerMode; } void configureViewForTest(const TestInvocation&); bool beforeUnloadReturnValue() const { return m_beforeUnloadReturnValue; } @@ -95,10 +97,13 @@ bool isGeolocationProviderActive() const; // MediaStream. + String saltForOrigin(WKFrameRef, String); + void getUserMediaInfoForOrigin(WKFrameRef, WKStringRef originKey, bool&, WKRetainPtr&); + WKStringRef getUserMediaSaltForOrigin(WKFrameRef, WKStringRef originKey); void setUserMediaPermission(bool); - void setUserMediaPermissionForOrigin(bool permission, WKStringRef url); - void handleUserMediaPermissionRequest(WKSecurityOriginRef, WKUserMediaPermissionRequestRef); - void handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginRef, const WKUserMediaPermissionCheckRef&); + void setUserMediaPermissionForOrigin(bool, WKStringRef userMediaDocumentOriginString, WKStringRef topLevelDocumentOriginString); + void handleUserMediaPermissionRequest(WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionRequestRef); + void handleCheckOfUserMediaPermissionForOrigin(WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, const WKUserMediaPermissionCheckRef&); // Policy delegate. void setCustomPolicyDelegate(bool enabled, bool permissive); @@ -106,17 +111,21 @@ // Page Visibility. void setHidden(bool); - bool resetStateToConsistentValues(); - void resetPreferencesToConsistentValues(); + unsigned imageCountInGeneralPasteboard() const; + + bool resetStateToConsistentValues(const TestOptions&); + void resetPreferencesToConsistentValues(const TestOptions&); void terminateWebContentProcess(); void reattachPageToWebProcess(); static const char* webProcessName(); static const char* networkProcessName(); + static const char* databaseProcessName(); WorkQueueManager& workQueueManager() { return m_workQueueManager; } + void setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value) { m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges = value; } void setHandlesAuthenticationChallenges(bool value) { m_handlesAuthenticationChallenges = value; } void setAuthenticationUsername(String username) { m_authenticationUsername = username; } void setAuthenticationPassword(String password) { m_authenticationPassword = password; } @@ -124,12 +133,14 @@ void setBlockAllPlugins(bool shouldBlock) { m_shouldBlockAllPlugins = shouldBlock; } void setShouldLogHistoryClientCallbacks(bool shouldLog) { m_shouldLogHistoryClientCallbacks = shouldLog; } + void setShouldLogCanAuthenticateAgainstProtectionSpace(bool shouldLog) { m_shouldLogCanAuthenticateAgainstProtectionSpace = shouldLog; } bool isCurrentInvocation(TestInvocation* invocation) const { return invocation == m_currentInvocation.get(); } void setShouldDecideNavigationPolicyAfterDelay(bool value) { m_shouldDecideNavigationPolicyAfterDelay = value; } void setNavigationGesturesEnabled(bool value); + void setIgnoresViewportScaleLimits(bool); private: WKRetainPtr generatePageConfiguration(WKContextConfigurationRef); @@ -173,18 +184,22 @@ // WKContextInjectedBundleClient static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void*); static void didReceiveSynchronousMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void*); + static WKTypeRef getInjectedBundleInitializationUserData(WKContextRef, const void *clientInfo); // WKPageInjectedBundleClient static void didReceivePageMessageFromInjectedBundle(WKPageRef, WKStringRef messageName, WKTypeRef messageBody, const void*); static void didReceiveSynchronousPageMessageFromInjectedBundle(WKPageRef, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void*); void didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody); WKRetainPtr didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody); + WKRetainPtr getInjectedBundleInitializationUserData(); void didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef messageBodyDictionary, bool synchronous); // WKContextClient static void networkProcessDidCrash(WKContextRef, const void*); void networkProcessDidCrash(); + static void databaseProcessDidCrash(WKContextRef, const void*); + void databaseProcessDidCrash(); // WKPageNavigationClient static void didCommitNavigation(WKPageRef, WKNavigationRef, WKTypeRef userData, const void*); @@ -193,6 +208,19 @@ static void didFinishNavigation(WKPageRef, WKNavigationRef, WKTypeRef userData, const void*); void didFinishNavigation(WKPageRef, WKNavigationRef); + + // WKContextDownloadClient + static void downloadDidStart(WKContextRef, WKDownloadRef, const void*); + void downloadDidStart(WKContextRef, WKDownloadRef); + static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef, WKStringRef filename, bool* allowOverwrite, const void *clientInfo); + WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef, WKStringRef filename, bool*& allowOverwrite); + static void downloadDidFinish(WKContextRef, WKDownloadRef, const void*); + void downloadDidFinish(WKContextRef, WKDownloadRef); + static void downloadDidFail(WKContextRef, WKDownloadRef, WKErrorRef, const void*); + void downloadDidFail(WKContextRef, WKDownloadRef, WKErrorRef); + static void downloadDidCancel(WKContextRef, WKDownloadRef, const void*); + void downloadDidCancel(WKContextRef, WKDownloadRef); + static void processDidCrash(WKPageRef, const void* clientInfo); void processDidCrash(); @@ -214,9 +242,10 @@ static void unavailablePluginButtonClicked(WKPageRef, WKPluginUnavailabilityReason, WKDictionaryRef, const void*); - static bool canAuthenticateAgainstProtectionSpace(WKPageRef, WKProtectionSpaceRef, const void *clientInfo); + static bool canAuthenticateAgainstProtectionSpace(WKPageRef, WKProtectionSpaceRef, const void*); + bool canAuthenticateAgainstProtectionSpace(WKPageRef, WKProtectionSpaceRef); - static void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef, const void *clientInfo); + static void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef, const void*); void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef); static void decidePolicyForNavigationAction(WKPageRef, WKNavigationActionRef, WKFramePolicyListenerRef, WKTypeRef, const void*); @@ -248,11 +277,11 @@ std::unique_ptr m_currentInvocation; - bool m_verbose; - bool m_printSeparators; - bool m_usingServerMode; - bool m_gcBetweenTests; - bool m_shouldDumpPixelsForAllTests; + bool m_verbose { false }; + bool m_printSeparators { false }; + bool m_usingServerMode { false }; + bool m_gcBetweenTests { false }; + bool m_shouldDumpPixelsForAllTests { false }; std::vector m_paths; std::vector m_allowedHosts; WKRetainPtr m_injectedBundlePath; @@ -269,46 +298,48 @@ Resetting, RunningTest }; - State m_state; - bool m_doneResetting; + State m_state { Initial }; + bool m_doneResetting { false }; - bool m_useWaitToDumpWatchdogTimer; - bool m_forceNoTimeout; + bool m_useWaitToDumpWatchdogTimer { true }; + bool m_forceNoTimeout { false }; - bool m_didPrintWebProcessCrashedMessage; - bool m_shouldExitWhenWebProcessCrashes; + bool m_didPrintWebProcessCrashedMessage { false }; + bool m_shouldExitWhenWebProcessCrashes { true }; - bool m_beforeUnloadReturnValue; + bool m_beforeUnloadReturnValue { true }; std::unique_ptr m_geolocationProvider; Vector > m_geolocationPermissionRequests; - bool m_isGeolocationPermissionSet; - bool m_isGeolocationPermissionAllowed; + bool m_isGeolocationPermissionSet { false }; + bool m_isGeolocationPermissionAllowed { false }; - WKRetainPtr m_userMediaOriginPermissions; + HashMap> m_cahcedUserMediaPermissions; - typedef Vector, WKRetainPtr>> PermissionRequestList; + typedef Vector>> PermissionRequestList; PermissionRequestList m_userMediaPermissionRequests; - bool m_isUserMediaPermissionSet; - bool m_isUserMediaPermissionAllowed; + bool m_isUserMediaPermissionSet { false }; + bool m_isUserMediaPermissionAllowed { false }; - bool m_policyDelegateEnabled; - bool m_policyDelegatePermissive; + bool m_policyDelegateEnabled { false }; + bool m_policyDelegatePermissive { false }; - bool m_handlesAuthenticationChallenges; + bool m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges { false }; + bool m_handlesAuthenticationChallenges { false }; String m_authenticationUsername; String m_authenticationPassword; - bool m_shouldBlockAllPlugins; - - bool m_forceComplexText; - bool m_shouldUseAcceleratedDrawing; - bool m_shouldUseRemoteLayerTree; - - bool m_shouldLogHistoryClientCallbacks; - bool m_shouldShowWebView; + bool m_shouldBlockAllPlugins { false }; + bool m_forceComplexText { false }; + bool m_shouldUseAcceleratedDrawing { false }; + bool m_shouldUseRemoteLayerTree { false }; + + bool m_shouldLogCanAuthenticateAgainstProtectionSpace { false }; + bool m_shouldLogHistoryClientCallbacks { false }; + bool m_shouldShowWebView { false }; + bool m_shouldDecideNavigationPolicyAfterDelay { false }; std::unique_ptr m_eventSenderProxy; diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestInvocation.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestInvocation.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestInvocation.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestInvocation.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2016 Apple Inc. All rights reserved. * Copyright (C) 2012 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ #include "StringFunctions.h" #include "TestController.h" #include "UIScriptController.h" +#include "WebCoreTestSupport.h" #include #include #include @@ -38,8 +39,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -171,13 +174,13 @@ if (m_webProcessIsUnresponsive) dumpWebProcessUnresponsiveness(); - else if (!TestController::singleton().resetStateToConsistentValues()) { - // The process froze while loading about:blank, let's start a fresh one. - // It would be nice to report that the previous test froze after dumping results, but we have no way to do that. - TestController::singleton().terminateWebContentProcess(); - // Make sure that we have a process, as invoke() will need one to send bundle messages for the next test. - TestController::singleton().reattachPageToWebProcess(); - } + else if (TestController::singleton().resetStateToConsistentValues(m_options)) + return; + + // The process is unresponsive, so let's start a new one. + TestController::singleton().terminateWebContentProcess(); + // Make sure that we have a process, as invoke() will need one to send bundle messages for the next test. + TestController::singleton().reattachPageToWebProcess(); } void TestInvocation::dumpWebProcessUnresponsiveness() @@ -187,15 +190,25 @@ void TestInvocation::dumpWebProcessUnresponsiveness(const char* errorMessage) { - char errorMessageToStderr[1024]; + fprintf(stderr, "%s", errorMessage); + char buffer[1024] = { }; #if PLATFORM(COCOA) pid_t pid = WKPageGetProcessIdentifier(TestController::singleton().mainWebView()->page()); - sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast(pid)); + snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast(pid)); #else - sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s", TestController::webProcessName()); + snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s\n", TestController::webProcessName()); #endif - dump(errorMessage, errorMessageToStderr, true); + dump(errorMessage, buffer, true); + + if (!TestController::singleton().usingServerMode()) + return; + + if (isatty(fileno(stdin)) || isatty(fileno(stderr))) + fputs("Grab an image of the stack, then hit enter...\n", stderr); + + if (!fgets(buffer, sizeof(buffer), stdin) || strcmp(buffer, "#SAMPLE FINISHED\n")) + fprintf(stderr, "Failed receive expected sample response, got:\n\t\"%s\"\nContinuing...\n", buffer); } void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bool seenError) @@ -246,8 +259,8 @@ m_webProcessIsUnresponsive = true; return; } + WKRetainPtr windowSnapshot = TestController::singleton().mainWebView()->windowSnapshotImage(); - ASSERT(windowSnapshot); dumpPixelsAndCompareWithExpected(windowSnapshot.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebView); } } @@ -477,10 +490,13 @@ WKBooleanRef permissionWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, permissionKeyWK.get())); bool permission = WKBooleanGetValue(permissionWK); - WKRetainPtr urlKey(AdoptWK, WKStringCreateWithUTF8CString("url")); - WKStringRef urlWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, urlKey.get())); + WKRetainPtr originKey(AdoptWK, WKStringCreateWithUTF8CString("origin")); + WKStringRef originWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, originKey.get())); + + WKRetainPtr parentOriginKey(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin")); + WKStringRef parentOriginWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, parentOriginKey.get())); - TestController::singleton().setUserMediaPermissionForOrigin(permission, urlWK); + TestController::singleton().setUserMediaPermissionForOrigin(permission, originWK, parentOriginWK); return; } @@ -594,13 +610,27 @@ return; } - if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenge")) { + if (WKStringIsEqualToUTF8CString(messageName, "SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef value = static_cast(messageBody); + TestController::singleton().setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(WKBooleanGetValue(value)); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenges")) { ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); WKBooleanRef value = static_cast(messageBody); TestController::singleton().setHandlesAuthenticationChallenges(WKBooleanGetValue(value)); return; } + if (WKStringIsEqualToUTF8CString(messageName, "SetShouldLogCanAuthenticateAgainstProtectionSpace")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef value = static_cast(messageBody); + TestController::singleton().setShouldLogCanAuthenticateAgainstProtectionSpace(WKBooleanGetValue(value)); + return; + } + if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) { ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID()); WKStringRef username = static_cast(messageBody); @@ -635,6 +665,13 @@ TestController::singleton().setNavigationGesturesEnabled(WKBooleanGetValue(value)); return; } + + if (WKStringIsEqualToUTF8CString(messageName, "SetIgnoresViewportScaleLimits")) { + ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID()); + WKBooleanRef value = static_cast(messageBody); + TestController::singleton().setIgnoresViewportScaleLimits(WKBooleanGetValue(value)); + return; + } if (WKStringIsEqualToUTF8CString(messageName, "RunUIProcessScript")) { WKDictionaryRef messageBodyDictionary = static_cast(messageBody); @@ -662,6 +699,20 @@ return nullptr; } + if (WKStringIsEqualToUTF8CString(messageName, "SetViewSize")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + + WKDictionaryRef messageBodyDictionary = static_cast(messageBody); + WKRetainPtr widthKey(AdoptWK, WKStringCreateWithUTF8CString("width")); + WKRetainPtr heightKey(AdoptWK, WKStringCreateWithUTF8CString("height")); + + WKDoubleRef widthWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, widthKey.get())); + WKDoubleRef heightWK = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, heightKey.get())); + + TestController::singleton().mainWebView()->resizeTo(WKDoubleGetValue(widthWK), WKDoubleGetValue(heightWK)); + return nullptr; + } + if (WKStringIsEqualToUTF8CString(messageName, "IsGeolocationClientActive")) { bool isActive = TestController::singleton().isGeolocationProviderActive(); WKRetainPtr result(AdoptWK, WKBooleanCreate(isActive)); @@ -691,6 +742,89 @@ return nullptr; } + if (WKStringIsEqualToUTF8CString(messageName, "ImageCountInGeneralPasteboard")) { + unsigned count = TestController::singleton().imageCountInGeneralPasteboard(); + WKRetainPtr result(AdoptWK, WKUInt64Create(count)); + return result; + } + + if (WKStringIsEqualToUTF8CString(messageName, "DeleteAllIndexedDatabases")) { + WKWebsiteDataStoreRemoveAllIndexedDatabases(WKContextGetWebsiteDataStore(TestController::singleton().context())); + return nullptr; + } + +#if PLATFORM(MAC) + if (WKStringIsEqualToUTF8CString(messageName, "ConnectMockGamepad")) { + ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); + + uint64_t index = WKUInt64GetValue(static_cast(messageBody)); + WebCoreTestSupport::connectMockGamepad(index); + + return nullptr; + } + + if (WKStringIsEqualToUTF8CString(messageName, "DisconnectMockGamepad")) { + ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID()); + + uint64_t index = WKUInt64GetValue(static_cast(messageBody)); + WebCoreTestSupport::disconnectMockGamepad(index); + + return nullptr; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadDetails")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + + WKDictionaryRef messageBodyDictionary = static_cast(messageBody); + WKRetainPtr gamepadIndexKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex")); + WKRetainPtr gamepadIDKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadID")); + WKRetainPtr axisCountKey(AdoptWK, WKStringCreateWithUTF8CString("AxisCount")); + WKRetainPtr buttonCountKey(AdoptWK, WKStringCreateWithUTF8CString("ButtonCount")); + + WKUInt64Ref gamepadIndex = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIndexKey.get())); + WKStringRef gamepadID = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIDKey.get())); + WKUInt64Ref axisCount = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, axisCountKey.get())); + WKUInt64Ref buttonCount = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, buttonCountKey.get())); + + WebCoreTestSupport::setMockGamepadDetails(WKUInt64GetValue(gamepadIndex), toWTFString(gamepadID), WKUInt64GetValue(axisCount), WKUInt64GetValue(buttonCount)); + return nullptr; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadAxisValue")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + + WKDictionaryRef messageBodyDictionary = static_cast(messageBody); + WKRetainPtr gamepadIndexKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex")); + WKRetainPtr axisIndexKey(AdoptWK, WKStringCreateWithUTF8CString("AxisIndex")); + WKRetainPtr valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value")); + + WKUInt64Ref gamepadIndex = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIndexKey.get())); + WKUInt64Ref axisIndex = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, axisIndexKey.get())); + WKDoubleRef value = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get())); + + WebCoreTestSupport::setMockGamepadAxisValue(WKUInt64GetValue(gamepadIndex), WKUInt64GetValue(axisIndex), WKDoubleGetValue(value)); + + return nullptr; + } + + if (WKStringIsEqualToUTF8CString(messageName, "SetMockGamepadButtonValue")) { + ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); + + WKDictionaryRef messageBodyDictionary = static_cast(messageBody); + WKRetainPtr gamepadIndexKey(AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex")); + WKRetainPtr buttonIndexKey(AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex")); + WKRetainPtr valueKey(AdoptWK, WKStringCreateWithUTF8CString("Value")); + + WKUInt64Ref gamepadIndex = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, gamepadIndexKey.get())); + WKUInt64Ref buttonIndex = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, buttonIndexKey.get())); + WKDoubleRef value = static_cast(WKDictionaryGetItemForKey(messageBodyDictionary, valueKey.get())); + + WebCoreTestSupport::setMockGamepadButtonValue(WKUInt64GetValue(gamepadIndex), WKUInt64GetValue(buttonIndex), WKDoubleGetValue(value)); + + return nullptr; + } +#endif // PLATFORM(MAC) + ASSERT_NOT_REACHED(); return nullptr; } @@ -712,10 +846,10 @@ if (!m_UIScriptContext) m_UIScriptContext = std::make_unique(*this); - m_UIScriptContext->runUIScript(script, scriptCallbackID); + m_UIScriptContext->runUIScript(toWTFString(script), scriptCallbackID); } -void TestInvocation::uiScriptDidComplete(WKStringRef result, unsigned scriptCallbackID) +void TestInvocation::uiScriptDidComplete(const String& result, unsigned scriptCallbackID) { WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("CallUISideScriptCallback")); @@ -724,7 +858,7 @@ WKRetainPtr callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID")); WKRetainPtr callbackIDValue = adoptWK(WKUInt64Create(scriptCallbackID)); - WKDictionarySetItem(messageBody.get(), resultKey.get(), result); + WKDictionarySetItem(messageBody.get(), resultKey.get(), toWK(result).get()); WKDictionarySetItem(messageBody.get(), callbackIDKey.get(), callbackIDValue.get()); WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), messageBody.get()); @@ -759,4 +893,10 @@ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); } +void TestInvocation::notifyDownloadDone() +{ + WKRetainPtr messageName = adoptWK(WKStringCreateWithUTF8CString("NotifyDownloadDone")); + WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0); +} + } // namespace WTR diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestInvocation.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestInvocation.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestInvocation.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestInvocation.h 2016-11-03 07:04:21.000000000 +0000 @@ -65,6 +65,8 @@ void didEndSwipe(); void didRemoveSwipeSnapshot(); + void notifyDownloadDone(); + private: void dumpResults(); static void dump(const char* textToStdout, const char* textToStderr = 0, bool seenError = false); @@ -87,7 +89,7 @@ void runUISideScript(WKStringRef, unsigned callbackID); // UIScriptContextDelegate - void uiScriptDidComplete(WKStringRef result, unsigned callbackID) override; + void uiScriptDidComplete(const String& result, unsigned callbackID) override; const TestOptions m_options; diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestOptions.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestOptions.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestOptions.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestOptions.cpp 2016-11-03 07:04:21.000000000 +0000 @@ -56,16 +56,20 @@ return pathContains(pathOrURL, "svg/W3C-SVG-1.1") || pathContains(pathOrURL, "svg\\W3C-SVG-1.1"); } -static bool isHiDPITestPath(const std::string& pathOrURL) +static float deviceScaleFactorForTest(const std::string& pathOrURL) { - return pathContains(pathOrURL, "/hidpi-"); + if (pathContains(pathOrURL, "/hidpi-3x-")) + return 3; + if (pathContains(pathOrURL, "/hidpi-")) + return 2; + return 1; } TestOptions::TestOptions(const std::string& pathOrURL) : useFlexibleViewport(shouldMakeViewportFlexible(pathOrURL)) , useFixedLayout(shouldUseFixedLayout(pathOrURL)) , isSVGTest(isSVGTestPath(pathOrURL)) - , isHiDPITest(isHiDPITestPath(pathOrURL)) + , deviceScaleFactor(deviceScaleFactorForTest(pathOrURL)) { } diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestOptions.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestOptions.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/TestOptions.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/TestOptions.h 2016-11-03 07:04:21.000000000 +0000 @@ -38,9 +38,12 @@ bool useFlexibleViewport { false }; bool useFixedLayout { false }; bool isSVGTest { false }; - bool isHiDPITest { false }; bool useDataDetection { false }; + bool useMockScrollbars { true }; + bool needsSiteSpecificQuirks { false }; + bool ignoresViewportScaleLimits { false }; + float deviceScaleFactor { 1 }; Vector overrideLanguages; TestOptions(const std::string& pathOrURL); diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -interface UIScriptController { - - void doAsyncTask(object callback); // Used to test the harness. - - void zoomToScale(double scale, object callback); - - // Interaction. - // These functions post events asynchronously. The callback is fired when the events have been dispatched, but any - // resulting behavior may also be asynchronous. - void touchDownAtPoint(long x, long y, long touchCount, object callback); - void liftUpAtPoint(long x, long y, long touchCount, object callback); - void singleTapAtPoint(long x, long y, object callback); - void doubleTapAtPoint(long x, long y, object callback); - - void typeCharacterUsingHardwareKeyboard(DOMString character, object callback); - void keyDownUsingHardwareKeyboard(DOMString character, object callback); - void keyUpUsingHardwareKeyboard(DOMString character, object callback); - - attribute object didShowKeyboardCallback; - attribute object didHideKeyboardCallback; - - attribute object willBeginZoomingCallback; - attribute object didEndZoomingCallback; - - attribute object didEndScrollingCallback; - - // View state - readonly attribute double zoomScale; - readonly attribute double minimumZoomScale; - readonly attribute double maximumZoomScale; - - readonly attribute object contentVisibleRect; // Returned object has 'left', 'top', 'width', 'height' properties. - - void uiScriptComplete(DOMString result); -}; diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "UIScriptContext.h" - -#include "StringFunctions.h" -#include "UIScriptController.h" -#include -#include -#include -#include -#include - -using namespace WTR; - -static inline bool isPersistentCallbackID(unsigned callbackID) -{ - return callbackID < firstNonPersistentCallbackID; -} - -UIScriptContext::UIScriptContext(UIScriptContextDelegate& delegate) - : m_context(Adopt, JSGlobalContextCreate(nullptr)) - , m_delegate(delegate) -{ - m_controller = UIScriptController::create(*this); - - JSObjectRef globalObject = JSContextGetGlobalObject(m_context.get()); - - JSValueRef exception = nullptr; - m_controller->makeWindowObject(m_context.get(), globalObject, &exception); -} - -UIScriptContext::~UIScriptContext() -{ - m_controller->contextDestroyed(); -} - -void UIScriptContext::runUIScript(WKStringRef script, unsigned scriptCallbackID) -{ - m_currentScriptCallbackID = scriptCallbackID; - - auto scriptRef = toJS(script); - - JSValueRef exception = nullptr; - JSValueRef result = JSEvaluateScript(m_context.get(), scriptRef.get(), 0, 0, 1, &exception); - - if (!hasOutstandingAsyncTasks()) { - JSValueRef stringifyException = nullptr; - requestUIScriptCompletion(JSValueToStringCopy(m_context.get(), result, &stringifyException)); - tryToCompleteUIScriptForCurrentParentCallback(); - } -} - -unsigned UIScriptContext::nextTaskCallbackID(CallbackType type) -{ - if (type == CallbackTypeNonPersistent) - return ++m_nextTaskCallbackID + firstNonPersistentCallbackID; - - return type; -} - -unsigned UIScriptContext::prepareForAsyncTask(JSValueRef callback, CallbackType type) -{ - unsigned callbackID = nextTaskCallbackID(type); - - JSValueProtect(m_context.get(), callback); - Task task; - task.parentScriptCallbackID = m_currentScriptCallbackID; - task.callback = callback; - - ASSERT(!m_callbacks.contains(callbackID)); - m_callbacks.add(callbackID, task); - - return callbackID; -} - -void UIScriptContext::asyncTaskComplete(unsigned callbackID) -{ - Task task = m_callbacks.take(callbackID); - ASSERT(task.callback); - - JSValueRef exception = nullptr; - JSObjectRef callbackObject = JSValueToObject(m_context.get(), task.callback, &exception); - - m_currentScriptCallbackID = task.parentScriptCallbackID; - - exception = nullptr; - JSObjectCallAsFunction(m_context.get(), callbackObject, JSContextGetGlobalObject(m_context.get()), 0, nullptr, &exception); - JSValueUnprotect(m_context.get(), task.callback); - - tryToCompleteUIScriptForCurrentParentCallback(); - m_currentScriptCallbackID = 0; -} - -unsigned UIScriptContext::registerCallback(JSValueRef taskCallback, CallbackType type) -{ - if (m_callbacks.contains(type)) - unregisterCallback(type); - - return prepareForAsyncTask(taskCallback, type); -} - -void UIScriptContext::unregisterCallback(unsigned callbackID) -{ - Task task = m_callbacks.take(callbackID); - ASSERT(task.callback); - JSValueUnprotect(m_context.get(), task.callback); -} - -JSValueRef UIScriptContext::callbackWithID(unsigned callbackID) -{ - Task task = m_callbacks.get(callbackID); - return task.callback; -} - -void UIScriptContext::fireCallback(unsigned callbackID) -{ - Task task = m_callbacks.get(callbackID); - ASSERT(task.callback); - - JSValueRef exception = nullptr; - JSObjectRef callbackObject = JSValueToObject(m_context.get(), task.callback, &exception); - - m_currentScriptCallbackID = task.parentScriptCallbackID; - - exception = nullptr; - JSObjectCallAsFunction(m_context.get(), callbackObject, JSContextGetGlobalObject(m_context.get()), 0, nullptr, &exception); - - tryToCompleteUIScriptForCurrentParentCallback(); - m_currentScriptCallbackID = 0; -} - -void UIScriptContext::requestUIScriptCompletion(JSStringRef result) -{ - ASSERT(m_currentScriptCallbackID); - if (currentParentCallbackIsPendingCompletion()) - return; - - // This request for the UI script to complete is not fulfilled until the last non-persistent task for the parent callback is finished. - m_uiScriptResultsPendingCompletion.add(m_currentScriptCallbackID, result ? JSStringRetain(result) : nullptr); -} - -void UIScriptContext::tryToCompleteUIScriptForCurrentParentCallback() -{ - if (!currentParentCallbackIsPendingCompletion() || currentParentCallbackHasOutstandingAsyncTasks()) - return; - - JSStringRef result = m_uiScriptResultsPendingCompletion.take(m_currentScriptCallbackID); - WKRetainPtr uiScriptResult = adoptWK(WKStringCreateWithJSString(result)); - m_delegate.uiScriptDidComplete(uiScriptResult.get(), m_currentScriptCallbackID); - m_currentScriptCallbackID = 0; - if (result) - JSStringRelease(result); -} - -JSObjectRef UIScriptContext::objectFromRect(const WKRect& rect) const -{ - JSObjectRef object = JSObjectMake(m_context.get(), nullptr, nullptr); - - JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("left")).get(), JSValueMakeNumber(m_context.get(), rect.origin.x), kJSPropertyAttributeNone, nullptr); - JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("top")).get(), JSValueMakeNumber(m_context.get(), rect.origin.y), kJSPropertyAttributeNone, nullptr); - JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("width")).get(), JSValueMakeNumber(m_context.get(), rect.size.width), kJSPropertyAttributeNone, nullptr); - JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("height")).get(), JSValueMakeNumber(m_context.get(), rect.size.height), kJSPropertyAttributeNone, nullptr); - - return object; -} - -bool UIScriptContext::currentParentCallbackHasOutstandingAsyncTasks() const -{ - for (auto entry : m_callbacks) { - unsigned callbackID = entry.key; - Task task = entry.value; - if (task.parentScriptCallbackID == m_currentScriptCallbackID && !isPersistentCallbackID(callbackID)) - return true; - } - - return false; -} - diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UIScriptContext_h -#define UIScriptContext_h - -#include -#include -#include - -namespace WTR { - -class UIScriptController; - -class UIScriptContextDelegate { -public: - virtual void uiScriptDidComplete(WKStringRef result, unsigned callbackID) = 0; -}; - -const unsigned firstNonPersistentCallbackID = 1000; - -typedef enum { - CallbackTypeWillBeginZooming = 0, - CallbackTypeDidEndZooming, - CallbackTypeDidShowKeyboard, - CallbackTypeDidHideKeyboard, - CallbackTypeDidEndScrolling, - CallbackTypeNonPersistent = firstNonPersistentCallbackID -} CallbackType; - -class UIScriptContext { - WTF_MAKE_NONCOPYABLE(UIScriptContext); -public: - UIScriptContext(UIScriptContextDelegate&); - ~UIScriptContext(); - - void runUIScript(WKStringRef script, unsigned scriptCallbackID); - void requestUIScriptCompletion(JSStringRef); - - // For one-shot tasks callbacks. - unsigned prepareForAsyncTask(JSValueRef taskCallback, CallbackType); - void asyncTaskComplete(unsigned taskCallbackID); - - // For persistent callbacks. - unsigned registerCallback(JSValueRef taskCallback, CallbackType); - JSValueRef callbackWithID(unsigned callbackID); - void unregisterCallback(unsigned callbackID); - void fireCallback(unsigned callbackID); - - unsigned nextTaskCallbackID(CallbackType); - - JSObjectRef objectFromRect(const WKRect&) const; - -private: - JSRetainPtr m_context; - - bool hasOutstandingAsyncTasks() const { return !m_callbacks.isEmpty(); } - bool currentParentCallbackIsPendingCompletion() const { return m_uiScriptResultsPendingCompletion.contains(m_currentScriptCallbackID); } - bool currentParentCallbackHasOutstandingAsyncTasks() const; - void tryToCompleteUIScriptForCurrentParentCallback(); - - struct Task { - unsigned parentScriptCallbackID { 0 }; - JSValueRef callback { nullptr }; - }; - HashMap m_callbacks; - HashMap m_uiScriptResultsPendingCompletion; - - UIScriptContextDelegate& m_delegate; - RefPtr m_controller; - - unsigned m_currentScriptCallbackID { 0 }; - unsigned m_nextTaskCallbackID { 0 }; -}; - -} - -#endif // UIScriptContext_h diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "UIScriptController.h" - -#include "JSUIScriptController.h" -#include "UIScriptContext.h" -#include - -namespace WTR { - -UIScriptController::UIScriptController(UIScriptContext& context) - : m_context(&context) -{ -} - -void UIScriptController::contextDestroyed() -{ - m_context = nullptr; -} - -void UIScriptController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception) -{ - setProperty(context, windowObject, "uiController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception); -} - -JSClassRef UIScriptController::wrapperClass() -{ - return JSUIScriptController::uIScriptControllerClass(); -} - -#if !PLATFORM(COCOA) -void UIScriptController::doAsyncTask(JSValueRef) -{ -} -#endif - -void UIScriptController::setWillBeginZoomingCallback(JSValueRef callback) -{ - m_context->registerCallback(callback, CallbackTypeWillBeginZooming); - platformSetWillBeginZoomingCallback(); -} - -JSValueRef UIScriptController::willBeginZoomingCallback() const -{ - return m_context->callbackWithID(CallbackTypeWillBeginZooming); -} - -void UIScriptController::setDidEndZoomingCallback(JSValueRef callback) -{ - m_context->registerCallback(callback, CallbackTypeDidEndZooming); - platformSetDidEndZoomingCallback(); -} - -JSValueRef UIScriptController::didEndZoomingCallback() const -{ - return m_context->callbackWithID(CallbackTypeDidEndZooming); -} - -void UIScriptController::setDidEndScrollingCallback(JSValueRef callback) -{ - m_context->registerCallback(callback, CallbackTypeDidEndScrolling); - platformSetDidEndScrollingCallback(); -} - -JSValueRef UIScriptController::didEndScrollingCallback() const -{ - return m_context->callbackWithID(CallbackTypeDidEndScrolling); -} - -void UIScriptController::setDidShowKeyboardCallback(JSValueRef callback) -{ - m_context->registerCallback(callback, CallbackTypeDidShowKeyboard); - platformSetDidShowKeyboardCallback(); -} - -JSValueRef UIScriptController::didShowKeyboardCallback() const -{ - return m_context->callbackWithID(CallbackTypeDidShowKeyboard); -} - -void UIScriptController::setDidHideKeyboardCallback(JSValueRef callback) -{ - m_context->registerCallback(callback, CallbackTypeDidHideKeyboard); - platformSetDidHideKeyboardCallback(); -} - -JSValueRef UIScriptController::didHideKeyboardCallback() const -{ - return m_context->callbackWithID(CallbackTypeDidHideKeyboard); -} - -#if !PLATFORM(IOS) -void UIScriptController::zoomToScale(double, JSValueRef) -{ -} - -void UIScriptController::touchDownAtPoint(long x, long y, long touchCount, JSValueRef) -{ -} - -void UIScriptController::liftUpAtPoint(long x, long y, long touchCount, JSValueRef) -{ -} - -void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef) -{ -} - -void UIScriptController::doubleTapAtPoint(long x, long y, JSValueRef) -{ -} - -void UIScriptController::typeCharacterUsingHardwareKeyboard(JSStringRef, JSValueRef) -{ -} - -void UIScriptController::keyUpUsingHardwareKeyboard(JSStringRef, JSValueRef) -{ -} - -void UIScriptController::keyDownUsingHardwareKeyboard(JSStringRef, JSValueRef) -{ -} - -double UIScriptController::zoomScale() const -{ - return 1; -} - -double UIScriptController::minimumZoomScale() const -{ - return 1; -} - -double UIScriptController::maximumZoomScale() const -{ - return 1; -} - -JSObjectRef UIScriptController::contentVisibleRect() const -{ - return nullptr; -} - -void UIScriptController::platformSetWillBeginZoomingCallback() -{ -} - -void UIScriptController::platformSetDidEndZoomingCallback() -{ -} - -void UIScriptController::platformSetDidEndScrollingCallback() -{ -} - -void UIScriptController::platformSetDidShowKeyboardCallback() -{ -} - -void UIScriptController::platformSetDidHideKeyboardCallback() -{ -} - -void UIScriptController::platformClearAllCallbacks() -{ -} -#endif - -void UIScriptController::uiScriptComplete(JSStringRef result) -{ - m_context->requestUIScriptCompletion(result); - platformClearAllCallbacks(); -} - -} diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h 2016-05-23 10:03:36.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UIScriptController_h -#define UIScriptController_h - -#include "JSWrappable.h" -#include - -namespace WTR { - -class UIScriptContext; - -class UIScriptController : public JSWrappable { -public: - static Ref create(UIScriptContext& context) - { - return adoptRef(*new UIScriptController(context)); - } - - void contextDestroyed(); - - void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); - - void doAsyncTask(JSValueRef callback); - void zoomToScale(double scale, JSValueRef callback); - - void touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback); - void liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback); - void singleTapAtPoint(long x, long y, JSValueRef callback); - void doubleTapAtPoint(long x, long y, JSValueRef callback); - - void typeCharacterUsingHardwareKeyboard(JSStringRef character, JSValueRef callback); - void keyDownUsingHardwareKeyboard(JSStringRef character, JSValueRef callback); - void keyUpUsingHardwareKeyboard(JSStringRef character, JSValueRef callback); - - void setWillBeginZoomingCallback(JSValueRef); - JSValueRef willBeginZoomingCallback() const; - - void setDidEndZoomingCallback(JSValueRef); - JSValueRef didEndZoomingCallback() const; - - void setDidShowKeyboardCallback(JSValueRef); - JSValueRef didShowKeyboardCallback() const; - - void setDidHideKeyboardCallback(JSValueRef); - JSValueRef didHideKeyboardCallback() const; - - void setDidEndScrollingCallback(JSValueRef); - JSValueRef didEndScrollingCallback() const; - - double zoomScale() const; - double minimumZoomScale() const; - double maximumZoomScale() const; - - JSObjectRef contentVisibleRect() const; - - void uiScriptComplete(JSStringRef result); - -private: - UIScriptController(UIScriptContext&); - - void platformSetWillBeginZoomingCallback(); - void platformSetDidEndZoomingCallback(); - void platformSetDidShowKeyboardCallback(); - void platformSetDidHideKeyboardCallback(); - void platformSetDidEndScrollingCallback(); - void platformClearAllCallbacks(); - - virtual JSClassRef wrapperClass() override; - - JSObjectRef objectFromRect(const WKRect&) const; - - UIScriptContext* m_context; -}; - -} - -#endif // UIScriptController_h diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h 2015-07-22 12:37:58.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -// -// AppDelegate.h -// WebKitTestRunnerApp -// -// Created by David Farler on 1/22/14. -// -// - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -@end diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebKitTestRunner.sln webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebKitTestRunner.sln --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebKitTestRunner.sln 2013-08-03 16:10:41.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebKitTestRunner.sln 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebKitTestRunner", "win\WebKitTestRunner.vcproj", "{3B99669B-1817-443B-BCBE-835580146668}" - ProjectSection(ProjectDependencies) = postProject - {CBC3391C-F060-4BF5-A66E-81404168816B} = {CBC3391C-F060-4BF5-A66E-81404168816B} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectedBundleGenerated", "win\InjectedBundleGenerated.vcproj", "{4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}" - ProjectSection(ProjectDependencies) = postProject - {C0737398-3565-439E-A2B8-AB2BE4D5430C} = {C0737398-3565-439E-A2B8-AB2BE4D5430C} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiff", "..\DumpRenderTree\win\ImageDiff.vcproj", "{59CC0547-70AC-499C-9B19-EC01C6F61137}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectedBundle", "win\InjectedBundle.vcproj", "{CBC3391C-F060-4BF5-A66E-81404168816B}" - ProjectSection(ProjectDependencies) = postProject - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD} = {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestNetscapePlugin", "..\DumpRenderTree\TestNetscapePlugIn\win\TestNetscapePlugin.vcproj", "{C0737398-3565-439E-A2B8-AB2BE4D5430C}" - ProjectSection(ProjectDependencies) = postProject - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017} = {DD7949B6-F2B4-47C2-9C42-E21E84CB1017} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebKitTestRunnerLauncher", "win\WebKitTestRunnerLauncher.vcproj", "{C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}" - ProjectSection(ProjectDependencies) = postProject - {3B99669B-1817-443B-BCBE-835580146668} = {3B99669B-1817-443B-BCBE-835580146668} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiffLauncher", "..\DumpRenderTree\win\ImageDiffLauncher.vcproj", "{DD7949B6-F2B4-47C2-9C42-E21E84CB1017}" - ProjectSection(ProjectDependencies) = postProject - {59CC0547-70AC-499C-9B19-EC01C6F61137} = {59CC0547-70AC-499C-9B19-EC01C6F61137} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug_All|Win32 = Debug_All|Win32 - Debug|Win32 = Debug|Win32 - Production|Win32 = Production|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3B99669B-1817-443B-BCBE-835580146668}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Debug|Win32.ActiveCfg = Debug|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Debug|Win32.Build.0 = Debug|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Production|Win32.ActiveCfg = Production|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Production|Win32.Build.0 = Production|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Release|Win32.ActiveCfg = Release|Win32 - {3B99669B-1817-443B-BCBE-835580146668}.Release|Win32.Build.0 = Release|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug|Win32.ActiveCfg = Debug|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug|Win32.Build.0 = Debug|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Production|Win32.ActiveCfg = Production|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Production|Win32.Build.0 = Production|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Release|Win32.ActiveCfg = Release|Win32 - {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Release|Win32.Build.0 = Release|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.ActiveCfg = Debug|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.Build.0 = Debug|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Production|Win32.ActiveCfg = Production|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Production|Win32.Build.0 = Production|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.ActiveCfg = Release|Win32 - {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.Build.0 = Release|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug|Win32.Build.0 = Debug|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Production|Win32.ActiveCfg = Production|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Production|Win32.Build.0 = Production|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Release|Win32.ActiveCfg = Release|Win32 - {CBC3391C-F060-4BF5-A66E-81404168816B}.Release|Win32.Build.0 = Release|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.ActiveCfg = Debug|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.Build.0 = Debug|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Production|Win32.ActiveCfg = Production|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Production|Win32.Build.0 = Production|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.ActiveCfg = Release|Win32 - {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.Build.0 = Release|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug|Win32.ActiveCfg = Debug|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug|Win32.Build.0 = Debug|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Production|Win32.ActiveCfg = Production|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Production|Win32.Build.0 = Production|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Release|Win32.ActiveCfg = Release|Win32 - {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Release|Win32.Build.0 = Release|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug|Win32.ActiveCfg = Debug|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug|Win32.Build.0 = Debug|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Production|Win32.ActiveCfg = Production|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Production|Win32.Build.0 = Production|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release|Win32.ActiveCfg = Release|Win32 - {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebNotificationProvider.cpp webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebNotificationProvider.cpp --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebNotificationProvider.cpp 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebNotificationProvider.cpp 2016-09-16 09:56:48.000000000 +0000 @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -95,10 +96,23 @@ ASSERT_UNUSED(addResult, addResult.isNewEntry); auto addResult2 = m_owningManager.set(id, notificationManager); ASSERT_UNUSED(addResult2, addResult2.isNewEntry); + auto addResult3 = m_localToGlobalNotificationIDMap.add(std::make_pair(page, WKNotificationManagerGetLocalIDForTesting(notificationManager, notification)), id); + ASSERT_UNUSED(addResult3, addResult3.isNewEntry); WKNotificationManagerProviderDidShowNotification(notificationManager, id); } +static void removeGlobalIDFromIDMap(HashMap, uint64_t>& map, uint64_t id) +{ + for (auto iter = map.begin(); iter != map.end(); ++iter) { + if (iter->value == id) { + map.remove(iter); + return; + } + } + ASSERT_NOT_REACHED(); +} + void WebNotificationProvider::closeWebNotification(WKNotificationRef notification) { uint64_t id = WKNotificationGetID(notification); @@ -110,6 +124,8 @@ ASSERT_UNUSED(success, success); m_owningManager.remove(id); + removeGlobalIDFromIDMap(m_localToGlobalNotificationIDMap, id); + WKRetainPtr wkID = WKUInt64Create(id); WKRetainPtr array(AdoptWK, WKMutableArrayCreate()); WKArrayAppendItem(array.get(), wkID.get()); @@ -132,6 +148,7 @@ for (uint64_t notificationID : toRemove) { bool success = m_owningManager.remove(notificationID); ASSERT_UNUSED(success, success); + removeGlobalIDFromIDMap(m_localToGlobalNotificationIDMap, notificationID); WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get()); } WKNotificationManagerProviderDidCloseNotifications(manager, array.get()); @@ -143,10 +160,12 @@ return WKMutableDictionaryCreate(); } -void WebNotificationProvider::simulateWebNotificationClick(uint64_t notificationID) +void WebNotificationProvider::simulateWebNotificationClick(WKPageRef page, uint64_t notificationID) { - ASSERT(m_owningManager.contains(notificationID)); - WKNotificationManagerProviderDidClickNotification(m_owningManager.get(notificationID), notificationID); + ASSERT(m_localToGlobalNotificationIDMap.contains(std::make_pair(page, notificationID))); + auto globalID = m_localToGlobalNotificationIDMap.get(std::make_pair(page, notificationID)); + ASSERT(m_owningManager.contains(globalID)); + WKNotificationManagerProviderDidClickNotification(m_owningManager.get(globalID), globalID); } void WebNotificationProvider::reset() @@ -162,6 +181,7 @@ WKNotificationManagerProviderDidCloseNotifications(notificationPair.key.get(), array.get()); } m_owningManager.clear(); + m_localToGlobalNotificationIDMap.clear(); } } // namespace WTR diff -Nru webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebNotificationProvider.h webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebNotificationProvider.h --- webkit2gtk-2.12.3/Tools/WebKitTestRunner/WebNotificationProvider.h 2016-04-11 06:18:44.000000000 +0000 +++ webkit2gtk-2.14.2/Tools/WebKitTestRunner/WebNotificationProvider.h 2016-09-16 09:56:48.000000000 +0000 @@ -46,13 +46,15 @@ void removeNotificationManager(WKNotificationManagerRef); WKDictionaryRef notificationPermissions(); - void simulateWebNotificationClick(uint64_t notificationID); + void simulateWebNotificationClick(WKPageRef, uint64_t notificationID); void reset(); private: // Inverses of each other. HashMap, HashSet> m_ownedNotifications; HashMap m_owningManager; + + HashMap, uint64_t> m_localToGlobalNotificationIDMap; }; }