LibJS: Consolidate TDZ check emission into Generator helper
Move the duplicated ThrowIfTDZ emission logic from three places in ASTCodegen.cpp into a single Generator::emit_tdz_check_if_needed() helper. This handles both argument TDZ (which requires a Mov to empty first) and lexically-declared variable TDZ uniformly. This avoids emitting some unnecessary ThrowIfTDZ instructions.
This commit is contained in:
parent
9923745d34
commit
47e552e8fd
5 changed files with 36 additions and 36 deletions
|
|
@ -555,17 +555,8 @@ Optional<ScopedOperand> Identifier::generate_bytecode(Bytecode::Generator& gener
|
|||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||
|
||||
if (is_local()) {
|
||||
auto local_index = this->local_index();
|
||||
auto local = generator.local(local_index);
|
||||
if (!generator.is_local_initialized(local_index)) {
|
||||
if (local_index.is_argument()) {
|
||||
// Arguments are initialized to undefined by default, so here we need to replace it with the empty value to
|
||||
// trigger the TDZ check.
|
||||
generator.emit<Bytecode::Op::Mov>(local, generator.add_constant(js_special_empty_value()));
|
||||
}
|
||||
generator.emit<Bytecode::Op::ThrowIfTDZ>(local);
|
||||
}
|
||||
return local;
|
||||
generator.emit_tdz_check_if_needed(*this);
|
||||
return generator.local(local_index());
|
||||
}
|
||||
|
||||
if (is_global()) {
|
||||
|
|
@ -731,13 +722,8 @@ Optional<ScopedOperand> AssignmentExpression::generate_bytecode(Bytecode::Genera
|
|||
// e. Perform ? PutValue(lref, rval).
|
||||
if (is<Identifier>(*lhs)) {
|
||||
auto& identifier = static_cast<Identifier const&>(*lhs);
|
||||
if (identifier.is_local()) {
|
||||
auto is_initialized = generator.is_local_initialized(identifier.local_index());
|
||||
auto is_lexically_declared = generator.is_local_lexically_declared(identifier.local_index());
|
||||
if (is_lexically_declared && !is_initialized) {
|
||||
generator.emit<Bytecode::Op::ThrowIfTDZ>(generator.local(identifier.local_index()));
|
||||
}
|
||||
}
|
||||
if (identifier.is_local())
|
||||
generator.emit_tdz_check_if_needed(identifier);
|
||||
generator.emit_set_variable(identifier, rval);
|
||||
} else if (is<MemberExpression>(*lhs)) {
|
||||
auto& expression = static_cast<MemberExpression const&>(*lhs);
|
||||
|
|
@ -1933,11 +1919,8 @@ Optional<ScopedOperand> CallExpression::generate_bytecode(Bytecode::Generator& g
|
|||
call_type = Bytecode::Op::CallType::DirectEval;
|
||||
}
|
||||
if (identifier.is_local()) {
|
||||
auto local = generator.local(identifier.local_index());
|
||||
if (!generator.is_local_initialized(local.operand().index())) {
|
||||
generator.emit<Bytecode::Op::ThrowIfTDZ>(local);
|
||||
}
|
||||
original_callee = local;
|
||||
generator.emit_tdz_check_if_needed(identifier);
|
||||
original_callee = generator.local(identifier.local_index());
|
||||
} else if (identifier.is_global()) {
|
||||
original_callee = m_callee->generate_bytecode(generator).value();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1556,6 +1556,24 @@ bool Generator::is_local_lexically_declared(Identifier::Local const& local) cons
|
|||
return m_local_variables[local.index].declaration_kind == LocalVariable::DeclarationKind::LetOrConst;
|
||||
}
|
||||
|
||||
void Generator::emit_tdz_check_if_needed(Identifier const& identifier)
|
||||
{
|
||||
VERIFY(identifier.is_local());
|
||||
auto local_index = identifier.local_index();
|
||||
bool needs_tdz_check = local_index.is_argument()
|
||||
? !is_local_initialized(local_index)
|
||||
: is_local_lexically_declared(local_index) && !is_local_initialized(local_index);
|
||||
if (needs_tdz_check) {
|
||||
auto operand = local(local_index);
|
||||
if (local_index.is_argument()) {
|
||||
// Arguments are initialized to undefined by default, so here we need to replace it
|
||||
// with the empty value to trigger the TDZ check.
|
||||
emit<Bytecode::Op::Mov>(operand, add_constant(js_special_empty_value()));
|
||||
}
|
||||
emit<Bytecode::Op::ThrowIfTDZ>(operand);
|
||||
}
|
||||
}
|
||||
|
||||
ScopedOperand Generator::get_this(Optional<ScopedOperand> preferred_dst)
|
||||
{
|
||||
if (m_current_basic_block->has_resolved_this())
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ public:
|
|||
[[nodiscard]] bool is_local_initialized(Identifier::Local const&) const;
|
||||
[[nodiscard]] bool is_local_lexically_declared(Identifier::Local const& local) const;
|
||||
|
||||
void emit_tdz_check_if_needed(Identifier const&);
|
||||
|
||||
class SourceLocationScope {
|
||||
public:
|
||||
SourceLocationScope(Generator&, ASTNode const& node);
|
||||
|
|
|
|||
|
|
@ -42,9 +42,8 @@ JS bytecode executable "forLetClosure"
|
|||
|
||||
JS bytecode executable ""
|
||||
[ 0] 0: GetLexicalEnvironment dst:reg4
|
||||
[ 8] ThrowIfTDZ src:arg0
|
||||
[ 10] Call dst:reg5, callee:arg0, this_value:Undefined, f
|
||||
[ 30] Return value:reg5
|
||||
[ 8] Call dst:reg5, callee:arg0, this_value:Undefined, f
|
||||
[ 28] Return value:reg5
|
||||
|
||||
JS bytecode executable ""
|
||||
[ 0] 0: GetLexicalEnvironment dst:reg4
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@ JS bytecode executable "isect"
|
|||
[ 0] 0: GetLexicalEnvironment dst:reg4
|
||||
[ 8] Mov dst:i~0, src:Undefined
|
||||
[ 18] Mov dst:i~0, src:Int32(0)
|
||||
[ 28] Jump target:@48
|
||||
[ 30] 1: ThrowIfTDZ src:i~0
|
||||
[ 38] PostfixIncrement dst:reg5, src:i~0
|
||||
[ 48] 2: ThrowIfTDZ src:i~0
|
||||
[ 50] JumpLessThan lhs:i~0, rhs:Int32(3), true_target:@30, false_target:@68
|
||||
[ 68] 3: Mov dst:i~0, src:Int32(0)
|
||||
[ 78] Jump target:@90
|
||||
[ 80] 4: PostfixIncrement dst:reg5, src:i~0
|
||||
[ 90] 5: JumpLessThan lhs:i~0, rhs:Int32(3), true_target:@80, false_target:@a8
|
||||
[ a8] 6: End value:Undefined
|
||||
[ 28] Jump target:@40
|
||||
[ 30] 1: PostfixIncrement dst:reg5, src:i~0
|
||||
[ 40] 2: JumpLessThan lhs:i~0, rhs:Int32(3), true_target:@30, false_target:@58
|
||||
[ 58] 3: Mov dst:i~0, src:Int32(0)
|
||||
[ 68] Jump target:@80
|
||||
[ 70] 4: PostfixIncrement dst:reg5, src:i~0
|
||||
[ 80] 5: JumpLessThan lhs:i~0, rhs:Int32(3), true_target:@70, false_target:@98
|
||||
[ 98] 6: End value:Undefined
|
||||
|
|
|
|||
Loading…
Reference in a new issue