mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:07:45 +00:00
LibJS: Don't create lexical environment for native (C++) function calls
This was creating a ton of pointless busywork for the garbage collector and can be avoided simply by tolerating that the current call frame has a null scope object for the duration of a NativeFunction activation.
This commit is contained in:
parent
d0bed24ca1
commit
d69cd3f5bf
2 changed files with 16 additions and 9 deletions
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/LexicalEnvironment.h>
|
|
||||||
#include <LibJS/Runtime/NativeFunction.h>
|
#include <LibJS/Runtime/NativeFunction.h>
|
||||||
#include <LibJS/Runtime/Value.h>
|
#include <LibJS/Runtime/Value.h>
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ Value NativeFunction::construct(Function&)
|
||||||
|
|
||||||
LexicalEnvironment* NativeFunction::create_environment()
|
LexicalEnvironment* NativeFunction::create_environment()
|
||||||
{
|
{
|
||||||
return heap().allocate<LexicalEnvironment>(global_object(), LexicalEnvironment::EnvironmentRecordType::Function);
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeFunction::is_strict_mode() const
|
bool NativeFunction::is_strict_mode() const
|
||||||
|
|
|
@ -399,12 +399,14 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
|
||||||
call_frame.arguments.append(arguments.value().values());
|
call_frame.arguments.append(arguments.value().values());
|
||||||
auto* environment = function.create_environment();
|
auto* environment = function.create_environment();
|
||||||
call_frame.scope = environment;
|
call_frame.scope = environment;
|
||||||
environment->set_new_target(&new_target);
|
if (environment)
|
||||||
|
environment->set_new_target(&new_target);
|
||||||
|
|
||||||
Object* new_object = nullptr;
|
Object* new_object = nullptr;
|
||||||
if (function.constructor_kind() == Function::ConstructorKind::Base) {
|
if (function.constructor_kind() == Function::ConstructorKind::Base) {
|
||||||
new_object = Object::create_empty(global_object);
|
new_object = Object::create_empty(global_object);
|
||||||
environment->bind_this_value(global_object, new_object);
|
if (environment)
|
||||||
|
environment->bind_this_value(global_object, new_object);
|
||||||
if (exception())
|
if (exception())
|
||||||
return {};
|
return {};
|
||||||
auto prototype = new_target.get(names.prototype);
|
auto prototype = new_target.get(names.prototype);
|
||||||
|
@ -422,15 +424,18 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
|
||||||
call_frame.this_value = this_value;
|
call_frame.this_value = this_value;
|
||||||
auto result = function.construct(new_target);
|
auto result = function.construct(new_target);
|
||||||
|
|
||||||
this_value = call_frame.scope->get_this_binding(global_object);
|
if (environment)
|
||||||
|
this_value = environment->get_this_binding(global_object);
|
||||||
pop_call_frame();
|
pop_call_frame();
|
||||||
call_frame_popper.disarm();
|
call_frame_popper.disarm();
|
||||||
|
|
||||||
// If we are constructing an instance of a derived class,
|
// If we are constructing an instance of a derived class,
|
||||||
// set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
|
// set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
|
||||||
if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
|
if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
|
||||||
VERIFY(is<LexicalEnvironment>(current_scope()));
|
if (environment) {
|
||||||
static_cast<LexicalEnvironment*>(current_scope())->replace_this_binding(result);
|
VERIFY(is<LexicalEnvironment>(current_scope()));
|
||||||
|
static_cast<LexicalEnvironment*>(current_scope())->replace_this_binding(result);
|
||||||
|
}
|
||||||
auto prototype = new_target.get(names.prototype);
|
auto prototype = new_target.get(names.prototype);
|
||||||
if (exception())
|
if (exception())
|
||||||
return {};
|
return {};
|
||||||
|
@ -507,8 +512,11 @@ Value VM::call_internal(Function& function, Value this_value, Optional<MarkedVal
|
||||||
auto* environment = function.create_environment();
|
auto* environment = function.create_environment();
|
||||||
call_frame.scope = environment;
|
call_frame.scope = environment;
|
||||||
|
|
||||||
VERIFY(environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
|
if (environment) {
|
||||||
environment->bind_this_value(function.global_object(), call_frame.this_value);
|
VERIFY(environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
|
||||||
|
environment->bind_this_value(function.global_object(), call_frame.this_value);
|
||||||
|
}
|
||||||
|
|
||||||
if (exception())
|
if (exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue