LibJS: Make ExecutionContext::function_name a GCPtr<PrimitiveString>

This required setting things up so that all function objects can plop
a PrimitiveString there instead of an AK string.

This is a step towards making ExecutionContext easier to allocate.
This commit is contained in:
Andreas Kling 2023-11-27 13:38:19 +01:00
parent eda2a6d9f7
commit 845da3901d
Notes: sideshowbarker 2024-07-17 06:28:38 +09:00
9 changed files with 34 additions and 16 deletions

View File

@ -142,9 +142,9 @@ ThrowCompletionOr<Value> Console::trace()
// NOTE: -2 to skip the console.trace() execution context
for (ssize_t i = execution_context_stack.size() - 2; i >= 0; --i) {
auto const& function_name = execution_context_stack[i]->function_name;
trace.stack.append(function_name.is_empty()
trace.stack.append((!function_name || function_name->is_empty())
? "<anonymous>"_string
: TRY_OR_THROW_OOM(vm, String::from_deprecated_string(function_name)));
: function_name->utf8_string());
}
// 2. Optionally, let formattedData be the result of Formatter(data), and incorporate formattedData as a label for trace.

View File

@ -333,8 +333,10 @@ void ECMAScriptFunctionObject::initialize(Realm& realm)
// which must give the properties in chronological order which in this case is the order they
// are defined in the spec.
m_name_string = PrimitiveString::create(vm, m_name);
MUST(define_property_or_throw(vm.names.length, { .value = Value(m_function_length), .writable = false, .enumerable = false, .configurable = true }));
MUST(define_property_or_throw(vm.names.name, { .value = PrimitiveString::create(vm, m_name.is_null() ? "" : m_name), .writable = false, .enumerable = false, .configurable = true }));
MUST(define_property_or_throw(vm.names.name, { .value = m_name_string, .writable = false, .enumerable = false, .configurable = true }));
if (!m_is_arrow_function) {
Object* prototype = nullptr;
@ -936,7 +938,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::prepare_for_ordinary_call(Exec
// 3. Set the Function of calleeContext to F.
callee_context.function = this;
callee_context.function_name = m_name;
callee_context.function_name = m_name_string;
// 4. Let calleeRealm be F.[[Realm]].
auto callee_realm = m_realm;
@ -1243,6 +1245,7 @@ void ECMAScriptFunctionObject::set_name(DeprecatedFlyString const& name)
VERIFY(!name.is_null());
auto& vm = this->vm();
m_name = name;
MUST(define_property_or_throw(vm.names.name, { .value = PrimitiveString::create(vm, m_name), .writable = false, .enumerable = false, .configurable = true }));
m_name_string = PrimitiveString::create(vm, m_name);
MUST(define_property_or_throw(vm.names.name, { .value = m_name_string, .writable = false, .enumerable = false, .configurable = true }));
}
}

View File

@ -112,6 +112,8 @@ private:
ThrowCompletionOr<void> function_declaration_instantiation();
DeprecatedFlyString m_name;
GCPtr<PrimitiveString> m_name_string;
GCPtr<Bytecode::Executable> m_bytecode_executable;
Vector<NonnullGCPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables;
i32 m_function_length { 0 };

View File

@ -85,7 +85,7 @@ void Error::populate_stack()
if (element.source_range.has_value())
range = element.source_range.value();
TracebackFrame frame {
.function_name = context->function_name,
.function_name = context->function_name ? context->function_name->deprecated_string() : "",
.source_range_storage = range,
};

View File

@ -53,6 +53,7 @@ void ExecutionContext::visit_edges(Cell::Visitor& visitor)
visitor.visit(this_value);
if (instruction_stream_iterator.has_value())
visitor.visit(const_cast<Bytecode::Executable*>(instruction_stream_iterator.value().executable()));
visitor.visit(function_name);
script_or_module.visit(
[](Empty) {},
[&](auto& script_or_module) {

View File

@ -49,7 +49,7 @@ public:
GCPtr<Cell> context_owner;
Optional<Bytecode::InstructionStreamIterator> instruction_stream_iterator;
DeprecatedFlyString function_name;
GCPtr<PrimitiveString> function_name;
Value this_value;
MarkedVector<Value> arguments;
MarkedVector<Value> local_variables;

View File

@ -17,6 +17,20 @@ namespace JS {
JS_DEFINE_ALLOCATOR(NativeFunction);
void NativeFunction::initialize(Realm& realm)
{
Base::initialize(realm);
m_name_string = PrimitiveString::create(vm(), m_name);
}
void NativeFunction::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_native_function);
visitor.visit(m_realm);
visitor.visit(m_name_string);
}
// 10.3.3 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] ), https://tc39.es/ecma262/#sec-createbuiltinfunction
// NOTE: This doesn't consider additionalInternalSlotsList, which is rarely used, and can either be implemented using only the `function` lambda, or needs a NativeFunction subclass.
NonnullGCPtr<NativeFunction> NativeFunction::create(Realm& allocating_realm, Function<ThrowCompletionOr<Value>(VM&)> behaviour, i32 length, PropertyKey const& name, Optional<Realm*> realm, Optional<Object*> prototype, Optional<StringView> const& prefix)
@ -111,7 +125,7 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Read
// 4. Set the Function of calleeContext to F.
callee_context.function = this;
callee_context.function_name = m_name;
callee_context.function_name = m_name_string;
// 5. Let calleeRealm be F.[[Realm]].
auto callee_realm = m_realm;
@ -175,7 +189,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(Reado
// 4. Set the Function of calleeContext to F.
callee_context.function = this;
callee_context.function_name = m_name;
callee_context.function_name = m_name_string;
// 5. Let calleeRealm be F.[[Realm]].
auto callee_realm = m_realm;

View File

@ -48,16 +48,14 @@ protected:
NativeFunction(DeprecatedFlyString name, JS::GCPtr<JS::HeapFunction<ThrowCompletionOr<Value>(VM&)>>, Object& prototype);
explicit NativeFunction(Object& prototype);
virtual void visit_edges(Cell::Visitor& visitor) override
{
Base::visit_edges(visitor);
visitor.visit(m_native_function);
}
virtual void initialize(Realm&) override;
virtual void visit_edges(Cell::Visitor& visitor) override;
private:
virtual bool is_native_function() const final { return true; }
DeprecatedFlyString m_name;
GCPtr<PrimitiveString> m_name_string;
Optional<DeprecatedFlyString> m_initial_name; // [[InitialName]]
JS::GCPtr<JS::HeapFunction<ThrowCompletionOr<Value>(VM&)>> m_native_function;
GCPtr<Realm> m_realm;

View File

@ -749,9 +749,9 @@ void VM::dump_backtrace() const
auto& frame = m_execution_context_stack[i];
if (frame->instruction_stream_iterator.has_value() && frame->instruction_stream_iterator->source_code()) {
auto source_range = frame->instruction_stream_iterator->source_range().realize();
dbgln("-> {} @ {}:{},{}", frame->function_name, source_range.filename(), source_range.start.line, source_range.start.column);
dbgln("-> {} @ {}:{},{}", frame->function_name ? frame->function_name->utf8_string() : ""_string, source_range.filename(), source_range.start.line, source_range.start.column);
} else {
dbgln("-> {}", frame->function_name);
dbgln("-> {}", frame->function_name ? frame->function_name->utf8_string() : ""_string);
}
}
}