Explorar o código

LibJS/Bytecode: Begin moving shareable (JIT+Interpreter) stuff somewhere

There are a lot of native C++ functions that will be used by both the
bytecode interpreter and jitted code. Let's put them in their own file
instead of having them in Interpreter.cpp.
Andreas Kling hai 1 ano
pai
achega
8905682a16

+ 63 - 0
Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Bytecode/CommonImplementations.h>
+#include <LibJS/Bytecode/Interpreter.h>
+
+namespace JS::Bytecode {
+
+ThrowCompletionOr<NonnullGCPtr<Object>> base_object_for_get(Bytecode::Interpreter& interpreter, Value base_value)
+{
+    auto& vm = interpreter.vm();
+    if (base_value.is_object())
+        return base_value.as_object();
+
+    // OPTIMIZATION: For various primitives we can avoid actually creating a new object for them.
+    if (base_value.is_string())
+        return vm.current_realm()->intrinsics().string_prototype();
+    if (base_value.is_number())
+        return vm.current_realm()->intrinsics().number_prototype();
+    if (base_value.is_boolean())
+        return vm.current_realm()->intrinsics().boolean_prototype();
+
+    return base_value.to_object(vm);
+}
+
+ThrowCompletionOr<Value> get_by_id(Bytecode::Interpreter& interpreter, IdentifierTableIndex property, Value base_value, Value this_value, u32 cache_index)
+{
+    auto& vm = interpreter.vm();
+    auto const& name = interpreter.current_executable().get_identifier(property);
+    auto& cache = interpreter.current_executable().property_lookup_caches[cache_index];
+
+    if (base_value.is_string()) {
+        auto string_value = TRY(base_value.as_string().get(vm, name));
+        if (string_value.has_value())
+            return *string_value;
+    }
+
+    auto base_obj = TRY(base_object_for_get(interpreter, base_value));
+
+    // OPTIMIZATION: If the shape of the object hasn't changed, we can use the cached property offset.
+    // NOTE: Unique shapes don't change identity, so we compare their serial numbers instead.
+    auto& shape = base_obj->shape();
+    if (&shape == cache.shape
+        && (!shape.is_unique() || shape.unique_shape_serial_number() == cache.unique_shape_serial_number)) {
+        return base_obj->get_direct(cache.property_offset.value());
+    }
+
+    CacheablePropertyMetadata cacheable_metadata;
+    auto value = TRY(base_obj->internal_get(name, this_value, &cacheable_metadata));
+
+    if (cacheable_metadata.type == CacheablePropertyMetadata::Type::OwnProperty) {
+        cache.shape = shape;
+        cache.property_offset = cacheable_metadata.property_offset.value();
+        cache.unique_shape_serial_number = shape.unique_shape_serial_number();
+    }
+
+    return value;
+}
+
+}

+ 17 - 0
Userland/Libraries/LibJS/Bytecode/CommonImplementations.h

@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Bytecode/IdentifierTable.h>
+#include <LibJS/Runtime/Completion.h>
+
+namespace JS::Bytecode {
+
+ThrowCompletionOr<NonnullGCPtr<Object>> base_object_for_get(Bytecode::Interpreter&, Value base_value);
+ThrowCompletionOr<Value> get_by_id(Bytecode::Interpreter&, IdentifierTableIndex, Value base_value, Value this_value, u32 cache_index);
+
+}

+ 5 - 56
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -9,6 +9,7 @@
 #include <AK/TemporaryChange.h>
 #include <LibJS/AST.h>
 #include <LibJS/Bytecode/BasicBlock.h>
+#include <LibJS/Bytecode/CommonImplementations.h>
 #include <LibJS/Bytecode/Generator.h>
 #include <LibJS/Bytecode/Instruction.h>
 #include <LibJS/Bytecode/Interpreter.h>
@@ -1032,71 +1033,19 @@ ThrowCompletionOr<void> SetLocal::execute_impl(Bytecode::Interpreter&) const
     __builtin_unreachable();
 }
 
