Commit graph

65 commits

Author SHA1 Message Date
Andreas Kling
3c74dc9f4d LibJS: Segregate GC-allocated objects by type
This patch adds two macros to declare per-type allocators:

- JS_DECLARE_ALLOCATOR(TypeName)
- JS_DEFINE_ALLOCATOR(TypeName)

When used, they add a type-specific CellAllocator that the Heap will
delegate allocation requests to.

The result of this is that GC objects of the same type always end up
within the same HeapBlock, drastically reducing the ability to perform
type confusion attacks.

It also improves HeapBlock utilization, since each block now has cells
sized exactly to the type used within that block. (Previously we only
had a handful of block sizes available, and most GC allocations ended
up with a large amount of slack in their tails.)

There is a small performance hit from this, but I'm sure we can make
up for it elsewhere.

Note that the old size-based allocators still exist, and we fall back
to them for any type that doesn't have its own CellAllocator.
2023-11-19 12:10:31 +01:00
Andreas Kling
18c54d8d40 LibJS: Make Cell::initialize() return void
Stop worrying about tiny OOMs.

Work towards #20405
2023-08-08 07:39:11 +02:00
Timothy Flynn
2692db8699 LibJS+Everywhere: Allow Cell::initialize overrides to throw OOM errors
Note that as of this commit, there aren't any such throwers, and the
call site in Heap::allocate will drop exceptions on the floor. This
commit only serves to change the declaration of the overrides, make sure
they return an empty value, and to propagate OOM errors frm their base
initialize invocations.
2023-01-29 00:02:45 +00:00
Andreas Kling
35c9aa7c05 LibJS: Hide all the constructors!
Now that the GC allocator is able to invoke Cell subclass constructors
directly via friendship, we no longer need to keep them public. :^)
2022-08-29 03:24:54 +02:00
Linus Groh
040e3abb1d LibJS: Implement SetDefaultGlobalBindings as a standalone function
Instead of hardcoding all the property definitions in GlobalObject's
initialize() function, make it the standalone AO it is supposed to be
that can then be used by other global objects that don't inherit from
JS::GlobalObject.
2022-08-28 19:34:10 +01:00
Linus Groh
e3804e6426 LibJS: Move construction of GlobalObject native functions to Intrinsics
This will later allow global objects not inheriting from the regular
JS::GlobalObject to pull in these functions without having to implement
them from scratch. The primary use case here is, again, a wrapper-less
HTML::Window in LibWeb :^)

Allocating these upfront now allows us to get rid of two hacks:

- The GlobalObject assigning Intrinsics private members after finishing
  its initialization
- The GlobalObject defining the parseInt and parseFloat properties of
  the NumberConstructor object, as they are supposed to be identical
  with the global functions of the same name
2022-08-28 19:34:10 +01:00
Linus Groh
72730422bb LibJS: Remove Shape::global_object() and Object::global_object()
Same reason as in commit 275dea9.
2022-08-28 16:36:56 +01:00
Linus Groh
cfa5885855 LibJS: Turn initialize_global_object() into a regular initialize()
There's nothing special about global object initialization anymore, this
can just work the same way as for any other object now.
2022-08-28 16:36:56 +01:00
Linus Groh
867ad03995 LibJS: Move Console ownership from GlobalObject to ConsoleObject
GlobalObject is now a regular object with no special properties :^)
2022-08-28 16:36:56 +01:00
Linus Groh
dfb7588d30 LibJS: Remove GlobalObject::{set_,}associated_realm() 2022-08-27 11:29:10 +01:00
Linus Groh
50428ea8d2 LibJS: Move intrinsics to the realm
Intrinsics, i.e. mostly constructor and prototype objects, but also
things like empty and new object shape now live on a new heap-allocated
JS::Intrinsics object, thus completing the long journey of taking all
the magic away from the global object.
This represents the Realm's [[Intrinsics]] slot in the spec and matches
its existing [[GlobalObject]] / [[GlobalEnv]] slots in terms of
architecture.

In the majority of cases it should now be possibly to fully allocate a
regular object without the global object existing, and in fact that's
what we do now - the realm is allocated before the global object, and
the intrinsics between both :^)
2022-08-27 11:29:10 +01:00
Linus Groh
7c468b5a77 LibJS: Pass Realm to GlobalObject::initialize_global_object()
Global object initialization is tightly coupled to realm creation, so
simply pass it to the function instead of relying on the non-standard
'associated realm' concept, which I'd like to remove later.

This works essentially the same way as regular Object::initialize() now.

Additionally this allows us to forward the realm to GlobalObject's
add_constructor() / initialize_constructor() helpers, so they set the
correct realm on the allocated constructor function object.
2022-08-23 13:58:30 +01:00
Linus Groh
a022e548b8 LibJS: Replace GlobalObject with VM in Value AOs [Part 4/19]
This is where the fun begins. :^)
2022-08-23 13:58:30 +01:00
Linus Groh
e992a9f469 LibJS+LibWeb: Replace GlobalObject with Realm in Heap::allocate<T>()
This is a continuation of the previous three commits.

Now that create() receives the allocating realm, we can simply forward
that to allocate(), which accounts for the majority of these changes.
Additionally, we can get rid of the realm_from_global_object() in one
place, with one more remaining in VM::throw_completion().
2022-08-23 13:58:30 +01:00
Linus Groh
ecd163bdf1 LibJS+LibWeb: Replace GlobalObject with Realm in object constructors
No functional changes - we can still very easily get to the global
object via `Realm::global_object()`. This is in preparation of moving
the intrinsics to the realm and no longer having to pass a global
object when allocating any object.
In a few (now, and many more in subsequent commits) places we get a
realm using `GlobalObject::associated_realm()`, this is intended to be
temporary. For example, create() functions will later receive the same
treatment and are passed a realm instead of a global object.
2022-08-23 13:58:30 +01:00
Andreas Kling
50d951aea2 LibJS: Let Shape store a Realm instead of a GlobalObject
This is a cautious first step towards being able to create JS objects
before a global object has been instantiated.
2022-08-05 12:42:46 +02:00
Linus Groh
dd547c3374 LibJS: Add getters for %{Async,}GeneratorFunction.prototype.prototype%
These exist as {Async,}GeneratorPrototype of course, but the spec
doesn't always refer to them by the direct name.
2022-05-05 22:40:57 +02:00
Linus Groh
0c65624a32 LibJS: Add AsyncGenerator / AsyncGeneratorPrototype
Not implementing any prototype functions yet, but stubbing out async
generator infrastructure will allow us to make some progress in that
direction.
2022-05-05 22:40:57 +02:00
Linus Groh
2c68ec9097 LibJS: Use Object* for 'manual' GlobalObject::foo_prototype() getters
Not doing so only leads to problems down the line, e.g. not being able
to pass them as function pointers to ordinary_create_from_constructor().
2022-05-05 22:40:57 +02:00
Linus Groh
00b8ce4a6d LibJS: Pass this value to fallback func in Array.prototype.toString()
The existing code looks innocently correct, implementing the following
step:

    3. If IsCallable(func) is false, set func to the intrinsic function
       %Object.prototype.toString%.

as

    return ObjectPrototype::to_string(vm, global_object);

However, this misses the fact that the next step calls the function with
the previously ToObject()'d this value (`array`):

    4. Return ? Call(func, array).

This doesn't happen in the current implementation, which will use the
unaltered this value from the Array.prototype.toString() call, and make
another, unequal object in %Object.prototype.toString%. Since both that
and Array.prototype.toString() do a Get() call on said object, this
behavior is observable (see newly added test).

Fix this by actually doing what the spec says and calling the fallback
function the regular way.
2022-04-12 00:23:27 +01:00
Idan Horowitz
08d1ae58b1 LibJS: Initialize {Async,}{Generator,}Function constructors properly
We were previously manually initializing them instead of just calling
GlobalObject::initialize_constructor, which aside from duplicating code
also meant we didn't set the required name property.
2022-02-19 18:06:39 +00:00
Linus Groh
bc183dbbcb LibJS: Replace uses of MarkedValueList with MarkedVector<Value>
This is effectively a drop-in replacement.
2022-02-09 12:25:27 +00:00
Linus Groh
6f20f49b21 Everywhere: Rename JS::PropertyKey variables from property_{name => key}
PropertyKey used to be called PropertyName, but got renamed. Let's
update all the variables of this type as well.
2022-02-06 22:02:45 +00:00
Idan Horowitz
bbacea255f LibJS: Start implementing Intl Segments objects 2022-01-30 19:47:01 +00:00
davidot
202de6ed25 LibJS: Expose JSON.parse as an intrinsic value of the global object
This will allow us to safely call it if we need to parse JSON within
LibJS.
2022-01-30 17:40:20 +00:00
Linus Groh
4ed49e05a9 LibJS: Rename GeneratorObjectPrototype to GeneratorPrototype
Given we usually call objects Foo{Object,Constructor,Prototype} or
Foo{,Constructor,Prototype}, this name was an odd choice.
The new one matches the spec better, which calls it the "Generator
Prototype Object", so we simply omit the Object suffix as usual as it's
implied.
2022-01-16 14:50:22 +01:00
Timothy Flynn
4cc8cf9233 LibJS: Add an accessor for the %Date.now% instrinsic property 2021-12-08 11:29:36 +00:00
davidot
064c8be627 LibJS: Add AsyncFromSyncIteratorPrototype and Async-From-Sync instances
Until we have actual iterator records we have to store the sync iterator
as the raw object.
2021-11-29 15:20:07 +00:00
Luke Wilde
3666d2132b LibJS: Remove fallback value for get_offset_nanoseconds_for
This is a normative change in the Temporal spec.

See: https://github.com/tc39/proposal-temporal/commit/664f02d

Note that the tests are not comprehensive.
2021-11-17 11:30:13 +00:00
Linus Groh
27d84bebd4 LibJS: Remove redundant exception checks from initialize_constructor()
define_direct_property() simply wraps storage_set(), which cannot throw.
2021-11-14 16:14:38 +00:00
Timothy Flynn
e92d14d498 LibJS: Convert GlobalObject to ThrowCompletionOr 2021-10-31 07:50:30 +02:00
Andreas Kling
398c181c79 LibJS: Rename PropertyName to PropertyKey
Let's use the same name as the spec. :^)
2021-10-24 17:18:07 +02:00
Idan Horowitz
20163c0584 LibJS: Add ThrowCompletionOr versions of the JS native function macros
The old versions were renamed to JS_DECLARE_OLD_NATIVE_FUNCTION and
JS_DEFINE_OLD_NATIVE_FUNCTION, and will be eventually removed once all
native functions were converted to the new format.
2021-10-20 12:27:19 +01:00
Linus Groh
cbbf4abb0d LibJS: Add a way to get from a GlobalObject to its associated Realm
This is just another workaround, but it should be much more reliable
than Interpreter::realm(), especially when allocating NativeFunctions
and ECMAScriptFunctionObjects: we're guaranteed to have a GlobalObject
at that point, and it likely was set as the GlobalObject of a Realm and
can lead us back to it. We're however not guaranteed that the VM can
give us an Interpreter, which is why functions in LibWeb can be a bit
crashy at the moment.

We use a WeakPtr<Realm> to properly handle the unlikely case where the
Realm goes away after associating a GlobalObject to it.

We'll always need _something_ of this sort if we want to support
OrdinaryFunctionCreate and CreateBuiltinFunction without the explicit
realm argument while no JS is running, because they want to use the
current Realm Record (always in the first and as fallback in the second
case).
2021-10-14 23:02:19 +01:00
Andreas Kling
14c57b4b7f LibJS: Remove transition avoidance & start caching prototype transitions
The way that transition avoidance (foo_without_transition) was
implemented led to shapes being unshareable and caused shape explosion
instead, precisely what we were trying to avoid.

This patch removes all the attempts to avoid transitioning shapes, and
instead *adds* transitions when changing an object's prototype.
This makes transitions flow naturally, and as a result we end up with
way fewer shape objects in real-world situations.

When we run out of big problems, we can get back to avoiding transitions
as an optimization, but for now, let's avoid ballooning our processes
with a unique shape for every object.
2021-10-01 02:59:29 +02:00
Idan Horowitz
ab594e5f2f LibJS: Convert Value::invoke and VM::call to ThrowCompletionOr 2021-09-23 23:59:13 +03:00
Linus Groh
f29a82dd84 LibJS: Move the GlobalEnvironment from GlobalObject to Realm
This is where the spec wants to have it. Requires a couple of hacks as
currently everything that needs a Realm actually has a GlobalObject, so
we need to go via the Interpreter.
2021-09-12 11:10:20 +01:00
Linus Groh
45eef97906 LibJS: Avoid transitions in GlobalObject::initialize_constructor()
We don't need transitions for either of these:

- Adding the 'name' property to a constructor object
- Adding the 'constructor' property to its prototype object
2021-08-28 23:17:01 +01:00
davidot
151447bdf7 LibJS: Move Object::invoke to Value::invoke and fix it for primitives
This is a tiny difference and only changes anything for primitives in
strict mode. However this is tested in test262 and can be noticed by
overriding toString of primitive values.

This does now require one to wrap an object in a Value to call invoke
but all code using invoke has been migrated.
2021-08-09 17:33:14 +01:00
Linus Groh
44a8b55c50 LibJS: Add preparation for Intl constructors and prototypes
Add a JS_ENUMERATE_INTL_OBJECTS macro and use it to generate:

- Forward declarations
- CommonPropertyNames class name members
- Constructor and prototype GlobalObject members, getters, visitors,
  and initialize_constructor() calls
2021-08-08 20:14:59 +01:00
Linus Groh
c303bbde54 LibJS: Implement Temporal.Now.plainDate()
...and ten required AOs we didn't have yet:

- BalanceISODate
- BalanceISODateTime
- BalanceISOYearMonth
- BalanceTime
- BuiltinTimeZoneGetPlainDateTimeFor
- GetISOPartsFromEpoch
- GetOffsetNanosecondsFor
- ParseTemporalTimeZone
- SystemDateTime
- ToTemporalTimeZone
2021-07-27 19:51:44 +01:00
Linus Groh
1c1354db07 LibJS: Store the %Array.prototype.values% intrinsic on the global object
Also group the getter functions for all the additional intrinsics (not
generated via macros), and initialize the members.
2021-07-25 23:44:36 +01:00
Linus Groh
6735353b96 LibJS: Add preparation for Temporal constructors and prototypes
Add a JS_ENUMERATE_TEMPORAL_OBJECTS macro and use it to generate:

- Forward declarations
- CommonPropertyNames class name members
- Constructor and prototype GlobalObject members, getters, visitors,
  and initialize_constructor() calls
2021-07-07 00:42:01 +01:00
Idan Horowitz
a6b8291a9b LibJS: Add define_direct_property and remove the define_property helper
This removes all usages of the non-standard define_property helper
method and replaces all it's usages with the specification required
alternative or with define_direct_property where appropriate.
2021-07-06 14:20:30 +01:00
Andreas Kling
44221756ab LibJS: Drop "Record" suffix from all the *Environment record classes
"Records" in the spec are basically C++ classes, so let's drop this
mouthful of a suffix.
2021-07-01 12:28:57 +02:00
Idan Horowitz
e2e695bc9f LibJS: Add and use the %ThrowTypeError% intrinsic 2021-06-28 08:55:14 +01:00
Andreas Kling
c8270dbe2e LibJS: Rename ScriptFunction => OrdinaryFunctionObject
These are basically what the spec calls "ordinary function objects",
so let's have the name reflect that. :^)
2021-06-27 22:36:04 +02:00
Andreas Kling
ba9d5c4d54 LibJS: Rename Function => FunctionObject 2021-06-27 22:36:04 +02:00
Anonymous
2822da8c8f LibJS: Correct behaviour of direct vs. indirect eval
eval only has direct access to the local scope when accessed through
the name eval. This includes locals named eval, because of course it
does.
2021-06-23 09:38:33 +01:00
Andreas Kling
1f8b6ac3c3 LibJS: Begin implementing GlobalEnvironmentRecord
These represent the outermost scope in the environment record
hierarchy. The spec says they should be a "composite" of two things:

- An ObjectEnvironmentRecord wrapping the global object
- A DeclarativeEnvironmentRecord for other declarations

It's not yet clear to me how this should work, so this patch only
implements the first part, an object record wrapping the global object.
2021-06-22 18:44:53 +02:00