LibJS: Make bytecode generation infallible
Remove CodeGenerationError and make all bytecode generation functions return their results directly instead of wrapping them in CodeGenerationErrorOr. For the few remaining sites where codegen encounters an unimplemented or unexpected AST node, we now use a new emit_todo() helper that emits a NewTypeError + Throw sequence at compile time (preserving the runtime behavior) and then switches to a dead basic block so subsequent codegen for the same function can continue without issue. This allows us to remove error handling from all callers of the bytecode compiler, simplifying the code significantly.
This commit is contained in:
parent
20f50d1f71
commit
7281091fdb
23 changed files with 469 additions and 556 deletions
|
|
@ -16,7 +16,6 @@
|
|||
#include <AK/Utf16String.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibJS/Bytecode/CodeGenerationError.h>
|
||||
#include <LibJS/Bytecode/Executable.h>
|
||||
#include <LibJS/Bytecode/IdentifierTable.h>
|
||||
#include <LibJS/Bytecode/Op.h>
|
||||
|
|
@ -65,7 +64,7 @@ public:
|
|||
// NOTE: This is here to stop ASAN complaining about mismatch between new/delete sizes in ASTNodeWithTailArray.
|
||||
void operator delete(void* ptr) { ::operator delete(ptr); }
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
virtual void dump(ASTDumpState const& state = {}) const;
|
||||
|
||||
[[nodiscard]] SourceRange const& source_range() const { return m_source_range; }
|
||||
|
|
@ -185,8 +184,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
|
||||
FlyString const& label() const { return m_label; }
|
||||
FlyString& label() { return m_label; }
|
||||
|
|
@ -214,7 +213,7 @@ class IterationStatement : public Statement {
|
|||
public:
|
||||
using Statement::Statement;
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const = 0;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const = 0;
|
||||
|
||||
private:
|
||||
virtual bool is_iteration_statement() const final { return true; }
|
||||
|
|
@ -226,7 +225,7 @@ public:
|
|||
: Statement(move(source_range))
|
||||
{
|
||||
}
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
};
|
||||
|
||||
class ErrorStatement final : public Statement {
|
||||
|
|
@ -246,7 +245,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Expression const& expression() const { return m_expression; }
|
||||
|
||||
|
|
@ -326,7 +325,7 @@ public:
|
|||
|
||||
Vector<NonnullRefPtr<Statement const>> const& children() const { return m_children; }
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
void add_var_scoped_declaration(NonnullRefPtr<Declaration const> variables);
|
||||
void add_lexical_declaration(NonnullRefPtr<Declaration const> variables);
|
||||
|
|
@ -414,7 +413,7 @@ public:
|
|||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
bool has_bound_name(Utf16FlyString const& name) const;
|
||||
Vector<ImportEntry> const& entries() const { return m_entries; }
|
||||
|
|
@ -506,7 +505,7 @@ public:
|
|||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
bool has_export(Utf16FlyString const& export_name) const;
|
||||
|
||||
|
|
@ -670,7 +669,7 @@ struct BindingPattern : RefCounted<BindingPattern> {
|
|||
|
||||
bool contains_expression() const;
|
||||
|
||||
Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&, Bytecode::Op::BindingInitializationMode initialization_mode, Bytecode::ScopedOperand const& object) const;
|
||||
void generate_bytecode(Bytecode::Generator&, Bytecode::Op::BindingInitializationMode initialization_mode, Bytecode::ScopedOperand const& object) const;
|
||||
|
||||
Vector<BindingEntry> entries;
|
||||
Kind kind { Kind::Object };
|
||||
|
|
@ -731,7 +730,7 @@ public:
|
|||
void set_is_inside_scope_with_eval() { m_is_inside_scope_with_eval = true; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
virtual bool is_identifier() const override { return true; }
|
||||
|
|
@ -856,7 +855,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override;
|
||||
|
||||
|
|
@ -886,8 +885,8 @@ public:
|
|||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::ScopedOperand> preferred_dst = {}, bool is_method = false) const;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Optional<Bytecode::ScopedOperand> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::ScopedOperand> preferred_dst = {}, bool is_method = false) const;
|
||||
|
||||
bool has_name() const override { return !name().is_empty(); }
|
||||
|
||||
|
|
@ -918,7 +917,7 @@ public:
|
|||
bool is_yield_from() const { return m_is_yield_from; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
RefPtr<Expression const> m_argument;
|
||||
|
|
@ -934,7 +933,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_argument;
|
||||
|
|
@ -951,7 +950,7 @@ public:
|
|||
Expression const* argument() const { return m_argument; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
RefPtr<Expression const> m_argument;
|
||||
|
|
@ -972,7 +971,7 @@ public:
|
|||
Statement const* alternate() const { return m_alternate; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_predicate;
|
||||
|
|
@ -993,8 +992,8 @@ public:
|
|||
Statement const& body() const { return *m_body; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_test;
|
||||
|
|
@ -1014,8 +1013,8 @@ public:
|
|||
Statement const& body() const { return *m_body; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_test;
|
||||
|
|
@ -1035,7 +1034,7 @@ public:
|
|||
Statement const& body() const { return *m_body; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_object;
|
||||
|
|
@ -1059,8 +1058,8 @@ public:
|
|||
Statement const& body() const { return *m_body; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
RefPtr<ASTNode const> m_init;
|
||||
|
|
@ -1083,8 +1082,8 @@ public:
|
|||
Expression const& rhs() const { return *m_rhs; }
|
||||
Statement const& body() const { return *m_body; }
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
|
||||
private:
|
||||
|
|
@ -1107,8 +1106,8 @@ public:
|
|||
Expression const& rhs() const { return *m_rhs; }
|
||||
Statement const& body() const { return *m_body; }
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
|
||||
private:
|
||||
|
|
@ -1127,8 +1126,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
|
||||
private:
|
||||
|
|
@ -1173,7 +1172,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
BinaryOp m_op;
|
||||
|
|
@ -1202,7 +1201,7 @@ public:
|
|||
NonnullRefPtr<Expression const> rhs() const { return m_rhs; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
LogicalOp m_op;
|
||||
|
|
@ -1233,7 +1232,7 @@ public:
|
|||
auto const& op() const { return m_op; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
UnaryOp m_op;
|
||||
|
|
@ -1250,7 +1249,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
Vector<NonnullRefPtr<Expression const>> m_expressions;
|
||||
|
|
@ -1279,7 +1278,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
virtual Value value() const override { return Value(m_value); }
|
||||
|
||||
|
|
@ -1298,7 +1297,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
virtual Value value() const override { return m_value; }
|
||||
|
||||
|
|
@ -1319,7 +1318,7 @@ public:
|
|||
ByteString const& raw_value() const { return m_value; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
ByteString m_value;
|
||||
|
|
@ -1334,7 +1333,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Utf16String const& value() const { return m_value; }
|
||||
|
||||
|
|
@ -1352,7 +1351,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
virtual Value value() const override { return js_null(); }
|
||||
|
||||
|
|
@ -1373,7 +1372,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
regex::Parser::Result const& parsed_regex() const { return m_parsed_regex; }
|
||||
String const& parsed_pattern() const { return m_parsed_pattern; }
|
||||
|
|
@ -1510,7 +1509,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
virtual bool is_super_expression() const override { return true; }
|
||||
};
|
||||
|
|
@ -1533,8 +1532,8 @@ public:
|
|||
RefPtr<FunctionExpression const> constructor() const { return m_constructor; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Optional<Bytecode::ScopedOperand> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
|
||||
bool has_name() const { return m_name; }
|
||||
|
||||
|
|
@ -1559,7 +1558,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
ThrowCompletionOr<void> for_each_bound_identifier(ThrowCompletionOrVoidCallback<Identifier const&>&&) const override;
|
||||
|
||||
|
|
@ -1587,7 +1586,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const&) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_expression;
|
||||
|
|
@ -1603,7 +1602,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
virtual bool is_spread_expression() const override { return true; }
|
||||
|
|
@ -1618,7 +1617,7 @@ public:
|
|||
{
|
||||
}
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
};
|
||||
|
||||
struct CallExpressionArgument {
|
||||
|
|
@ -1648,7 +1647,7 @@ public:
|
|||
static NonnullRefPtr<CallExpression> create(SourceRange, NonnullRefPtr<Expression const> callee, ReadonlySpan<Argument> arguments, InvocationStyleEnum invocation_style, InsideParenthesesEnum inside_parens);
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Expression const& callee() const { return m_callee; }
|
||||
|
||||
|
|
@ -1716,7 +1715,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
Vector<CallExpression::Argument> const m_arguments;
|
||||
|
|
@ -1761,7 +1760,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
AssignmentOp m_op;
|
||||
|
|
@ -1785,7 +1784,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
virtual bool is_update_expression() const override { return true; }
|
||||
|
|
@ -1839,7 +1838,7 @@ public:
|
|||
DeclarationKind declaration_kind() const { return m_declaration_kind; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Vector<NonnullRefPtr<VariableDeclarator const>> const& declarations() const { return m_declarations; }
|
||||
|
||||
|
|
@ -1925,7 +1924,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
virtual bool is_object_expression() const override { return true; }
|
||||
|
|
@ -1944,7 +1943,7 @@ public:
|
|||
Vector<RefPtr<Expression const>> const& elements() const { return m_elements; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
virtual bool is_array_expression() const override { return true; }
|
||||
|
|
@ -1968,7 +1967,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Vector<NonnullRefPtr<Expression const>> const& expressions() const { return m_expressions; }
|
||||
Vector<NonnullRefPtr<StringLiteral const>> const& raw_strings() const { return m_raw_strings; }
|
||||
|
|
@ -1988,7 +1987,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> const m_tag;
|
||||
|
|
@ -2006,7 +2005,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
bool is_computed() const { return m_computed; }
|
||||
Expression const& object() const { return *m_object; }
|
||||
|
|
@ -2058,7 +2057,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Expression const& base() const { return *m_base; }
|
||||
Vector<Reference> const& references() const { return m_references; }
|
||||
|
|
@ -2084,7 +2083,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
|
|
@ -2100,7 +2099,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
virtual bool is_import_call() const override { return true; }
|
||||
|
|
@ -2120,7 +2119,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_test;
|
||||
|
|
@ -2176,7 +2175,7 @@ public:
|
|||
BlockStatement const* finalizer() const { return m_finalizer; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<BlockStatement const> m_block;
|
||||
|
|
@ -2195,7 +2194,7 @@ public:
|
|||
Expression const& argument() const { return m_argument; }
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Expression const> m_argument;
|
||||
|
|
@ -2226,8 +2225,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void dump(ASTDumpState const& state = {}) const override;
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
Optional<Bytecode::ScopedOperand> generate_labelled_evaluation(Bytecode::Generator&, Vector<FlyString> const&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const;
|
||||
|
||||
void add_case(NonnullRefPtr<SwitchCase const> switch_case) { m_cases.append(move(switch_case)); }
|
||||
|
||||
|
|
@ -2245,7 +2244,7 @@ public:
|
|||
}
|
||||
|
||||
Optional<FlyString> const& target_label() const { return m_target_label; }
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
private:
|
||||
Optional<FlyString> m_target_label;
|
||||
|
|
@ -2259,7 +2258,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
|
||||
Optional<FlyString> const& target_label() const { return m_target_label; }
|
||||
|
||||
|
|
@ -2274,7 +2273,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual Bytecode::CodeGenerationErrorOr<Optional<Bytecode::ScopedOperand>> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
virtual Optional<Bytecode::ScopedOperand> generate_bytecode(Bytecode::Generator&, Optional<Bytecode::ScopedOperand> preferred_dst = {}) const override;
|
||||
};
|
||||
|
||||
class SyntheticReferenceExpression final : public Expression {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Bytecode/CodeGenerationError.h>
|
||||
|
||||
namespace JS::Bytecode {
|
||||
|
||||
ErrorOr<String> CodeGenerationError::to_string() const
|
||||
{
|
||||
return String::formatted("CodeGenerationError in {}: {}", failing_node ? failing_node->class_name() : "<unknown node>", reason_literal);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibJS/Forward.h>
|
||||
|
||||
namespace JS::Bytecode {
|
||||
|
||||
struct CodeGenerationError {
|
||||
ASTNode const* failing_node { nullptr };
|
||||
StringView reason_literal;
|
||||
|
||||
ErrorOr<String> to_string() const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using CodeGenerationErrorOr = ErrorOr<T, CodeGenerationError>;
|
||||
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ u32 Generator::register_class_blueprint(ClassBlueprint blueprint)
|
|||
return index;
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(SharedFunctionInstanceData const& shared_function_instance_data)
|
||||
void Generator::emit_function_declaration_instantiation(SharedFunctionInstanceData const& shared_function_instance_data)
|
||||
{
|
||||
if (shared_function_instance_data.m_has_parameter_expressions) {
|
||||
bool has_non_local_parameters = false;
|
||||
|
|
@ -114,7 +114,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(S
|
|||
Label { if_not_undefined_block });
|
||||
|
||||
switch_to_basic_block(if_undefined_block);
|
||||
auto operand = TRY(parameter.default_value->generate_bytecode(*this));
|
||||
auto operand = parameter.default_value->generate_bytecode(*this);
|
||||
emit<Op::Mov>(Operand { Operand::Type::Argument, param_index }, *operand);
|
||||
emit<Op::Jump>(Label { if_not_undefined_block });
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(S
|
|||
} else if (auto const* binding_pattern = parameter.binding.get_pointer<NonnullRefPtr<BindingPattern const>>(); binding_pattern) {
|
||||
ScopedOperand argument { *this, Operand { Operand::Type::Argument, param_index } };
|
||||
auto init_mode = shared_function_instance_data.m_has_duplicates ? Op::BindingInitializationMode::Set : Bytecode::Op::BindingInitializationMode::Initialize;
|
||||
TRY((*binding_pattern)->generate_bytecode(*this, init_mode, argument));
|
||||
(*binding_pattern)->generate_bytecode(*this, init_mode, argument);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,11 +226,9 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(S
|
|||
emit<Op::SetVariableBinding>(intern_identifier(function_to_initialize.name), function);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GC::Ptr<SharedFunctionInstanceData const> shared_function_instance_data, MustPropagateCompletion must_propagate_completion, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled, Vector<LocalVariable> local_variable_names)
|
||||
GC::Ref<Executable> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GC::Ptr<SharedFunctionInstanceData const> shared_function_instance_data, MustPropagateCompletion must_propagate_completion, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled, Vector<LocalVariable> local_variable_names)
|
||||
{
|
||||
Generator generator(vm, shared_function_instance_data, must_propagate_completion, builtin_abstract_operations_enabled);
|
||||
|
||||
|
|
@ -260,7 +258,7 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
generator.ensure_lexical_environment_register_initialized();
|
||||
|
||||
if (shared_function_instance_data)
|
||||
TRY(generator.emit_function_declaration_instantiation(*shared_function_instance_data));
|
||||
generator.emit_function_declaration_instantiation(*shared_function_instance_data);
|
||||
|
||||
if (generator.is_in_generator_function()) {
|
||||
// Immediately yield with no value.
|
||||
|
|
@ -271,7 +269,7 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
// will not enter the generator from the SuspendedStart state and immediately completes the generator.
|
||||
}
|
||||
|
||||
auto last_value = TRY(node.generate_bytecode(generator));
|
||||
auto last_value = node.generate_bytecode(generator);
|
||||
|
||||
if (!generator.current_block().is_terminated() && last_value.has_value()) {
|
||||
generator.emit<Bytecode::Op::End>(last_value.value());
|
||||
|
|
@ -542,7 +540,7 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
return executable;
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<GC::Ref<Executable>> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind)
|
||||
GC::Ref<Executable> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind)
|
||||
{
|
||||
Vector<LocalVariable> local_variable_names;
|
||||
if (is<ScopeNode>(node))
|
||||
|
|
@ -550,7 +548,7 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::generate_from_ast_node(VM&
|
|||
return compile(vm, node, enclosing_function_kind, {}, MustPropagateCompletion::Yes, BuiltinAbstractOperationsEnabled::No, move(local_variable_names));
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<GC::Ref<Executable>> Generator::generate_from_function(VM& vm, GC::Ref<SharedFunctionInstanceData const> shared_function_instance_data, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled)
|
||||
GC::Ref<Executable> Generator::generate_from_function(VM& vm, GC::Ref<SharedFunctionInstanceData const> shared_function_instance_data, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled)
|
||||
{
|
||||
VERIFY(!shared_function_instance_data->m_executable);
|
||||
return compile(vm, *shared_function_instance_data->m_ecmascript_code, shared_function_instance_data->m_kind, shared_function_instance_data, MustPropagateCompletion::No, builtin_abstract_operations_enabled, shared_function_instance_data->m_local_variables_names);
|
||||
|
|
@ -769,7 +767,7 @@ void Generator::end_breakable_scope()
|
|||
end_boundary(BlockBoundaryType::Break);
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_super_reference(MemberExpression const& expression)
|
||||
Generator::ReferenceOperands Generator::emit_super_reference(MemberExpression const& expression)
|
||||
{
|
||||
VERIFY(is<SuperExpression>(expression.object()));
|
||||
|
||||
|
|
@ -785,7 +783,7 @@ CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_super_refere
|
|||
// SuperProperty : super [ Expression ]
|
||||
// 3. Let propertyNameReference be ? Evaluation of Expression.
|
||||
// 4. Let propertyNameValue be ? GetValue(propertyNameReference).
|
||||
computed_property_value = TRY(expression.property().generate_bytecode(*this)).value();
|
||||
computed_property_value = expression.property().generate_bytecode(*this).value();
|
||||
} else {
|
||||
// SuperProperty : super . IdentifierName
|
||||
// 3. Let propertyKey be the StringValue of IdentifierName.
|
||||
|
|
@ -811,26 +809,30 @@ CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_super_refere
|
|||
};
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_load_from_reference(JS::ASTNode const& node, Optional<ScopedOperand> preferred_dst)
|
||||
Generator::ReferenceOperands Generator::emit_load_from_reference(JS::ASTNode const& node, Optional<ScopedOperand> preferred_dst)
|
||||
{
|
||||
if (is<Identifier>(node)) {
|
||||
auto& identifier = static_cast<Identifier const&>(node);
|
||||
auto loaded_value = TRY(identifier.generate_bytecode(*this, preferred_dst)).value();
|
||||
auto loaded_value = identifier.generate_bytecode(*this, preferred_dst).value();
|
||||
return ReferenceOperands {
|
||||
.loaded_value = loaded_value,
|
||||
};
|
||||
}
|
||||
if (!is<MemberExpression>(node)) {
|
||||
return CodeGenerationError {
|
||||
&node,
|
||||
"Unimplemented/invalid node used as a reference"sv
|
||||
emit_todo("Unimplemented/invalid node used as a reference"sv);
|
||||
auto dummy = add_constant(js_undefined());
|
||||
return ReferenceOperands {
|
||||
.base = dummy,
|
||||
.referenced_name = dummy,
|
||||
.this_value = dummy,
|
||||
.loaded_value = dummy,
|
||||
};
|
||||
}
|
||||
auto& expression = static_cast<MemberExpression const&>(node);
|
||||
|
||||
// https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
|
||||
if (is<SuperExpression>(expression.object())) {
|
||||
auto super_reference = TRY(emit_super_reference(expression));
|
||||
auto super_reference = emit_super_reference(expression);
|
||||
auto dst = preferred_dst.has_value() ? preferred_dst.value() : allocate_register();
|
||||
|
||||
if (super_reference.referenced_name.has_value()) {
|
||||
|
|
@ -846,11 +848,11 @@ CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_load_from_re
|
|||
return super_reference;
|
||||
}
|
||||
|
||||
auto base = TRY(expression.object().generate_bytecode(*this)).value();
|
||||
auto base = expression.object().generate_bytecode(*this).value();
|
||||
auto base_identifier = intern_identifier_for_expression(expression.object());
|
||||
|
||||
if (expression.is_computed()) {
|
||||
auto property = TRY(expression.property().generate_bytecode(*this)).value();
|
||||
auto property = expression.property().generate_bytecode(*this).value();
|
||||
auto saved_property = allocate_register();
|
||||
emit<Bytecode::Op::Mov>(saved_property, property);
|
||||
auto dst = preferred_dst.has_value() ? preferred_dst.value() : allocate_register();
|
||||
|
|
@ -887,19 +889,19 @@ CodeGenerationErrorOr<Generator::ReferenceOperands> Generator::emit_load_from_re
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<void> Generator::emit_store_to_reference(JS::ASTNode const& node, ScopedOperand value)
|
||||
void Generator::emit_store_to_reference(JS::ASTNode const& node, ScopedOperand value)
|
||||
{
|
||||
if (is<Identifier>(node)) {
|
||||
auto& identifier = static_cast<Identifier const&>(node);
|
||||
emit_set_variable(identifier, value);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
if (is<MemberExpression>(node)) {
|
||||
auto& expression = static_cast<MemberExpression const&>(node);
|
||||
|
||||
// https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
|
||||
if (is<SuperExpression>(expression.object())) {
|
||||
auto super_reference = TRY(emit_super_reference(expression));
|
||||
auto super_reference = emit_super_reference(expression);
|
||||
|
||||
// 4. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }.
|
||||
if (super_reference.referenced_name.has_value()) {
|
||||
|
|
@ -911,10 +913,10 @@ CodeGenerationErrorOr<void> Generator::emit_store_to_reference(JS::ASTNode const
|
|||
emit<Bytecode::Op::PutNormalByIdWithThis>(*super_reference.base, *super_reference.this_value, property_key_table_index, value, next_property_lookup_cache());
|
||||
}
|
||||
} else {
|
||||
auto object = TRY(expression.object().generate_bytecode(*this)).value();
|
||||
auto object = expression.object().generate_bytecode(*this).value();
|
||||
|
||||
if (expression.is_computed()) {
|
||||
auto property = TRY(expression.property().generate_bytecode(*this)).value();
|
||||
auto property = expression.property().generate_bytecode(*this).value();
|
||||
emit_put_by_value(object, property, value, PutKind::Normal, {});
|
||||
} else if (expression.property().is_identifier()) {
|
||||
auto property_key_table_index = intern_property_key(as<Identifier>(expression.property()).string());
|
||||
|
|
@ -927,36 +929,33 @@ CodeGenerationErrorOr<void> Generator::emit_store_to_reference(JS::ASTNode const
|
|||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
return CodeGenerationError {
|
||||
&node,
|
||||
"Unimplemented/invalid node used a reference"sv
|
||||
};
|
||||
emit_todo("Unimplemented/invalid node used as a reference"sv);
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<void> Generator::emit_store_to_reference(ReferenceOperands const& reference, ScopedOperand value)
|
||||
void Generator::emit_store_to_reference(ReferenceOperands const& reference, ScopedOperand value)
|
||||
{
|
||||
if (reference.referenced_private_identifier.has_value()) {
|
||||
emit<Bytecode::Op::PutPrivateById>(*reference.base, *reference.referenced_private_identifier, value);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
if (reference.referenced_identifier.has_value()) {
|
||||
if (reference.base == reference.this_value)
|
||||
emit_put_by_id(*reference.base, *reference.referenced_identifier, value, Bytecode::PutKind::Normal, next_property_lookup_cache());
|
||||
else
|
||||
emit<Bytecode::Op::PutNormalByIdWithThis>(*reference.base, *reference.this_value, *reference.referenced_identifier, value, next_property_lookup_cache());
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
if (reference.base == reference.this_value)
|
||||
emit_put_by_value(*reference.base, *reference.referenced_name, value, PutKind::Normal, {});
|
||||
else
|
||||
emit_put_by_value_with_this(*reference.base, *reference.referenced_name, *reference.this_value, value, PutKind::Normal);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<Optional<ScopedOperand>> Generator::emit_delete_reference(JS::ASTNode const& node)
|
||||
Optional<ScopedOperand> Generator::emit_delete_reference(JS::ASTNode const& node)
|
||||
{
|
||||
if (is<Identifier>(node)) {
|
||||
auto& identifier = static_cast<Identifier const&>(node);
|
||||
|
|
@ -973,7 +972,7 @@ CodeGenerationErrorOr<Optional<ScopedOperand>> Generator::emit_delete_reference(
|
|||
|
||||
// https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
|
||||
if (is<SuperExpression>(expression.object())) {
|
||||
auto super_reference = TRY(emit_super_reference(expression));
|
||||
auto super_reference = emit_super_reference(expression);
|
||||
|
||||
auto exception = allocate_register();
|
||||
emit<Bytecode::Op::NewReferenceError>(exception, intern_string(ErrorType::UnsupportedDeleteSuperProperty.message()));
|
||||
|
|
@ -986,11 +985,11 @@ CodeGenerationErrorOr<Optional<ScopedOperand>> Generator::emit_delete_reference(
|
|||
return add_constant(js_undefined());
|
||||
}
|
||||
|
||||
auto object = TRY(expression.object().generate_bytecode(*this)).value();
|
||||
auto object = expression.object().generate_bytecode(*this).value();
|
||||
auto dst = allocate_register();
|
||||
|
||||
if (expression.is_computed()) {
|
||||
auto property = TRY(expression.property().generate_bytecode(*this)).value();
|
||||
auto property = expression.property().generate_bytecode(*this).value();
|
||||
emit<Bytecode::Op::DeleteByValue>(dst, object, property);
|
||||
} else if (expression.property().is_identifier()) {
|
||||
auto property_key_table_index = intern_property_key(as<Identifier>(expression.property()).string());
|
||||
|
|
@ -1008,7 +1007,7 @@ CodeGenerationErrorOr<Optional<ScopedOperand>> Generator::emit_delete_reference(
|
|||
// 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
|
||||
// 1. Let ref be the result of evaluating UnaryExpression.
|
||||
// 2. ReturnIfAbrupt(ref).
|
||||
(void)TRY(node.generate_bytecode(*this));
|
||||
(void)node.generate_bytecode(*this);
|
||||
|
||||
// 3. If ref is not a Reference Record, return true.
|
||||
// NOTE: The rest of the steps are handled by Delete{Variable,ByValue,Id}.
|
||||
|
|
@ -1294,23 +1293,23 @@ void Generator::emit_new_function(ScopedOperand dst, FunctionExpression const& f
|
|||
}
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<ScopedOperand> Generator::emit_named_evaluation_if_anonymous_function(Expression const& expression, Optional<IdentifierTableIndex> lhs_name, Optional<ScopedOperand> preferred_dst, bool is_method)
|
||||
ScopedOperand Generator::emit_named_evaluation_if_anonymous_function(Expression const& expression, Optional<IdentifierTableIndex> lhs_name, Optional<ScopedOperand> preferred_dst, bool is_method)
|
||||
{
|
||||
if (is<FunctionExpression>(expression)) {
|
||||
auto const& function_expression = static_cast<FunctionExpression const&>(expression);
|
||||
if (!function_expression.has_name()) {
|
||||
return TRY(function_expression.generate_bytecode_with_lhs_name(*this, move(lhs_name), preferred_dst, is_method)).value();
|
||||
return function_expression.generate_bytecode_with_lhs_name(*this, move(lhs_name), preferred_dst, is_method).value();
|
||||
}
|
||||
}
|
||||
|
||||
if (is<ClassExpression>(expression)) {
|
||||
auto const& class_expression = static_cast<ClassExpression const&>(expression);
|
||||
if (!class_expression.has_name()) {
|
||||
return TRY(class_expression.generate_bytecode_with_lhs_name(*this, move(lhs_name), preferred_dst)).value();
|
||||
return class_expression.generate_bytecode_with_lhs_name(*this, move(lhs_name), preferred_dst).value();
|
||||
}
|
||||
}
|
||||
|
||||
return TRY(expression.generate_bytecode(*this, preferred_dst)).value();
|
||||
return expression.generate_bytecode(*this, preferred_dst).value();
|
||||
}
|
||||
|
||||
void Generator::emit_get_by_id(ScopedOperand dst, ScopedOperand base, PropertyKeyTableIndex property_key_table_index, Optional<IdentifierTableIndex> base_identifier)
|
||||
|
|
@ -1528,6 +1527,20 @@ bool Generator::fuse_compare_and_jump(ScopedOperand const& condition, Label true
|
|||
return false;
|
||||
}
|
||||
|
||||
void Generator::emit_todo(StringView message)
|
||||
{
|
||||
auto error_message = MUST(String::formatted("TODO: {}", message));
|
||||
auto message_string = intern_string(Utf16String::from_utf8(error_message));
|
||||
auto error_register = allocate_register();
|
||||
emit<Op::NewTypeError>(error_register, message_string);
|
||||
perform_needed_unwinds<Op::Throw>();
|
||||
emit<Op::Throw>(error_register);
|
||||
// Switch to a new block so subsequent codegen doesn't crash trying to
|
||||
// emit into a terminated block.
|
||||
auto& dead_block = make_block("dead"_string);
|
||||
switch_to_basic_block(dead_block);
|
||||
}
|
||||
|
||||
void Generator::emit_jump_if(ScopedOperand const& condition, Label true_target, Label false_target)
|
||||
{
|
||||
if (condition.operand().is_constant()) {
|
||||
|
|
@ -1606,7 +1619,7 @@ ScopedOperand Generator::add_constant(Value value)
|
|||
return append_new_constant();
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Identifier const& builtin_identifier, ReadonlySpan<CallExpression::Argument> arguments, ScopedOperand const& dst)
|
||||
void Generator::generate_builtin_abstract_operation(Identifier const& builtin_identifier, ReadonlySpan<CallExpression::Argument> arguments, ScopedOperand const& dst)
|
||||
{
|
||||
VERIFY(m_builtin_abstract_operations_enabled);
|
||||
for (auto const& argument : arguments)
|
||||
|
|
@ -1616,30 +1629,30 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
|
||||
if (operation_name == "IsCallable"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto source = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto source = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::IsCallable>(dst, source);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "IsConstructor"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto source = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto source = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::IsConstructor>(dst, source);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "ToBoolean"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto source = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto source = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::ToBoolean>(dst, source);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "ToObject"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto source = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto source = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::ToObject>(dst, source);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "ThrowTypeError"sv) {
|
||||
|
|
@ -1652,28 +1665,28 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
emit<Op::NewTypeError>(type_error_register, message_string);
|
||||
perform_needed_unwinds<Op::Throw>();
|
||||
emit<Op::Throw>(type_error_register);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "ThrowIfNotObject"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto source = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto source = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::ThrowIfNotObject>(source);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "Call"sv) {
|
||||
VERIFY(arguments.size() >= 2);
|
||||
|
||||
auto const& callee_argument = arguments[0].value;
|
||||
auto callee = TRY(callee_argument->generate_bytecode(*this)).value();
|
||||
auto this_value = TRY(arguments[1].value->generate_bytecode(*this)).value();
|
||||
auto callee = callee_argument->generate_bytecode(*this).value();
|
||||
auto this_value = arguments[1].value->generate_bytecode(*this).value();
|
||||
auto arguments_to_call_with = arguments.slice(2);
|
||||
|
||||
Vector<ScopedOperand> argument_operands;
|
||||
argument_operands.ensure_capacity(arguments_to_call_with.size());
|
||||
for (auto const& argument : arguments_to_call_with) {
|
||||
auto argument_value = TRY(argument.value->generate_bytecode(*this)).value();
|
||||
auto argument_value = argument.value->generate_bytecode(*this).value();
|
||||
argument_operands.unchecked_append(copy_if_needed_to_preserve_evaluation_order(argument_value));
|
||||
}
|
||||
|
||||
|
|
@ -1698,30 +1711,30 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
this_value,
|
||||
expression_string_index,
|
||||
argument_operands);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "NewObjectWithNoPrototype"sv) {
|
||||
VERIFY(arguments.is_empty());
|
||||
emit<Op::NewObjectWithNoPrototype>(dst);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "CreateAsyncFromSyncIterator"sv) {
|
||||
VERIFY(arguments.size() == 3);
|
||||
auto iterator = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto next_method = TRY(arguments[1].value->generate_bytecode(*this)).value();
|
||||
auto done = TRY(arguments[2].value->generate_bytecode(*this)).value();
|
||||
auto iterator = arguments[0].value->generate_bytecode(*this).value();
|
||||
auto next_method = arguments[1].value->generate_bytecode(*this).value();
|
||||
auto done = arguments[2].value->generate_bytecode(*this).value();
|
||||
|
||||
emit<Op::CreateAsyncFromSyncIterator>(dst, iterator, next_method, done);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "ToLength"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto value = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto value = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::ToLength>(dst, value);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "NewTypeError"sv) {
|
||||
|
|
@ -1731,23 +1744,23 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
|
||||
auto message_string = intern_string(message->value());
|
||||
emit<Op::NewTypeError>(dst, message_string);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "NewArrayWithLength"sv) {
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto length = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto length = arguments[0].value->generate_bytecode(*this).value();
|
||||
emit<Op::NewArrayWithLength>(dst, length);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation_name == "CreateDataPropertyOrThrow"sv) {
|
||||
VERIFY(arguments.size() == 3);
|
||||
auto object = TRY(arguments[0].value->generate_bytecode(*this)).value();
|
||||
auto property = TRY(arguments[1].value->generate_bytecode(*this)).value();
|
||||
auto value = TRY(arguments[2].value->generate_bytecode(*this)).value();
|
||||
auto object = arguments[0].value->generate_bytecode(*this).value();
|
||||
auto property = arguments[1].value->generate_bytecode(*this).value();
|
||||
auto value = arguments[2].value->generate_bytecode(*this).value();
|
||||
emit<Op::CreateDataPropertyOrThrow>(object, property, value);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
#define __JS_ENUMERATE(snake_name, functionName, length) \
|
||||
|
|
@ -1755,7 +1768,7 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
Vector<ScopedOperand> argument_operands; \
|
||||
argument_operands.ensure_capacity(arguments.size()); \
|
||||
for (auto const& argument : arguments) { \
|
||||
auto argument_value = TRY(argument.value->generate_bytecode(*this)).value(); \
|
||||
auto argument_value = argument.value->generate_bytecode(*this).value(); \
|
||||
argument_operands.unchecked_append(copy_if_needed_to_preserve_evaluation_order(argument_value)); \
|
||||
} \
|
||||
emit_with_extra_operand_slots<Bytecode::Op::Call>( \
|
||||
|
|
@ -1765,7 +1778,7 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
add_constant(js_undefined()), \
|
||||
intern_string(builtin_identifier.string().to_utf16_string()), \
|
||||
argument_operands); \
|
||||
return {}; \
|
||||
return; \
|
||||
}
|
||||
JS_ENUMERATE_NATIVE_JAVASCRIPT_BACKED_ABSTRACT_OPERATIONS
|
||||
#undef __JS_ENUMERATE
|
||||
|
|
@ -1773,7 +1786,7 @@ CodeGenerationErrorOr<void> Generator::generate_builtin_abstract_operation(Ident
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<Optional<ScopedOperand>> Generator::maybe_generate_builtin_constant(Identifier const& builtin_identifier)
|
||||
Optional<ScopedOperand> Generator::maybe_generate_builtin_constant(Identifier const& builtin_identifier)
|
||||
{
|
||||
auto const& constant_name = builtin_identifier.string();
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Bytecode/BasicBlock.h>
|
||||
#include <LibJS/Bytecode/BuiltinAbstractOperationsEnabled.h>
|
||||
#include <LibJS/Bytecode/CodeGenerationError.h>
|
||||
#include <LibJS/Bytecode/Executable.h>
|
||||
#include <LibJS/Bytecode/IdentifierTable.h>
|
||||
#include <LibJS/Bytecode/Label.h>
|
||||
|
|
@ -41,10 +40,10 @@ public:
|
|||
Yes,
|
||||
};
|
||||
|
||||
static CodeGenerationErrorOr<GC::Ref<Executable>> generate_from_ast_node(VM&, ASTNode const&, FunctionKind = FunctionKind::Normal);
|
||||
static CodeGenerationErrorOr<GC::Ref<Executable>> generate_from_function(VM&, GC::Ref<SharedFunctionInstanceData const> shared_function_instance_data, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled = BuiltinAbstractOperationsEnabled::No);
|
||||
static GC::Ref<Executable> generate_from_ast_node(VM&, ASTNode const&, FunctionKind = FunctionKind::Normal);
|
||||
static GC::Ref<Executable> generate_from_function(VM&, GC::Ref<SharedFunctionInstanceData const> shared_function_instance_data, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled = BuiltinAbstractOperationsEnabled::No);
|
||||
|
||||
CodeGenerationErrorOr<void> emit_function_declaration_instantiation(SharedFunctionInstanceData const& shared_function_instance_data);
|
||||
void emit_function_declaration_instantiation(SharedFunctionInstanceData const& shared_function_instance_data);
|
||||
|
||||
[[nodiscard]] ScopedOperand allocate_register();
|
||||
[[nodiscard]] ScopedOperand local(Identifier::Local const&);
|
||||
|
|
@ -188,6 +187,8 @@ public:
|
|||
|
||||
void emit_jump_if(ScopedOperand const& condition, Label true_target, Label false_target);
|
||||
|
||||
void emit_todo(StringView message);
|
||||
|
||||
struct ReferenceOperands {
|
||||
Optional<ScopedOperand> base {}; // [[Base]]
|
||||
Optional<ScopedOperand> referenced_name {}; // [[ReferencedName]] as an operand
|
||||
|
|
@ -197,12 +198,12 @@ public:
|
|||
Optional<ScopedOperand> loaded_value {}; // Loaded value, if we've performed a load.
|
||||
};
|
||||
|
||||
CodeGenerationErrorOr<ReferenceOperands> emit_load_from_reference(JS::ASTNode const&, Optional<ScopedOperand> preferred_dst = {});
|
||||
CodeGenerationErrorOr<void> emit_store_to_reference(JS::ASTNode const&, ScopedOperand value);
|
||||
CodeGenerationErrorOr<void> emit_store_to_reference(ReferenceOperands const&, ScopedOperand value);
|
||||
CodeGenerationErrorOr<Optional<ScopedOperand>> emit_delete_reference(JS::ASTNode const&);
|
||||
ReferenceOperands emit_load_from_reference(JS::ASTNode const&, Optional<ScopedOperand> preferred_dst = {});
|
||||
void emit_store_to_reference(JS::ASTNode const&, ScopedOperand value);
|
||||
void emit_store_to_reference(ReferenceOperands const&, ScopedOperand value);
|
||||
Optional<ScopedOperand> emit_delete_reference(JS::ASTNode const&);
|
||||
|
||||
CodeGenerationErrorOr<ReferenceOperands> emit_super_reference(MemberExpression const&);
|
||||
ReferenceOperands emit_super_reference(MemberExpression const&);
|
||||
|
||||
void emit_set_variable(JS::Identifier const& identifier, ScopedOperand value, Bytecode::Op::BindingInitializationMode initialization_mode = Bytecode::Op::BindingInitializationMode::Set, Bytecode::Op::EnvironmentMode mode = Bytecode::Op::EnvironmentMode::Lexical);
|
||||
|
||||
|
|
@ -213,7 +214,7 @@ public:
|
|||
u32 register_shared_function_data(GC::Ref<SharedFunctionInstanceData>);
|
||||
u32 register_class_blueprint(ClassBlueprint);
|
||||
|
||||
CodeGenerationErrorOr<ScopedOperand> emit_named_evaluation_if_anonymous_function(Expression const&, Optional<IdentifierTableIndex> lhs_name, Optional<ScopedOperand> preferred_dst = {}, bool is_method = false);
|
||||
ScopedOperand emit_named_evaluation_if_anonymous_function(Expression const&, Optional<IdentifierTableIndex> lhs_name, Optional<ScopedOperand> preferred_dst = {}, bool is_method = false);
|
||||
|
||||
void ensure_lexical_environment_register_initialized();
|
||||
[[nodiscard]] ScopedOperand current_lexical_environment_register() const;
|
||||
|
|
@ -433,13 +434,13 @@ public:
|
|||
|
||||
[[nodiscard]] bool builtin_abstract_operations_enabled() const { return m_builtin_abstract_operations_enabled; }
|
||||
|
||||
CodeGenerationErrorOr<void> generate_builtin_abstract_operation(Identifier const& builtin_identifier, ReadonlySpan<CallExpression::Argument> arguments, ScopedOperand const& dst);
|
||||
CodeGenerationErrorOr<Optional<ScopedOperand>> maybe_generate_builtin_constant(Identifier const& builtin_identifier);
|
||||
void generate_builtin_abstract_operation(Identifier const& builtin_identifier, ReadonlySpan<CallExpression::Argument> arguments, ScopedOperand const& dst);
|
||||
Optional<ScopedOperand> maybe_generate_builtin_constant(Identifier const& builtin_identifier);
|
||||
|
||||
private:
|
||||
VM& m_vm;
|
||||
|
||||
static CodeGenerationErrorOr<GC::Ref<Executable>> compile(VM&, ASTNode const&, FunctionKind, GC::Ptr<SharedFunctionInstanceData const>, MustPropagateCompletion, BuiltinAbstractOperationsEnabled, Vector<LocalVariable> local_variable_names);
|
||||
static GC::Ref<Executable> compile(VM&, ASTNode const&, FunctionKind, GC::Ptr<SharedFunctionInstanceData const>, MustPropagateCompletion, BuiltinAbstractOperationsEnabled, Vector<LocalVariable> local_variable_names);
|
||||
|
||||
enum class JumpType {
|
||||
Continue,
|
||||
|
|
|
|||
|
|
@ -127,25 +127,11 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record, GC::Ptr<Environ
|
|||
// 11. Let script be scriptRecord.[[ECMAScriptCode]].
|
||||
GC::Ptr<Executable> executable = script_record.cached_executable();
|
||||
if (!executable && result.type() == Completion::Type::Normal) {
|
||||
auto executable_result = JS::Bytecode::Generator::generate_from_ast_node(vm, *script_record.parse_node(), {});
|
||||
|
||||
if (executable_result.is_error()) {
|
||||
if (auto error_string = executable_result.error().to_string(); error_string.is_error())
|
||||
result = vm.template throw_completion<JS::InternalError>(vm.error_message(JS::VM::ErrorMessage::OutOfMemory));
|
||||
else if (error_string = String::formatted("TODO({})", error_string.value()); error_string.is_error())
|
||||
result = vm.template throw_completion<JS::InternalError>(vm.error_message(JS::VM::ErrorMessage::OutOfMemory));
|
||||
else
|
||||
result = vm.template throw_completion<JS::InternalError>(error_string.release_value());
|
||||
} else {
|
||||
executable = executable_result.release_value();
|
||||
script_record.cache_executable(*executable);
|
||||
|
||||
// Drop the AST now that we have compiled bytecode.
|
||||
script_record.drop_ast();
|
||||
|
||||
if (g_dump_bytecode)
|
||||
executable->dump();
|
||||
}
|
||||
executable = JS::Bytecode::Generator::generate_from_ast_node(vm, *script_record.parse_node(), {});
|
||||
script_record.cache_executable(*executable);
|
||||
script_record.drop_ast();
|
||||
if (g_dump_bytecode)
|
||||
executable->dump();
|
||||
}
|
||||
|
||||
u32 registers_and_locals_count = 0;
|
||||
|
|
@ -634,13 +620,9 @@ void Interpreter::catch_exception(Operand dst)
|
|||
reg(Register::exception()) = js_special_empty_value();
|
||||
}
|
||||
|
||||
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, Utf16FlyString const& name)
|
||||
GC::Ref<Bytecode::Executable> compile(VM& vm, ASTNode const& node, FunctionKind kind, Utf16FlyString const& name)
|
||||
{
|
||||
auto executable_result = Bytecode::Generator::generate_from_ast_node(vm, node, kind);
|
||||
if (executable_result.is_error()) [[unlikely]]
|
||||
return vm.throw_completion<InternalError>(ErrorType::NotImplemented, TRY_OR_THROW_OOM(vm, executable_result.error().to_string()));
|
||||
|
||||
auto bytecode_executable = executable_result.release_value();
|
||||
auto bytecode_executable = Bytecode::Generator::generate_from_ast_node(vm, node, kind);
|
||||
bytecode_executable->name = name;
|
||||
|
||||
if (Bytecode::g_dump_bytecode)
|
||||
|
|
@ -649,15 +631,11 @@ ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, ASTNode const&
|
|||
return bytecode_executable;
|
||||
}
|
||||
|
||||
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, GC::Ref<SharedFunctionInstanceData const> shared_function_instance_data, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled)
|
||||
GC::Ref<Bytecode::Executable> compile(VM& vm, GC::Ref<SharedFunctionInstanceData const> shared_function_instance_data, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled)
|
||||
{
|
||||
auto const& name = shared_function_instance_data->m_name;
|
||||
|
||||
auto executable_result = Bytecode::Generator::generate_from_function(vm, shared_function_instance_data, builtin_abstract_operations_enabled);
|
||||
if (executable_result.is_error()) [[unlikely]]
|
||||
return vm.throw_completion<InternalError>(ErrorType::NotImplemented, TRY_OR_THROW_OOM(vm, executable_result.error().to_string()));
|
||||
|
||||
auto bytecode_executable = executable_result.release_value();
|
||||
auto bytecode_executable = Bytecode::Generator::generate_from_function(vm, shared_function_instance_data, builtin_abstract_operations_enabled);
|
||||
bytecode_executable->name = name;
|
||||
|
||||
if (Bytecode::g_dump_bytecode)
|
||||
|
|
@ -2536,7 +2514,7 @@ static ThrowCompletionOr<void> execute_call(
|
|||
size_t registers_and_locals_count = 0;
|
||||
size_t constants_count = 0;
|
||||
size_t argument_count = arguments.size();
|
||||
TRY(function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK_WITHOUT_CLEARING_ARGS(callee_context, registers_and_locals_count, constants_count, max(arguments.size(), argument_count));
|
||||
|
||||
auto* callee_context_argument_values = callee_context->arguments.data();
|
||||
|
|
@ -2609,7 +2587,7 @@ static ThrowCompletionOr<void> call_with_argument_array(
|
|||
size_t argument_count = argument_array_length;
|
||||
size_t registers_and_locals_count = 0;
|
||||
size_t constants_count = 0;
|
||||
TRY(function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK_WITHOUT_CLEARING_ARGS(callee_context, registers_and_locals_count, constants_count, max(argument_array_length, argument_count));
|
||||
|
||||
auto* callee_context_argument_values = callee_context->arguments.data();
|
||||
|
|
@ -2690,7 +2668,7 @@ ThrowCompletionOr<void> SuperCallWithArgumentArray::execute_impl(Bytecode::Inter
|
|||
size_t argument_count = argument_array_length;
|
||||
size_t registers_and_locals_count = 0;
|
||||
size_t constants_count = 0;
|
||||
TRY(function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK_WITHOUT_CLEARING_ARGS(callee_context, registers_and_locals_count, constants_count, max(argument_array_length, argument_count));
|
||||
|
||||
auto* callee_context_argument_values = callee_context->arguments.data();
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ private:
|
|||
|
||||
JS_API extern bool g_dump_bytecode;
|
||||
|
||||
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, ASTNode const&, JS::FunctionKind kind, Utf16FlyString const& name);
|
||||
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, GC::Ref<SharedFunctionInstanceData const>, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled);
|
||||
GC::Ref<Bytecode::Executable> compile(VM&, ASTNode const&, JS::FunctionKind kind, Utf16FlyString const& name);
|
||||
GC::Ref<Bytecode::Executable> compile(VM&, GC::Ref<SharedFunctionInstanceData const>, BuiltinAbstractOperationsEnabled builtin_abstract_operations_enabled);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ set(SOURCES
|
|||
Bytecode/ASTCodegen.cpp
|
||||
Bytecode/BasicBlock.cpp
|
||||
Bytecode/Builtins.cpp
|
||||
Bytecode/CodeGenerationError.cpp
|
||||
Bytecode/Executable.cpp
|
||||
Bytecode/Generator.cpp
|
||||
Bytecode/IdentifierTable.cpp
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ ThrowCompletionOr<Value> call_impl(VM& vm, Value function, Value this_value, Rea
|
|||
size_t registers_and_locals_count = 0;
|
||||
size_t constants_count = 0;
|
||||
size_t argument_count = arguments_list.size();
|
||||
TRY(function_object.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
function_object.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_locals_count, constants_count, argument_count);
|
||||
|
||||
auto* argument_values = callee_context->arguments.data();
|
||||
|
|
@ -88,7 +88,7 @@ ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_val
|
|||
size_t registers_and_locals_count = 0;
|
||||
size_t constants_count = 0;
|
||||
size_t argument_count = arguments_list.size();
|
||||
TRY(function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_locals_count, constants_count, argument_count);
|
||||
|
||||
auto* argument_values = callee_context->arguments.data();
|
||||
|
|
@ -113,7 +113,7 @@ ThrowCompletionOr<GC::Ref<Object>> construct_impl(VM&, FunctionObject& function,
|
|||
size_t registers_and_locals_count = 0;
|
||||
size_t constants_count = 0;
|
||||
size_t argument_count = arguments_list.size();
|
||||
TRY(function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
function.get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_locals_count, constants_count, argument_count);
|
||||
|
||||
auto* argument_values = callee_context->arguments.data();
|
||||
|
|
@ -729,10 +729,7 @@ ThrowCompletionOr<Value> perform_eval(VM& vm, Value x, CallerMode strict_caller,
|
|||
|
||||
// 31. If result.[[Type]] is normal, then
|
||||
// a. Set result to the result of evaluating body.
|
||||
auto executable_result = Bytecode::Generator::generate_from_ast_node(vm, program, {});
|
||||
if (executable_result.is_error())
|
||||
return vm.throw_completion<InternalError>(ErrorType::NotImplemented, TRY_OR_THROW_OOM(vm, executable_result.error().to_string()));
|
||||
auto executable = executable_result.release_value();
|
||||
auto executable = Bytecode::Generator::generate_from_ast_node(vm, program, {});
|
||||
executable->name = "eval"_utf16_fly_string;
|
||||
if (Bytecode::g_dump_bytecode)
|
||||
executable->dump();
|
||||
|
|
|
|||
|
|
@ -108,11 +108,10 @@ void BoundFunction::visit_edges(Visitor& visitor)
|
|||
visitor.visit(m_bound_arguments);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> BoundFunction::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
void BoundFunction::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
{
|
||||
TRY(m_bound_target_function->get_stack_frame_size(registers_and_locals_count, constants_count, argument_count));
|
||||
m_bound_target_function->get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
argument_count += m_bound_arguments.size();
|
||||
return {};
|
||||
}
|
||||
|
||||
Utf16String BoundFunction::name_for_call_stack() const
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public:
|
|||
private:
|
||||
BoundFunction(Realm&, FunctionObject& target_function, Value bound_this, Vector<Value> bound_arguments, Object* prototype);
|
||||
|
||||
ThrowCompletionOr<void> get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
void get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
virtual bool is_bound_function() const final { return true; }
|
||||
|
|
|
|||
|
|
@ -213,21 +213,20 @@ void ECMAScriptFunctionObject::initialize(Realm& realm)
|
|||
}
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> ECMAScriptFunctionObject::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
void ECMAScriptFunctionObject::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
{
|
||||
auto& executable = shared_data().m_executable;
|
||||
if (!executable) {
|
||||
if (is_module_wrapper()) {
|
||||
executable = TRY(Bytecode::compile(vm(), ecmascript_code(), kind(), name()));
|
||||
executable = Bytecode::compile(vm(), ecmascript_code(), kind(), name());
|
||||
} else {
|
||||
executable = TRY(Bytecode::compile(vm(), shared_data(), Bytecode::BuiltinAbstractOperationsEnabled::No));
|
||||
executable = Bytecode::compile(vm(), shared_data(), Bytecode::BuiltinAbstractOperationsEnabled::No);
|
||||
}
|
||||
m_shared_data->clear_compile_inputs();
|
||||
}
|
||||
registers_and_locals_count = executable->registers_and_locals_count;
|
||||
constants_count = executable->constants.size();
|
||||
argument_count = max(argument_count, static_cast<size_t>(formal_parameter_count()));
|
||||
return {};
|
||||
}
|
||||
|
||||
// 10.2.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
|
||||
|
|
@ -537,11 +536,8 @@ void async_block_start(VM& vm, T const& async_body, PromiseCapability const& pro
|
|||
// b. If asyncBody is a Parse Node, then
|
||||
if constexpr (!IsSame<T, GC::Function<Completion()>>) {
|
||||
// i. Let result be Completion(Evaluation of asyncBody).
|
||||
auto maybe_executable = Bytecode::compile(vm, async_body, FunctionKind::Async, "AsyncBlockStart"_utf16_fly_string);
|
||||
if (maybe_executable.is_error())
|
||||
result = maybe_executable.release_error();
|
||||
else
|
||||
result = vm.bytecode_interpreter().run_executable(vm.running_execution_context(), *maybe_executable.value(), {});
|
||||
auto executable = Bytecode::compile(vm, async_body, FunctionKind::Async, "AsyncBlockStart"_utf16_fly_string);
|
||||
result = vm.bytecode_interpreter().run_executable(vm.running_execution_context(), *executable, {});
|
||||
}
|
||||
// c. Else,
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public:
|
|||
virtual void initialize(Realm&) override;
|
||||
virtual ~ECMAScriptFunctionObject() override = default;
|
||||
|
||||
virtual ThrowCompletionOr<void> get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
virtual void get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
virtual ThrowCompletionOr<Value> internal_call(ExecutionContext&, Value this_argument) override;
|
||||
virtual ThrowCompletionOr<GC::Ref<Object>> internal_construct(ExecutionContext&, FunctionObject& new_target) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public:
|
|||
|
||||
// Table 5: Additional Essential Internal Methods of Function Objects, https://tc39.es/ecma262/#table-additional-essential-internal-methods-of-function-objects
|
||||
|
||||
virtual ThrowCompletionOr<void> get_stack_frame_size([[maybe_unused]] size_t& registers_and_locals_count, [[maybe_unused]] size_t& constants_count, [[maybe_unused]] size_t& argument_count) { return {}; }
|
||||
virtual void get_stack_frame_size([[maybe_unused]] size_t& registers_and_locals_count, [[maybe_unused]] size_t& constants_count, [[maybe_unused]] size_t& argument_count) { }
|
||||
virtual ThrowCompletionOr<Value> internal_call(ExecutionContext&, Value this_argument) = 0;
|
||||
virtual ThrowCompletionOr<GC::Ref<Object>> internal_construct(ExecutionContext&, [[maybe_unused]] FunctionObject& new_target) { VERIFY_NOT_REACHED(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -61,13 +61,12 @@ void NativeJavaScriptBackedFunction::visit_edges(Visitor& visitor)
|
|||
visitor.visit(m_shared_function_instance_data);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> NativeJavaScriptBackedFunction::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
void NativeJavaScriptBackedFunction::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
{
|
||||
auto& bytecode_executable = this->bytecode_executable();
|
||||
registers_and_locals_count = bytecode_executable.registers_and_locals_count;
|
||||
constants_count = bytecode_executable.constants.size();
|
||||
argument_count = max(argument_count, m_shared_function_instance_data->m_function_length);
|
||||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<Value> NativeJavaScriptBackedFunction::call()
|
||||
|
|
@ -99,7 +98,7 @@ Bytecode::Executable& NativeJavaScriptBackedFunction::bytecode_executable()
|
|||
{
|
||||
auto& executable = m_shared_function_instance_data->m_executable;
|
||||
if (!executable) {
|
||||
executable = MUST(Bytecode::compile(vm(), m_shared_function_instance_data, Bytecode::BuiltinAbstractOperationsEnabled::Yes));
|
||||
executable = Bytecode::compile(vm(), m_shared_function_instance_data, Bytecode::BuiltinAbstractOperationsEnabled::Yes);
|
||||
m_shared_function_instance_data->clear_compile_inputs();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public:
|
|||
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
virtual ThrowCompletionOr<void> get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
virtual void get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
|
||||
virtual ThrowCompletionOr<Value> call() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -890,9 +890,9 @@ void ProxyObject::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(m_handler);
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> ProxyObject::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
void ProxyObject::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
{
|
||||
return as<FunctionObject>(*m_target).get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
as<FunctionObject>(*m_target).get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
}
|
||||
|
||||
Utf16String ProxyObject::name_for_call_stack() const
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ private:
|
|||
virtual bool is_proxy_object() const final { return true; }
|
||||
virtual bool eligible_for_own_property_enumeration_fast_path() const override final { return false; }
|
||||
|
||||
virtual ThrowCompletionOr<void> get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
virtual void get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
|
||||
GC::Ref<Object> m_target;
|
||||
GC::Ref<Object> m_handler;
|
||||
|
|
|
|||
|
|
@ -149,10 +149,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(VM& vm, Value source, Realm&
|
|||
// 5. If runningContext is not already suspended, suspend runningContext.
|
||||
// NOTE: This would be unused due to step 9 and is omitted for that reason.
|
||||
|
||||
auto maybe_executable = Bytecode::compile(vm, program, FunctionKind::Normal, "ShadowRealmEval"_utf16_fly_string);
|
||||
if (maybe_executable.is_error())
|
||||
return vm.throw_completion<TypeError>(ErrorType::ShadowRealmEvaluateAbruptCompletion);
|
||||
auto executable = maybe_executable.release_value();
|
||||
auto executable = Bytecode::compile(vm, program, FunctionKind::Normal, "ShadowRealmEval"_utf16_fly_string);
|
||||
|
||||
// 6. Let evalContext be GetShadowRealmContext(evalRealm, strictEval).
|
||||
auto eval_context = get_shadow_realm_context(eval_realm, strict_eval, executable->registers_and_locals_count, executable->constants.size());
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ ThrowCompletionOr<Value> WrappedFunction::internal_call(ExecutionContext& callee
|
|||
return result;
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> WrappedFunction::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
void WrappedFunction::get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count)
|
||||
{
|
||||
return m_wrapped_target_function->get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
m_wrapped_target_function->get_stack_frame_size(registers_and_locals_count, constants_count, argument_count);
|
||||
}
|
||||
|
||||
// 2.2 OrdinaryWrappedFunctionCall ( F: a wrapped function exotic object, thisArgument: an ECMAScript language value, argumentsList: a List of ECMAScript language values, ), https://tc39.es/proposal-shadowrealm/#sec-ordinary-wrapped-function-call
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
FunctionObject const& wrapped_target_function() const { return m_wrapped_target_function; }
|
||||
FunctionObject& wrapped_target_function() { return m_wrapped_target_function; }
|
||||
|
||||
virtual ThrowCompletionOr<void> get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
virtual void get_stack_frame_size(size_t& registers_and_locals_count, size_t& constants_count, size_t& argument_count) override;
|
||||
|
||||
virtual Utf16String name_for_call_stack() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -707,10 +707,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GC::Ptr<Promise
|
|||
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] SourceTextModule::execute_module({}, PromiseCapability @ {})", filename(), capability.ptr());
|
||||
|
||||
if (!m_has_top_level_await && !m_executable) {
|
||||
auto maybe_executable = Bytecode::compile(vm, *m_ecmascript_code, FunctionKind::Normal, "ShadowRealmEval"_utf16_fly_string);
|
||||
if (maybe_executable.is_error())
|
||||
return maybe_executable.release_error();
|
||||
m_executable = maybe_executable.release_value();
|
||||
m_executable = Bytecode::compile(vm, *m_ecmascript_code, FunctionKind::Normal, "ShadowRealmEval"_utf16_fly_string);
|
||||
m_ecmascript_code = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue