Commit graph

115 commits

Author SHA1 Message Date
Linus Groh
e77503e49b LibJS: Make string_to_number() return double instead of Optional<Value>
This would never return an empty optional or non-numeric value, and in
fact every caller as_double()'d the value right away.
Let's make the type match reality instead :^)
2023-03-01 17:55:42 +00:00
Timothy Flynn
ba40ef1f3a LibJS: Remove Value::to_deprecated_string_without_side_effects 2023-02-16 14:32:22 +01:00
Timothy Flynn
24e9cea524 LibJS: Convert remaining usages of Value::TDSWOSE to Value::TSWOSE
Note the couple of cases using MUST are just debugging statements.
2023-02-16 14:32:22 +01:00
Timothy Flynn
3ffb6d9b5a LibJS: Define Value::to_string_without_side_effects for String 2023-02-16 14:32:22 +01:00
Timothy Flynn
dc4207323b LibJS: Remove the VM parameter from the NumberToString AO
This will be needed by Value::to_string_without_side_effects, which can
be called in contexts without a VM (e.g. in AK::Format specializations).
So to_string_without_side_effects will need to be callable without a VM,
thus NumberToString must be as well.
2023-02-16 14:32:22 +01:00
Timothy Flynn
b245300ba1 LibJS+Everywhere: Deprecate Value::to_string_without_side_effects 2023-02-16 14:32:22 +01:00
Timothy Flynn
1c1b902a6a LibJS+LibWeb: Move headers around to allow including Value from Cell
The goal here is to allow Cell::initialize to return a ThrowCompletion,
to handle OOM for example. Cell.h will then need to include Completion.h
which must include Value.h. This currently can't happen because Value.h
includes BigInt.h, which in turn includes Cell.h. So we would have an
include cycle.

This removes BigInt.h from Value.h, as it is forward-declarable (it is
only referred to with a reference or pointer). Then the Value overload
for Cell::Visitor::visit is moved to Cell.h, and missing BigInt.h
includes as peppered as needed.
2023-01-29 00:02:45 +00:00
Linus Groh
2ff989914d LibJS: Make Value::typeof() return a StringView 2023-01-26 17:26:31 +00:00
Timothy Flynn
c9056b824e LibJS: Define Value::to_string to convert a Value to a String 2023-01-15 01:00:20 +00:00
Timothy Flynn
afeb7273cc LibJS+Everywhere: Rename Value::to_string to to_deprecated_string 2023-01-15 01:00:20 +00:00
Timothy Flynn
0b58748156 LibJS: Define number_to_string to convert a double to a String 2023-01-15 01:00:20 +00:00
Timothy Flynn
8a88d4434f LibJS+LibWeb: Rename number_to_string to number_to_deprecated_string 2023-01-15 01:00:20 +00:00
Timothy Flynn
49b24b0968 LibJS: Let Utf16String be forward-declared in Value.h
It's only used as a template parameter, so let it be forward-declared.
Otherwise, we aren't able to include Completion.h in Utf16String.h, as
there would be a Utf16String -> Completion -> Value -> Utf16String
include cycle.
2023-01-08 12:13:15 +01:00
Ben Wiederhake
f07847e099 Everywhere: Remove unused includes of AK/Concepts.h
These instances were detected by searching for files that include
AK/Concepts.h, but don't match the regex:

\\b(AnyString|Arithmetic|ArrayLike|DerivedFrom|Enum|FallibleFunction|Flo
atingPoint|Fundamental|HashCompatible|Indexable|Integral|IterableContain
er|IteratorFunction|IteratorPairWith|OneOf|OneOfIgnoringCV|SameAs|Signed
|SpecializationOf|Unsigned|VoidFunction)\\b

(Without the linebreaks.)

This regex is pessimistic, so there might be more files that don't
actually use any concepts.

In theory, one might use LibCPP to detect things like this
automatically, but let's do this one step after another.
2023-01-02 20:27:20 -05:00
Linus Groh
ff5882291f LibJS: Rename same_value_non_{numeric => number}() and handle BigInts
This is an editorial change in the ECMA-262 spec.

See: https://github.com/tc39/ecma262/commit/f660b14

Note that the explicit check for zero sign equality is no longer needed
as of b0d6399, which removed the ability of Crypto::SignedBigInteger to
represent negative zero.
2022-12-10 11:35:20 +00:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Linus Groh
d26aabff04 Everywhere: Run clang-format 2022-12-03 23:52:23 +00:00
davidot
54b2d8c1b8 LibJS: Reuse as_i32 in as_double in JS::Value
Since this might be complicated with NaN boxing keeping it as one
implementation makes this easier to check and change.
2022-11-17 16:05:20 +00:00
Timothy Flynn
9620a092de LibJS: Publicly expose double_to_string and rename it number_to_string
Rename it to match the name used by the spec.

Add an override mode to skip formatting numbers with an exponential sign
(e.g. 1e23). This mode is needed by Number and Intl.NumberFormat, who
don't call out a specific number-to-string method to use (they just say
to make "the String consisting of the digits of n").
2022-11-04 21:12:10 +00:00
Timothy Flynn
e952dca026 LibJS: Expose the StringToNumber AO for public use
This will be needed outside of Value.cpp.
2022-10-15 18:05:02 +02:00
Linus Groh
d3b7c06712 LibJS: Add Value(GCPtr<T>) and Value(NonnullGCPtr<T>) constructors
Let's avoid reaching for ptr() as much as possible.
2022-10-02 23:02:27 +01:00
Daniel Bertalan
2b69af2dfe AK+LibJS: Handle NaN-boxing pointers on AArch64
JS::Value stores 48 bit pointers to separately allocated objects in its
payload. On x86-64, canonical addresses have their top 16 bits set to
the same value as bit 47, effectively meaning that the value has to be
sign-extended to get the pointer. AArch64, however, expects the topmost
bits to be all zeros.

This commit gates sign extension behind `#if ARCH(X86_64)`, and adds an
`#error` for unsupported architectures, so that we do not forget to
think about pointer handling when porting to a new architecture.

Fixes #15290
Fixes SerenityOS/ladybird#56
2022-09-21 11:55:57 +02:00
davidot
d4736d17ae LibJS: Allow negative pointers in Value
Also ensure that all a nullptr input gives null object and you don't
accidentally dereference a nullptr.
2022-09-10 00:05:32 +01:00
Linus Groh
69415f0608 LibJS: Make string_to_bigint() a standalone function
This now matches the newly added string_to_number().
2022-08-30 10:30:54 +01:00
davidot
a9d2d806b6 LibJS: Use __builtin_isnan in static_assert instead of isnan
For the fuzzer build isnan was not usable in a constexpr context however
__builtin_isnan seems to always be.

Also while we're here add my name to the copyright since I forgot after
the Value rewrite.
2022-08-23 22:30:15 +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
davidot
e746360b9a LibJS: Use NaN boxing to decrease the memory size of Values
Using the fact that there are 2^52-2 NaN representations we can
"NaN-box" all the Values possible. This means that Value no longer has
an explicit "Type" but that information is now stored in the bits of a
double. This is done by "tagging" the top two bytes of the double.
For a full explanation see the large comment with asserts at the top of
Value.

We can also use the exact representation of the tags to make checking
properties like nullish, or is_cell quicker. But the largest gains are
in the fact that the size of a Value is now halved.

The SunSpider and other benchmarks have been ran to confirm that there
are no regressions in performance compared to the previous
implementation. The tests never performed worse and in some cases
performed better. But the biggest differences can be seen in memory
usage when large arrays are allocated. A simple test which allocates a
1000 arrays of size 100000 has roughly half the memory usage.

There is also space in the representations for future expansions such as
tuples and records.

To ensure that Values on the stack and registers are not lost during
garbage collection we also have to add a check to the Heap to check for
any of the cell tags and extracting the canonical form of the pointer
if it matches.
2022-08-15 17:11:25 +02:00
davidot
8381e7f1e6 LibJS: Specialize Optional<Value>
Values can be "empty" which only has a valid meaning for array holes.
We can however use this state the represent the empty state of an
Optional<Value> which is used in a lot of placed, because of Completion
having one.
This saves 8 bytes for every Optional<Value>.
2022-08-15 17:11:25 +02:00
Linus Groh
1132151f3d LibJS: Use a template for 'Value from integral number' constructors
This also allows constructing from other integral types like u64, which
would have been ambiguous before (at least on i686):

```
error: call of overloaded 'Value(u64&)' is ambiguous
note: candidate: 'JS::Value::Value(i32)'
  175 |     explicit Value(i32 value)
      |              ^~~~~
note: candidate: 'JS::Value::Value(unsigned int)'
  164 |     explicit Value(unsigned value)
      |              ^~~~~
note: candidate: 'JS::Value::Value(long unsigned int)'
  153 |     explicit Value(unsigned long value)
      |              ^~~~~
note: candidate: 'JS::Value::Value(double)'
  141 |     explicit Value(double value)
      |              ^~~~~
```
2022-07-04 10:10:11 +02:00
Obinna Ikeh
3d99e83a86 LibJS: Update order of parameters in our is_less_than implementation
This change updates the parameter order of the is_less_than function
signature and calls to match accordingly with the spec
(https://tc39.es/ecma262/#sec-islessthan)
2022-06-13 17:37:11 -07:00
Linus Groh
b9b3d01bea LibJS: Add variant of to_integer_or_infinity() for plain doubles
In many cases we already know a certain value is a number, or don't have
JS values at all and would need to wrap doubles in a value. To optimize
these cases and avoid having to pass a global object into functions that
won't ever allocate or throw, add a standalone implementation of this
function that takes and returns doubles directly.
2022-05-06 22:32:47 +02:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Andreas Kling
4b412e8fee Revert "LibJS: Get rid of unnecessary work from canonical_numeric_index_string"
This reverts commit 3a184f7841.

This broke a number of test262 tests under "TypedArrayConstructors".
The issue is that the CanonicalNumericIndexString AO should not fail
for inputs like "1.1", despite them not being integral indices.
2022-02-13 16:01:32 +01:00
Anonymous
d1cc67bbe1 LibJS: Avoid unnecessary ToObject conversion when resolving references
When performing GetValue on a primitive type we do not need to perform
the ToObject conversion as it will resolve to a property on the
prototype object.

To avoid this we skip the initial ToObject conversion on the base value
as it only serves to get the primitive's boxed prototype. We further
specialize on PrimitiveString in order to get efficient behaviour
behaviour for the direct properties.

Depending on the tests anywhere from 20 to 60%, with significant loop
overhead.
2022-02-13 14:44:36 +01:00
Anonymous
3a184f7841 LibJS: Get rid of unnecessary work from canonical_numeric_index_string
The spec version of canonical_numeric_index_string is absurdly complex,
and ends up converting from a string to a number, and then back again
which is both slow and also requires a few allocations and a string
compare.

Instead lets use the logic we already have as that is much more
efficient.

This improves performance of all non-numeric property names.
2022-02-13 14:44:36 +01: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
Timothy Flynn
281b0411f2 LibJS: Implement conversion of strings to BigInts according to the spec
The spec defines a StringToBigInt AO which allows for converting binary,
octal, decimal, and hexadecimal strings to a BigInt. Our conversion was
only allowing for decimal strings.
2022-01-31 17:50:54 +00:00
Timothy Flynn
236025df19 LibJS: Prevent implicit pointer-to-bool conversion in Value constructor
For example, say you try to create a Value from an Array and forgot to
include LibJS/Runtime/Array.h. This would cause the boolean constructor
to be used instead of a compile error.
2022-01-27 16:27:00 +00:00
Andreas Kling
216e21a1fa AK: Convert AK::Format formatting helpers to returning ErrorOr<void>
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
2021-11-17 00:21:13 +01:00
Andreas Kling
65a7296b8f LibJS: Make Value::to_property_key() return a JS::PropertyKey
Instead of returning JS::StringOrSymbol, which is a space-optimized type
used in Shape property tables, this now returns JS::PropertyKey which is
*not* space-optimized, but has other niceties like optimized storage of
numeric ("indexed") properties.
2021-10-24 17:18:09 +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
545d403f6b LibJS: Convert Value operator AOs to ThrowCompletionOr 2021-10-18 23:06:11 +01:00
Idan Horowitz
48ac15758e LibJS: Convert is_loosely_equal() to ThrowCompletionOr 2021-10-18 23:06:11 +01:00
Idan Horowitz
b5e28410c5 LibJS: Convert is_less_than() to ThrowCompletionOr 2021-10-18 23:06:11 +01:00
Idan Horowitz
c15a3b0576 LibJS: Convert Value::get() to ThrowCompletionOr 2021-10-18 23:06:11 +01:00
Linus Groh
be28a6142b LibJS: Convert to_integer_or_infinity() to ThrowCompletionOr 2021-10-18 21:24:30 +01:00
Idan Horowitz
85a28a6555 LibJS: Convert to_index() to ThrowCompletionOr 2021-10-18 08:01:38 +03:00
Idan Horowitz
aad12b050b LibJS: Convert to_length() to ThrowCompletionOr 2021-10-18 08:01:38 +03:00
Idan Horowitz
750da61c0f LibJS: Convert to_u8_clamp() to ThrowCompletionOr 2021-10-18 08:01:38 +03:00