mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-02 16:33:13 +00:00
By doing that all instructions required for instantiation are emitted once in compilation and then reused for subsequent calls, instead of running generic instantiation process for each call.
205 lines
6.8 KiB
C++
205 lines
6.8 KiB
C++
/*
|
|
* Copyright (c) 2021-2024, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Forward.h>
|
|
#include <AK/Function.h>
|
|
#include <AK/Span.h>
|
|
#include <LibJS/Bytecode/Executable.h>
|
|
#include <LibJS/Forward.h>
|
|
#include <LibJS/SourceRange.h>
|
|
|
|
#define ENUMERATE_BYTECODE_OPS(O) \
|
|
O(Add) \
|
|
O(ArrayAppend) \
|
|
O(AsyncIteratorClose) \
|
|
O(Await) \
|
|
O(BitwiseAnd) \
|
|
O(BitwiseNot) \
|
|
O(BitwiseOr) \
|
|
O(BitwiseXor) \
|
|
O(BlockDeclarationInstantiation) \
|
|
O(Call) \
|
|
O(CallWithArgumentArray) \
|
|
O(Catch) \
|
|
O(ConcatString) \
|
|
O(ContinuePendingUnwind) \
|
|
O(CopyObjectExcludingProperties) \
|
|
O(CreateLexicalEnvironment) \
|
|
O(CreateVariableEnvironment) \
|
|
O(CreateVariable) \
|
|
O(CreateRestParams) \
|
|
O(CreateArguments) \
|
|
O(Decrement) \
|
|
O(DeleteById) \
|
|
O(DeleteByIdWithThis) \
|
|
O(DeleteByValue) \
|
|
O(DeleteByValueWithThis) \
|
|
O(DeleteVariable) \
|
|
O(Div) \
|
|
O(Dump) \
|
|
O(End) \
|
|
O(EnterObjectEnvironment) \
|
|
O(EnterUnwindContext) \
|
|
O(Exp) \
|
|
O(GetArgument) \
|
|
O(GetById) \
|
|
O(GetByIdWithThis) \
|
|
O(GetByValue) \
|
|
O(GetByValueWithThis) \
|
|
O(GetCalleeAndThisFromEnvironment) \
|
|
O(GetIterator) \
|
|
O(GetMethod) \
|
|
O(GetNewTarget) \
|
|
O(GetNextMethodFromIteratorRecord) \
|
|
O(GetObjectFromIteratorRecord) \
|
|
O(GetImportMeta) \
|
|
O(GetObjectPropertyIterator) \
|
|
O(GetPrivateById) \
|
|
O(GetVariable) \
|
|
O(GetGlobal) \
|
|
O(GreaterThan) \
|
|
O(GreaterThanEquals) \
|
|
O(HasPrivateId) \
|
|
O(ImportCall) \
|
|
O(In) \
|
|
O(Increment) \
|
|
O(InstanceOf) \
|
|
O(IteratorClose) \
|
|
O(IteratorNext) \
|
|
O(IteratorToArray) \
|
|
O(Jump) \
|
|
O(JumpFalse) \
|
|
O(JumpGreaterThan) \
|
|
O(JumpGreaterThanEquals) \
|
|
O(JumpIf) \
|
|
O(JumpLessThan) \
|
|
O(JumpLessThanEquals) \
|
|
O(JumpLooselyEquals) \
|
|
O(JumpLooselyInequals) \
|
|
O(JumpNullish) \
|
|
O(JumpStrictlyEquals) \
|
|
O(JumpStrictlyInequals) \
|
|
O(JumpTrue) \
|
|
O(JumpUndefined) \
|
|
O(LeaveFinally) \
|
|
O(LeaveLexicalEnvironment) \
|
|
O(LeaveUnwindContext) \
|
|
O(LeftShift) \
|
|
O(LessThan) \
|
|
O(LessThanEquals) \
|
|
O(LooselyEquals) \
|
|
O(LooselyInequals) \
|
|
O(Mod) \
|
|
O(Mov) \
|
|
O(Mul) \
|
|
O(NewArray) \
|
|
O(NewClass) \
|
|
O(NewFunction) \
|
|
O(NewObject) \
|
|
O(NewPrimitiveArray) \
|
|
O(NewRegExp) \
|
|
O(NewTypeError) \
|
|
O(Not) \
|
|
O(PostfixDecrement) \
|
|
O(PostfixIncrement) \
|
|
O(PutById) \
|
|
O(PutByIdWithThis) \
|
|
O(PutByValue) \
|
|
O(PutByValueWithThis) \
|
|
O(PutPrivateById) \
|
|
O(ResolveThisBinding) \
|
|
O(ResolveSuperBase) \
|
|
O(RestoreScheduledJump) \
|
|
O(Return) \
|
|
O(RightShift) \
|
|
O(ScheduleJump) \
|
|
O(SetArgument) \
|
|
O(SetVariable) \
|
|
O(SetLocal) \
|
|
O(StrictlyEquals) \
|
|
O(StrictlyInequals) \
|
|
O(Sub) \
|
|
O(SuperCallWithArgumentArray) \
|
|
O(Throw) \
|
|
O(ThrowIfNotObject) \
|
|
O(ThrowIfNullish) \
|
|
O(ThrowIfTDZ) \
|
|
O(Typeof) \
|
|
O(TypeofVariable) \
|
|
O(UnaryMinus) \
|
|
O(UnaryPlus) \
|
|
O(UnsignedRightShift) \
|
|
O(Yield)
|
|
|
|
namespace JS::Bytecode {
|
|
|
|
class alignas(void*) Instruction {
|
|
public:
|
|
constexpr static bool IsTerminator = false;
|
|
static constexpr bool IsVariableLength = false;
|
|
|
|
enum class Type {
|
|
#define __BYTECODE_OP(op) \
|
|
op,
|
|
ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
|
|
#undef __BYTECODE_OP
|
|
};
|
|
|
|
Type type() const { return m_type; }
|
|
size_t length() const;
|
|
ByteString to_byte_string(Bytecode::Executable const&) const;
|
|
void visit_labels(Function<void(Label&)> visitor);
|
|
static void destroy(Instruction&);
|
|
|
|
protected:
|
|
explicit Instruction(Type type)
|
|
: m_type(type)
|
|
{
|
|
}
|
|
|
|
void visit_labels_impl(Function<void(Label&)>) { }
|
|
|
|
private:
|
|
Type m_type {};
|
|
};
|
|
|
|
class InstructionStreamIterator {
|
|
public:
|
|
InstructionStreamIterator(ReadonlyBytes bytes, Executable const* executable = nullptr, size_t offset = 0)
|
|
: m_begin(bytes.data())
|
|
, m_end(bytes.data() + bytes.size())
|
|
, m_ptr(bytes.data() + offset)
|
|
, m_executable(executable)
|
|
{
|
|
}
|
|
|
|
size_t offset() const { return m_ptr - m_begin; }
|
|
bool at_end() const { return m_ptr >= m_end; }
|
|
|
|
Instruction const& operator*() const { return dereference(); }
|
|
|
|
ALWAYS_INLINE void operator++()
|
|
{
|
|
m_ptr += dereference().length();
|
|
}
|
|
|
|
UnrealizedSourceRange source_range() const;
|
|
RefPtr<SourceCode> source_code() const;
|
|
|
|
Executable const* executable() const { return m_executable; }
|
|
|
|
private:
|
|
Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); }
|
|
|
|
u8 const* m_begin { nullptr };
|
|
u8 const* m_end { nullptr };
|
|
u8 const* m_ptr { nullptr };
|
|
GCPtr<Executable const> m_executable;
|
|
};
|
|
|
|
}
|