-static ThrowCompletionOr<NonnullGCPtr<Object>> base_object_for_get(Bytecode::Interpreter& interpreter, Value base_value)
-{
-    auto& vm = interpreter.vm();
-    if (base_value.is_object())
-        return base_value.as_object();
-
-    // OPTIMIZATION: For various primitives we can avoid actually creating a new object for them.
-    if (base_value.is_string())
-        return vm.current_realm()->intrinsics().string_prototype();
-    if (base_value.is_number())
-        return vm.current_realm()->intrinsics().number_prototype();
-    if (base_value.is_boolean())
-        return vm.current_realm()->intrinsics().boolean_prototype();
-
-    return base_value.to_object(vm);
-}
-
-static ThrowCompletionOr<void> get_by_id(Bytecode::Interpreter& interpreter, IdentifierTableIndex property, Value base_value, Value this_value, u32 cache_index)
-{
-    auto& vm = interpreter.vm();
-    auto const& name = interpreter.current_executable().get_identifier(property);
-    auto& cache = interpreter.current_executable().property_lookup_caches[cache_index];
-
-    if (base_value.is_string()) {
-        auto string_value = TRY(base_value.as_string().get(vm, name));
-        if (string_value.has_value()) {
-            interpreter.accumulator() = *string_value;
-            return {};
-        }
-    }
-
-    auto base_obj = TRY(base_object_for_get(interpreter, base_value));
-
-    // OPTIMIZATION: If the shape of the object hasn't changed, we can use the cached property offset.
-    // NOTE: Unique shapes don't change identity, so we compare their serial numbers instead.
-    auto& shape = base_obj->shape();
-    if (&shape == cache.shape
-        && (!shape.is_unique() || shape.unique_shape_serial_number() == cache.unique_shape_serial_number)) {
-        interpreter.accumulator() = base_obj->get_direct(cache.property_offset.value());
-        return {};
-    }
-
-    CacheablePropertyMetadata cacheable_metadata;
-    interpreter.accumulator() = TRY(base_obj->internal_get(name, this_value, &cacheable_metadata));
-
-    if (cacheable_metadata.type == CacheablePropertyMetadata::Type::OwnProperty) {
-        cache.shape = shape;
-        cache.property_offset = cacheable_metadata.property_offset.value();
-        cache.unique_shape_serial_number = shape.unique_shape_serial_number();
-    }
-
-    return {};
-}
-
 ThrowCompletionOr<void> GetById::execute_impl(Bytecode::Interpreter& interpreter) const
 {
     auto base_value = interpreter.accumulator();
-    return get_by_id(interpreter, m_property, base_value, base_value, m_cache_index);
+    interpreter.accumulator() = TRY(get_by_id(interpreter, m_property, base_value, base_value, m_cache_index));
+    return {};
 }
 
 ThrowCompletionOr<void> GetByIdWithThis::execute_impl(Bytecode::Interpreter& interpreter) const
 {
     auto base_value = interpreter.accumulator();
     auto this_value = interpreter.reg(m_this_value);
-    return get_by_id(interpreter, m_property, base_value, this_value, m_cache_index);
+    interpreter.accumulator() = TRY(get_by_id(interpreter, m_property, base_value, this_value, m_cache_index));
+    return {};
 }
 
 ThrowCompletionOr<void> GetPrivateById::execute_impl(Bytecode::Interpreter& interpreter) const

+ 1 - 0
Userland/Libraries/LibJS/CMakeLists.txt

@@ -3,6 +3,7 @@ set(SOURCES
     Bytecode/ASTCodegen.cpp
     Bytecode/BasicBlock.cpp
     Bytecode/CodeGenerationError.cpp
+    Bytecode/CommonImplementations.cpp
     Bytecode/Executable.cpp
     Bytecode/Generator.cpp
     Bytecode/IdentifierTable.cpp