mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:48:11 +00:00
Ladybird+LibJS: Add CLI option to run browser with LibJS bytecode VM
This required quite a bit of plumbing, but now you can run ladybird --use-bytecode
This commit is contained in:
parent
7ec7015750
commit
9c568282dc
20 changed files with 91 additions and 38 deletions
|
@ -39,10 +39,11 @@ static QIcon const& app_icon()
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
BrowserWindow::BrowserWindow(Browser::CookieJar& cookie_jar, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling, WebView::UseJavaScriptBytecode use_javascript_bytecode)
|
||||||
: m_cookie_jar(cookie_jar)
|
: m_cookie_jar(cookie_jar)
|
||||||
, m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
, m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
||||||
, m_enable_callgrind_profiling(enable_callgrind_profiling)
|
, m_enable_callgrind_profiling(enable_callgrind_profiling)
|
||||||
|
, m_use_javascript_bytecode(use_javascript_bytecode)
|
||||||
{
|
{
|
||||||
setWindowIcon(app_icon());
|
setWindowIcon(app_icon());
|
||||||
m_tabs_container = new QTabWidget(this);
|
m_tabs_container = new QTabWidget(this);
|
||||||
|
@ -415,7 +416,7 @@ void BrowserWindow::debug_request(DeprecatedString const& request, DeprecatedStr
|
||||||
|
|
||||||
Tab& BrowserWindow::new_tab(QString const& url, Web::HTML::ActivateTab activate_tab)
|
Tab& BrowserWindow::new_tab(QString const& url, Web::HTML::ActivateTab activate_tab)
|
||||||
{
|
{
|
||||||
auto tab = make<Tab>(this, m_webdriver_content_ipc_path, m_enable_callgrind_profiling);
|
auto tab = make<Tab>(this, m_webdriver_content_ipc_path, m_enable_callgrind_profiling, m_use_javascript_bytecode);
|
||||||
auto tab_ptr = tab.ptr();
|
auto tab_ptr = tab.ptr();
|
||||||
m_tabs.append(std::move(tab));
|
m_tabs.append(std::move(tab));
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class CookieJar;
|
||||||
class BrowserWindow : public QMainWindow {
|
class BrowserWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit BrowserWindow(Browser::CookieJar&, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
|
explicit BrowserWindow(Browser::CookieJar&, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling, WebView::UseJavaScriptBytecode);
|
||||||
|
|
||||||
WebContentView& view() const { return m_current_tab->view(); }
|
WebContentView& view() const { return m_current_tab->view(); }
|
||||||
|
|
||||||
|
@ -115,4 +115,5 @@ private:
|
||||||
|
|
||||||
StringView m_webdriver_content_ipc_path;
|
StringView m_webdriver_content_ipc_path;
|
||||||
WebView::EnableCallgrindProfiling m_enable_callgrind_profiling;
|
WebView::EnableCallgrindProfiling m_enable_callgrind_profiling;
|
||||||
|
WebView::UseJavaScriptBytecode m_use_javascript_bytecode;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ ConsoleWidget::ConsoleWidget()
|
||||||
{
|
{
|
||||||
setLayout(new QVBoxLayout);
|
setLayout(new QVBoxLayout);
|
||||||
|
|
||||||
m_output_view = new WebContentView({}, WebView::EnableCallgrindProfiling::No);
|
m_output_view = new WebContentView({}, WebView::EnableCallgrindProfiling::No, WebView::UseJavaScriptBytecode::No);
|
||||||
if (is_using_dark_system_theme(*this))
|
if (is_using_dark_system_theme(*this))
|
||||||
m_output_view->update_palette(WebContentView::PaletteMode::Dark);
|
m_output_view->update_palette(WebContentView::PaletteMode::Dark);
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ static QIcon render_svg_icon_with_theme_colors(QString name, QPalette const& pal
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling, WebView::UseJavaScriptBytecode use_javascript_bytecode)
|
||||||
: QWidget(window)
|
: QWidget(window)
|
||||||
, m_window(window)
|
, m_window(window)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ Tab::Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::
|
||||||
m_layout->setSpacing(0);
|
m_layout->setSpacing(0);
|
||||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
m_view = new WebContentView(webdriver_content_ipc_path, enable_callgrind_profiling);
|
m_view = new WebContentView(webdriver_content_ipc_path, enable_callgrind_profiling, use_javascript_bytecode);
|
||||||
m_toolbar = new QToolBar(this);
|
m_toolbar = new QToolBar(this);
|
||||||
m_location_edit = new LocationEdit(this);
|
m_location_edit = new LocationEdit(this);
|
||||||
m_reset_zoom_button = new QToolButton(m_toolbar);
|
m_reset_zoom_button = new QToolButton(m_toolbar);
|
||||||
|
|
|
@ -27,7 +27,7 @@ class InspectorWidget;
|
||||||
class Tab final : public QWidget {
|
class Tab final : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
|
Tab(BrowserWindow* window, StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling, WebView::UseJavaScriptBytecode);
|
||||||
virtual ~Tab() override;
|
virtual ~Tab() override;
|
||||||
|
|
||||||
WebContentView& view() { return *m_view; }
|
WebContentView& view() { return *m_view; }
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <LibCore/System.h>
|
#include <LibCore/System.h>
|
||||||
#include <LibCore/SystemServerTakeover.h>
|
#include <LibCore/SystemServerTakeover.h>
|
||||||
#include <LibIPC/ConnectionFromClient.h>
|
#include <LibIPC/ConnectionFromClient.h>
|
||||||
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
#include <LibMain/Main.h>
|
#include <LibMain/Main.h>
|
||||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||||
#include <LibWeb/Loader/ContentFilter.h>
|
#include <LibWeb/Loader/ContentFilter.h>
|
||||||
|
@ -69,12 +70,16 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
int webcontent_fd_passing_socket { -1 };
|
int webcontent_fd_passing_socket { -1 };
|
||||||
bool is_layout_test_mode = false;
|
bool is_layout_test_mode = false;
|
||||||
|
bool use_javascript_bytecode = false;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_option(webcontent_fd_passing_socket, "File descriptor of the passing socket for the WebContent connection", "webcontent-fd-passing-socket", 'c', "webcontent_fd_passing_socket");
|
args_parser.add_option(webcontent_fd_passing_socket, "File descriptor of the passing socket for the WebContent connection", "webcontent-fd-passing-socket", 'c', "webcontent_fd_passing_socket");
|
||||||
args_parser.add_option(is_layout_test_mode, "Is layout test mode", "layout-test-mode", 0);
|
args_parser.add_option(is_layout_test_mode, "Is layout test mode", "layout-test-mode", 0);
|
||||||
|
args_parser.add_option(use_javascript_bytecode, "Enable JavaScript bytecode VM", "use-bytecode", 0);
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
|
JS::Bytecode::Interpreter::set_enabled(use_javascript_bytecode);
|
||||||
|
|
||||||
VERIFY(webcontent_fd_passing_socket >= 0);
|
VERIFY(webcontent_fd_passing_socket >= 0);
|
||||||
|
|
||||||
Web::Platform::FontPlugin::install(*new Ladybird::FontPluginQt(is_layout_test_mode));
|
Web::Platform::FontPlugin::install(*new Ladybird::FontPluginQt(is_layout_test_mode));
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
bool is_using_dark_system_theme(QWidget&);
|
bool is_using_dark_system_theme(QWidget&);
|
||||||
|
|
||||||
WebContentView::WebContentView(StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
WebContentView::WebContentView(StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling enable_callgrind_profiling, WebView::UseJavaScriptBytecode use_javascript_bytecode)
|
||||||
: m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
: m_webdriver_content_ipc_path(webdriver_content_ipc_path)
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
@ -72,7 +72,7 @@ WebContentView::WebContentView(StringView webdriver_content_ipc_path, WebView::E
|
||||||
update_viewport_rect();
|
update_viewport_rect();
|
||||||
});
|
});
|
||||||
|
|
||||||
create_client(enable_callgrind_profiling);
|
create_client(enable_callgrind_profiling, use_javascript_bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebContentView::~WebContentView() = default;
|
WebContentView::~WebContentView() = default;
|
||||||
|
@ -512,12 +512,12 @@ void WebContentView::update_palette(PaletteMode mode)
|
||||||
client().async_update_system_theme(make_system_theme_from_qt_palette(*this, mode));
|
client().async_update_system_theme(make_system_theme_from_qt_palette(*this, mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContentView::create_client(WebView::EnableCallgrindProfiling enable_callgrind_profiling)
|
void WebContentView::create_client(WebView::EnableCallgrindProfiling enable_callgrind_profiling, WebView::UseJavaScriptBytecode use_javascript_bytecode)
|
||||||
{
|
{
|
||||||
m_client_state = {};
|
m_client_state = {};
|
||||||
|
|
||||||
auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
|
auto candidate_web_content_paths = get_paths_for_helper_process("WebContent"sv).release_value_but_fixme_should_propagate_errors();
|
||||||
auto new_client = launch_web_content_process(candidate_web_content_paths, enable_callgrind_profiling).release_value_but_fixme_should_propagate_errors();
|
auto new_client = launch_web_content_process(candidate_web_content_paths, enable_callgrind_profiling, WebView::IsLayoutTestMode::No, use_javascript_bytecode).release_value_but_fixme_should_propagate_errors();
|
||||||
|
|
||||||
m_client_state.client = new_client;
|
m_client_state.client = new_client;
|
||||||
m_client_state.client->on_web_content_process_crash = [this] {
|
m_client_state.client->on_web_content_process_crash = [this] {
|
||||||
|
|
|
@ -39,7 +39,7 @@ class WebContentView final
|
||||||
, public WebView::ViewImplementation {
|
, public WebView::ViewImplementation {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit WebContentView(StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling);
|
explicit WebContentView(StringView webdriver_content_ipc_path, WebView::EnableCallgrindProfiling, WebView::UseJavaScriptBytecode);
|
||||||
virtual ~WebContentView() override;
|
virtual ~WebContentView() override;
|
||||||
|
|
||||||
Function<String(const AK::URL&, Web::HTML::ActivateTab)> on_tab_open_request;
|
Function<String(const AK::URL&, Web::HTML::ActivateTab)> on_tab_open_request;
|
||||||
|
@ -96,7 +96,7 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^WebView::ViewImplementation
|
// ^WebView::ViewImplementation
|
||||||
virtual void create_client(WebView::EnableCallgrindProfiling = WebView::EnableCallgrindProfiling::No) override;
|
virtual void create_client(WebView::EnableCallgrindProfiling = WebView::EnableCallgrindProfiling::No, WebView::UseJavaScriptBytecode = WebView::UseJavaScriptBytecode::No) override;
|
||||||
virtual void update_zoom() override;
|
virtual void update_zoom() override;
|
||||||
virtual Gfx::IntRect viewport_rect() const override;
|
virtual Gfx::IntRect viewport_rect() const override;
|
||||||
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override;
|
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override;
|
||||||
|
|
|
@ -70,6 +70,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
StringView webdriver_content_ipc_path;
|
StringView webdriver_content_ipc_path;
|
||||||
bool enable_callgrind_profiling = false;
|
bool enable_callgrind_profiling = false;
|
||||||
bool enable_sql_database = false;
|
bool enable_sql_database = false;
|
||||||
|
bool use_javascript_bytecode = false;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.set_general_help("The Ladybird web browser :^)");
|
args_parser.set_general_help("The Ladybird web browser :^)");
|
||||||
|
@ -77,6 +78,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path");
|
args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path");
|
||||||
args_parser.add_option(enable_callgrind_profiling, "Enable Callgrind profiling", "enable-callgrind-profiling", 'P');
|
args_parser.add_option(enable_callgrind_profiling, "Enable Callgrind profiling", "enable-callgrind-profiling", 'P');
|
||||||
args_parser.add_option(enable_sql_database, "Enable SQL database", "enable-sql-database", 0);
|
args_parser.add_option(enable_sql_database, "Enable SQL database", "enable-sql-database", 0);
|
||||||
|
args_parser.add_option(use_javascript_bytecode, "Enable JavaScript bytecode VM", "use-bytecode", 0);
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
auto get_formatted_url = [&](StringView const& raw_url) -> ErrorOr<URL> {
|
auto get_formatted_url = [&](StringView const& raw_url) -> ErrorOr<URL> {
|
||||||
|
@ -99,7 +101,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
auto cookie_jar = database ? TRY(Browser::CookieJar::create(*database)) : Browser::CookieJar::create();
|
auto cookie_jar = database ? TRY(Browser::CookieJar::create(*database)) : Browser::CookieJar::create();
|
||||||
|
|
||||||
s_settings = adopt_own_if_nonnull(new Browser::Settings());
|
s_settings = adopt_own_if_nonnull(new Browser::Settings());
|
||||||
BrowserWindow window(cookie_jar, webdriver_content_ipc_path, enable_callgrind_profiling ? WebView::EnableCallgrindProfiling::Yes : WebView::EnableCallgrindProfiling::No);
|
BrowserWindow window(cookie_jar, webdriver_content_ipc_path, enable_callgrind_profiling ? WebView::EnableCallgrindProfiling::Yes : WebView::EnableCallgrindProfiling::No, use_javascript_bytecode ? WebView::UseJavaScriptBytecode::Yes : WebView::UseJavaScriptBytecode::No);
|
||||||
window.setWindowTitle("Ladybird");
|
window.setWindowTitle("Ladybird");
|
||||||
window.resize(800, 600);
|
window.resize(800, 600);
|
||||||
window.show();
|
window.show();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <LibJS/AST.h>
|
#include <LibJS/AST.h>
|
||||||
#include <LibJS/Bytecode/Generator.h>
|
#include <LibJS/Bytecode/Generator.h>
|
||||||
#include <LibJS/Bytecode/Interpreter.h>
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
|
#include <LibJS/Bytecode/PassManager.h>
|
||||||
#include <LibJS/Interpreter.h>
|
#include <LibJS/Interpreter.h>
|
||||||
#include <LibJS/Runtime/VM.h>
|
#include <LibJS/Runtime/VM.h>
|
||||||
#include <LibJS/Script.h>
|
#include <LibJS/Script.h>
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static DeprecatedString s_current_test = "";
|
static DeprecatedString s_current_test = "";
|
||||||
static bool s_use_bytecode = false;
|
|
||||||
static bool s_enable_bytecode_optimizations = false;
|
static bool s_enable_bytecode_optimizations = false;
|
||||||
static bool s_parse_only = false;
|
static bool s_parse_only = false;
|
||||||
static DeprecatedString s_harness_file_directory;
|
static DeprecatedString s_harness_file_directory;
|
||||||
|
@ -217,11 +216,11 @@ static Result<void, TestError> run_test(StringView source, StringView filepath,
|
||||||
return program_or_error.release_error();
|
return program_or_error.release_error();
|
||||||
|
|
||||||
OwnPtr<JS::Bytecode::Interpreter> bytecode_interpreter = nullptr;
|
OwnPtr<JS::Bytecode::Interpreter> bytecode_interpreter = nullptr;
|
||||||
if (s_use_bytecode)
|
if (JS::Bytecode::Interpreter::enabled())
|
||||||
bytecode_interpreter = make<JS::Bytecode::Interpreter>(realm);
|
bytecode_interpreter = make<JS::Bytecode::Interpreter>(realm);
|
||||||
|
|
||||||
auto run_with_interpreter = [&](ScriptOrModuleProgram& program) {
|
auto run_with_interpreter = [&](ScriptOrModuleProgram& program) {
|
||||||
if (s_use_bytecode)
|
if (JS::Bytecode::Interpreter::enabled())
|
||||||
return run_program(*bytecode_interpreter, program);
|
return run_program(*bytecode_interpreter, program);
|
||||||
return run_program(*ast_interpreter, program);
|
return run_program(*ast_interpreter, program);
|
||||||
};
|
};
|
||||||
|
@ -572,11 +571,12 @@ int main(int argc, char** argv)
|
||||||
int timeout = 10;
|
int timeout = 10;
|
||||||
bool enable_debug_printing = false;
|
bool enable_debug_printing = false;
|
||||||
bool disable_core_dumping = false;
|
bool disable_core_dumping = false;
|
||||||
|
bool use_bytecode = false;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.set_general_help("LibJS test262 runner for streaming tests");
|
args_parser.set_general_help("LibJS test262 runner for streaming tests");
|
||||||
args_parser.add_option(s_harness_file_directory, "Directory containing the harness files", "harness-location", 'l', "harness-files");
|
args_parser.add_option(s_harness_file_directory, "Directory containing the harness files", "harness-location", 'l', "harness-files");
|
||||||
args_parser.add_option(s_use_bytecode, "Use the bytecode interpreter", "use-bytecode", 'b');
|
args_parser.add_option(use_bytecode, "Use the bytecode interpreter", "use-bytecode", 'b');
|
||||||
args_parser.add_option(s_enable_bytecode_optimizations, "Enable the bytecode optimization passes", "enable-bytecode-optimizations", 'e');
|
args_parser.add_option(s_enable_bytecode_optimizations, "Enable the bytecode optimization passes", "enable-bytecode-optimizations", 'e');
|
||||||
args_parser.add_option(s_parse_only, "Only parse the files", "parse-only", 'p');
|
args_parser.add_option(s_parse_only, "Only parse the files", "parse-only", 'p');
|
||||||
args_parser.add_option(timeout, "Seconds before test should timeout", "timeout", 't', "seconds");
|
args_parser.add_option(timeout, "Seconds before test should timeout", "timeout", 't', "seconds");
|
||||||
|
@ -584,6 +584,8 @@ int main(int argc, char** argv)
|
||||||
args_parser.add_option(disable_core_dumping, "Disable core dumping", "disable-core-dump", 0);
|
args_parser.add_option(disable_core_dumping, "Disable core dumping", "disable-core-dump", 0);
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
|
JS::Bytecode::Interpreter::set_enabled(use_bytecode);
|
||||||
|
|
||||||
#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN)
|
#if !defined(AK_OS_MACOS) && !defined(AK_OS_EMSCRIPTEN)
|
||||||
if (disable_core_dumping && prctl(PR_SET_DUMPABLE, 0, 0) < 0) {
|
if (disable_core_dumping && prctl(PR_SET_DUMPABLE, 0, 0) < 0) {
|
||||||
perror("prctl(PR_SET_DUMPABLE)");
|
perror("prctl(PR_SET_DUMPABLE)");
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
#include <AK/TemporaryChange.h>
|
#include <AK/TemporaryChange.h>
|
||||||
#include <LibJS/AST.h>
|
#include <LibJS/AST.h>
|
||||||
#include <LibJS/Bytecode/BasicBlock.h>
|
#include <LibJS/Bytecode/BasicBlock.h>
|
||||||
|
#include <LibJS/Bytecode/Generator.h>
|
||||||
#include <LibJS/Bytecode/Instruction.h>
|
#include <LibJS/Bytecode/Instruction.h>
|
||||||
#include <LibJS/Bytecode/Interpreter.h>
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
#include <LibJS/Bytecode/Op.h>
|
#include <LibJS/Bytecode/Op.h>
|
||||||
|
#include <LibJS/Bytecode/PassManager.h>
|
||||||
#include <LibJS/Interpreter.h>
|
#include <LibJS/Interpreter.h>
|
||||||
#include <LibJS/Runtime/GlobalEnvironment.h>
|
#include <LibJS/Runtime/GlobalEnvironment.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
@ -18,6 +20,18 @@
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
|
static bool s_bytecode_interpreter_enabled = false;
|
||||||
|
|
||||||
|
bool Interpreter::enabled()
|
||||||
|
{
|
||||||
|
return s_bytecode_interpreter_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Interpreter::set_enabled(bool enabled)
|
||||||
|
{
|
||||||
|
s_bytecode_interpreter_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
static Interpreter* s_current;
|
static Interpreter* s_current;
|
||||||
bool g_dump_bytecode = false;
|
bool g_dump_bytecode = false;
|
||||||
|
|
||||||
|
@ -425,4 +439,14 @@ Bytecode::PassManager& Interpreter::optimization_pipeline(Interpreter::Optimizat
|
||||||
return passes;
|
return passes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Interpreter::pc() const
|
||||||
|
{
|
||||||
|
return m_pc ? m_pc->offset() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeprecatedString Interpreter::debug_position() const
|
||||||
|
{
|
||||||
|
return DeprecatedString::formatted("{}:{:2}:{:4x}", m_current_executable->name, m_current_block->name(), pc());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Generator.h"
|
|
||||||
#include "PassManager.h"
|
|
||||||
#include <LibJS/Bytecode/Label.h>
|
#include <LibJS/Bytecode/Label.h>
|
||||||
#include <LibJS/Bytecode/Register.h>
|
#include <LibJS/Bytecode/Register.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
|
@ -18,6 +16,9 @@
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
|
class InstructionStreamIterator;
|
||||||
|
class PassManager;
|
||||||
|
|
||||||
struct RegisterWindow {
|
struct RegisterWindow {
|
||||||
MarkedVector<Value> registers;
|
MarkedVector<Value> registers;
|
||||||
MarkedVector<GCPtr<Environment>> saved_lexical_environments;
|
MarkedVector<GCPtr<Environment>> saved_lexical_environments;
|
||||||
|
@ -27,6 +28,9 @@ struct RegisterWindow {
|
||||||
|
|
||||||
class Interpreter {
|
class Interpreter {
|
||||||
public:
|
public:
|
||||||
|
[[nodiscard]] static bool enabled();
|
||||||
|
static void set_enabled(bool);
|
||||||
|
|
||||||
explicit Interpreter(Realm&);
|
explicit Interpreter(Realm&);
|
||||||
~Interpreter();
|
~Interpreter();
|
||||||
|
|
||||||
|
@ -82,11 +86,8 @@ public:
|
||||||
|
|
||||||
Executable const& current_executable() { return *m_current_executable; }
|
Executable const& current_executable() { return *m_current_executable; }
|
||||||
BasicBlock const& current_block() const { return *m_current_block; }
|
BasicBlock const& current_block() const { return *m_current_block; }
|
||||||
size_t pc() const { return m_pc ? m_pc->offset() : 0; }
|
size_t pc() const;
|
||||||
DeprecatedString debug_position()
|
DeprecatedString debug_position() const;
|
||||||
{
|
|
||||||
return DeprecatedString::formatted("{}:{:2}:{:4x}", m_current_executable->name, m_current_block->name(), pc());
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class OptimizationLevel {
|
enum class OptimizationLevel {
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <LibJS/Bytecode/BasicBlock.h>
|
#include <LibJS/Bytecode/BasicBlock.h>
|
||||||
#include <LibJS/Bytecode/Generator.h>
|
#include <LibJS/Bytecode/Generator.h>
|
||||||
#include <LibJS/Bytecode/Interpreter.h>
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
|
#include <LibJS/Bytecode/PassManager.h>
|
||||||
#include <LibJS/Interpreter.h>
|
#include <LibJS/Interpreter.h>
|
||||||
#include <LibJS/Runtime/AbstractOperations.h>
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Array.h>
|
#include <LibJS/Runtime/Array.h>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <LibCore/ElapsedTimer.h>
|
#include <LibCore/ElapsedTimer.h>
|
||||||
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
#include <LibJS/Interpreter.h>
|
#include <LibJS/Interpreter.h>
|
||||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||||
|
@ -94,9 +95,13 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, JS::GCPtr<JS::En
|
||||||
auto timer = Core::ElapsedTimer::start_new();
|
auto timer = Core::ElapsedTimer::start_new();
|
||||||
|
|
||||||
// 6. Otherwise, set evaluationStatus to ScriptEvaluation(script's record).
|
// 6. Otherwise, set evaluationStatus to ScriptEvaluation(script's record).
|
||||||
auto interpreter = JS::Interpreter::create_with_existing_realm(m_script_record->realm());
|
if (JS::Bytecode::Interpreter::enabled()) {
|
||||||
|
auto interpreter = JS::Bytecode::Interpreter(m_script_record->realm());
|
||||||
evaluation_status = interpreter->run(*m_script_record, lexical_environment_override);
|
evaluation_status = interpreter.run(*m_script_record, lexical_environment_override);
|
||||||
|
} else {
|
||||||
|
auto interpreter = JS::Interpreter::create_with_existing_realm(m_script_record->realm());
|
||||||
|
evaluation_status = interpreter->run(*m_script_record, lexical_environment_override);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: If ScriptEvaluation does not complete because the user agent has aborted the running script, leave evaluationStatus as null.
|
// FIXME: If ScriptEvaluation does not complete because the user agent has aborted the running script, leave evaluationStatus as null.
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ OutOfProcessWebView::OutOfProcessWebView()
|
||||||
|
|
||||||
OutOfProcessWebView::~OutOfProcessWebView() = default;
|
OutOfProcessWebView::~OutOfProcessWebView() = default;
|
||||||
|
|
||||||
void OutOfProcessWebView::create_client(EnableCallgrindProfiling)
|
void OutOfProcessWebView::create_client(EnableCallgrindProfiling, UseJavaScriptBytecode)
|
||||||
{
|
{
|
||||||
m_client_state = {};
|
m_client_state = {};
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ private:
|
||||||
virtual void did_scroll() override;
|
virtual void did_scroll() override;
|
||||||
|
|
||||||
// ^WebView::ViewImplementation
|
// ^WebView::ViewImplementation
|
||||||
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No) override;
|
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No, UseJavaScriptBytecode = UseJavaScriptBytecode::No) override;
|
||||||
virtual void update_zoom() override;
|
virtual void update_zoom() override;
|
||||||
virtual void notify_server_did_layout(Badge<WebContentClient>, Gfx::IntSize content_size) override;
|
virtual void notify_server_did_layout(Badge<WebContentClient>, Gfx::IntSize content_size) override;
|
||||||
virtual void notify_server_did_paint(Badge<WebContentClient>, i32 bitmap_id, Gfx::IntSize) override;
|
virtual void notify_server_did_paint(Badge<WebContentClient>, i32 bitmap_id, Gfx::IntSize) override;
|
||||||
|
|
|
@ -179,7 +179,7 @@ void ViewImplementation::handle_resize()
|
||||||
|
|
||||||
#if !defined(AK_OS_SERENITY)
|
#if !defined(AK_OS_SERENITY)
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling enable_callgrind_profiling, IsLayoutTestMode is_layout_test_mode)
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling enable_callgrind_profiling, IsLayoutTestMode is_layout_test_mode, UseJavaScriptBytecode use_javascript_bytecode)
|
||||||
{
|
{
|
||||||
int socket_fds[2] {};
|
int socket_fds[2] {};
|
||||||
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
|
TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds));
|
||||||
|
@ -221,6 +221,8 @@ ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web
|
||||||
arguments.remove(0, callgrind_prefix_length);
|
arguments.remove(0, callgrind_prefix_length);
|
||||||
if (is_layout_test_mode == IsLayoutTestMode::Yes)
|
if (is_layout_test_mode == IsLayoutTestMode::Yes)
|
||||||
arguments.append("--layout-test-mode"sv);
|
arguments.append("--layout-test-mode"sv);
|
||||||
|
if (use_javascript_bytecode == UseJavaScriptBytecode::Yes)
|
||||||
|
arguments.append("--use-bytecode"sv);
|
||||||
|
|
||||||
result = Core::System::exec(arguments[0], arguments.span(), Core::System::SearchInPath::Yes);
|
result = Core::System::exec(arguments[0], arguments.span(), Core::System::SearchInPath::Yes);
|
||||||
if (!result.is_error())
|
if (!result.is_error())
|
||||||
|
|
|
@ -30,6 +30,11 @@ enum class IsLayoutTestMode {
|
||||||
Yes
|
Yes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class UseJavaScriptBytecode {
|
||||||
|
No,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
|
||||||
class ViewImplementation {
|
class ViewImplementation {
|
||||||
public:
|
public:
|
||||||
virtual ~ViewImplementation() { }
|
virtual ~ViewImplementation() { }
|
||||||
|
@ -167,10 +172,10 @@ protected:
|
||||||
void request_repaint();
|
void request_repaint();
|
||||||
void handle_resize();
|
void handle_resize();
|
||||||
|
|
||||||
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No) {};
|
virtual void create_client(EnableCallgrindProfiling = EnableCallgrindProfiling::No, UseJavaScriptBytecode = UseJavaScriptBytecode::No) { }
|
||||||
|
|
||||||
#if !defined(AK_OS_SERENITY)
|
#if !defined(AK_OS_SERENITY)
|
||||||
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling = EnableCallgrindProfiling::No, IsLayoutTestMode = IsLayoutTestMode::No);
|
ErrorOr<NonnullRefPtr<WebView::WebContentClient>> launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, EnableCallgrindProfiling = EnableCallgrindProfiling::No, IsLayoutTestMode = IsLayoutTestMode::No, UseJavaScriptBytecode = UseJavaScriptBytecode::No);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handle_web_content_process_crash();
|
void handle_web_content_process_crash();
|
||||||
|
|
|
@ -46,16 +46,17 @@
|
||||||
|
|
||||||
class HeadlessWebContentView final : public WebView::ViewImplementation {
|
class HeadlessWebContentView final : public WebView::ViewImplementation {
|
||||||
public:
|
public:
|
||||||
static ErrorOr<NonnullOwnPtr<HeadlessWebContentView>> create(Core::AnonymousBuffer theme, Gfx::IntSize const& window_size, StringView web_driver_ipc_path, WebView::IsLayoutTestMode is_layout_test_mode = WebView::IsLayoutTestMode::No)
|
static ErrorOr<NonnullOwnPtr<HeadlessWebContentView>> create(Core::AnonymousBuffer theme, Gfx::IntSize const& window_size, StringView web_driver_ipc_path, WebView::IsLayoutTestMode is_layout_test_mode = WebView::IsLayoutTestMode::No, WebView::UseJavaScriptBytecode use_javascript_bytecode = WebView::UseJavaScriptBytecode::No)
|
||||||
{
|
{
|
||||||
auto view = TRY(adopt_nonnull_own_or_enomem(new (nothrow) HeadlessWebContentView()));
|
auto view = TRY(adopt_nonnull_own_or_enomem(new (nothrow) HeadlessWebContentView()));
|
||||||
|
|
||||||
#if defined(AK_OS_SERENITY)
|
#if defined(AK_OS_SERENITY)
|
||||||
view->m_client_state.client = TRY(WebView::WebContentClient::try_create(*view));
|
view->m_client_state.client = TRY(WebView::WebContentClient::try_create(*view));
|
||||||
(void)is_layout_test_mode;
|
(void)is_layout_test_mode;
|
||||||
|
(void)use_javascript_bytecode;
|
||||||
#else
|
#else
|
||||||
auto candidate_web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
|
auto candidate_web_content_paths = TRY(get_paths_for_helper_process("WebContent"sv));
|
||||||
view->m_client_state.client = TRY(view->launch_web_content_process(candidate_web_content_paths, WebView::EnableCallgrindProfiling::No, is_layout_test_mode));
|
view->m_client_state.client = TRY(view->launch_web_content_process(candidate_web_content_paths, WebView::EnableCallgrindProfiling::No, is_layout_test_mode, use_javascript_bytecode));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
view->client().async_update_system_theme(move(theme));
|
view->client().async_update_system_theme(move(theme));
|
||||||
|
@ -123,7 +124,7 @@ private:
|
||||||
|
|
||||||
void notify_server_did_finish_handling_input_event(bool) override { }
|
void notify_server_did_finish_handling_input_event(bool) override { }
|
||||||
void update_zoom() override { }
|
void update_zoom() override { }
|
||||||
void create_client(WebView::EnableCallgrindProfiling) override { }
|
void create_client(WebView::EnableCallgrindProfiling, WebView::UseJavaScriptBytecode) override { }
|
||||||
|
|
||||||
virtual Gfx::IntRect viewport_rect() const override { return m_viewport_rect; }
|
virtual Gfx::IntRect viewport_rect() const override { return m_viewport_rect; }
|
||||||
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override { return widget_position; }
|
virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const override { return widget_position; }
|
||||||
|
@ -396,6 +397,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
bool dump_layout_tree = false;
|
bool dump_layout_tree = false;
|
||||||
bool dump_text = false;
|
bool dump_text = false;
|
||||||
bool is_layout_test_mode = false;
|
bool is_layout_test_mode = false;
|
||||||
|
bool use_javascript_bytecode = false;
|
||||||
StringView test_root_path;
|
StringView test_root_path;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
|
@ -407,6 +409,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
args_parser.add_option(resources_folder, "Path of the base resources folder (defaults to /res)", "resources", 'r', "resources-root-path");
|
args_parser.add_option(resources_folder, "Path of the base resources folder (defaults to /res)", "resources", 'r', "resources-root-path");
|
||||||
args_parser.add_option(web_driver_ipc_path, "Path to the WebDriver IPC socket", "webdriver-ipc-path", 0, "path");
|
args_parser.add_option(web_driver_ipc_path, "Path to the WebDriver IPC socket", "webdriver-ipc-path", 0, "path");
|
||||||
args_parser.add_option(is_layout_test_mode, "Enable layout test mode", "layout-test-mode", 0);
|
args_parser.add_option(is_layout_test_mode, "Enable layout test mode", "layout-test-mode", 0);
|
||||||
|
args_parser.add_option(use_javascript_bytecode, "Enable JavaScript bytecode VM", "use-bytecode", 0);
|
||||||
args_parser.add_positional_argument(url, "URL to open", "url", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(url, "URL to open", "url", Core::ArgsParser::Required::No);
|
||||||
args_parser.parse(arguments);
|
args_parser.parse(arguments);
|
||||||
|
|
||||||
|
@ -428,7 +431,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
is_layout_test_mode = true;
|
is_layout_test_mode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto view = TRY(HeadlessWebContentView::create(move(theme), window_size, web_driver_ipc_path, is_layout_test_mode ? WebView::IsLayoutTestMode::Yes : WebView::IsLayoutTestMode::No));
|
auto view = TRY(HeadlessWebContentView::create(move(theme), window_size, web_driver_ipc_path, is_layout_test_mode ? WebView::IsLayoutTestMode::Yes : WebView::IsLayoutTestMode::No, use_javascript_bytecode ? WebView::UseJavaScriptBytecode::Yes : WebView::UseJavaScriptBytecode::No));
|
||||||
RefPtr<Core::Timer> timer;
|
RefPtr<Core::Timer> timer;
|
||||||
|
|
||||||
if (!test_root_path.is_empty()) {
|
if (!test_root_path.is_empty()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue