Before this change, each AST node had a 64-byte SourceRange member.
This SourceRange had the following layout:
filename: StringView (16 bytes)
start: Position (24 bytes)
end: Position (24 bytes)
The Position structs have { line, column, offset }, all members size_t.
To reduce memory consumption, AST nodes now only store the following:
source_code: NonnullRefPtr<SourceCode> (8 bytes)
start_offset: u32 (4 bytes)
end_offset: u32 (4 bytes)
SourceCode is a new ref-counted data structure that keeps the filename
and original parsed source code in a single location, and all AST nodes
have a pointer to it.
The start_offset and end_offset can be turned into (line, column) when
necessary by calling SourceCode::range_from_offsets(). This will walk
the source code string and compute line/column numbers on the fly, so
it's not necessarily fast, but it should be rare since this information
is primarily used for diagnostics and exception stack traces.
With this, ASTNode shrinks from 80 bytes to 32 bytes. This gives us a
~23% reduction in memory usage when loading twitter.com/awesomekling
(330 MiB before, 253 MiB after!) :^)
We can't be nuking the ESO while its owned execution context is still on
the VM's execution context stack, as that may lead to a use-after-free.
This patch solves this by adding a `context_owner` field to each context
and treating it as a GC root.
We were mistakenly trying to append UTF-16 code units to a StringBuilder
via the append(char) API. This patch fixes that by accumulating the
result in a Vector<u16> instead.
This'll be a bit worse for performance, since we're now doing additional
UTF-16 string conversions, but we're going for correctness at this stage
and can worry about performance later.
These lambdas were marked mutable as they captured a Ptr wrapper
class by value, which then only returned const-qualified references
to the value they point from the previous const pointer operators.
Nothing is actually mutating in the lambdas state here, and now
that the Ptr operators don't add extra const qualifiers these
can be removed.
Even if the pointer value is const, the value they point to is not
necessarily const, so these functions should not add the qualifier.
This also removes the redundant non-const implementations of these
operators.
Before this could give the `must be followed by in` error before the
undeclared private identifier error. Fixing the `in` error would not
have resolved the other error so this order makes the errors more
actionable.
If we don't check that a private identifier is valid this can break the
assumption that we have a private environment when evaluation the
private identifier. Also an unknown private identifier this should
be a SyntaxError.
This is only visible with something like `Object.getOwnPropertyNames` on
the global object. All other declaration instantiations put the
functions on an environment making the order invisible.
Note that spec order is not quite tree order as in non-strict mode
functions which get hoisted out of blocks appear before top level
functions.
Co-authored-by: Hendiadyoin1 <leon.a@serenityos.org>
This has to get quite messy because we currently do evaluation to value
and reference separately meaning we have to deal with a lot of edge
cases here.
Before this change we would ignore that the second backslash is escaped
and template strings ending with ` \\` would be unterminated as the
second slash was used to escape the closing quote.
This means that rather than this:
```
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false,
false, true, FunctionAddress);
```
We now have this:
```
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, FunctionAddress, Arithmetic,
Comparison, Increment);
```
Which is a lot more readable. :^)
Co-authored-by: Ali Mohammad Pur <mpfard@serenityos.org>
This patch adds a special EnvironmentCoordinate::global_marker value
that signifies that a binding lookup ended up searching the global
environment. It doesn't matter if we find it there or not, the global
marker is always returned. This allows us to bypass other environments
on subsequent access, going directly to the global environment.
I wrote these tests a while ago while trying to improve the bytecode,
but didn't end up making them pass and gave up. They work in AST
interpreter mode, so we can have them in now to have them around for
anyone who wants to try and make them pass in bytecode.
C++20 can automatically synthesize `operator!=` from `operator==`, so
there is no point in writing such functions by hand if all they do is
call through to `operator==`.
This fixes a compile error with compilers that implement P2468 (Clang
16 currently). This paper restores the C++17 behavior that if both
`T::operator==(U)` and `T::operator!=(U)` exist, `U == T` won't be
rewritten in reverse to call `T::operator==(U)`. Removing `!=` operators
makes the rewriting possible again.
See https://reviews.llvm.org/D134529#3853062
This is an editorial change to the ECMA-402 spec. See:
46aa5cc
Also add an ECMA-402 spec link to the DefaultTimeZone implementation, as
that definition supersedes ECMA-262.