Reland "[base] Move most of src/numbers into base"
This is a reland of 9701d4a420
with a small fix for some code landed in between the dry-run and
submission.
Original change's description:
> [base] Move most of src/numbers into base
>
> Moves all but conversions.*, hash-seed-inl.h and math-random.* into
> base, in preparation for moving the parts of conversions that don't
> access HeapObjects.
>
> Also moves uc16 and uc32 out of commons/globals.h into base/strings.h.
>
> Bug: v8:11917
> Change-Id: Ife359148bb0961a63833aff40d26331454b6afb6
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2979595
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
> Auto-Submit: Dan Elphick <delphick@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#75354}
Bug: v8:11917
Change-Id: Ie1ec9032fe56646a7c7303185cecc70fce5694ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2982607
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75368}
This commit is contained in:
parent
84da489d08
commit
44e73e0b78
34
BUILD.bazel
34
BUILD.bazel
@ -246,6 +246,23 @@ filegroup(
|
|||||||
"src/base/logging.h",
|
"src/base/logging.h",
|
||||||
"src/base/macros.h",
|
"src/base/macros.h",
|
||||||
"src/base/memory.h",
|
"src/base/memory.h",
|
||||||
|
"src/base/numbers/bignum-dtoa.cc",
|
||||||
|
"src/base/numbers/bignum-dtoa.h",
|
||||||
|
"src/base/numbers/bignum.cc",
|
||||||
|
"src/base/numbers/bignum.h",
|
||||||
|
"src/base/numbers/cached-powers.cc",
|
||||||
|
"src/base/numbers/cached-powers.h",
|
||||||
|
"src/base/numbers/diy-fp.cc",
|
||||||
|
"src/base/numbers/diy-fp.h",
|
||||||
|
"src/base/numbers/double.h",
|
||||||
|
"src/base/numbers/dtoa.cc",
|
||||||
|
"src/base/numbers/dtoa.h",
|
||||||
|
"src/base/numbers/fast-dtoa.cc",
|
||||||
|
"src/base/numbers/fast-dtoa.h",
|
||||||
|
"src/base/numbers/fixed-dtoa.cc",
|
||||||
|
"src/base/numbers/fixed-dtoa.h",
|
||||||
|
"src/base/numbers/strtod.cc",
|
||||||
|
"src/base/numbers/strtod.h",
|
||||||
"src/base/once.cc",
|
"src/base/once.cc",
|
||||||
"src/base/once.h",
|
"src/base/once.h",
|
||||||
"src/base/optional.h",
|
"src/base/optional.h",
|
||||||
@ -1144,29 +1161,12 @@ filegroup(
|
|||||||
"src/logging/tracing-flags.h",
|
"src/logging/tracing-flags.h",
|
||||||
"src/logging/runtime-call-stats.h",
|
"src/logging/runtime-call-stats.h",
|
||||||
"src/logging/runtime-call-stats-scope.h",
|
"src/logging/runtime-call-stats-scope.h",
|
||||||
"src/numbers/bignum-dtoa.cc",
|
|
||||||
"src/numbers/bignum-dtoa.h",
|
|
||||||
"src/numbers/bignum.cc",
|
|
||||||
"src/numbers/bignum.h",
|
|
||||||
"src/numbers/cached-powers.cc",
|
|
||||||
"src/numbers/cached-powers.h",
|
|
||||||
"src/numbers/conversions-inl.h",
|
"src/numbers/conversions-inl.h",
|
||||||
"src/numbers/conversions.cc",
|
"src/numbers/conversions.cc",
|
||||||
"src/numbers/conversions.h",
|
"src/numbers/conversions.h",
|
||||||
"src/numbers/diy-fp.cc",
|
|
||||||
"src/numbers/diy-fp.h",
|
|
||||||
"src/numbers/double.h",
|
|
||||||
"src/numbers/dtoa.cc",
|
|
||||||
"src/numbers/dtoa.h",
|
|
||||||
"src/numbers/fast-dtoa.cc",
|
|
||||||
"src/numbers/fast-dtoa.h",
|
|
||||||
"src/numbers/fixed-dtoa.cc",
|
|
||||||
"src/numbers/fixed-dtoa.h",
|
|
||||||
"src/numbers/hash-seed-inl.h",
|
"src/numbers/hash-seed-inl.h",
|
||||||
"src/numbers/math-random.cc",
|
"src/numbers/math-random.cc",
|
||||||
"src/numbers/math-random.h",
|
"src/numbers/math-random.h",
|
||||||
"src/numbers/strtod.cc",
|
|
||||||
"src/numbers/strtod.h",
|
|
||||||
"src/objects/all-objects-inl.h",
|
"src/objects/all-objects-inl.h",
|
||||||
"src/objects/allocation-site-inl.h",
|
"src/objects/allocation-site-inl.h",
|
||||||
"src/objects/allocation-site-scopes-inl.h",
|
"src/objects/allocation-site-scopes-inl.h",
|
||||||
|
34
BUILD.gn
34
BUILD.gn
@ -2815,19 +2815,10 @@ v8_header_set("v8_internal_headers") {
|
|||||||
"src/logging/runtime-call-stats-scope.h",
|
"src/logging/runtime-call-stats-scope.h",
|
||||||
"src/logging/runtime-call-stats.h",
|
"src/logging/runtime-call-stats.h",
|
||||||
"src/logging/tracing-flags.h",
|
"src/logging/tracing-flags.h",
|
||||||
"src/numbers/bignum-dtoa.h",
|
|
||||||
"src/numbers/bignum.h",
|
|
||||||
"src/numbers/cached-powers.h",
|
|
||||||
"src/numbers/conversions-inl.h",
|
"src/numbers/conversions-inl.h",
|
||||||
"src/numbers/conversions.h",
|
"src/numbers/conversions.h",
|
||||||
"src/numbers/diy-fp.h",
|
|
||||||
"src/numbers/double.h",
|
|
||||||
"src/numbers/dtoa.h",
|
|
||||||
"src/numbers/fast-dtoa.h",
|
|
||||||
"src/numbers/fixed-dtoa.h",
|
|
||||||
"src/numbers/hash-seed-inl.h",
|
"src/numbers/hash-seed-inl.h",
|
||||||
"src/numbers/math-random.h",
|
"src/numbers/math-random.h",
|
||||||
"src/numbers/strtod.h",
|
|
||||||
"src/objects/all-objects-inl.h",
|
"src/objects/all-objects-inl.h",
|
||||||
"src/objects/allocation-site-inl.h",
|
"src/objects/allocation-site-inl.h",
|
||||||
"src/objects/allocation-site-scopes-inl.h",
|
"src/objects/allocation-site-scopes-inl.h",
|
||||||
@ -3908,16 +3899,8 @@ v8_source_set("v8_base_without_compiler") {
|
|||||||
"src/logging/metrics.cc",
|
"src/logging/metrics.cc",
|
||||||
"src/logging/runtime-call-stats.cc",
|
"src/logging/runtime-call-stats.cc",
|
||||||
"src/logging/tracing-flags.cc",
|
"src/logging/tracing-flags.cc",
|
||||||
"src/numbers/bignum-dtoa.cc",
|
|
||||||
"src/numbers/bignum.cc",
|
|
||||||
"src/numbers/cached-powers.cc",
|
|
||||||
"src/numbers/conversions.cc",
|
"src/numbers/conversions.cc",
|
||||||
"src/numbers/diy-fp.cc",
|
|
||||||
"src/numbers/dtoa.cc",
|
|
||||||
"src/numbers/fast-dtoa.cc",
|
|
||||||
"src/numbers/fixed-dtoa.cc",
|
|
||||||
"src/numbers/math-random.cc",
|
"src/numbers/math-random.cc",
|
||||||
"src/numbers/strtod.cc",
|
|
||||||
"src/objects/backing-store.cc",
|
"src/objects/backing-store.cc",
|
||||||
"src/objects/bigint.cc",
|
"src/objects/bigint.cc",
|
||||||
"src/objects/code-kind.cc",
|
"src/objects/code-kind.cc",
|
||||||
@ -4669,6 +4652,23 @@ v8_component("v8_libbase") {
|
|||||||
"src/base/logging.h",
|
"src/base/logging.h",
|
||||||
"src/base/macros.h",
|
"src/base/macros.h",
|
||||||
"src/base/memory.h",
|
"src/base/memory.h",
|
||||||
|
"src/base/numbers/bignum-dtoa.cc",
|
||||||
|
"src/base/numbers/bignum-dtoa.h",
|
||||||
|
"src/base/numbers/bignum.cc",
|
||||||
|
"src/base/numbers/bignum.h",
|
||||||
|
"src/base/numbers/cached-powers.cc",
|
||||||
|
"src/base/numbers/cached-powers.h",
|
||||||
|
"src/base/numbers/diy-fp.cc",
|
||||||
|
"src/base/numbers/diy-fp.h",
|
||||||
|
"src/base/numbers/double.h",
|
||||||
|
"src/base/numbers/dtoa.cc",
|
||||||
|
"src/base/numbers/dtoa.h",
|
||||||
|
"src/base/numbers/fast-dtoa.cc",
|
||||||
|
"src/base/numbers/fast-dtoa.h",
|
||||||
|
"src/base/numbers/fixed-dtoa.cc",
|
||||||
|
"src/base/numbers/fixed-dtoa.h",
|
||||||
|
"src/base/numbers/strtod.cc",
|
||||||
|
"src/base/numbers/strtod.h",
|
||||||
"src/base/once.cc",
|
"src/base/once.cc",
|
||||||
"src/base/once.h",
|
"src/base/once.h",
|
||||||
"src/base/optional.h",
|
"src/base/optional.h",
|
||||||
|
@ -85,7 +85,7 @@ void AsmJsScanner::Next() {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
position_ = stream_->pos();
|
position_ = stream_->pos();
|
||||||
uc32 ch = stream_->Advance();
|
base::uc32 ch = stream_->Advance();
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
@ -223,7 +223,7 @@ void AsmJsScanner::Seek(size_t pos) {
|
|||||||
Next();
|
Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsmJsScanner::ConsumeIdentifier(uc32 ch) {
|
void AsmJsScanner::ConsumeIdentifier(base::uc32 ch) {
|
||||||
// Consume characters while still part of the identifier.
|
// Consume characters while still part of the identifier.
|
||||||
identifier_string_.clear();
|
identifier_string_.clear();
|
||||||
while (IsIdentifierPart(ch)) {
|
while (IsIdentifierPart(ch)) {
|
||||||
@ -271,7 +271,7 @@ void AsmJsScanner::ConsumeIdentifier(uc32 ch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsmJsScanner::ConsumeNumber(uc32 ch) {
|
void AsmJsScanner::ConsumeNumber(base::uc32 ch) {
|
||||||
std::string number;
|
std::string number;
|
||||||
number.assign(1, ch);
|
number.assign(1, ch);
|
||||||
bool has_dot = ch == '.';
|
bool has_dot = ch == '.';
|
||||||
@ -344,7 +344,7 @@ void AsmJsScanner::ConsumeNumber(uc32 ch) {
|
|||||||
|
|
||||||
bool AsmJsScanner::ConsumeCComment() {
|
bool AsmJsScanner::ConsumeCComment() {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uc32 ch = stream_->Advance();
|
base::uc32 ch = stream_->Advance();
|
||||||
while (ch == '*') {
|
while (ch == '*') {
|
||||||
ch = stream_->Advance();
|
ch = stream_->Advance();
|
||||||
if (ch == '/') {
|
if (ch == '/') {
|
||||||
@ -362,7 +362,7 @@ bool AsmJsScanner::ConsumeCComment() {
|
|||||||
|
|
||||||
void AsmJsScanner::ConsumeCPPComment() {
|
void AsmJsScanner::ConsumeCPPComment() {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uc32 ch = stream_->Advance();
|
base::uc32 ch = stream_->Advance();
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
preceded_by_newline_ = true;
|
preceded_by_newline_ = true;
|
||||||
return;
|
return;
|
||||||
@ -373,11 +373,11 @@ void AsmJsScanner::ConsumeCPPComment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsmJsScanner::ConsumeString(uc32 quote) {
|
void AsmJsScanner::ConsumeString(base::uc32 quote) {
|
||||||
// Only string allowed is 'use asm' / "use asm".
|
// Only string allowed is 'use asm' / "use asm".
|
||||||
const char* expected = "use asm";
|
const char* expected = "use asm";
|
||||||
for (; *expected != '\0'; ++expected) {
|
for (; *expected != '\0'; ++expected) {
|
||||||
if (stream_->Advance() != static_cast<uc32>(*expected)) {
|
if (stream_->Advance() != static_cast<base::uc32>(*expected)) {
|
||||||
token_ = kParseError;
|
token_ = kParseError;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -389,8 +389,8 @@ void AsmJsScanner::ConsumeString(uc32 quote) {
|
|||||||
token_ = kToken_UseAsm;
|
token_ = kToken_UseAsm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsmJsScanner::ConsumeCompareOrShift(uc32 ch) {
|
void AsmJsScanner::ConsumeCompareOrShift(base::uc32 ch) {
|
||||||
uc32 next_ch = stream_->Advance();
|
base::uc32 next_ch = stream_->Advance();
|
||||||
if (next_ch == '=') {
|
if (next_ch == '=') {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '<':
|
case '<':
|
||||||
@ -423,14 +423,16 @@ void AsmJsScanner::ConsumeCompareOrShift(uc32 ch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsmJsScanner::IsIdentifierStart(uc32 ch) {
|
bool AsmJsScanner::IsIdentifierStart(base::uc32 ch) {
|
||||||
return base::IsInRange(AsciiAlphaToLower(ch), 'a', 'z') || ch == '_' ||
|
return base::IsInRange(AsciiAlphaToLower(ch), 'a', 'z') || ch == '_' ||
|
||||||
ch == '$';
|
ch == '$';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsmJsScanner::IsIdentifierPart(uc32 ch) { return IsAsciiIdentifier(ch); }
|
bool AsmJsScanner::IsIdentifierPart(base::uc32 ch) {
|
||||||
|
return IsAsciiIdentifier(ch);
|
||||||
|
}
|
||||||
|
|
||||||
bool AsmJsScanner::IsNumberStart(uc32 ch) {
|
bool AsmJsScanner::IsNumberStart(base::uc32 ch) {
|
||||||
return ch == '.' || IsDecimalDigit(ch);
|
return ch == '.' || IsDecimalDigit(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "src/asmjs/asm-names.h"
|
#include "src/asmjs/asm-names.h"
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -135,7 +136,8 @@ class V8_EXPORT_PRIVATE AsmJsScanner {
|
|||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
static constexpr uc32 kEndOfInputU = static_cast<uc32>(kEndOfInput);
|
static constexpr base::uc32 kEndOfInputU =
|
||||||
|
static_cast<base::uc32>(kEndOfInput);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utf16CharacterStream* stream_;
|
Utf16CharacterStream* stream_;
|
||||||
@ -157,17 +159,17 @@ class V8_EXPORT_PRIVATE AsmJsScanner {
|
|||||||
bool preceded_by_newline_;
|
bool preceded_by_newline_;
|
||||||
|
|
||||||
// Consume multiple characters.
|
// Consume multiple characters.
|
||||||
void ConsumeIdentifier(uc32 ch);
|
void ConsumeIdentifier(base::uc32 ch);
|
||||||
void ConsumeNumber(uc32 ch);
|
void ConsumeNumber(base::uc32 ch);
|
||||||
bool ConsumeCComment();
|
bool ConsumeCComment();
|
||||||
void ConsumeCPPComment();
|
void ConsumeCPPComment();
|
||||||
void ConsumeString(uc32 quote);
|
void ConsumeString(base::uc32 quote);
|
||||||
void ConsumeCompareOrShift(uc32 ch);
|
void ConsumeCompareOrShift(base::uc32 ch);
|
||||||
|
|
||||||
// Classify character categories.
|
// Classify character categories.
|
||||||
bool IsIdentifierStart(uc32 ch);
|
bool IsIdentifierStart(base::uc32 ch);
|
||||||
bool IsIdentifierPart(uc32 ch);
|
bool IsIdentifierPart(base::uc32 ch);
|
||||||
bool IsNumberStart(uc32 ch);
|
bool IsNumberStart(base::uc32 ch);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
#include "src/ast/scopes.h"
|
#include "src/ast/scopes.h"
|
||||||
#include "src/base/hashmap.h"
|
#include "src/base/hashmap.h"
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/base/platform/wrappers.h"
|
#include "src/base/platform/wrappers.h"
|
||||||
#include "src/builtins/builtins-constructor.h"
|
#include "src/builtins/builtins-constructor.h"
|
||||||
#include "src/builtins/builtins.h"
|
#include "src/builtins/builtins.h"
|
||||||
#include "src/common/assert-scope.h"
|
#include "src/common/assert-scope.h"
|
||||||
#include "src/heap/local-factory-inl.h"
|
#include "src/heap/local-factory-inl.h"
|
||||||
#include "src/numbers/conversions-inl.h"
|
#include "src/numbers/conversions-inl.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/contexts.h"
|
#include "src/objects/contexts.h"
|
||||||
#include "src/objects/elements-kind.h"
|
#include "src/objects/elements-kind.h"
|
||||||
#include "src/objects/elements.h"
|
#include "src/objects/elements.h"
|
||||||
@ -1044,7 +1044,7 @@ uint32_t Literal::Hash() {
|
|||||||
return ComputeLongHash(index);
|
return ComputeLongHash(index);
|
||||||
}
|
}
|
||||||
return IsString() ? AsRawString()->Hash()
|
return IsString() ? AsRawString()->Hash()
|
||||||
: ComputeLongHash(double_to_uint64(AsNumber()));
|
: ComputeLongHash(base::double_to_uint64(AsNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -2,17 +2,16 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "src/numbers/bignum-dtoa.h"
|
#include "src/base/numbers/bignum-dtoa.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/numbers/bignum.h"
|
#include "src/base/numbers/bignum.h"
|
||||||
#include "src/numbers/double.h"
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/utils/utils.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
static int NormalizedExponent(uint64_t significand, int exponent) {
|
static int NormalizedExponent(uint64_t significand, int exponent) {
|
||||||
DCHECK_NE(significand, 0);
|
DCHECK_NE(significand, 0);
|
||||||
@ -45,22 +44,22 @@ static void FixupMultiply10(int estimated_power, bool is_even,
|
|||||||
// digits yield the shortest decimal representation of v.
|
// digits yield the shortest decimal representation of v.
|
||||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||||
Bignum* delta_minus, Bignum* delta_plus,
|
Bignum* delta_minus, Bignum* delta_plus,
|
||||||
bool is_even, base::Vector<char> buffer,
|
bool is_even, Vector<char> buffer,
|
||||||
int* length);
|
int* length);
|
||||||
// Generates 'requested_digits' after the decimal point.
|
// Generates 'requested_digits' after the decimal point.
|
||||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||||
Bignum* numerator, Bignum* denominator,
|
Bignum* numerator, Bignum* denominator,
|
||||||
base::Vector<char>(buffer), int* length);
|
Vector<char>(buffer), int* length);
|
||||||
// Generates 'count' digits of numerator/denominator.
|
// Generates 'count' digits of numerator/denominator.
|
||||||
// Once 'count' digits have been produced rounds the result depending on the
|
// Once 'count' digits have been produced rounds the result depending on the
|
||||||
// remainder (remainders of exactly .5 round upwards). Might update the
|
// remainder (remainders of exactly .5 round upwards). Might update the
|
||||||
// decimal_point when rounding up (for example for 0.9999).
|
// decimal_point when rounding up (for example for 0.9999).
|
||||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||||
Bignum* numerator, Bignum* denominator,
|
Bignum* numerator, Bignum* denominator,
|
||||||
base::Vector<char>(buffer), int* length);
|
Vector<char>(buffer), int* length);
|
||||||
|
|
||||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
||||||
base::Vector<char> buffer, int* length, int* decimal_point) {
|
Vector<char> buffer, int* length, int* decimal_point) {
|
||||||
DCHECK_GT(v, 0);
|
DCHECK_GT(v, 0);
|
||||||
DCHECK(!Double(v).IsSpecial());
|
DCHECK(!Double(v).IsSpecial());
|
||||||
uint64_t significand = Double(v).Significand();
|
uint64_t significand = Double(v).Significand();
|
||||||
@ -135,7 +134,7 @@ void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
|||||||
// will be produced. This should be the standard precondition.
|
// will be produced. This should be the standard precondition.
|
||||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||||
Bignum* delta_minus, Bignum* delta_plus,
|
Bignum* delta_minus, Bignum* delta_plus,
|
||||||
bool is_even, base::Vector<char> buffer,
|
bool is_even, Vector<char> buffer,
|
||||||
int* length) {
|
int* length) {
|
||||||
// Small optimization: if delta_minus and delta_plus are the same just reuse
|
// Small optimization: if delta_minus and delta_plus are the same just reuse
|
||||||
// one of the two bignums.
|
// one of the two bignums.
|
||||||
@ -232,7 +231,7 @@ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
|||||||
// exponent (decimal_point), when rounding upwards.
|
// exponent (decimal_point), when rounding upwards.
|
||||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||||
Bignum* numerator, Bignum* denominator,
|
Bignum* numerator, Bignum* denominator,
|
||||||
base::Vector<char>(buffer), int* length) {
|
Vector<char>(buffer), int* length) {
|
||||||
DCHECK_GE(count, 0);
|
DCHECK_GE(count, 0);
|
||||||
for (int i = 0; i < count - 1; ++i) {
|
for (int i = 0; i < count - 1; ++i) {
|
||||||
uint16_t digit;
|
uint16_t digit;
|
||||||
@ -273,7 +272,7 @@ static void GenerateCountedDigits(int count, int* decimal_point,
|
|||||||
// Input verifies: 1 <= (numerator + delta) / denominator < 10.
|
// Input verifies: 1 <= (numerator + delta) / denominator < 10.
|
||||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||||
Bignum* numerator, Bignum* denominator,
|
Bignum* numerator, Bignum* denominator,
|
||||||
base::Vector<char>(buffer), int* length) {
|
Vector<char>(buffer), int* length) {
|
||||||
// Note that we have to look at more than just the requested_digits, since
|
// Note that we have to look at more than just the requested_digits, since
|
||||||
// a number could be rounded up. Example: v=0.5 with requested_digits=0.
|
// a number could be rounded up. Example: v=0.5 with requested_digits=0.
|
||||||
// Even though the power of v equals 0 we can't just stop here.
|
// Even though the power of v equals 0 we can't just stop here.
|
||||||
@ -604,5 +603,5 @@ static void FixupMultiply10(int estimated_power, bool is_even,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,13 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_BIGNUM_DTOA_H_
|
#ifndef V8_BASE_NUMBERS_BIGNUM_DTOA_H_
|
||||||
#define V8_NUMBERS_BIGNUM_DTOA_H_
|
#define V8_BASE_NUMBERS_BIGNUM_DTOA_H_
|
||||||
|
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
enum BignumDtoaMode {
|
enum BignumDtoaMode {
|
||||||
// Return the shortest correct representation.
|
// Return the shortest correct representation.
|
||||||
@ -52,12 +52,11 @@ enum BignumDtoaMode {
|
|||||||
// Halfway cases are again rounded up.
|
// Halfway cases are again rounded up.
|
||||||
// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
|
// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
|
||||||
// and a terminating null-character.
|
// and a terminating null-character.
|
||||||
V8_EXPORT_PRIVATE void BignumDtoa(double v, BignumDtoaMode mode,
|
V8_BASE_EXPORT void BignumDtoa(double v, BignumDtoaMode mode,
|
||||||
int requested_digits,
|
int requested_digits, Vector<char> buffer,
|
||||||
base::Vector<char> buffer, int* length,
|
int* length, int* point);
|
||||||
int* point);
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_BIGNUM_DTOA_H_
|
#endif // V8_BASE_NUMBERS_BIGNUM_DTOA_H_
|
@ -2,11 +2,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "src/numbers/bignum.h"
|
#include "src/base/numbers/bignum.h"
|
||||||
#include "src/utils/utils.h"
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
Bignum::Bignum()
|
Bignum::Bignum()
|
||||||
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
||||||
@ -59,7 +60,7 @@ void Bignum::AssignBignum(const Bignum& other) {
|
|||||||
used_digits_ = other.used_digits_;
|
used_digits_ = other.used_digits_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t ReadUInt64(base::Vector<const char> buffer, int from,
|
static uint64_t ReadUInt64(Vector<const char> buffer, int from,
|
||||||
int digits_to_read) {
|
int digits_to_read) {
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
int to = from + digits_to_read;
|
int to = from + digits_to_read;
|
||||||
@ -72,7 +73,7 @@ static uint64_t ReadUInt64(base::Vector<const char> buffer, int from,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bignum::AssignDecimalString(base::Vector<const char> value) {
|
void Bignum::AssignDecimalString(Vector<const char> value) {
|
||||||
// 2^64 = 18446744073709551616 > 10^19
|
// 2^64 = 18446744073709551616 > 10^19
|
||||||
const int kMaxUint64DecimalDigits = 19;
|
const int kMaxUint64DecimalDigits = 19;
|
||||||
Zero();
|
Zero();
|
||||||
@ -99,7 +100,7 @@ static int HexCharValue(char c) {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bignum::AssignHexString(base::Vector<const char> value) {
|
void Bignum::AssignHexString(Vector<const char> value) {
|
||||||
Zero();
|
Zero();
|
||||||
int length = value.length();
|
int length = value.length();
|
||||||
|
|
||||||
@ -712,5 +713,5 @@ void Bignum::SubtractTimes(const Bignum& other, int factor) {
|
|||||||
DCHECK(Bignum::Equal(a, *this));
|
DCHECK(Bignum::Equal(a, *this));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,15 +2,15 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_BIGNUM_H_
|
#ifndef V8_BASE_NUMBERS_BIGNUM_H_
|
||||||
#define V8_NUMBERS_BIGNUM_H_
|
#define V8_BASE_NUMBERS_BIGNUM_H_
|
||||||
|
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
class V8_EXPORT_PRIVATE Bignum {
|
class V8_BASE_EXPORT Bignum {
|
||||||
public:
|
public:
|
||||||
// 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
|
// 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
|
||||||
// This bignum can encode much bigger numbers, since it contains an
|
// This bignum can encode much bigger numbers, since it contains an
|
||||||
@ -24,8 +24,8 @@ class V8_EXPORT_PRIVATE Bignum {
|
|||||||
void AssignUInt64(uint64_t value);
|
void AssignUInt64(uint64_t value);
|
||||||
void AssignBignum(const Bignum& other);
|
void AssignBignum(const Bignum& other);
|
||||||
|
|
||||||
void AssignDecimalString(base::Vector<const char> value);
|
void AssignDecimalString(Vector<const char> value);
|
||||||
void AssignHexString(base::Vector<const char> value);
|
void AssignHexString(Vector<const char> value);
|
||||||
|
|
||||||
void AssignPowerUInt16(uint16_t base, int exponent);
|
void AssignPowerUInt16(uint16_t base, int exponent);
|
||||||
|
|
||||||
@ -109,13 +109,13 @@ class V8_EXPORT_PRIVATE Bignum {
|
|||||||
Chunk bigits_buffer_[kBigitCapacity];
|
Chunk bigits_buffer_[kBigitCapacity];
|
||||||
// A vector backed by bigits_buffer_. This way accesses to the array are
|
// A vector backed by bigits_buffer_. This way accesses to the array are
|
||||||
// checked for out-of-bounds errors.
|
// checked for out-of-bounds errors.
|
||||||
base::Vector<Chunk> bigits_;
|
Vector<Chunk> bigits_;
|
||||||
int used_digits_;
|
int used_digits_;
|
||||||
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
|
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
|
||||||
int exponent_;
|
int exponent_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_BIGNUM_H_
|
#endif // V8_BASE_NUMBERS_BIGNUM_H_
|
@ -2,18 +2,18 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "src/numbers/cached-powers.h"
|
#include "src/base/numbers/cached-powers.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/common/globals.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
struct CachedPower {
|
struct CachedPower {
|
||||||
uint64_t significand;
|
uint64_t significand;
|
||||||
@ -109,5 +109,5 @@ void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
|
|||||||
DCHECK(requested_exponent < *found_exponent + kDecimalExponentDistance);
|
DCHECK(requested_exponent < *found_exponent + kDecimalExponentDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,14 +2,14 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_CACHED_POWERS_H_
|
#ifndef V8_BASE_NUMBERS_CACHED_POWERS_H_
|
||||||
#define V8_NUMBERS_CACHED_POWERS_H_
|
#define V8_BASE_NUMBERS_CACHED_POWERS_H_
|
||||||
|
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/numbers/diy-fp.h"
|
#include "src/base/numbers/diy-fp.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
class PowersOfTenCache {
|
class PowersOfTenCache {
|
||||||
public:
|
public:
|
||||||
@ -37,7 +37,7 @@ class PowersOfTenCache {
|
|||||||
int* found_exponent);
|
int* found_exponent);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_CACHED_POWERS_H_
|
#endif // V8_BASE_NUMBERS_CACHED_POWERS_H_
|
@ -2,12 +2,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "src/numbers/diy-fp.h"
|
#include "src/base/numbers/diy-fp.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
void DiyFp::Multiply(const DiyFp& other) {
|
void DiyFp::Multiply(const DiyFp& other) {
|
||||||
// Simply "emulates" a 128 bit multiplication.
|
// Simply "emulates" a 128 bit multiplication.
|
||||||
@ -32,5 +32,5 @@ void DiyFp::Multiply(const DiyFp& other) {
|
|||||||
f_ = result_f;
|
f_ = result_f;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_DIY_FP_H_
|
#ifndef V8_BASE_NUMBERS_DIY_FP_H_
|
||||||
#define V8_NUMBERS_DIY_FP_H_
|
#define V8_BASE_NUMBERS_DIY_FP_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -11,7 +11,7 @@
|
|||||||
#include "src/base/macros.h"
|
#include "src/base/macros.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// This "Do It Yourself Floating Point" class implements a floating-point number
|
// This "Do It Yourself Floating Point" class implements a floating-point number
|
||||||
// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
|
// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
|
||||||
@ -45,7 +45,7 @@ class DiyFp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this = this * other.
|
// this = this * other.
|
||||||
V8_EXPORT_PRIVATE void Multiply(const DiyFp& other);
|
V8_BASE_EXPORT void Multiply(const DiyFp& other);
|
||||||
|
|
||||||
// returns a * b;
|
// returns a * b;
|
||||||
static DiyFp Times(const DiyFp& a, const DiyFp& b) {
|
static DiyFp Times(const DiyFp& a, const DiyFp& b) {
|
||||||
@ -93,7 +93,7 @@ class DiyFp {
|
|||||||
int e_;
|
int e_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_DIY_FP_H_
|
#endif // V8_BASE_NUMBERS_DIY_FP_H_
|
@ -2,14 +2,14 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_DOUBLE_H_
|
#ifndef V8_BASE_NUMBERS_DOUBLE_H_
|
||||||
#define V8_NUMBERS_DOUBLE_H_
|
#define V8_BASE_NUMBERS_DOUBLE_H_
|
||||||
|
|
||||||
#include "src/base/macros.h"
|
#include "src/base/macros.h"
|
||||||
#include "src/numbers/diy-fp.h"
|
#include "src/base/numbers/diy-fp.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// We assume that doubles and uint64_t have the same endianness.
|
// We assume that doubles and uint64_t have the same endianness.
|
||||||
inline uint64_t double_to_uint64(double d) { return bit_cast<uint64_t>(d); }
|
inline uint64_t double_to_uint64(double d) { return bit_cast<uint64_t>(d); }
|
||||||
@ -204,7 +204,7 @@ class Double {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_DOUBLE_H_
|
#endif // V8_BASE_NUMBERS_DOUBLE_H_
|
@ -2,20 +2,18 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/base/numbers/dtoa.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/base/numbers/bignum-dtoa.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/numbers/dtoa.h"
|
#include "src/base/numbers/fast-dtoa.h"
|
||||||
|
#include "src/base/numbers/fixed-dtoa.h"
|
||||||
#include "src/numbers/bignum-dtoa.h"
|
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/numbers/fast-dtoa.h"
|
|
||||||
#include "src/numbers/fixed-dtoa.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
static BignumDtoaMode DtoaToBignumDtoaMode(DtoaMode dtoa_mode) {
|
static BignumDtoaMode DtoaToBignumDtoaMode(DtoaMode dtoa_mode) {
|
||||||
switch (dtoa_mode) {
|
switch (dtoa_mode) {
|
||||||
@ -31,8 +29,7 @@ static BignumDtoaMode DtoaToBignumDtoaMode(DtoaMode dtoa_mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DoubleToAscii(double v, DtoaMode mode, int requested_digits,
|
void DoubleToAscii(double v, DtoaMode mode, int requested_digits,
|
||||||
base::Vector<char> buffer, int* sign, int* length,
|
Vector<char> buffer, int* sign, int* length, int* point) {
|
||||||
int* point) {
|
|
||||||
DCHECK(!Double(v).IsSpecial());
|
DCHECK(!Double(v).IsSpecial());
|
||||||
DCHECK(mode == DTOA_SHORTEST || requested_digits >= 0);
|
DCHECK(mode == DTOA_SHORTEST || requested_digits >= 0);
|
||||||
|
|
||||||
@ -80,5 +77,5 @@ void DoubleToAscii(double v, DtoaMode mode, int requested_digits,
|
|||||||
buffer[*length] = '\0';
|
buffer[*length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,13 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_DTOA_H_
|
#ifndef V8_BASE_NUMBERS_DTOA_H_
|
||||||
#define V8_NUMBERS_DTOA_H_
|
#define V8_BASE_NUMBERS_DTOA_H_
|
||||||
|
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
enum DtoaMode {
|
enum DtoaMode {
|
||||||
// Return the shortest correct representation.
|
// Return the shortest correct representation.
|
||||||
@ -61,12 +61,11 @@ const int kBase10MaximalLength = 17;
|
|||||||
// and a terminating null-character. In SHORTEST-mode it expects a buffer of
|
// and a terminating null-character. In SHORTEST-mode it expects a buffer of
|
||||||
// at least kBase10MaximalLength + 1. Otherwise, the size of the output is
|
// at least kBase10MaximalLength + 1. Otherwise, the size of the output is
|
||||||
// limited to requested_digits digits plus the null terminator.
|
// limited to requested_digits digits plus the null terminator.
|
||||||
V8_EXPORT_PRIVATE void DoubleToAscii(double v, DtoaMode mode,
|
V8_BASE_EXPORT void DoubleToAscii(double v, DtoaMode mode, int requested_digits,
|
||||||
int requested_digits,
|
Vector<char> buffer, int* sign, int* length,
|
||||||
base::Vector<char> buffer, int* sign,
|
int* point);
|
||||||
int* length, int* point);
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_DTOA_H_
|
#endif // V8_BASE_NUMBERS_DTOA_H_
|
@ -2,18 +2,18 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/base/numbers/fast-dtoa.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/base/numbers/cached-powers.h"
|
||||||
|
#include "src/base/numbers/diy-fp.h"
|
||||||
#include "src/numbers/fast-dtoa.h"
|
#include "src/base/numbers/double.h"
|
||||||
|
#include "src/base/v8-fallthrough.h"
|
||||||
#include "src/numbers/cached-powers.h"
|
|
||||||
#include "src/numbers/diy-fp.h"
|
|
||||||
#include "src/numbers/double.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// The minimal and maximal target exponent define the range of w's binary
|
// The minimal and maximal target exponent define the range of w's binary
|
||||||
// exponent, where 'w' is the result of multiplying the input by a cached power
|
// exponent, where 'w' is the result of multiplying the input by a cached power
|
||||||
@ -39,7 +39,7 @@ static const int kMaximalTargetExponent = -32;
|
|||||||
// Output: returns true if the buffer is guaranteed to contain the closest
|
// Output: returns true if the buffer is guaranteed to contain the closest
|
||||||
// representable number to the input.
|
// representable number to the input.
|
||||||
// Modifies the generated digits in the buffer to approach (round towards) w.
|
// Modifies the generated digits in the buffer to approach (round towards) w.
|
||||||
static bool RoundWeed(base::Vector<char> buffer, int length,
|
static bool RoundWeed(Vector<char> buffer, int length,
|
||||||
uint64_t distance_too_high_w, uint64_t unsafe_interval,
|
uint64_t distance_too_high_w, uint64_t unsafe_interval,
|
||||||
uint64_t rest, uint64_t ten_kappa, uint64_t unit) {
|
uint64_t rest, uint64_t ten_kappa, uint64_t unit) {
|
||||||
uint64_t small_distance = distance_too_high_w - unit;
|
uint64_t small_distance = distance_too_high_w - unit;
|
||||||
@ -153,9 +153,8 @@ static bool RoundWeed(base::Vector<char> buffer, int length,
|
|||||||
// unambiguously determined.
|
// unambiguously determined.
|
||||||
//
|
//
|
||||||
// Precondition: rest < ten_kappa.
|
// Precondition: rest < ten_kappa.
|
||||||
static bool RoundWeedCounted(base::Vector<char> buffer, int length,
|
static bool RoundWeedCounted(Vector<char> buffer, int length, uint64_t rest,
|
||||||
uint64_t rest, uint64_t ten_kappa, uint64_t unit,
|
uint64_t ten_kappa, uint64_t unit, int* kappa) {
|
||||||
int* kappa) {
|
|
||||||
DCHECK(rest < ten_kappa);
|
DCHECK(rest < ten_kappa);
|
||||||
// The following tests are done in a specific order to avoid overflows. They
|
// The following tests are done in a specific order to avoid overflows. They
|
||||||
// will work correctly with any uint64 values of rest < ten_kappa and unit.
|
// will work correctly with any uint64 values of rest < ten_kappa and unit.
|
||||||
@ -355,7 +354,7 @@ static void BiggestPowerTen(uint32_t number, int number_bits, uint32_t* power,
|
|||||||
// represent 'w' we can stop. Everything inside the interval low - high
|
// represent 'w' we can stop. Everything inside the interval low - high
|
||||||
// represents w. However we have to pay attention to low, high and w's
|
// represents w. However we have to pay attention to low, high and w's
|
||||||
// imprecision.
|
// imprecision.
|
||||||
static bool DigitGen(DiyFp low, DiyFp w, DiyFp high, base::Vector<char> buffer,
|
static bool DigitGen(DiyFp low, DiyFp w, DiyFp high, Vector<char> buffer,
|
||||||
int* length, int* kappa) {
|
int* length, int* kappa) {
|
||||||
DCHECK(low.e() == w.e() && w.e() == high.e());
|
DCHECK(low.e() == w.e() && w.e() == high.e());
|
||||||
DCHECK(low.f() + 1 <= high.f() - 1);
|
DCHECK(low.f() + 1 <= high.f() - 1);
|
||||||
@ -475,9 +474,8 @@ static bool DigitGen(DiyFp low, DiyFp w, DiyFp high, base::Vector<char> buffer,
|
|||||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||||
// then false is returned. This usually happens rarely, but the failure-rate
|
// then false is returned. This usually happens rarely, but the failure-rate
|
||||||
// increases with higher requested_digits.
|
// increases with higher requested_digits.
|
||||||
static bool DigitGenCounted(DiyFp w, int requested_digits,
|
static bool DigitGenCounted(DiyFp w, int requested_digits, Vector<char> buffer,
|
||||||
base::Vector<char> buffer, int* length,
|
int* length, int* kappa) {
|
||||||
int* kappa) {
|
|
||||||
DCHECK(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
|
DCHECK(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
|
||||||
DCHECK_GE(kMinimalTargetExponent, -60);
|
DCHECK_GE(kMinimalTargetExponent, -60);
|
||||||
DCHECK_LE(kMaximalTargetExponent, -32);
|
DCHECK_LE(kMaximalTargetExponent, -32);
|
||||||
@ -561,7 +559,7 @@ static bool DigitGenCounted(DiyFp w, int requested_digits,
|
|||||||
// The last digit will be closest to the actual v. That is, even if several
|
// The last digit will be closest to the actual v. That is, even if several
|
||||||
// digits might correctly yield 'v' when read again, the closest will be
|
// digits might correctly yield 'v' when read again, the closest will be
|
||||||
// computed.
|
// computed.
|
||||||
static bool Grisu3(double v, base::Vector<char> buffer, int* length,
|
static bool Grisu3(double v, Vector<char> buffer, int* length,
|
||||||
int* decimal_exponent) {
|
int* decimal_exponent) {
|
||||||
DiyFp w = Double(v).AsNormalizedDiyFp();
|
DiyFp w = Double(v).AsNormalizedDiyFp();
|
||||||
// boundary_minus and boundary_plus are the boundaries between v and its
|
// boundary_minus and boundary_plus are the boundaries between v and its
|
||||||
@ -622,9 +620,8 @@ static bool Grisu3(double v, base::Vector<char> buffer, int* length,
|
|||||||
// and with enough requested digits 0.1 will at some point print as 0.9999999...
|
// and with enough requested digits 0.1 will at some point print as 0.9999999...
|
||||||
// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
|
// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
|
||||||
// therefore the rounding strategy for halfway cases is irrelevant.
|
// therefore the rounding strategy for halfway cases is irrelevant.
|
||||||
static bool Grisu3Counted(double v, int requested_digits,
|
static bool Grisu3Counted(double v, int requested_digits, Vector<char> buffer,
|
||||||
base::Vector<char> buffer, int* length,
|
int* length, int* decimal_exponent) {
|
||||||
int* decimal_exponent) {
|
|
||||||
DiyFp w = Double(v).AsNormalizedDiyFp();
|
DiyFp w = Double(v).AsNormalizedDiyFp();
|
||||||
DiyFp ten_mk; // Cached power of ten: 10^-k
|
DiyFp ten_mk; // Cached power of ten: 10^-k
|
||||||
int mk; // -k
|
int mk; // -k
|
||||||
@ -663,7 +660,7 @@ static bool Grisu3Counted(double v, int requested_digits,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FastDtoa(double v, FastDtoaMode mode, int requested_digits,
|
bool FastDtoa(double v, FastDtoaMode mode, int requested_digits,
|
||||||
base::Vector<char> buffer, int* length, int* decimal_point) {
|
Vector<char> buffer, int* length, int* decimal_point) {
|
||||||
DCHECK_GT(v, 0);
|
DCHECK_GT(v, 0);
|
||||||
DCHECK(!Double(v).IsSpecial());
|
DCHECK(!Double(v).IsSpecial());
|
||||||
|
|
||||||
@ -687,5 +684,5 @@ bool FastDtoa(double v, FastDtoaMode mode, int requested_digits,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,13 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_FAST_DTOA_H_
|
#ifndef V8_BASE_NUMBERS_FAST_DTOA_H_
|
||||||
#define V8_NUMBERS_FAST_DTOA_H_
|
#define V8_BASE_NUMBERS_FAST_DTOA_H_
|
||||||
|
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
enum FastDtoaMode {
|
enum FastDtoaMode {
|
||||||
// Computes the shortest representation of the given input. The returned
|
// Computes the shortest representation of the given input. The returned
|
||||||
@ -50,11 +50,11 @@ const int kFastDtoaMaximalLength = 17;
|
|||||||
// If there are two values that are equally close, then FastDtoa returns
|
// If there are two values that are equally close, then FastDtoa returns
|
||||||
// false.
|
// false.
|
||||||
// For both modes the buffer must be large enough to hold the result.
|
// For both modes the buffer must be large enough to hold the result.
|
||||||
V8_EXPORT_PRIVATE bool FastDtoa(double d, FastDtoaMode mode,
|
V8_BASE_EXPORT bool FastDtoa(double d, FastDtoaMode mode, int requested_digits,
|
||||||
int requested_digits, base::Vector<char> buffer,
|
Vector<char> buffer, int* length,
|
||||||
int* length, int* decimal_point);
|
int* decimal_point);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_FAST_DTOA_H_
|
#endif // V8_BASE_NUMBERS_FAST_DTOA_H_
|
@ -2,18 +2,17 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/base/numbers/fixed-dtoa.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/base/numbers/double.h"
|
||||||
|
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/numbers/fixed-dtoa.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// Represents a 128bit type. This class should be replaced by a native type on
|
// Represents a 128bit type. This class should be replaced by a native type on
|
||||||
// platforms that support 128bit integers.
|
// platforms that support 128bit integers.
|
||||||
@ -97,7 +96,7 @@ class UInt128 {
|
|||||||
static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
|
static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
|
||||||
|
|
||||||
static void FillDigits32FixedLength(uint32_t number, int requested_length,
|
static void FillDigits32FixedLength(uint32_t number, int requested_length,
|
||||||
base::Vector<char> buffer, int* length) {
|
Vector<char> buffer, int* length) {
|
||||||
for (int i = requested_length - 1; i >= 0; --i) {
|
for (int i = requested_length - 1; i >= 0; --i) {
|
||||||
buffer[(*length) + i] = '0' + number % 10;
|
buffer[(*length) + i] = '0' + number % 10;
|
||||||
number /= 10;
|
number /= 10;
|
||||||
@ -105,8 +104,7 @@ static void FillDigits32FixedLength(uint32_t number, int requested_length,
|
|||||||
*length += requested_length;
|
*length += requested_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FillDigits32(uint32_t number, base::Vector<char> buffer,
|
static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
|
||||||
int* length) {
|
|
||||||
int number_length = 0;
|
int number_length = 0;
|
||||||
// We fill the digits in reverse order and exchange them afterwards.
|
// We fill the digits in reverse order and exchange them afterwards.
|
||||||
while (number != 0) {
|
while (number != 0) {
|
||||||
@ -129,7 +127,7 @@ static void FillDigits32(uint32_t number, base::Vector<char> buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void FillDigits64FixedLength(uint64_t number, int requested_length,
|
static void FillDigits64FixedLength(uint64_t number, int requested_length,
|
||||||
base::Vector<char> buffer, int* length) {
|
Vector<char> buffer, int* length) {
|
||||||
const uint32_t kTen7 = 10000000;
|
const uint32_t kTen7 = 10000000;
|
||||||
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
||||||
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
||||||
@ -142,8 +140,7 @@ static void FillDigits64FixedLength(uint64_t number, int requested_length,
|
|||||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FillDigits64(uint64_t number, base::Vector<char> buffer,
|
static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
|
||||||
int* length) {
|
|
||||||
const uint32_t kTen7 = 10000000;
|
const uint32_t kTen7 = 10000000;
|
||||||
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
||||||
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
||||||
@ -163,8 +160,7 @@ static void FillDigits64(uint64_t number, base::Vector<char> buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DtoaRoundUp(base::Vector<char> buffer, int* length,
|
static void DtoaRoundUp(Vector<char> buffer, int* length, int* decimal_point) {
|
||||||
int* decimal_point) {
|
|
||||||
// An empty buffer represents 0.
|
// An empty buffer represents 0.
|
||||||
if (*length == 0) {
|
if (*length == 0) {
|
||||||
buffer[0] = '1';
|
buffer[0] = '1';
|
||||||
@ -205,7 +201,7 @@ static void DtoaRoundUp(base::Vector<char> buffer, int* length,
|
|||||||
// already contained "199" (thus yielding a buffer of "19999") then a
|
// already contained "199" (thus yielding a buffer of "19999") then a
|
||||||
// rounding-up will change the contents of the buffer to "20000".
|
// rounding-up will change the contents of the buffer to "20000".
|
||||||
static void FillFractionals(uint64_t fractionals, int exponent,
|
static void FillFractionals(uint64_t fractionals, int exponent,
|
||||||
int fractional_count, base::Vector<char> buffer,
|
int fractional_count, Vector<char> buffer,
|
||||||
int* length, int* decimal_point) {
|
int* length, int* decimal_point) {
|
||||||
DCHECK(-128 <= exponent && exponent <= 0);
|
DCHECK(-128 <= exponent && exponent <= 0);
|
||||||
// 'fractionals' is a fixed-point number, with binary point at bit
|
// 'fractionals' is a fixed-point number, with binary point at bit
|
||||||
@ -262,8 +258,7 @@ static void FillFractionals(uint64_t fractionals, int exponent,
|
|||||||
|
|
||||||
// Removes leading and trailing zeros.
|
// Removes leading and trailing zeros.
|
||||||
// If leading zeros are removed then the decimal point position is adjusted.
|
// If leading zeros are removed then the decimal point position is adjusted.
|
||||||
static void TrimZeros(base::Vector<char> buffer, int* length,
|
static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
|
||||||
int* decimal_point) {
|
|
||||||
while (*length > 0 && buffer[(*length) - 1] == '0') {
|
while (*length > 0 && buffer[(*length) - 1] == '0') {
|
||||||
(*length)--;
|
(*length)--;
|
||||||
}
|
}
|
||||||
@ -280,7 +275,7 @@ static void TrimZeros(base::Vector<char> buffer, int* length,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FastFixedDtoa(double v, int fractional_count, base::Vector<char> buffer,
|
bool FastFixedDtoa(double v, int fractional_count, Vector<char> buffer,
|
||||||
int* length, int* decimal_point) {
|
int* length, int* decimal_point) {
|
||||||
const uint32_t kMaxUInt32 = 0xFFFFFFFF;
|
const uint32_t kMaxUInt32 = 0xFFFFFFFF;
|
||||||
uint64_t significand = Double(v).Significand();
|
uint64_t significand = Double(v).Significand();
|
||||||
@ -372,5 +367,5 @@ bool FastFixedDtoa(double v, int fractional_count, base::Vector<char> buffer,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,13 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_FIXED_DTOA_H_
|
#ifndef V8_BASE_NUMBERS_FIXED_DTOA_H_
|
||||||
#define V8_NUMBERS_FIXED_DTOA_H_
|
#define V8_BASE_NUMBERS_FIXED_DTOA_H_
|
||||||
|
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// Produces digits necessary to print a given number with
|
// Produces digits necessary to print a given number with
|
||||||
// 'fractional_count' digits after the decimal point.
|
// 'fractional_count' digits after the decimal point.
|
||||||
@ -26,11 +26,11 @@ namespace internal {
|
|||||||
//
|
//
|
||||||
// This method only works for some parameters. If it can't handle the input it
|
// This method only works for some parameters. If it can't handle the input it
|
||||||
// returns false. The output is null-terminated when the function succeeds.
|
// returns false. The output is null-terminated when the function succeeds.
|
||||||
V8_EXPORT_PRIVATE bool FastFixedDtoa(double v, int fractional_count,
|
V8_BASE_EXPORT bool FastFixedDtoa(double v, int fractional_count,
|
||||||
base::Vector<char> buffer, int* length,
|
Vector<char> buffer, int* length,
|
||||||
int* decimal_point);
|
int* decimal_point);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_FIXED_DTOA_H_
|
#endif // V8_BASE_NUMBERS_FIXED_DTOA_H_
|
@ -2,19 +2,19 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "src/numbers/strtod.h"
|
#include "src/base/numbers/strtod.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "src/common/globals.h"
|
#include <cmath>
|
||||||
#include "src/numbers/bignum.h"
|
#include <limits>
|
||||||
#include "src/numbers/cached-powers.h"
|
|
||||||
#include "src/numbers/double.h"
|
#include "src/base/numbers/bignum.h"
|
||||||
#include "src/utils/utils.h"
|
#include "src/base/numbers/cached-powers.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// 2^53 = 9007199254740992.
|
// 2^53 = 9007199254740992.
|
||||||
// Any integer with at most 15 decimal digits will hence fit into a double
|
// Any integer with at most 15 decimal digits will hence fit into a double
|
||||||
@ -70,28 +70,26 @@ static const int kExactPowersOfTenSize = arraysize(exact_powers_of_ten);
|
|||||||
// we round up to 780.
|
// we round up to 780.
|
||||||
static const int kMaxSignificantDecimalDigits = 780;
|
static const int kMaxSignificantDecimalDigits = 780;
|
||||||
|
|
||||||
static base::Vector<const char> TrimLeadingZeros(
|
static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
|
||||||
base::Vector<const char> buffer) {
|
|
||||||
for (int i = 0; i < buffer.length(); i++) {
|
for (int i = 0; i < buffer.length(); i++) {
|
||||||
if (buffer[i] != '0') {
|
if (buffer[i] != '0') {
|
||||||
return buffer.SubVector(i, buffer.length());
|
return buffer.SubVector(i, buffer.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return base::Vector<const char>(buffer.begin(), 0);
|
return Vector<const char>(buffer.begin(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static base::Vector<const char> TrimTrailingZeros(
|
static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
|
||||||
base::Vector<const char> buffer) {
|
|
||||||
for (int i = buffer.length() - 1; i >= 0; --i) {
|
for (int i = buffer.length() - 1; i >= 0; --i) {
|
||||||
if (buffer[i] != '0') {
|
if (buffer[i] != '0') {
|
||||||
return buffer.SubVector(0, i + 1);
|
return buffer.SubVector(0, i + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return base::Vector<const char>(buffer.begin(), 0);
|
return Vector<const char>(buffer.begin(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TrimToMaxSignificantDigits(base::Vector<const char> buffer,
|
static void TrimToMaxSignificantDigits(Vector<const char> buffer, int exponent,
|
||||||
int exponent, char* significant_buffer,
|
char* significant_buffer,
|
||||||
int* significant_exponent) {
|
int* significant_exponent) {
|
||||||
for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
|
for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
|
||||||
significant_buffer[i] = buffer[i];
|
significant_buffer[i] = buffer[i];
|
||||||
@ -111,7 +109,7 @@ static void TrimToMaxSignificantDigits(base::Vector<const char> buffer,
|
|||||||
// When the string starts with "1844674407370955161" no further digit is read.
|
// When the string starts with "1844674407370955161" no further digit is read.
|
||||||
// Since 2^64 = 18446744073709551616 it would still be possible read another
|
// Since 2^64 = 18446744073709551616 it would still be possible read another
|
||||||
// digit if it was less or equal than 6, but this would complicate the code.
|
// digit if it was less or equal than 6, but this would complicate the code.
|
||||||
static uint64_t ReadUint64(base::Vector<const char> buffer,
|
static uint64_t ReadUint64(Vector<const char> buffer,
|
||||||
int* number_of_read_digits) {
|
int* number_of_read_digits) {
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -128,7 +126,7 @@ static uint64_t ReadUint64(base::Vector<const char> buffer,
|
|||||||
// The returned DiyFp is not necessarily normalized.
|
// The returned DiyFp is not necessarily normalized.
|
||||||
// If remaining_decimals is zero then the returned DiyFp is accurate.
|
// If remaining_decimals is zero then the returned DiyFp is accurate.
|
||||||
// Otherwise it has been rounded and has error of at most 1/2 ulp.
|
// Otherwise it has been rounded and has error of at most 1/2 ulp.
|
||||||
static void ReadDiyFp(base::Vector<const char> buffer, DiyFp* result,
|
static void ReadDiyFp(Vector<const char> buffer, DiyFp* result,
|
||||||
int* remaining_decimals) {
|
int* remaining_decimals) {
|
||||||
int read_digits;
|
int read_digits;
|
||||||
uint64_t significand = ReadUint64(buffer, &read_digits);
|
uint64_t significand = ReadUint64(buffer, &read_digits);
|
||||||
@ -147,7 +145,7 @@ static void ReadDiyFp(base::Vector<const char> buffer, DiyFp* result,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DoubleStrtod(base::Vector<const char> trimmed, int exponent,
|
static bool DoubleStrtod(Vector<const char> trimmed, int exponent,
|
||||||
double* result) {
|
double* result) {
|
||||||
#if (V8_TARGET_ARCH_IA32 || defined(USE_SIMULATOR)) && !defined(_MSC_VER)
|
#if (V8_TARGET_ARCH_IA32 || defined(USE_SIMULATOR)) && !defined(_MSC_VER)
|
||||||
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
|
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
|
||||||
@ -233,7 +231,7 @@ static DiyFp AdjustmentPowerOfTen(int exponent) {
|
|||||||
// If the function returns true then the result is the correct double.
|
// If the function returns true then the result is the correct double.
|
||||||
// Otherwise it is either the correct double or the double that is just below
|
// Otherwise it is either the correct double or the double that is just below
|
||||||
// the correct double.
|
// the correct double.
|
||||||
static bool DiyFpStrtod(base::Vector<const char> buffer, int exponent,
|
static bool DiyFpStrtod(Vector<const char> buffer, int exponent,
|
||||||
double* result) {
|
double* result) {
|
||||||
DiyFp input;
|
DiyFp input;
|
||||||
int remaining_decimals;
|
int remaining_decimals;
|
||||||
@ -347,9 +345,9 @@ static bool DiyFpStrtod(base::Vector<const char> buffer, int exponent,
|
|||||||
// buffer.length() + exponent <= kMaxDecimalPower + 1
|
// buffer.length() + exponent <= kMaxDecimalPower + 1
|
||||||
// buffer.length() + exponent > kMinDecimalPower
|
// buffer.length() + exponent > kMinDecimalPower
|
||||||
// buffer.length() <= kMaxDecimalSignificantDigits
|
// buffer.length() <= kMaxDecimalSignificantDigits
|
||||||
static double BignumStrtod(base::Vector<const char> buffer, int exponent,
|
static double BignumStrtod(Vector<const char> buffer, int exponent,
|
||||||
double guess) {
|
double guess) {
|
||||||
if (guess == V8_INFINITY) {
|
if (guess == std::numeric_limits<double>::infinity()) {
|
||||||
return guess;
|
return guess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,9 +388,9 @@ static double BignumStrtod(base::Vector<const char> buffer, int exponent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Strtod(base::Vector<const char> buffer, int exponent) {
|
double Strtod(Vector<const char> buffer, int exponent) {
|
||||||
base::Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
|
Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
|
||||||
base::Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
|
Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
|
||||||
exponent += left_trimmed.length() - trimmed.length();
|
exponent += left_trimmed.length() - trimmed.length();
|
||||||
if (trimmed.length() == 0) return 0.0;
|
if (trimmed.length() == 0) return 0.0;
|
||||||
if (trimmed.length() > kMaxSignificantDecimalDigits) {
|
if (trimmed.length() > kMaxSignificantDecimalDigits) {
|
||||||
@ -400,11 +398,12 @@ double Strtod(base::Vector<const char> buffer, int exponent) {
|
|||||||
int significant_exponent;
|
int significant_exponent;
|
||||||
TrimToMaxSignificantDigits(trimmed, exponent, significant_buffer,
|
TrimToMaxSignificantDigits(trimmed, exponent, significant_buffer,
|
||||||
&significant_exponent);
|
&significant_exponent);
|
||||||
return Strtod(base::Vector<const char>(significant_buffer,
|
return Strtod(
|
||||||
kMaxSignificantDecimalDigits),
|
Vector<const char>(significant_buffer, kMaxSignificantDecimalDigits),
|
||||||
significant_exponent);
|
significant_exponent);
|
||||||
}
|
}
|
||||||
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
|
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower)
|
||||||
|
return std::numeric_limits<double>::infinity();
|
||||||
if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
|
if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
|
||||||
|
|
||||||
double guess;
|
double guess;
|
||||||
@ -415,5 +414,5 @@ double Strtod(base::Vector<const char> buffer, int exponent) {
|
|||||||
return BignumStrtod(trimmed, exponent, guess);
|
return BignumStrtod(trimmed, exponent, guess);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
@ -2,19 +2,19 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef V8_NUMBERS_STRTOD_H_
|
#ifndef V8_BASE_NUMBERS_STRTOD_H_
|
||||||
#define V8_NUMBERS_STRTOD_H_
|
#define V8_BASE_NUMBERS_STRTOD_H_
|
||||||
|
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace base {
|
||||||
|
|
||||||
// The buffer must only contain digits in the range [0-9]. It must not
|
// The buffer must only contain digits in the range [0-9]. It must not
|
||||||
// contain a dot or a sign. It must not start with '0', and must not be empty.
|
// contain a dot or a sign. It must not start with '0', and must not be empty.
|
||||||
V8_EXPORT_PRIVATE double Strtod(base::Vector<const char> buffer, int exponent);
|
V8_BASE_EXPORT double Strtod(Vector<const char> buffer, int exponent);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
#endif // V8_NUMBERS_STRTOD_H_
|
#endif // V8_BASE_NUMBERS_STRTOD_H_
|
@ -12,6 +12,13 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
|
// Latin1/UTF-16 constants
|
||||||
|
// Code-point values in Unicode 4.0 are 21 bits wide.
|
||||||
|
// Code units in UTF-16 are 16 bits wide.
|
||||||
|
using uc16 = uint16_t;
|
||||||
|
using uc32 = uint32_t;
|
||||||
|
constexpr int kUC16Size = sizeof(uc16);
|
||||||
|
|
||||||
V8_BASE_EXPORT int PRINTF_FORMAT(2, 0)
|
V8_BASE_EXPORT int PRINTF_FORMAT(2, 0)
|
||||||
VSNPrintF(Vector<char> str, const char* format, va_list args);
|
VSNPrintF(Vector<char> str, const char* format, va_list args);
|
||||||
|
|
||||||
@ -22,6 +29,22 @@ V8_BASE_EXPORT int PRINTF_FORMAT(2, 3)
|
|||||||
|
|
||||||
V8_BASE_EXPORT void StrNCpy(base::Vector<char> dest, const char* src, size_t n);
|
V8_BASE_EXPORT void StrNCpy(base::Vector<char> dest, const char* src, size_t n);
|
||||||
|
|
||||||
|
// Returns the value (0 .. 15) of a hexadecimal character c.
|
||||||
|
// If c is not a legal hexadecimal character, returns a value < 0.
|
||||||
|
inline int HexValue(uc32 c) {
|
||||||
|
c -= '0';
|
||||||
|
if (static_cast<unsigned>(c) <= 9) return c;
|
||||||
|
c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36.
|
||||||
|
if (static_cast<unsigned>(c) <= 5) return c + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char HexCharOfValue(int value) {
|
||||||
|
DCHECK(0 <= value && value <= 16);
|
||||||
|
if (value < 10) return value + '0';
|
||||||
|
return value - 10 + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
|
@ -525,7 +525,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
|||||||
pushed_stack_space += kNumDoubleCalleeSaved * kDoubleSize;
|
pushed_stack_space += kNumDoubleCalleeSaved * kDoubleSize;
|
||||||
|
|
||||||
// Set up the reserved register for 0.0.
|
// Set up the reserved register for 0.0.
|
||||||
__ vmov(kDoubleRegZero, Double(0.0));
|
__ vmov(kDoubleRegZero, base::Double(0.0));
|
||||||
|
|
||||||
// Initialize the root register.
|
// Initialize the root register.
|
||||||
// C calling convention. The first argument is passed in r0.
|
// C calling convention. The first argument is passed in r0.
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/builtins/builtins-string-gen.h"
|
#include "src/builtins/builtins-string-gen.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/builtins/builtins-regexp-gen.h"
|
#include "src/builtins/builtins-regexp-gen.h"
|
||||||
#include "src/builtins/builtins-utils-gen.h"
|
#include "src/builtins/builtins-utils-gen.h"
|
||||||
#include "src/builtins/builtins.h"
|
#include "src/builtins/builtins.h"
|
||||||
@ -73,7 +74,7 @@ TNode<IntPtrT> StringBuiltinsAssembler::SearchOneByteStringInTwoByteString(
|
|||||||
const TNode<RawPtrT> subject_ptr, const TNode<IntPtrT> subject_length,
|
const TNode<RawPtrT> subject_ptr, const TNode<IntPtrT> subject_length,
|
||||||
const TNode<RawPtrT> search_ptr, const TNode<IntPtrT> search_length,
|
const TNode<RawPtrT> search_ptr, const TNode<IntPtrT> search_length,
|
||||||
const TNode<IntPtrT> start_position) {
|
const TNode<IntPtrT> start_position) {
|
||||||
return CallSearchStringRaw<const uc16, const uint8_t>(
|
return CallSearchStringRaw<const base::uc16, const uint8_t>(
|
||||||
subject_ptr, subject_length, search_ptr, search_length, start_position);
|
subject_ptr, subject_length, search_ptr, search_length, start_position);
|
||||||
}
|
}
|
||||||
TNode<IntPtrT> StringBuiltinsAssembler::SearchOneByteStringInOneByteString(
|
TNode<IntPtrT> StringBuiltinsAssembler::SearchOneByteStringInOneByteString(
|
||||||
@ -87,14 +88,14 @@ TNode<IntPtrT> StringBuiltinsAssembler::SearchTwoByteStringInTwoByteString(
|
|||||||
const TNode<RawPtrT> subject_ptr, const TNode<IntPtrT> subject_length,
|
const TNode<RawPtrT> subject_ptr, const TNode<IntPtrT> subject_length,
|
||||||
const TNode<RawPtrT> search_ptr, const TNode<IntPtrT> search_length,
|
const TNode<RawPtrT> search_ptr, const TNode<IntPtrT> search_length,
|
||||||
const TNode<IntPtrT> start_position) {
|
const TNode<IntPtrT> start_position) {
|
||||||
return CallSearchStringRaw<const uc16, const uc16>(
|
return CallSearchStringRaw<const base::uc16, const base::uc16>(
|
||||||
subject_ptr, subject_length, search_ptr, search_length, start_position);
|
subject_ptr, subject_length, search_ptr, search_length, start_position);
|
||||||
}
|
}
|
||||||
TNode<IntPtrT> StringBuiltinsAssembler::SearchTwoByteStringInOneByteString(
|
TNode<IntPtrT> StringBuiltinsAssembler::SearchTwoByteStringInOneByteString(
|
||||||
const TNode<RawPtrT> subject_ptr, const TNode<IntPtrT> subject_length,
|
const TNode<RawPtrT> subject_ptr, const TNode<IntPtrT> subject_length,
|
||||||
const TNode<RawPtrT> search_ptr, const TNode<IntPtrT> search_length,
|
const TNode<RawPtrT> search_ptr, const TNode<IntPtrT> search_length,
|
||||||
const TNode<IntPtrT> start_position) {
|
const TNode<IntPtrT> start_position) {
|
||||||
return CallSearchStringRaw<const uint8_t, const uc16>(
|
return CallSearchStringRaw<const uint8_t, const base::uc16>(
|
||||||
subject_ptr, subject_length, search_ptr, search_length, start_position);
|
subject_ptr, subject_length, search_ptr, search_length, start_position);
|
||||||
}
|
}
|
||||||
TNode<IntPtrT> StringBuiltinsAssembler::SearchOneByteInOneByteString(
|
TNode<IntPtrT> StringBuiltinsAssembler::SearchOneByteInOneByteString(
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#ifdef V8_INTL_SUPPORT
|
#ifdef V8_INTL_SUPPORT
|
||||||
#include "src/objects/intl-objects.h"
|
#include "src/objects/intl-objects.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/regexp/regexp-utils.h"
|
#include "src/regexp/regexp-utils.h"
|
||||||
#include "src/strings/string-builder-inl.h"
|
#include "src/strings/string-builder-inl.h"
|
||||||
#include "src/strings/string-case.h"
|
#include "src/strings/string-case.h"
|
||||||
@ -40,9 +41,9 @@ bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr uc32 kInvalidCodePoint = static_cast<uc32>(-1);
|
static constexpr base::uc32 kInvalidCodePoint = static_cast<base::uc32>(-1);
|
||||||
|
|
||||||
uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
|
base::uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
|
||||||
Handle<Object> value = args.at(1 + index);
|
Handle<Object> value = args.at(1 + index);
|
||||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||||
isolate, value, Object::ToNumber(isolate, value), kInvalidCodePoint);
|
isolate, value, Object::ToNumber(isolate, value), kInvalidCodePoint);
|
||||||
@ -67,7 +68,7 @@ BUILTIN(StringFromCodePoint) {
|
|||||||
// characters.
|
// characters.
|
||||||
std::vector<uint8_t> one_byte_buffer;
|
std::vector<uint8_t> one_byte_buffer;
|
||||||
one_byte_buffer.reserve(length);
|
one_byte_buffer.reserve(length);
|
||||||
uc32 code = 0;
|
base::uc32 code = 0;
|
||||||
int index;
|
int index;
|
||||||
for (index = 0; index < length; index++) {
|
for (index = 0; index < length; index++) {
|
||||||
code = NextCodePoint(isolate, args, index);
|
code = NextCodePoint(isolate, args, index);
|
||||||
@ -86,11 +87,12 @@ BUILTIN(StringFromCodePoint) {
|
|||||||
one_byte_buffer.data(), one_byte_buffer.size())));
|
one_byte_buffer.data(), one_byte_buffer.size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uc16> two_byte_buffer;
|
std::vector<base::uc16> two_byte_buffer;
|
||||||
two_byte_buffer.reserve(length - index);
|
two_byte_buffer.reserve(length - index);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (code <= static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
if (code <=
|
||||||
|
static_cast<base::uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
||||||
two_byte_buffer.push_back(code);
|
two_byte_buffer.push_back(code);
|
||||||
} else {
|
} else {
|
||||||
two_byte_buffer.push_back(unibrow::Utf16::LeadSurrogate(code));
|
two_byte_buffer.push_back(unibrow::Utf16::LeadSurrogate(code));
|
||||||
@ -230,11 +232,11 @@ BUILTIN(StringPrototypeNormalize) {
|
|||||||
#ifndef V8_INTL_SUPPORT
|
#ifndef V8_INTL_SUPPORT
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
inline bool ToUpperOverflows(uc32 character) {
|
inline bool ToUpperOverflows(base::uc32 character) {
|
||||||
// y with umlauts and the micro sign are the only characters that stop
|
// y with umlauts and the micro sign are the only characters that stop
|
||||||
// fitting into one-byte when converting to uppercase.
|
// fitting into one-byte when converting to uppercase.
|
||||||
static const uc32 yuml_code = 0xFF;
|
static const base::uc32 yuml_code = 0xFF;
|
||||||
static const uc32 micro_code = 0xB5;
|
static const base::uc32 micro_code = 0xB5;
|
||||||
return (character == yuml_code || character == micro_code);
|
return (character == yuml_code || character == micro_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,11 +261,11 @@ V8_WARN_UNUSED_RESULT static Object ConvertCaseHelper(
|
|||||||
StringCharacterStream stream(string);
|
StringCharacterStream stream(string);
|
||||||
unibrow::uchar chars[Converter::kMaxWidth];
|
unibrow::uchar chars[Converter::kMaxWidth];
|
||||||
// We can assume that the string is not empty
|
// We can assume that the string is not empty
|
||||||
uc32 current = stream.GetNext();
|
base::uc32 current = stream.GetNext();
|
||||||
bool ignore_overflow = Converter::kIsToLower || result.IsSeqTwoByteString();
|
bool ignore_overflow = Converter::kIsToLower || result.IsSeqTwoByteString();
|
||||||
for (int i = 0; i < result_length;) {
|
for (int i = 0; i < result_length;) {
|
||||||
bool has_next = stream.HasMore();
|
bool has_next = stream.HasMore();
|
||||||
uc32 next = has_next ? stream.GetNext() : 0;
|
base::uc32 next = has_next ? stream.GetNext() : 0;
|
||||||
int char_length = mapping->get(current, next, chars);
|
int char_length = mapping->get(current, next, chars);
|
||||||
if (char_length == 0) {
|
if (char_length == 0) {
|
||||||
// The case conversion of this character is the character itself.
|
// The case conversion of this character is the character itself.
|
||||||
@ -272,7 +274,7 @@ V8_WARN_UNUSED_RESULT static Object ConvertCaseHelper(
|
|||||||
} else if (char_length == 1 &&
|
} else if (char_length == 1 &&
|
||||||
(ignore_overflow || !ToUpperOverflows(current))) {
|
(ignore_overflow || !ToUpperOverflows(current))) {
|
||||||
// Common case: converting the letter resulted in one character.
|
// Common case: converting the letter resulted in one character.
|
||||||
DCHECK(static_cast<uc32>(chars[0]) != current);
|
DCHECK(static_cast<base::uc32>(chars[0]) != current);
|
||||||
result.Set(i, chars[0]);
|
result.Set(i, chars[0]);
|
||||||
has_changed_character = true;
|
has_changed_character = true;
|
||||||
i++;
|
i++;
|
||||||
|
@ -3103,7 +3103,8 @@ void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
|
|||||||
__ j(below, &process_64_bits);
|
__ j(below, &process_64_bits);
|
||||||
|
|
||||||
// Result is entirely in lower 32-bits of mantissa
|
// Result is entirely in lower 32-bits of mantissa
|
||||||
int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
|
int delta =
|
||||||
|
HeapNumber::kExponentBias + base::Double::kPhysicalSignificandSize;
|
||||||
if (CpuFeatures::IsSupported(SSE3)) {
|
if (CpuFeatures::IsSupported(SSE3)) {
|
||||||
__ fstp(0);
|
__ fstp(0);
|
||||||
}
|
}
|
||||||
@ -3129,10 +3130,11 @@ void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
|
|||||||
__ sub(ecx, Immediate(delta));
|
__ sub(ecx, Immediate(delta));
|
||||||
__ neg(ecx);
|
__ neg(ecx);
|
||||||
__ mov(result_reg, exponent_operand);
|
__ mov(result_reg, exponent_operand);
|
||||||
__ and_(result_reg,
|
__ and_(
|
||||||
Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32)));
|
result_reg,
|
||||||
|
Immediate(static_cast<uint32_t>(base::Double::kSignificandMask >> 32)));
|
||||||
__ add(result_reg,
|
__ add(result_reg,
|
||||||
Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32)));
|
Immediate(static_cast<uint32_t>(base::Double::kHiddenBit >> 32)));
|
||||||
__ shrd_cl(scratch1, result_reg);
|
__ shrd_cl(scratch1, result_reg);
|
||||||
__ shr_cl(result_reg);
|
__ shr_cl(result_reg);
|
||||||
__ test(ecx, Immediate(32));
|
__ test(ecx, Immediate(32));
|
||||||
|
@ -527,7 +527,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
|||||||
// Save callee-saved double registers.
|
// Save callee-saved double registers.
|
||||||
__ MultiPushDoubles(kCalleeSavedDoubles);
|
__ MultiPushDoubles(kCalleeSavedDoubles);
|
||||||
// Set up the reserved register for 0.0.
|
// Set up the reserved register for 0.0.
|
||||||
__ LoadDoubleLiteral(kDoubleRegZero, Double(0.0), r0);
|
__ LoadDoubleLiteral(kDoubleRegZero, base::Double(0.0), r0);
|
||||||
|
|
||||||
// Initialize the root register.
|
// Initialize the root register.
|
||||||
// C calling convention. The first argument is passed in r3.
|
// C calling convention. The first argument is passed in r3.
|
||||||
|
@ -3772,7 +3772,8 @@ void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
|
|||||||
__ j(below, &process_64_bits, Label::kNear);
|
__ j(below, &process_64_bits, Label::kNear);
|
||||||
|
|
||||||
// Result is entirely in lower 32-bits of mantissa
|
// Result is entirely in lower 32-bits of mantissa
|
||||||
int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
|
int delta =
|
||||||
|
HeapNumber::kExponentBias + base::Double::kPhysicalSignificandSize;
|
||||||
__ subl(rcx, Immediate(delta));
|
__ subl(rcx, Immediate(delta));
|
||||||
__ xorl(result_reg, result_reg);
|
__ xorl(result_reg, result_reg);
|
||||||
__ cmpl(rcx, Immediate(31));
|
__ cmpl(rcx, Immediate(31));
|
||||||
|
@ -2674,7 +2674,7 @@ void Assembler::vstm(BlockAddrMode am, Register base, SwVfpRegister first,
|
|||||||
0xA * B8 | count);
|
0xA * B8 | count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DoubleAsTwoUInt32(Double d, uint32_t* lo, uint32_t* hi) {
|
static void DoubleAsTwoUInt32(base::Double d, uint32_t* lo, uint32_t* hi) {
|
||||||
uint64_t i = d.AsUint64();
|
uint64_t i = d.AsUint64();
|
||||||
|
|
||||||
*lo = i & 0xFFFFFFFF;
|
*lo = i & 0xFFFFFFFF;
|
||||||
@ -2747,7 +2747,7 @@ void Assembler::vmov(const QwNeonRegister dst, uint64_t imm) {
|
|||||||
|
|
||||||
// Only works for little endian floating point formats.
|
// Only works for little endian floating point formats.
|
||||||
// We don't support VFP on the mixed endian floating point platform.
|
// We don't support VFP on the mixed endian floating point platform.
|
||||||
static bool FitsVmovFPImmediate(Double d, uint32_t* encoding) {
|
static bool FitsVmovFPImmediate(base::Double d, uint32_t* encoding) {
|
||||||
// VMOV can accept an immediate of the form:
|
// VMOV can accept an immediate of the form:
|
||||||
//
|
//
|
||||||
// +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
|
// +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
|
||||||
@ -2796,7 +2796,7 @@ static bool FitsVmovFPImmediate(Double d, uint32_t* encoding) {
|
|||||||
void Assembler::vmov(const SwVfpRegister dst, Float32 imm) {
|
void Assembler::vmov(const SwVfpRegister dst, Float32 imm) {
|
||||||
uint32_t enc;
|
uint32_t enc;
|
||||||
if (CpuFeatures::IsSupported(VFPv3) &&
|
if (CpuFeatures::IsSupported(VFPv3) &&
|
||||||
FitsVmovFPImmediate(Double(imm.get_scalar()), &enc)) {
|
FitsVmovFPImmediate(base::Double(imm.get_scalar()), &enc)) {
|
||||||
CpuFeatureScope scope(this, VFPv3);
|
CpuFeatureScope scope(this, VFPv3);
|
||||||
// The float can be encoded in the instruction.
|
// The float can be encoded in the instruction.
|
||||||
//
|
//
|
||||||
@ -2815,7 +2815,7 @@ void Assembler::vmov(const SwVfpRegister dst, Float32 imm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::vmov(const DwVfpRegister dst, Double imm,
|
void Assembler::vmov(const DwVfpRegister dst, base::Double imm,
|
||||||
const Register extra_scratch) {
|
const Register extra_scratch) {
|
||||||
DCHECK(VfpRegisterIsAvailable(dst));
|
DCHECK(VfpRegisterIsAvailable(dst));
|
||||||
uint32_t enc;
|
uint32_t enc;
|
||||||
|
@ -45,13 +45,13 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/base/small-vector.h"
|
#include "src/base/small-vector.h"
|
||||||
#include "src/codegen/arm/constants-arm.h"
|
#include "src/codegen/arm/constants-arm.h"
|
||||||
#include "src/codegen/arm/register-arm.h"
|
#include "src/codegen/arm/register-arm.h"
|
||||||
#include "src/codegen/assembler.h"
|
#include "src/codegen/assembler.h"
|
||||||
#include "src/codegen/constant-pool.h"
|
#include "src/codegen/constant-pool.h"
|
||||||
#include "src/codegen/machine-type.h"
|
#include "src/codegen/machine-type.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/utils/boxed-float.h"
|
#include "src/utils/boxed-float.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -712,7 +712,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
|||||||
SwVfpRegister last, Condition cond = al);
|
SwVfpRegister last, Condition cond = al);
|
||||||
|
|
||||||
void vmov(const SwVfpRegister dst, Float32 imm);
|
void vmov(const SwVfpRegister dst, Float32 imm);
|
||||||
void vmov(const DwVfpRegister dst, Double imm,
|
void vmov(const DwVfpRegister dst, base::Double imm,
|
||||||
const Register extra_scratch = no_reg);
|
const Register extra_scratch = no_reg);
|
||||||
void vmov(const SwVfpRegister dst, const SwVfpRegister src,
|
void vmov(const SwVfpRegister dst, const SwVfpRegister src,
|
||||||
const Condition cond = al);
|
const Condition cond = al);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "src/base/bits.h"
|
#include "src/base/bits.h"
|
||||||
#include "src/base/division-by-constant.h"
|
#include "src/base/division-by-constant.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/base/utils/random-number-generator.h"
|
#include "src/base/utils/random-number-generator.h"
|
||||||
#include "src/codegen/assembler-inl.h"
|
#include "src/codegen/assembler-inl.h"
|
||||||
#include "src/codegen/callable.h"
|
#include "src/codegen/callable.h"
|
||||||
@ -21,7 +22,6 @@
|
|||||||
#include "src/heap/memory-chunk.h"
|
#include "src/heap/memory-chunk.h"
|
||||||
#include "src/init/bootstrapper.h"
|
#include "src/init/bootstrapper.h"
|
||||||
#include "src/logging/counters.h"
|
#include "src/logging/counters.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/objects-inl.h"
|
#include "src/objects/objects-inl.h"
|
||||||
#include "src/runtime/runtime.h"
|
#include "src/runtime/runtime.h"
|
||||||
#include "src/snapshot/snapshot.h"
|
#include "src/snapshot/snapshot.h"
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/label.h"
|
#include "src/codegen/label.h"
|
||||||
#include "src/codegen/reloc-info.h"
|
#include "src/codegen/reloc-info.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -29,7 +29,7 @@ class ConstantPoolEntry {
|
|||||||
merged_index_(sharing_ok ? SHARING_ALLOWED : SHARING_PROHIBITED),
|
merged_index_(sharing_ok ? SHARING_ALLOWED : SHARING_PROHIBITED),
|
||||||
value_(value),
|
value_(value),
|
||||||
rmode_(rmode) {}
|
rmode_(rmode) {}
|
||||||
ConstantPoolEntry(int position, Double value,
|
ConstantPoolEntry(int position, base::Double value,
|
||||||
RelocInfo::Mode rmode = RelocInfo::NONE)
|
RelocInfo::Mode rmode = RelocInfo::NONE)
|
||||||
: position_(position),
|
: position_(position),
|
||||||
merged_index_(SHARING_ALLOWED),
|
merged_index_(SHARING_ALLOWED),
|
||||||
@ -106,14 +106,14 @@ class ConstantPoolBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add double constant to the embedded constant pool
|
// Add double constant to the embedded constant pool
|
||||||
ConstantPoolEntry::Access AddEntry(int position, Double value) {
|
ConstantPoolEntry::Access AddEntry(int position, base::Double value) {
|
||||||
ConstantPoolEntry entry(position, value);
|
ConstantPoolEntry entry(position, value);
|
||||||
return AddEntry(&entry, ConstantPoolEntry::DOUBLE);
|
return AddEntry(&entry, ConstantPoolEntry::DOUBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add double constant to the embedded constant pool
|
// Add double constant to the embedded constant pool
|
||||||
ConstantPoolEntry::Access AddEntry(int position, double value) {
|
ConstantPoolEntry::Access AddEntry(int position, double value) {
|
||||||
return AddEntry(position, Double(value));
|
return AddEntry(position, base::Double(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Previews the access type required for the next new entry to be added.
|
// Previews the access type required for the next new entry to be added.
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#ifdef V8_INTL_SUPPORT
|
#ifdef V8_INTL_SUPPORT
|
||||||
#include "src/base/platform/wrappers.h"
|
#include "src/base/platform/wrappers.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/objects/intl-objects.h"
|
#include "src/objects/intl-objects.h"
|
||||||
#endif // V8_INTL_SUPPORT
|
#endif // V8_INTL_SUPPORT
|
||||||
|
|
||||||
@ -835,15 +836,15 @@ ExternalReference ExternalReference::search_string_raw_one_one() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExternalReference ExternalReference::search_string_raw_one_two() {
|
ExternalReference ExternalReference::search_string_raw_one_two() {
|
||||||
return search_string_raw<const uint8_t, const uc16>();
|
return search_string_raw<const uint8_t, const base::uc16>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalReference ExternalReference::search_string_raw_two_one() {
|
ExternalReference ExternalReference::search_string_raw_two_one() {
|
||||||
return search_string_raw<const uc16, const uint8_t>();
|
return search_string_raw<const base::uc16, const uint8_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalReference ExternalReference::search_string_raw_two_two() {
|
ExternalReference ExternalReference::search_string_raw_two_two() {
|
||||||
return search_string_raw<const uc16, const uc16>();
|
return search_string_raw<const base::uc16, const base::uc16>();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -961,11 +962,11 @@ ExternalReference ExternalReference::intl_to_latin1_lower_table() {
|
|||||||
template ExternalReference
|
template ExternalReference
|
||||||
ExternalReference::search_string_raw<const uint8_t, const uint8_t>();
|
ExternalReference::search_string_raw<const uint8_t, const uint8_t>();
|
||||||
template ExternalReference
|
template ExternalReference
|
||||||
ExternalReference::search_string_raw<const uint8_t, const uc16>();
|
ExternalReference::search_string_raw<const uint8_t, const base::uc16>();
|
||||||
template ExternalReference
|
template ExternalReference
|
||||||
ExternalReference::search_string_raw<const uc16, const uint8_t>();
|
ExternalReference::search_string_raw<const base::uc16, const uint8_t>();
|
||||||
template ExternalReference
|
template ExternalReference
|
||||||
ExternalReference::search_string_raw<const uc16, const uc16>();
|
ExternalReference::search_string_raw<const base::uc16, const base::uc16>();
|
||||||
|
|
||||||
ExternalReference ExternalReference::FromRawAddress(Address address) {
|
ExternalReference ExternalReference::FromRawAddress(Address address) {
|
||||||
return ExternalReference(address);
|
return ExternalReference(address);
|
||||||
|
@ -2142,7 +2142,7 @@ void TurboAssembler::Neg_d(FPURegister fd, FPURegister fs) {
|
|||||||
neg_d(fd, fs); // In delay slot.
|
neg_d(fd, fs); // In delay slot.
|
||||||
bind(&is_nan);
|
bind(&is_nan);
|
||||||
dmfc1(scratch1, fs);
|
dmfc1(scratch1, fs);
|
||||||
li(scratch2, Double::kSignMask);
|
li(scratch2, base::Double::kSignMask);
|
||||||
Xor(scratch1, scratch1, scratch2);
|
Xor(scratch1, scratch1, scratch2);
|
||||||
dmtc1(scratch1, fd);
|
dmtc1(scratch1, fd);
|
||||||
bind(&done);
|
bind(&done);
|
||||||
|
@ -41,16 +41,17 @@
|
|||||||
#define V8_CODEGEN_PPC_ASSEMBLER_PPC_H_
|
#define V8_CODEGEN_PPC_ASSEMBLER_PPC_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/assembler.h"
|
#include "src/codegen/assembler.h"
|
||||||
#include "src/codegen/constant-pool.h"
|
#include "src/codegen/constant-pool.h"
|
||||||
#include "src/codegen/external-reference.h"
|
#include "src/codegen/external-reference.h"
|
||||||
#include "src/codegen/label.h"
|
#include "src/codegen/label.h"
|
||||||
#include "src/codegen/ppc/constants-ppc.h"
|
#include "src/codegen/ppc/constants-ppc.h"
|
||||||
#include "src/codegen/ppc/register-ppc.h"
|
#include "src/codegen/ppc/register-ppc.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/smi.h"
|
#include "src/objects/smi.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -1251,7 +1252,7 @@ class Assembler : public AssemblerBase {
|
|||||||
!RelocInfo::IsWasmCall(rmode) && !RelocInfo::IsWasmStubCall(rmode));
|
!RelocInfo::IsWasmCall(rmode) && !RelocInfo::IsWasmStubCall(rmode));
|
||||||
return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
|
return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
|
||||||
}
|
}
|
||||||
ConstantPoolEntry::Access ConstantPoolAddEntry(Double value) {
|
ConstantPoolEntry::Access ConstantPoolAddEntry(base::Double value) {
|
||||||
return constant_pool_builder_.AddEntry(pc_offset(), value);
|
return constant_pool_builder_.AddEntry(pc_offset(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2341,8 +2341,8 @@ void TurboAssembler::LoadSmiLiteral(Register dst, Smi smi) {
|
|||||||
mov(dst, Operand(smi));
|
mov(dst, Operand(smi));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TurboAssembler::LoadDoubleLiteral(DoubleRegister result, Double value,
|
void TurboAssembler::LoadDoubleLiteral(DoubleRegister result,
|
||||||
Register scratch) {
|
base::Double value, Register scratch) {
|
||||||
if (FLAG_enable_embedded_constant_pool && is_constant_pool_available() &&
|
if (FLAG_enable_embedded_constant_pool && is_constant_pool_available() &&
|
||||||
!(scratch == r0 && ConstantPoolAccessIsInOverflow())) {
|
!(scratch == r0 && ConstantPoolAccessIsInOverflow())) {
|
||||||
ConstantPoolEntry::Access access = ConstantPoolAddEntry(value);
|
ConstantPoolEntry::Access access = ConstantPoolAddEntry(value);
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
#ifndef V8_CODEGEN_PPC_MACRO_ASSEMBLER_PPC_H_
|
#ifndef V8_CODEGEN_PPC_MACRO_ASSEMBLER_PPC_H_
|
||||||
#define V8_CODEGEN_PPC_MACRO_ASSEMBLER_PPC_H_
|
#define V8_CODEGEN_PPC_MACRO_ASSEMBLER_PPC_H_
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/bailout-reason.h"
|
#include "src/codegen/bailout-reason.h"
|
||||||
#include "src/codegen/ppc/assembler-ppc.h"
|
#include "src/codegen/ppc/assembler-ppc.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/contexts.h"
|
#include "src/objects/contexts.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -138,7 +138,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
|||||||
mov(kRootRegister, Operand(isolate_root));
|
mov(kRootRegister, Operand(isolate_root));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadDoubleLiteral(DoubleRegister result, Double value, Register scratch);
|
void LoadDoubleLiteral(DoubleRegister result, base::Double value,
|
||||||
|
Register scratch);
|
||||||
void LoadSimd128(Simd128Register dst, const MemOperand& mem);
|
void LoadSimd128(Simd128Register dst, const MemOperand& mem);
|
||||||
|
|
||||||
// load a literal signed int value <value> to GPR <dst>
|
// load a literal signed int value <value> to GPR <dst>
|
||||||
|
@ -223,7 +223,7 @@ constexpr int kElidedFrameSlots = 0;
|
|||||||
constexpr int kDoubleSizeLog2 = 3;
|
constexpr int kDoubleSizeLog2 = 3;
|
||||||
// The maximal length of the string representation for a double value
|
// The maximal length of the string representation for a double value
|
||||||
// (e.g. "-2.2250738585072020E-308"). It is composed as follows:
|
// (e.g. "-2.2250738585072020E-308"). It is composed as follows:
|
||||||
// - 17 decimal digits, see kBase10MaximalLength (dtoa.h)
|
// - 17 decimal digits, see base::kBase10MaximalLength (dtoa.h)
|
||||||
// - 1 sign
|
// - 1 sign
|
||||||
// - 1 decimal point
|
// - 1 decimal point
|
||||||
// - 1 E or e
|
// - 1 E or e
|
||||||
@ -379,13 +379,7 @@ constexpr int kBinary32ExponentShift = 23;
|
|||||||
// other bits set.
|
// other bits set.
|
||||||
constexpr uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
|
constexpr uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
|
||||||
|
|
||||||
// Latin1/UTF-16 constants
|
|
||||||
// Code-point values in Unicode 4.0 are 21 bits wide.
|
|
||||||
// Code units in UTF-16 are 16 bits wide.
|
|
||||||
using uc16 = uint16_t;
|
|
||||||
using uc32 = uint32_t;
|
|
||||||
constexpr int kOneByteSize = kCharSize;
|
constexpr int kOneByteSize = kCharSize;
|
||||||
constexpr int kUC16Size = sizeof(uc16);
|
|
||||||
|
|
||||||
// 128 bit SIMD value size.
|
// 128 bit SIMD value size.
|
||||||
constexpr int kSimd128Size = 16;
|
constexpr int kSimd128Size = 16;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/arm/constants-arm.h"
|
#include "src/codegen/arm/constants-arm.h"
|
||||||
#include "src/codegen/assembler-inl.h"
|
#include "src/codegen/assembler-inl.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
@ -13,7 +14,6 @@
|
|||||||
#include "src/compiler/node-matchers.h"
|
#include "src/compiler/node-matchers.h"
|
||||||
#include "src/compiler/osr.h"
|
#include "src/compiler/osr.h"
|
||||||
#include "src/heap/memory-chunk.h"
|
#include "src/heap/memory-chunk.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/utils/boxed-float.h"
|
#include "src/utils/boxed-float.h"
|
||||||
|
|
||||||
#if V8_ENABLE_WEBASSEMBLY
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
@ -2511,8 +2511,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
__ vshr(NeonS32, tmp, src, 31);
|
__ vshr(NeonS32, tmp, src, 31);
|
||||||
// Set i-th bit of each lane i. When AND with tmp, the lanes that
|
// Set i-th bit of each lane i. When AND with tmp, the lanes that
|
||||||
// are signed will have i-th bit set, unsigned will be 0.
|
// are signed will have i-th bit set, unsigned will be 0.
|
||||||
__ vmov(mask.low(), Double(uint64_t{0x0000'0002'0000'0001}));
|
__ vmov(mask.low(), base::Double(uint64_t{0x0000'0002'0000'0001}));
|
||||||
__ vmov(mask.high(), Double(uint64_t{0x0000'0008'0000'0004}));
|
__ vmov(mask.high(), base::Double(uint64_t{0x0000'0008'0000'0004}));
|
||||||
__ vand(tmp, mask, tmp);
|
__ vand(tmp, mask, tmp);
|
||||||
__ vpadd(Neon32, tmp.low(), tmp.low(), tmp.high());
|
__ vpadd(Neon32, tmp.low(), tmp.low(), tmp.high());
|
||||||
__ vpadd(Neon32, tmp.low(), tmp.low(), kDoubleRegZero);
|
__ vpadd(Neon32, tmp.low(), tmp.low(), kDoubleRegZero);
|
||||||
@ -2715,8 +2715,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
__ vshr(NeonS16, tmp, src, 15);
|
__ vshr(NeonS16, tmp, src, 15);
|
||||||
// Set i-th bit of each lane i. When AND with tmp, the lanes that
|
// Set i-th bit of each lane i. When AND with tmp, the lanes that
|
||||||
// are signed will have i-th bit set, unsigned will be 0.
|
// are signed will have i-th bit set, unsigned will be 0.
|
||||||
__ vmov(mask.low(), Double(uint64_t{0x0008'0004'0002'0001}));
|
__ vmov(mask.low(), base::Double(uint64_t{0x0008'0004'0002'0001}));
|
||||||
__ vmov(mask.high(), Double(uint64_t{0x0080'0040'0020'0010}));
|
__ vmov(mask.high(), base::Double(uint64_t{0x0080'0040'0020'0010}));
|
||||||
__ vand(tmp, mask, tmp);
|
__ vand(tmp, mask, tmp);
|
||||||
__ vpadd(Neon16, tmp.low(), tmp.low(), tmp.high());
|
__ vpadd(Neon16, tmp.low(), tmp.low(), tmp.high());
|
||||||
__ vpadd(Neon16, tmp.low(), tmp.low(), tmp.low());
|
__ vpadd(Neon16, tmp.low(), tmp.low(), tmp.low());
|
||||||
@ -2870,8 +2870,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
__ vshr(NeonS8, tmp, src, 7);
|
__ vshr(NeonS8, tmp, src, 7);
|
||||||
// Set i-th bit of each lane i. When AND with tmp, the lanes that
|
// Set i-th bit of each lane i. When AND with tmp, the lanes that
|
||||||
// are signed will have i-th bit set, unsigned will be 0.
|
// are signed will have i-th bit set, unsigned will be 0.
|
||||||
__ vmov(mask.low(), Double(uint64_t{0x8040'2010'0804'0201}));
|
__ vmov(mask.low(), base::Double(uint64_t{0x8040'2010'0804'0201}));
|
||||||
__ vmov(mask.high(), Double(uint64_t{0x8040'2010'0804'0201}));
|
__ vmov(mask.high(), base::Double(uint64_t{0x8040'2010'0804'0201}));
|
||||||
__ vand(tmp, mask, tmp);
|
__ vand(tmp, mask, tmp);
|
||||||
__ vext(mask, tmp, tmp, 8);
|
__ vext(mask, tmp, tmp, 8);
|
||||||
__ vzip(Neon8, mask, tmp);
|
__ vzip(Neon8, mask, tmp);
|
||||||
@ -2885,8 +2885,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
QwNeonRegister dst = i.OutputSimd128Register();
|
QwNeonRegister dst = i.OutputSimd128Register();
|
||||||
uint64_t imm1 = make_uint64(i.InputUint32(1), i.InputUint32(0));
|
uint64_t imm1 = make_uint64(i.InputUint32(1), i.InputUint32(0));
|
||||||
uint64_t imm2 = make_uint64(i.InputUint32(3), i.InputUint32(2));
|
uint64_t imm2 = make_uint64(i.InputUint32(3), i.InputUint32(2));
|
||||||
__ vmov(dst.low(), Double(imm1));
|
__ vmov(dst.low(), base::Double(imm1));
|
||||||
__ vmov(dst.high(), Double(imm2));
|
__ vmov(dst.high(), base::Double(imm2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kArmS128Zero: {
|
case kArmS128Zero: {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "src/base/compiler-specific.h"
|
#include "src/base/compiler-specific.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/external-reference.h"
|
#include "src/codegen/external-reference.h"
|
||||||
#include "src/codegen/register-arch.h"
|
#include "src/codegen/register-arch.h"
|
||||||
#include "src/codegen/source-position.h"
|
#include "src/codegen/source-position.h"
|
||||||
@ -20,7 +21,6 @@
|
|||||||
#include "src/compiler/feedback-source.h"
|
#include "src/compiler/feedback-source.h"
|
||||||
#include "src/compiler/frame.h"
|
#include "src/compiler/frame.h"
|
||||||
#include "src/compiler/opcodes.h"
|
#include "src/compiler/opcodes.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/zone/zone-allocator.h"
|
#include "src/zone/zone-allocator.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -1147,9 +1147,9 @@ class V8_EXPORT_PRIVATE Constant final {
|
|||||||
return bit_cast<uint32_t>(static_cast<int32_t>(value_));
|
return bit_cast<uint32_t>(static_cast<int32_t>(value_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Double ToFloat64() const {
|
base::Double ToFloat64() const {
|
||||||
DCHECK_EQ(kFloat64, type());
|
DCHECK_EQ(kFloat64, type());
|
||||||
return Double(bit_cast<uint64_t>(value_));
|
return base::Double(bit_cast<uint64_t>(value_));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalReference ToExternalReference() const {
|
ExternalReference ToExternalReference() const {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/assembler-inl.h"
|
#include "src/codegen/assembler-inl.h"
|
||||||
#include "src/codegen/callable.h"
|
#include "src/codegen/callable.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
@ -12,7 +13,6 @@
|
|||||||
#include "src/compiler/node-matchers.h"
|
#include "src/compiler/node-matchers.h"
|
||||||
#include "src/compiler/osr.h"
|
#include "src/compiler/osr.h"
|
||||||
#include "src/heap/memory-chunk.h"
|
#include "src/heap/memory-chunk.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
|
|
||||||
#if V8_ENABLE_WEBASSEMBLY
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
#include "src/wasm/wasm-code-manager.h"
|
#include "src/wasm/wasm-code-manager.h"
|
||||||
@ -4435,7 +4435,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
DoubleRegister dst = destination->IsFPRegister()
|
DoubleRegister dst = destination->IsFPRegister()
|
||||||
? g.ToDoubleRegister(destination)
|
? g.ToDoubleRegister(destination)
|
||||||
: kScratchDoubleReg;
|
: kScratchDoubleReg;
|
||||||
Double value;
|
base::Double value;
|
||||||
#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
|
#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
|
||||||
// casting double precision snan to single precision
|
// casting double precision snan to single precision
|
||||||
// converts it to qnan on ia32/x64
|
// converts it to qnan on ia32/x64
|
||||||
@ -4445,17 +4445,17 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
uint64_t dval = static_cast<uint64_t>(val);
|
uint64_t dval = static_cast<uint64_t>(val);
|
||||||
dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
|
dval = ((dval & 0xC0000000) << 32) | ((dval & 0x40000000) << 31) |
|
||||||
((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29);
|
((dval & 0x40000000) << 30) | ((dval & 0x7FFFFFFF) << 29);
|
||||||
value = Double(dval);
|
value = base::Double(dval);
|
||||||
} else {
|
} else {
|
||||||
value = Double(static_cast<double>(src.ToFloat32()));
|
value = base::Double(static_cast<double>(src.ToFloat32()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = Double(src.ToFloat64());
|
value = base::Double(src.ToFloat64());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
value = src.type() == Constant::kFloat32
|
value = src.type() == Constant::kFloat32
|
||||||
? Double(static_cast<double>(src.ToFloat32()))
|
? base::Double(static_cast<double>(src.ToFloat32()))
|
||||||
: Double(src.ToFloat64());
|
: base::Double(src.ToFloat64());
|
||||||
#endif
|
#endif
|
||||||
__ LoadDoubleLiteral(dst, value, kScratchReg);
|
__ LoadDoubleLiteral(dst, value, kScratchReg);
|
||||||
if (destination->IsDoubleStackSlot()) {
|
if (destination->IsDoubleStackSlot()) {
|
||||||
|
@ -544,7 +544,7 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
|
|||||||
case IrOpcode::kFloat64Sub: {
|
case IrOpcode::kFloat64Sub: {
|
||||||
Float64BinopMatcher m(node);
|
Float64BinopMatcher m(node);
|
||||||
if (allow_signalling_nan_ && m.right().Is(0) &&
|
if (allow_signalling_nan_ && m.right().Is(0) &&
|
||||||
(Double(m.right().ResolvedValue()).Sign() > 0)) {
|
(base::Double(m.right().ResolvedValue()).Sign() > 0)) {
|
||||||
return Replace(m.left().node()); // x - 0 => x
|
return Replace(m.left().node()); // x - 0 => x
|
||||||
}
|
}
|
||||||
if (m.right().IsNaN()) { // x - NaN => NaN
|
if (m.right().IsNaN()) { // x - NaN => NaN
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
|
|
||||||
#include "src/base/bounds.h"
|
#include "src/base/bounds.h"
|
||||||
#include "src/base/compiler-specific.h"
|
#include "src/base/compiler-specific.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/codegen/external-reference.h"
|
#include "src/codegen/external-reference.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/compiler/common-operator.h"
|
#include "src/compiler/common-operator.h"
|
||||||
#include "src/compiler/machine-operator.h"
|
#include "src/compiler/machine-operator.h"
|
||||||
#include "src/compiler/node.h"
|
#include "src/compiler/node.h"
|
||||||
#include "src/compiler/operator.h"
|
#include "src/compiler/operator.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/heap-object.h"
|
#include "src/objects/heap-object.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -216,7 +216,7 @@ struct FloatMatcher final : public ValueMatcher<T, kOpcode> {
|
|||||||
if (!this->HasResolvedValue() || (this->ResolvedValue() == 0.0)) {
|
if (!this->HasResolvedValue() || (this->ResolvedValue() == 0.0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Double value = Double(this->ResolvedValue());
|
base::Double value = base::Double(this->ResolvedValue());
|
||||||
return !value.IsInfinite() && base::bits::IsPowerOfTwo(value.Significand());
|
return !value.IsInfinite() && base::bits::IsPowerOfTwo(value.Significand());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
#include "torque-generated/class-verifiers.h"
|
#include "torque-generated/class-verifiers.h"
|
||||||
|
|
||||||
#if V8_ENABLE_WEBASSEMBLY
|
#if V8_ENABLE_WEBASSEMBLY
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/debug/debug-wasm-objects-inl.h"
|
#include "src/debug/debug-wasm-objects-inl.h"
|
||||||
#include "src/wasm/wasm-objects-inl.h"
|
#include "src/wasm/wasm-objects-inl.h"
|
||||||
#endif // V8_ENABLE_WEBASSEMBLY
|
#endif // V8_ENABLE_WEBASSEMBLY
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "src/extensions/externalize-string-extension.h"
|
#include "src/extensions/externalize-string-extension.h"
|
||||||
|
|
||||||
#include "src/api/api-inl.h"
|
#include "src/api/api-inl.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/execution/isolate.h"
|
#include "src/execution/isolate.h"
|
||||||
#include "src/handles/handles.h"
|
#include "src/handles/handles.h"
|
||||||
#include "src/objects/objects-inl.h"
|
#include "src/objects/objects-inl.h"
|
||||||
@ -34,7 +35,7 @@ class SimpleStringResource : public Base {
|
|||||||
using SimpleOneByteStringResource =
|
using SimpleOneByteStringResource =
|
||||||
SimpleStringResource<char, v8::String::ExternalOneByteStringResource>;
|
SimpleStringResource<char, v8::String::ExternalOneByteStringResource>;
|
||||||
using SimpleTwoByteStringResource =
|
using SimpleTwoByteStringResource =
|
||||||
SimpleStringResource<uc16, v8::String::ExternalStringResource>;
|
SimpleStringResource<base::uc16, v8::String::ExternalStringResource>;
|
||||||
|
|
||||||
const char* const ExternalizeStringExtension::kSource =
|
const char* const ExternalizeStringExtension::kSource =
|
||||||
"native function externalizeString();"
|
"native function externalizeString();"
|
||||||
@ -87,7 +88,7 @@ void ExternalizeStringExtension::Externalize(
|
|||||||
result = Utils::ToLocal(string)->MakeExternal(resource);
|
result = Utils::ToLocal(string)->MakeExternal(resource);
|
||||||
if (!result) delete resource;
|
if (!result) delete resource;
|
||||||
} else {
|
} else {
|
||||||
uc16* data = new uc16[string->length()];
|
base::uc16* data = new base::uc16[string->length()];
|
||||||
String::WriteToFlat(*string, data, 0, string->length());
|
String::WriteToFlat(*string, data, 0, string->length());
|
||||||
SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
|
SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
|
||||||
data, string->length());
|
data, string->length());
|
||||||
|
@ -530,12 +530,12 @@ Handle<SeqOneByteString> FactoryBase<Impl>::NewOneByteInternalizedString(
|
|||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
Handle<SeqTwoByteString> FactoryBase<Impl>::NewTwoByteInternalizedString(
|
Handle<SeqTwoByteString> FactoryBase<Impl>::NewTwoByteInternalizedString(
|
||||||
const base::Vector<const uc16>& str, uint32_t raw_hash_field) {
|
const base::Vector<const base::uc16>& str, uint32_t raw_hash_field) {
|
||||||
Handle<SeqTwoByteString> result =
|
Handle<SeqTwoByteString> result =
|
||||||
AllocateRawTwoByteInternalizedString(str.length(), raw_hash_field);
|
AllocateRawTwoByteInternalizedString(str.length(), raw_hash_field);
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
MemCopy(result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()),
|
MemCopy(result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()),
|
||||||
str.begin(), str.length() * kUC16Size);
|
str.begin(), str.length() * base::kUC16Size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ MaybeHandle<String> FactoryBase<Impl>::NewConsString(
|
|||||||
|
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
SharedStringAccessGuardIfNeeded access_guard(isolate());
|
SharedStringAccessGuardIfNeeded access_guard(isolate());
|
||||||
uc16* sink = result->GetChars(no_gc, access_guard);
|
base::uc16* sink = result->GetChars(no_gc, access_guard);
|
||||||
String::WriteToFlat(*left, sink, 0, left->length(), access_guard);
|
String::WriteToFlat(*left, sink, 0, left->length(), access_guard);
|
||||||
String::WriteToFlat(*right, sink + left->length(), 0, right->length(),
|
String::WriteToFlat(*right, sink + left->length(), 0, right->length(),
|
||||||
access_guard);
|
access_guard);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define V8_HEAP_FACTORY_BASE_H_
|
#define V8_HEAP_FACTORY_BASE_H_
|
||||||
|
|
||||||
#include "src/base/export-template.h"
|
#include "src/base/export-template.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/objects/function-kind.h"
|
#include "src/objects/function-kind.h"
|
||||||
#include "src/objects/instance-type.h"
|
#include "src/objects/instance-type.h"
|
||||||
@ -182,7 +183,7 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase
|
|||||||
Handle<SeqOneByteString> NewOneByteInternalizedString(
|
Handle<SeqOneByteString> NewOneByteInternalizedString(
|
||||||
const base::Vector<const uint8_t>& str, uint32_t raw_hash_field);
|
const base::Vector<const uint8_t>& str, uint32_t raw_hash_field);
|
||||||
Handle<SeqTwoByteString> NewTwoByteInternalizedString(
|
Handle<SeqTwoByteString> NewTwoByteInternalizedString(
|
||||||
const base::Vector<const uc16>& str, uint32_t raw_hash_field);
|
const base::Vector<const base::uc16>& str, uint32_t raw_hash_field);
|
||||||
|
|
||||||
Handle<SeqOneByteString> AllocateRawOneByteInternalizedString(
|
Handle<SeqOneByteString> AllocateRawOneByteInternalizedString(
|
||||||
int length, uint32_t raw_hash_field);
|
int length, uint32_t raw_hash_field);
|
||||||
|
@ -689,7 +689,7 @@ Handle<String> Factory::InternalizeUtf8String(
|
|||||||
std::unique_ptr<uint16_t[]> buffer(new uint16_t[decoder.utf16_length()]);
|
std::unique_ptr<uint16_t[]> buffer(new uint16_t[decoder.utf16_length()]);
|
||||||
decoder.Decode(buffer.get(), utf8_data);
|
decoder.Decode(buffer.get(), utf8_data);
|
||||||
return InternalizeString(
|
return InternalizeString(
|
||||||
base::Vector<const uc16>(buffer.get(), decoder.utf16_length()));
|
base::Vector<const base::uc16>(buffer.get(), decoder.utf16_length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SeqString>
|
template <typename SeqString>
|
||||||
@ -811,7 +811,7 @@ MaybeHandle<String> Factory::NewStringFromUtf8SubString(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeHandle<String> Factory::NewStringFromTwoByte(const uc16* string,
|
MaybeHandle<String> Factory::NewStringFromTwoByte(const base::uc16* string,
|
||||||
int length,
|
int length,
|
||||||
AllocationType allocation) {
|
AllocationType allocation) {
|
||||||
DCHECK_NE(allocation, AllocationType::kReadOnly);
|
DCHECK_NE(allocation, AllocationType::kReadOnly);
|
||||||
@ -835,12 +835,12 @@ MaybeHandle<String> Factory::NewStringFromTwoByte(const uc16* string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MaybeHandle<String> Factory::NewStringFromTwoByte(
|
MaybeHandle<String> Factory::NewStringFromTwoByte(
|
||||||
const base::Vector<const uc16>& string, AllocationType allocation) {
|
const base::Vector<const base::uc16>& string, AllocationType allocation) {
|
||||||
return NewStringFromTwoByte(string.begin(), string.length(), allocation);
|
return NewStringFromTwoByte(string.begin(), string.length(), allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeHandle<String> Factory::NewStringFromTwoByte(
|
MaybeHandle<String> Factory::NewStringFromTwoByte(
|
||||||
const ZoneVector<uc16>* string, AllocationType allocation) {
|
const ZoneVector<base::uc16>* string, AllocationType allocation) {
|
||||||
return NewStringFromTwoByte(string->data(), static_cast<int>(string->size()),
|
return NewStringFromTwoByte(string->data(), static_cast<int>(string->size()),
|
||||||
allocation);
|
allocation);
|
||||||
}
|
}
|
||||||
@ -979,7 +979,7 @@ Handle<String> Factory::NewSurrogatePairString(uint16_t lead, uint16_t trail) {
|
|||||||
Handle<SeqTwoByteString> str =
|
Handle<SeqTwoByteString> str =
|
||||||
isolate()->factory()->NewRawTwoByteString(2).ToHandleChecked();
|
isolate()->factory()->NewRawTwoByteString(2).ToHandleChecked();
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
uc16* dest = str->GetChars(no_gc);
|
base::uc16* dest = str->GetChars(no_gc);
|
||||||
dest[0] = lead;
|
dest[0] = lead;
|
||||||
dest[1] = trail;
|
dest[1] = trail;
|
||||||
return str;
|
return str;
|
||||||
@ -1020,7 +1020,7 @@ Handle<String> Factory::NewProperSubString(Handle<String> str, int begin,
|
|||||||
Handle<SeqTwoByteString> result =
|
Handle<SeqTwoByteString> result =
|
||||||
NewRawTwoByteString(length).ToHandleChecked();
|
NewRawTwoByteString(length).ToHandleChecked();
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
uc16* dest = result->GetChars(no_gc);
|
base::uc16* dest = result->GetChars(no_gc);
|
||||||
String::WriteToFlat(*str, dest, begin, end);
|
String::WriteToFlat(*str, dest, begin, end);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
// Clients of this interface shouldn't depend on lots of heap internals.
|
// Clients of this interface shouldn't depend on lots of heap internals.
|
||||||
// Do not include anything from src/heap here!
|
// Do not include anything from src/heap here!
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
#include "src/baseline/baseline.h"
|
#include "src/baseline/baseline.h"
|
||||||
#include "src/builtins/builtins.h"
|
#include "src/builtins/builtins.h"
|
||||||
@ -266,11 +267,11 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
|||||||
AllocationType allocation = AllocationType::kYoung);
|
AllocationType allocation = AllocationType::kYoung);
|
||||||
|
|
||||||
V8_WARN_UNUSED_RESULT MaybeHandle<String> NewStringFromTwoByte(
|
V8_WARN_UNUSED_RESULT MaybeHandle<String> NewStringFromTwoByte(
|
||||||
const base::Vector<const uc16>& str,
|
const base::Vector<const base::uc16>& str,
|
||||||
AllocationType allocation = AllocationType::kYoung);
|
AllocationType allocation = AllocationType::kYoung);
|
||||||
|
|
||||||
V8_WARN_UNUSED_RESULT MaybeHandle<String> NewStringFromTwoByte(
|
V8_WARN_UNUSED_RESULT MaybeHandle<String> NewStringFromTwoByte(
|
||||||
const ZoneVector<uc16>* str,
|
const ZoneVector<base::uc16>* str,
|
||||||
AllocationType allocation = AllocationType::kYoung);
|
AllocationType allocation = AllocationType::kYoung);
|
||||||
|
|
||||||
Handle<JSStringIterator> NewJSStringIterator(Handle<String> string);
|
Handle<JSStringIterator> NewJSStringIterator(Handle<String> string);
|
||||||
@ -1007,9 +1008,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
|||||||
uint32_t hash_field);
|
uint32_t hash_field);
|
||||||
|
|
||||||
Handle<String> AllocateTwoByteInternalizedString(
|
Handle<String> AllocateTwoByteInternalizedString(
|
||||||
const base::Vector<const uc16>& str, uint32_t hash_field);
|
const base::Vector<const base::uc16>& str, uint32_t hash_field);
|
||||||
|
|
||||||
MaybeHandle<String> NewStringFromTwoByte(const uc16* string, int length,
|
MaybeHandle<String> NewStringFromTwoByte(const base::uc16* string, int length,
|
||||||
AllocationType allocation);
|
AllocationType allocation);
|
||||||
|
|
||||||
// Attempt to find the number in a small cache. If we finds it, return
|
// Attempt to find the number in a small cache. If we finds it, return
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/json/json-parser.h"
|
#include "src/json/json-parser.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/message-template.h"
|
#include "src/common/message-template.h"
|
||||||
#include "src/debug/debug.h"
|
#include "src/debug/debug.h"
|
||||||
#include "src/numbers/conversions.h"
|
#include "src/numbers/conversions.h"
|
||||||
@ -281,7 +282,7 @@ void JsonParser<Char>::ReportUnexpectedToken(JsonToken token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void JsonParser<Char>::ReportUnexpectedCharacter(uc32 c) {
|
void JsonParser<Char>::ReportUnexpectedCharacter(base::uc32 c) {
|
||||||
JsonToken token = JsonToken::ILLEGAL;
|
JsonToken token = JsonToken::ILLEGAL;
|
||||||
if (c == kEndOfString) {
|
if (c == kEndOfString) {
|
||||||
token = JsonToken::EOS;
|
token = JsonToken::EOS;
|
||||||
@ -331,10 +332,10 @@ void JsonParser<Char>::SkipWhitespace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
uc32 JsonParser<Char>::ScanUnicodeCharacter() {
|
base::uc32 JsonParser<Char>::ScanUnicodeCharacter() {
|
||||||
uc32 value = 0;
|
base::uc32 value = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
int digit = HexValue(NextCharacter());
|
int digit = base::HexValue(NextCharacter());
|
||||||
if (V8_UNLIKELY(digit < 0)) return kInvalidUnicodeCharacter;
|
if (V8_UNLIKELY(digit < 0)) return kInvalidUnicodeCharacter;
|
||||||
value = value * 16 + digit;
|
value = value * 16 + digit;
|
||||||
}
|
}
|
||||||
@ -347,7 +348,7 @@ JsonString JsonParser<Char>::ScanJsonPropertyKey(JsonContinuation* cont) {
|
|||||||
{
|
{
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
const Char* start = cursor_;
|
const Char* start = cursor_;
|
||||||
uc32 first = CurrentCharacter();
|
base::uc32 first = CurrentCharacter();
|
||||||
if (first == '\\' && NextCharacter() == 'u') first = ScanUnicodeCharacter();
|
if (first == '\\' && NextCharacter() == 'u') first = ScanUnicodeCharacter();
|
||||||
if (IsDecimalDigit(first)) {
|
if (IsDecimalDigit(first)) {
|
||||||
if (first == '0') {
|
if (first == '0') {
|
||||||
@ -891,7 +892,7 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
|||||||
const Char* start = cursor_;
|
const Char* start = cursor_;
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
|
|
||||||
uc32 c = *cursor_;
|
base::uc32 c = *cursor_;
|
||||||
if (c == '-') {
|
if (c == '-') {
|
||||||
sign = -1;
|
sign = -1;
|
||||||
c = NextCharacter();
|
c = NextCharacter();
|
||||||
@ -920,7 +921,7 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
|||||||
ReportUnexpectedCharacter(CurrentCharacter());
|
ReportUnexpectedCharacter(CurrentCharacter());
|
||||||
return handle(Smi::FromInt(0), isolate_);
|
return handle(Smi::FromInt(0), isolate_);
|
||||||
}
|
}
|
||||||
uc32 c = CurrentCharacter();
|
base::uc32 c = CurrentCharacter();
|
||||||
STATIC_ASSERT(Smi::IsValid(-999999999));
|
STATIC_ASSERT(Smi::IsValid(-999999999));
|
||||||
STATIC_ASSERT(Smi::IsValid(999999999));
|
STATIC_ASSERT(Smi::IsValid(999999999));
|
||||||
const int kMaxSmiLength = 9;
|
const int kMaxSmiLength = 9;
|
||||||
@ -940,7 +941,7 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentCharacter() == '.') {
|
if (CurrentCharacter() == '.') {
|
||||||
uc32 c = NextCharacter();
|
base::uc32 c = NextCharacter();
|
||||||
if (!IsDecimalDigit(c)) {
|
if (!IsDecimalDigit(c)) {
|
||||||
AllowGarbageCollection allow_before_exception;
|
AllowGarbageCollection allow_before_exception;
|
||||||
ReportUnexpectedCharacter(c);
|
ReportUnexpectedCharacter(c);
|
||||||
@ -950,7 +951,7 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (AsciiAlphaToLower(CurrentCharacter()) == 'e') {
|
if (AsciiAlphaToLower(CurrentCharacter()) == 'e') {
|
||||||
uc32 c = NextCharacter();
|
base::uc32 c = NextCharacter();
|
||||||
if (c == '-' || c == '+') c = NextCharacter();
|
if (c == '-' || c == '+') c = NextCharacter();
|
||||||
if (!IsDecimalDigit(c)) {
|
if (!IsDecimalDigit(c)) {
|
||||||
AllowGarbageCollection allow_before_exception;
|
AllowGarbageCollection allow_before_exception;
|
||||||
@ -1080,12 +1081,12 @@ void JsonParser<Char>::DecodeString(SinkChar* sink, int start, int length) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EscapeKind::kUnicode: {
|
case EscapeKind::kUnicode: {
|
||||||
uc32 value = 0;
|
base::uc32 value = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
value = value * 16 + HexValue(*++cursor);
|
value = value * 16 + base::HexValue(*++cursor);
|
||||||
}
|
}
|
||||||
if (value <=
|
if (value <=
|
||||||
static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
static_cast<base::uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
||||||
*sink++ = value;
|
*sink++ = value;
|
||||||
} else {
|
} else {
|
||||||
*sink++ = unibrow::Utf16::LeadSurrogate(value);
|
*sink++ = unibrow::Utf16::LeadSurrogate(value);
|
||||||
@ -1107,7 +1108,7 @@ JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
|
|||||||
int start = position();
|
int start = position();
|
||||||
int offset = start;
|
int offset = start;
|
||||||
bool has_escape = false;
|
bool has_escape = false;
|
||||||
uc32 bits = 0;
|
base::uc32 bits = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
cursor_ = std::find_if(cursor_, end_, [&bits](Char c) {
|
cursor_ = std::find_if(cursor_, end_, [&bits](Char c) {
|
||||||
@ -1136,7 +1137,7 @@ JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
|
|||||||
|
|
||||||
if (*cursor_ == '\\') {
|
if (*cursor_ == '\\') {
|
||||||
has_escape = true;
|
has_escape = true;
|
||||||
uc32 c = NextCharacter();
|
base::uc32 c = NextCharacter();
|
||||||
if (V8_UNLIKELY(!base::IsInRange(
|
if (V8_UNLIKELY(!base::IsInRange(
|
||||||
c, 0, static_cast<int32_t>(unibrow::Latin1::kMaxChar)))) {
|
c, 0, static_cast<int32_t>(unibrow::Latin1::kMaxChar)))) {
|
||||||
AllowGarbageCollection allow_before_exception;
|
AllowGarbageCollection allow_before_exception;
|
||||||
@ -1155,7 +1156,7 @@ JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EscapeKind::kUnicode: {
|
case EscapeKind::kUnicode: {
|
||||||
uc32 value = ScanUnicodeCharacter();
|
base::uc32 value = ScanUnicodeCharacter();
|
||||||
if (value == kInvalidUnicodeCharacter) {
|
if (value == kInvalidUnicodeCharacter) {
|
||||||
AllowGarbageCollection allow_before_exception;
|
AllowGarbageCollection allow_before_exception;
|
||||||
ReportUnexpectedCharacter(CurrentCharacter());
|
ReportUnexpectedCharacter(CurrentCharacter());
|
||||||
@ -1164,7 +1165,7 @@ JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
|
|||||||
bits |= value;
|
bits |= value;
|
||||||
// \uXXXX results in either 1 or 2 Utf16 characters, depending on
|
// \uXXXX results in either 1 or 2 Utf16 characters, depending on
|
||||||
// whether the decoded value requires a surrogate pair.
|
// whether the decoded value requires a surrogate pair.
|
||||||
offset += 5 - (value > static_cast<uc32>(
|
offset += 5 - (value > static_cast<base::uc32>(
|
||||||
unibrow::Utf16::kMaxNonSurrogateCharCode));
|
unibrow::Utf16::kMaxNonSurrogateCharCode));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define V8_JSON_JSON_PARSER_H_
|
#define V8_JSON_JSON_PARSER_H_
|
||||||
|
|
||||||
#include "src/base/small-vector.h"
|
#include "src/base/small-vector.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/execution/isolate.h"
|
#include "src/execution/isolate.h"
|
||||||
#include "src/heap/factory.h"
|
#include "src/heap/factory.h"
|
||||||
#include "src/objects/objects.h"
|
#include "src/objects/objects.h"
|
||||||
@ -152,8 +153,9 @@ class JsonParser final {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr uc32 kEndOfString = static_cast<uc32>(-1);
|
static constexpr base::uc32 kEndOfString = static_cast<base::uc32>(-1);
|
||||||
static constexpr uc32 kInvalidUnicodeCharacter = static_cast<uc32>(-1);
|
static constexpr base::uc32 kInvalidUnicodeCharacter =
|
||||||
|
static_cast<base::uc32>(-1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -186,12 +188,12 @@ class JsonParser final {
|
|||||||
|
|
||||||
void advance() { ++cursor_; }
|
void advance() { ++cursor_; }
|
||||||
|
|
||||||
uc32 CurrentCharacter() {
|
base::uc32 CurrentCharacter() {
|
||||||
if (V8_UNLIKELY(is_at_end())) return kEndOfString;
|
if (V8_UNLIKELY(is_at_end())) return kEndOfString;
|
||||||
return *cursor_;
|
return *cursor_;
|
||||||
}
|
}
|
||||||
|
|
||||||
uc32 NextCharacter() {
|
base::uc32 NextCharacter() {
|
||||||
advance();
|
advance();
|
||||||
return CurrentCharacter();
|
return CurrentCharacter();
|
||||||
}
|
}
|
||||||
@ -263,7 +265,7 @@ class JsonParser final {
|
|||||||
// four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
|
// four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
|
||||||
JsonString ScanJsonString(bool needs_internalization);
|
JsonString ScanJsonString(bool needs_internalization);
|
||||||
JsonString ScanJsonPropertyKey(JsonContinuation* cont);
|
JsonString ScanJsonPropertyKey(JsonContinuation* cont);
|
||||||
uc32 ScanUnicodeCharacter();
|
base::uc32 ScanUnicodeCharacter();
|
||||||
Handle<String> MakeString(const JsonString& string,
|
Handle<String> MakeString(const JsonString& string,
|
||||||
Handle<String> hint = Handle<String>());
|
Handle<String> hint = Handle<String>());
|
||||||
|
|
||||||
@ -296,7 +298,7 @@ class JsonParser final {
|
|||||||
const SmallVector<Handle<Object>>& element_stack);
|
const SmallVector<Handle<Object>>& element_stack);
|
||||||
|
|
||||||
// Mark that a parsing error has happened at the current character.
|
// Mark that a parsing error has happened at the current character.
|
||||||
void ReportUnexpectedCharacter(uc32 c);
|
void ReportUnexpectedCharacter(base::uc32 c);
|
||||||
// Mark that a parsing error has happened at the current token.
|
// Mark that a parsing error has happened at the current token.
|
||||||
void ReportUnexpectedToken(JsonToken token);
|
void ReportUnexpectedToken(JsonToken token);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/json/json-stringifier.h"
|
#include "src/json/json-stringifier.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/message-template.h"
|
#include "src/common/message-template.h"
|
||||||
#include "src/numbers/conversions.h"
|
#include "src/numbers/conversions.h"
|
||||||
#include "src/objects/heap-number-inl.h"
|
#include "src/objects/heap-number-inl.h"
|
||||||
@ -127,7 +128,7 @@ class JsonStringifier {
|
|||||||
Handle<String> tojson_string_;
|
Handle<String> tojson_string_;
|
||||||
Handle<FixedArray> property_list_;
|
Handle<FixedArray> property_list_;
|
||||||
Handle<JSReceiver> replacer_function_;
|
Handle<JSReceiver> replacer_function_;
|
||||||
uc16* gap_;
|
base::uc16* gap_;
|
||||||
int indent_;
|
int indent_;
|
||||||
|
|
||||||
using KeyObject = std::pair<Handle<Object>, Handle<Object>>;
|
using KeyObject = std::pair<Handle<Object>, Handle<Object>>;
|
||||||
@ -303,7 +304,7 @@ bool JsonStringifier::InitializeGap(Handle<Object> gap) {
|
|||||||
Handle<String> gap_string = Handle<String>::cast(gap);
|
Handle<String> gap_string = Handle<String>::cast(gap);
|
||||||
if (gap_string->length() > 0) {
|
if (gap_string->length() > 0) {
|
||||||
int gap_length = std::min(gap_string->length(), 10);
|
int gap_length = std::min(gap_string->length(), 10);
|
||||||
gap_ = NewArray<uc16>(gap_length + 1);
|
gap_ = NewArray<base::uc16>(gap_length + 1);
|
||||||
String::WriteToFlat(*gap_string, gap_, 0, gap_length);
|
String::WriteToFlat(*gap_string, gap_, 0, gap_length);
|
||||||
for (int i = 0; i < gap_length; i++) {
|
for (int i = 0; i < gap_length; i++) {
|
||||||
if (gap_[i] > String::kMaxOneByteCharCode) {
|
if (gap_[i] > String::kMaxOneByteCharCode) {
|
||||||
@ -317,7 +318,7 @@ bool JsonStringifier::InitializeGap(Handle<Object> gap) {
|
|||||||
int num_value = DoubleToInt32(gap->Number());
|
int num_value = DoubleToInt32(gap->Number());
|
||||||
if (num_value > 0) {
|
if (num_value > 0) {
|
||||||
int gap_length = std::min(num_value, 10);
|
int gap_length = std::min(num_value, 10);
|
||||||
gap_ = NewArray<uc16>(gap_length + 1);
|
gap_ = NewArray<base::uc16>(gap_length + 1);
|
||||||
for (int i = 0; i < gap_length; i++) gap_[i] = ' ';
|
for (int i = 0; i < gap_length; i++) gap_[i] = ' ';
|
||||||
gap_[gap_length] = '\0';
|
gap_[gap_length] = '\0';
|
||||||
}
|
}
|
||||||
@ -877,8 +878,8 @@ template <typename SrcChar, typename DestChar>
|
|||||||
void JsonStringifier::SerializeStringUnchecked_(
|
void JsonStringifier::SerializeStringUnchecked_(
|
||||||
base::Vector<const SrcChar> src,
|
base::Vector<const SrcChar> src,
|
||||||
IncrementalStringBuilder::NoExtend<DestChar>* dest) {
|
IncrementalStringBuilder::NoExtend<DestChar>* dest) {
|
||||||
// Assert that uc16 character is not truncated down to 8 bit.
|
// Assert that base::uc16 character is not truncated down to 8 bit.
|
||||||
// The <uc16, char> version of this method must not be called.
|
// The <base::uc16, char> version of this method must not be called.
|
||||||
DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
|
DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
|
||||||
for (int i = 0; i < src.length(); i++) {
|
for (int i = 0; i < src.length(); i++) {
|
||||||
SrcChar c = src[i];
|
SrcChar c = src[i];
|
||||||
@ -1036,9 +1037,9 @@ void JsonStringifier::SerializeString(Handle<String> object) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (String::IsOneByteRepresentationUnderneath(*object)) {
|
if (String::IsOneByteRepresentationUnderneath(*object)) {
|
||||||
SerializeString_<uint8_t, uc16>(object);
|
SerializeString_<uint8_t, base::uc16>(object);
|
||||||
} else {
|
} else {
|
||||||
SerializeString_<uc16, uc16>(object);
|
SerializeString_<base::uc16, base::uc16>(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
// Extra POSIX/ANSI functions for Win32/MSVC.
|
// Extra POSIX/ANSI functions for Win32/MSVC.
|
||||||
|
|
||||||
#include "src/base/bits.h"
|
#include "src/base/bits.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/base/platform/platform.h"
|
#include "src/base/platform/platform.h"
|
||||||
#include "src/base/platform/wrappers.h"
|
#include "src/base/platform/wrappers.h"
|
||||||
#include "src/numbers/conversions.h"
|
#include "src/numbers/conversions.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/heap-number-inl.h"
|
#include "src/objects/heap-number-inl.h"
|
||||||
#include "src/objects/objects-inl.h"
|
#include "src/objects/objects-inl.h"
|
||||||
|
|
||||||
@ -94,11 +94,11 @@ int32_t DoubleToInt32(double x) {
|
|||||||
// All doubles within these limits are trivially convertable to an int.
|
// All doubles within these limits are trivially convertable to an int.
|
||||||
return static_cast<int32_t>(x);
|
return static_cast<int32_t>(x);
|
||||||
}
|
}
|
||||||
Double d(x);
|
base::Double d(x);
|
||||||
int exponent = d.Exponent();
|
int exponent = d.Exponent();
|
||||||
uint64_t bits;
|
uint64_t bits;
|
||||||
if (exponent < 0) {
|
if (exponent < 0) {
|
||||||
if (exponent <= -Double::kSignificandSize) return 0;
|
if (exponent <= -base::Double::kSignificandSize) return 0;
|
||||||
bits = d.Significand() >> -exponent;
|
bits = d.Significand() >> -exponent;
|
||||||
} else {
|
} else {
|
||||||
if (exponent > 31) return 0;
|
if (exponent > 31) return 0;
|
||||||
@ -118,11 +118,11 @@ inline int64_t DoubleToWebIDLInt64(double x) {
|
|||||||
// All doubles within these limits are trivially convertable to an int.
|
// All doubles within these limits are trivially convertable to an int.
|
||||||
return static_cast<int64_t>(x);
|
return static_cast<int64_t>(x);
|
||||||
}
|
}
|
||||||
Double d(x);
|
base::Double d(x);
|
||||||
int exponent = d.Exponent();
|
int exponent = d.Exponent();
|
||||||
uint64_t bits;
|
uint64_t bits;
|
||||||
if (exponent < 0) {
|
if (exponent < 0) {
|
||||||
if (exponent <= -Double::kSignificandSize) return 0;
|
if (exponent <= -base::Double::kSignificandSize) return 0;
|
||||||
bits = d.Significand() >> -exponent;
|
bits = d.Significand() >> -exponent;
|
||||||
} else {
|
} else {
|
||||||
if (exponent > 63) return 0;
|
if (exponent > 63) return 0;
|
||||||
|
@ -9,12 +9,12 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "src/base/numbers/dtoa.h"
|
||||||
|
#include "src/base/numbers/strtod.h"
|
||||||
#include "src/base/platform/wrappers.h"
|
#include "src/base/platform/wrappers.h"
|
||||||
#include "src/common/assert-scope.h"
|
#include "src/common/assert-scope.h"
|
||||||
#include "src/handles/handles.h"
|
#include "src/handles/handles.h"
|
||||||
#include "src/heap/factory.h"
|
#include "src/heap/factory.h"
|
||||||
#include "src/numbers/dtoa.h"
|
|
||||||
#include "src/numbers/strtod.h"
|
|
||||||
#include "src/objects/bigint.h"
|
#include "src/objects/bigint.h"
|
||||||
#include "src/objects/objects-inl.h"
|
#include "src/objects/objects-inl.h"
|
||||||
#include "src/objects/string-inl.h"
|
#include "src/objects/string-inl.h"
|
||||||
@ -143,7 +143,7 @@ inline double JunkStringValue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline double SignedZero(bool negative) {
|
inline double SignedZero(bool negative) {
|
||||||
return negative ? uint64_to_double(Double::kSignMask) : 0.0;
|
return negative ? base::uint64_to_double(base::Double::kSignMask) : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isDigit(int x, int radix) {
|
inline bool isDigit(int x, int radix) {
|
||||||
@ -340,7 +340,7 @@ class StringToIntHelper {
|
|||||||
return subject_->GetFlatContent(no_gc).ToOneByteVector();
|
return subject_->GetFlatContent(no_gc).ToOneByteVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
base::Vector<const uc16> GetTwoByteVector() {
|
base::Vector<const base::uc16> GetTwoByteVector() {
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
return subject_->GetFlatContent(no_gc).ToUC16Vector();
|
return subject_->GetFlatContent(no_gc).ToUC16Vector();
|
||||||
}
|
}
|
||||||
@ -381,7 +381,7 @@ void StringToIntHelper<IsolateT>::ParseInt() {
|
|||||||
base::Vector<const uint8_t> vector = GetOneByteVector();
|
base::Vector<const uint8_t> vector = GetOneByteVector();
|
||||||
DetectRadixInternal(vector.begin(), vector.length());
|
DetectRadixInternal(vector.begin(), vector.length());
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> vector = GetTwoByteVector();
|
base::Vector<const base::uc16> vector = GetTwoByteVector();
|
||||||
DetectRadixInternal(vector.begin(), vector.length());
|
DetectRadixInternal(vector.begin(), vector.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,7 +399,7 @@ void StringToIntHelper<IsolateT>::ParseInt() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> vector = GetTwoByteVector();
|
base::Vector<const base::uc16> vector = GetTwoByteVector();
|
||||||
DCHECK_EQ(length_, vector.length());
|
DCHECK_EQ(length_, vector.length());
|
||||||
if (ParseChunkInternal(vector.begin())) {
|
if (ParseChunkInternal(vector.begin())) {
|
||||||
break;
|
break;
|
||||||
@ -612,7 +612,7 @@ class NumberParseIntHelper : public StringToIntHelper<Isolate> {
|
|||||||
result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin())
|
result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin())
|
||||||
: HandleBaseTenCase(vector.begin());
|
: HandleBaseTenCase(vector.begin());
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> vector = GetTwoByteVector();
|
base::Vector<const base::uc16> vector = GetTwoByteVector();
|
||||||
DCHECK_EQ(length(), vector.length());
|
DCHECK_EQ(length(), vector.length());
|
||||||
result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin())
|
result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin())
|
||||||
: HandleBaseTenCase(vector.begin());
|
: HandleBaseTenCase(vector.begin());
|
||||||
@ -957,9 +957,9 @@ double StringToDouble(base::Vector<const uint8_t> str, int flags,
|
|||||||
empty_string_val);
|
empty_string_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
double StringToDouble(base::Vector<const uc16> str, int flags,
|
double StringToDouble(base::Vector<const base::uc16> str, int flags,
|
||||||
double empty_string_val) {
|
double empty_string_val) {
|
||||||
const uc16* end = str.begin() + str.length();
|
const base::uc16* end = str.begin() + str.length();
|
||||||
return InternalStringToDouble(str.begin(), end, flags, empty_string_val);
|
return InternalStringToDouble(str.begin(), end, flags, empty_string_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1099,13 +1099,14 @@ const char* DoubleToCString(double v, base::Vector<char> buffer) {
|
|||||||
SimpleStringBuilder builder(buffer.begin(), buffer.length());
|
SimpleStringBuilder builder(buffer.begin(), buffer.length());
|
||||||
int decimal_point;
|
int decimal_point;
|
||||||
int sign;
|
int sign;
|
||||||
const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
|
const int kV8DtoaBufferCapacity = base::kBase10MaximalLength + 1;
|
||||||
char decimal_rep[kV8DtoaBufferCapacity];
|
char decimal_rep[kV8DtoaBufferCapacity];
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
DoubleToAscii(v, DTOA_SHORTEST, 0,
|
base::DoubleToAscii(
|
||||||
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
|
v, base::DTOA_SHORTEST, 0,
|
||||||
&sign, &length, &decimal_point);
|
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity), &sign,
|
||||||
|
&length, &decimal_point);
|
||||||
|
|
||||||
if (sign) builder.AddCharacter('-');
|
if (sign) builder.AddCharacter('-');
|
||||||
|
|
||||||
@ -1191,9 +1192,9 @@ char* DoubleToFixedCString(double value, int f) {
|
|||||||
kMaxDigitsBeforePoint + kMaxFractionDigits + 1;
|
kMaxDigitsBeforePoint + kMaxFractionDigits + 1;
|
||||||
char decimal_rep[kDecimalRepCapacity];
|
char decimal_rep[kDecimalRepCapacity];
|
||||||
int decimal_rep_length;
|
int decimal_rep_length;
|
||||||
DoubleToAscii(value, DTOA_FIXED, f,
|
base::DoubleToAscii(value, base::DTOA_FIXED, f,
|
||||||
base::Vector<char>(decimal_rep, kDecimalRepCapacity), &sign,
|
base::Vector<char>(decimal_rep, kDecimalRepCapacity),
|
||||||
&decimal_rep_length, &decimal_point);
|
&sign, &decimal_rep_length, &decimal_point);
|
||||||
|
|
||||||
// Create a representation that is padded with zeros if needed.
|
// Create a representation that is padded with zeros if needed.
|
||||||
int zero_prefix_length = 0;
|
int zero_prefix_length = 0;
|
||||||
@ -1281,19 +1282,19 @@ char* DoubleToExponentialCString(double value, int f) {
|
|||||||
const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1;
|
const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1;
|
||||||
// Make sure that the buffer is big enough, even if we fall back to the
|
// Make sure that the buffer is big enough, even if we fall back to the
|
||||||
// shortest representation (which happens when f equals -1).
|
// shortest representation (which happens when f equals -1).
|
||||||
DCHECK_LE(kBase10MaximalLength, kMaxFractionDigits + 1);
|
DCHECK_LE(base::kBase10MaximalLength, kMaxFractionDigits + 1);
|
||||||
char decimal_rep[kV8DtoaBufferCapacity];
|
char decimal_rep[kV8DtoaBufferCapacity];
|
||||||
int decimal_rep_length;
|
int decimal_rep_length;
|
||||||
|
|
||||||
if (f == -1) {
|
if (f == -1) {
|
||||||
DoubleToAscii(value, DTOA_SHORTEST, 0,
|
base::DoubleToAscii(value, base::DTOA_SHORTEST, 0,
|
||||||
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity), &sign,
|
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
|
||||||
&decimal_rep_length, &decimal_point);
|
&sign, &decimal_rep_length, &decimal_point);
|
||||||
f = decimal_rep_length - 1;
|
f = decimal_rep_length - 1;
|
||||||
} else {
|
} else {
|
||||||
DoubleToAscii(value, DTOA_PRECISION, f + 1,
|
base::DoubleToAscii(value, base::DTOA_PRECISION, f + 1,
|
||||||
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity), &sign,
|
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
|
||||||
&decimal_rep_length, &decimal_point);
|
&sign, &decimal_rep_length, &decimal_point);
|
||||||
}
|
}
|
||||||
DCHECK_GT(decimal_rep_length, 0);
|
DCHECK_GT(decimal_rep_length, 0);
|
||||||
DCHECK(decimal_rep_length <= f + 1);
|
DCHECK(decimal_rep_length <= f + 1);
|
||||||
@ -1324,9 +1325,9 @@ char* DoubleToPrecisionCString(double value, int p) {
|
|||||||
char decimal_rep[kV8DtoaBufferCapacity];
|
char decimal_rep[kV8DtoaBufferCapacity];
|
||||||
int decimal_rep_length;
|
int decimal_rep_length;
|
||||||
|
|
||||||
DoubleToAscii(value, DTOA_PRECISION, p,
|
base::DoubleToAscii(value, base::DTOA_PRECISION, p,
|
||||||
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity), &sign,
|
base::Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
|
||||||
&decimal_rep_length, &decimal_point);
|
&sign, &decimal_rep_length, &decimal_point);
|
||||||
DCHECK(decimal_rep_length <= p);
|
DCHECK(decimal_rep_length <= p);
|
||||||
|
|
||||||
int exponent = decimal_point - 1;
|
int exponent = decimal_point - 1;
|
||||||
@ -1398,8 +1399,8 @@ char* DoubleToRadixCString(double value, int radix) {
|
|||||||
double integer = std::floor(value);
|
double integer = std::floor(value);
|
||||||
double fraction = value - integer;
|
double fraction = value - integer;
|
||||||
// We only compute fractional digits up to the input double's precision.
|
// We only compute fractional digits up to the input double's precision.
|
||||||
double delta = 0.5 * (Double(value).NextDouble() - value);
|
double delta = 0.5 * (base::Double(value).NextDouble() - value);
|
||||||
delta = std::max(Double(0.0).NextDouble(), delta);
|
delta = std::max(base::Double(0.0).NextDouble(), delta);
|
||||||
DCHECK_GT(delta, 0.0);
|
DCHECK_GT(delta, 0.0);
|
||||||
if (fraction >= delta) {
|
if (fraction >= delta) {
|
||||||
// Insert decimal point.
|
// Insert decimal point.
|
||||||
@ -1440,7 +1441,7 @@ char* DoubleToRadixCString(double value, int radix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute integer digits. Fill unrepresented digits with zero.
|
// Compute integer digits. Fill unrepresented digits with zero.
|
||||||
while (Double(integer / radix).Exponent() > 0) {
|
while (base::Double(integer / radix).Exponent() > 0) {
|
||||||
integer /= radix;
|
integer /= radix;
|
||||||
buffer[--integer_cursor] = '0';
|
buffer[--integer_cursor] = '0';
|
||||||
}
|
}
|
||||||
@ -1487,10 +1488,10 @@ base::Optional<double> TryStringToDouble(LocalIsolate* isolate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
|
const int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
|
||||||
auto buffer = std::make_unique<uc16[]>(max_length_for_conversion);
|
auto buffer = std::make_unique<base::uc16[]>(max_length_for_conversion);
|
||||||
SharedStringAccessGuardIfNeeded access_guard(isolate);
|
SharedStringAccessGuardIfNeeded access_guard(isolate);
|
||||||
String::WriteToFlat(*object, buffer.get(), 0, length, access_guard);
|
String::WriteToFlat(*object, buffer.get(), 0, length, access_guard);
|
||||||
base::Vector<const uc16> v(buffer.get(), length);
|
base::Vector<const base::uc16> v(buffer.get(), length);
|
||||||
return StringToDouble(v, flags);
|
return StringToDouble(v, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "src/base/export-template.h"
|
#include "src/base/export-template.h"
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
#include "src/base/optional.h"
|
#include "src/base/optional.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ enum ConversionFlags {
|
|||||||
// Converts a string into a double value according to ECMA-262 9.3.1
|
// Converts a string into a double value according to ECMA-262 9.3.1
|
||||||
double StringToDouble(base::Vector<const uint8_t> str, int flags,
|
double StringToDouble(base::Vector<const uint8_t> str, int flags,
|
||||||
double empty_string_val = 0);
|
double empty_string_val = 0);
|
||||||
double StringToDouble(base::Vector<const uc16> str, int flags,
|
double StringToDouble(base::Vector<const base::uc16> str, int flags,
|
||||||
double empty_string_val = 0);
|
double empty_string_val = 0);
|
||||||
// This version expects a zero-terminated character array.
|
// This version expects a zero-terminated character array.
|
||||||
double V8_EXPORT_PRIVATE StringToDouble(const char* str, int flags,
|
double V8_EXPORT_PRIVATE StringToDouble(const char* str, int flags,
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
#include "src/objects/bigint.h"
|
#include "src/objects/bigint.h"
|
||||||
|
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/bigint/bigint.h"
|
#include "src/bigint/bigint.h"
|
||||||
#include "src/execution/isolate-inl.h"
|
#include "src/execution/isolate-inl.h"
|
||||||
#include "src/heap/factory.h"
|
#include "src/heap/factory.h"
|
||||||
#include "src/heap/heap-write-barrier-inl.h"
|
#include "src/heap/heap-write-barrier-inl.h"
|
||||||
#include "src/numbers/conversions.h"
|
#include "src/numbers/conversions.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/heap-number-inl.h"
|
#include "src/objects/heap-number-inl.h"
|
||||||
#include "src/objects/instance-type-inl.h"
|
#include "src/objects/instance-type-inl.h"
|
||||||
#include "src/objects/objects-inl.h"
|
#include "src/objects/objects-inl.h"
|
||||||
@ -295,7 +295,8 @@ Handle<BigInt> MutableBigInt::NewFromDouble(Isolate* isolate, double value) {
|
|||||||
bool sign = value < 0; // -0 was already handled above.
|
bool sign = value < 0; // -0 was already handled above.
|
||||||
uint64_t double_bits = bit_cast<uint64_t>(value);
|
uint64_t double_bits = bit_cast<uint64_t>(value);
|
||||||
int raw_exponent =
|
int raw_exponent =
|
||||||
static_cast<int>(double_bits >> Double::kPhysicalSignificandSize) & 0x7FF;
|
static_cast<int>(double_bits >> base::Double::kPhysicalSignificandSize) &
|
||||||
|
0x7FF;
|
||||||
DCHECK_NE(raw_exponent, 0x7FF);
|
DCHECK_NE(raw_exponent, 0x7FF);
|
||||||
DCHECK_GE(raw_exponent, 0x3FF);
|
DCHECK_GE(raw_exponent, 0x3FF);
|
||||||
int exponent = raw_exponent - 0x3FF;
|
int exponent = raw_exponent - 0x3FF;
|
||||||
@ -314,8 +315,8 @@ Handle<BigInt> MutableBigInt::NewFromDouble(Isolate* isolate, double value) {
|
|||||||
// msd_topbit kDigitBits
|
// msd_topbit kDigitBits
|
||||||
//
|
//
|
||||||
uint64_t mantissa =
|
uint64_t mantissa =
|
||||||
(double_bits & Double::kSignificandMask) | Double::kHiddenBit;
|
(double_bits & base::Double::kSignificandMask) | base::Double::kHiddenBit;
|
||||||
const int kMantissaTopBit = Double::kSignificandSize - 1; // 0-indexed.
|
const int kMantissaTopBit = base::Double::kSignificandSize - 1; // 0-indexed.
|
||||||
// 0-indexed position of most significant bit in the most significant digit.
|
// 0-indexed position of most significant bit in the most significant digit.
|
||||||
int msd_topbit = exponent % kDigitBits;
|
int msd_topbit = exponent % kDigitBits;
|
||||||
// Number of unused bits in {mantissa}. We'll keep them shifted to the
|
// Number of unused bits in {mantissa}. We'll keep them shifted to the
|
||||||
@ -912,8 +913,9 @@ ComparisonResult BigInt::CompareToDouble(Handle<BigInt> x, double y) {
|
|||||||
}
|
}
|
||||||
uint64_t double_bits = bit_cast<uint64_t>(y);
|
uint64_t double_bits = bit_cast<uint64_t>(y);
|
||||||
int raw_exponent =
|
int raw_exponent =
|
||||||
static_cast<int>(double_bits >> Double::kPhysicalSignificandSize) & 0x7FF;
|
static_cast<int>(double_bits >> base::Double::kPhysicalSignificandSize) &
|
||||||
uint64_t mantissa = double_bits & Double::kSignificandMask;
|
0x7FF;
|
||||||
|
uint64_t mantissa = double_bits & base::Double::kSignificandMask;
|
||||||
// Non-finite doubles are handled above.
|
// Non-finite doubles are handled above.
|
||||||
DCHECK_NE(raw_exponent, 0x7FF);
|
DCHECK_NE(raw_exponent, 0x7FF);
|
||||||
int exponent = raw_exponent - 0x3FF;
|
int exponent = raw_exponent - 0x3FF;
|
||||||
@ -944,7 +946,7 @@ ComparisonResult BigInt::CompareToDouble(Handle<BigInt> x, double y) {
|
|||||||
// <--> <------>
|
// <--> <------>
|
||||||
// msd_topbit kDigitBits
|
// msd_topbit kDigitBits
|
||||||
//
|
//
|
||||||
mantissa |= Double::kHiddenBit;
|
mantissa |= base::Double::kHiddenBit;
|
||||||
const int kMantissaTopBit = 52; // 0-indexed.
|
const int kMantissaTopBit = 52; // 0-indexed.
|
||||||
// 0-indexed position of {x}'s most significant bit within the {msd}.
|
// 0-indexed position of {x}'s most significant bit within the {msd}.
|
||||||
int msd_topbit = kDigitBits - 1 - msd_leading_zeros;
|
int msd_topbit = kDigitBits - 1 - msd_leading_zeros;
|
||||||
@ -1107,7 +1109,7 @@ double MutableBigInt::ToDouble(Handle<BigIntBase> x) {
|
|||||||
mantissa++;
|
mantissa++;
|
||||||
// Incrementing the mantissa can overflow the mantissa bits. In that case
|
// Incrementing the mantissa can overflow the mantissa bits. In that case
|
||||||
// the new mantissa will be all zero (plus hidden bit).
|
// the new mantissa will be all zero (plus hidden bit).
|
||||||
if ((mantissa >> Double::kPhysicalSignificandSize) != 0) {
|
if ((mantissa >> base::Double::kPhysicalSignificandSize) != 0) {
|
||||||
mantissa = 0;
|
mantissa = 0;
|
||||||
exponent++;
|
exponent++;
|
||||||
// Incrementing the exponent can overflow too.
|
// Incrementing the exponent can overflow too.
|
||||||
@ -1118,7 +1120,7 @@ double MutableBigInt::ToDouble(Handle<BigIntBase> x) {
|
|||||||
}
|
}
|
||||||
// Assemble the result.
|
// Assemble the result.
|
||||||
uint64_t sign_bit = x->sign() ? (static_cast<uint64_t>(1) << 63) : 0;
|
uint64_t sign_bit = x->sign() ? (static_cast<uint64_t>(1) << 63) : 0;
|
||||||
exponent = (exponent + 0x3FF) << Double::kPhysicalSignificandSize;
|
exponent = (exponent + 0x3FF) << base::Double::kPhysicalSignificandSize;
|
||||||
uint64_t double_bits = sign_bit | exponent | mantissa;
|
uint64_t double_bits = sign_bit | exponent | mantissa;
|
||||||
return bit_cast<double>(double_bits);
|
return bit_cast<double>(double_bits);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "src/api/api-inl.h"
|
#include "src/api/api-inl.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/execution/isolate.h"
|
#include "src/execution/isolate.h"
|
||||||
#include "src/handles/global-handles.h"
|
#include "src/handles/global-handles.h"
|
||||||
#include "src/heap/factory.h"
|
#include "src/heap/factory.h"
|
||||||
@ -163,12 +164,12 @@ inline int FindFirstUpperOrNonAscii(String s, int length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UChar* GetUCharBufferFromFlat(const String::FlatContent& flat,
|
const UChar* GetUCharBufferFromFlat(const String::FlatContent& flat,
|
||||||
std::unique_ptr<uc16[]>* dest,
|
std::unique_ptr<base::uc16[]>* dest,
|
||||||
int32_t length) {
|
int32_t length) {
|
||||||
DCHECK(flat.IsFlat());
|
DCHECK(flat.IsFlat());
|
||||||
if (flat.IsOneByte()) {
|
if (flat.IsOneByte()) {
|
||||||
if (!*dest) {
|
if (!*dest) {
|
||||||
dest->reset(NewArray<uc16>(length));
|
dest->reset(NewArray<base::uc16>(length));
|
||||||
CopyChars(dest->get(), flat.ToOneByteVector().begin(), length);
|
CopyChars(dest->get(), flat.ToOneByteVector().begin(), length);
|
||||||
}
|
}
|
||||||
return reinterpret_cast<const UChar*>(dest->get());
|
return reinterpret_cast<const UChar*>(dest->get());
|
||||||
@ -195,7 +196,7 @@ icu::UnicodeString Intl::ToICUUnicodeString(Isolate* isolate,
|
|||||||
Handle<String> string) {
|
Handle<String> string) {
|
||||||
DCHECK(string->IsFlat());
|
DCHECK(string->IsFlat());
|
||||||
DisallowGarbageCollection no_gc;
|
DisallowGarbageCollection no_gc;
|
||||||
std::unique_ptr<uc16[]> sap;
|
std::unique_ptr<base::uc16[]> sap;
|
||||||
// Short one-byte strings can be expanded on the stack to avoid allocating a
|
// Short one-byte strings can be expanded on the stack to avoid allocating a
|
||||||
// temporary buffer.
|
// temporary buffer.
|
||||||
constexpr int kShortStringSize = 80;
|
constexpr int kShortStringSize = 80;
|
||||||
@ -237,7 +238,7 @@ MaybeHandle<String> LocaleConvertCase(Isolate* isolate, Handle<String> s,
|
|||||||
int32_t dest_length = src_length;
|
int32_t dest_length = src_length;
|
||||||
UErrorCode status;
|
UErrorCode status;
|
||||||
Handle<SeqTwoByteString> result;
|
Handle<SeqTwoByteString> result;
|
||||||
std::unique_ptr<uc16[]> sap;
|
std::unique_ptr<base::uc16[]> sap;
|
||||||
|
|
||||||
if (dest_length == 0) return ReadOnlyRoots(isolate).empty_string_handle();
|
if (dest_length == 0) return ReadOnlyRoots(isolate).empty_string_handle();
|
||||||
|
|
||||||
@ -1960,7 +1961,7 @@ MaybeHandle<String> Intl::Normalize(Isolate* isolate, Handle<String> string,
|
|||||||
int length = string->length();
|
int length = string->length();
|
||||||
string = String::Flatten(isolate, string);
|
string = String::Flatten(isolate, string);
|
||||||
icu::UnicodeString result;
|
icu::UnicodeString result;
|
||||||
std::unique_ptr<uc16[]> sap;
|
std::unique_ptr<base::uc16[]> sap;
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
icu::UnicodeString input = ToICUUnicodeString(isolate, string);
|
icu::UnicodeString input = ToICUUnicodeString(isolate, string);
|
||||||
// Getting a singleton. Should not free it.
|
// Getting a singleton. Should not free it.
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/objects/js-regexp.h"
|
#include "src/objects/js-regexp.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/objects/js-array-inl.h"
|
#include "src/objects/js-array-inl.h"
|
||||||
#include "src/objects/js-regexp-inl.h"
|
#include "src/objects/js-regexp-inl.h"
|
||||||
@ -383,7 +384,7 @@ MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
|
|||||||
bool needs_escapes = false;
|
bool needs_escapes = false;
|
||||||
int additional_escape_chars =
|
int additional_escape_chars =
|
||||||
one_byte ? CountAdditionalEscapeChars<uint8_t>(source, &needs_escapes)
|
one_byte ? CountAdditionalEscapeChars<uint8_t>(source, &needs_escapes)
|
||||||
: CountAdditionalEscapeChars<uc16>(source, &needs_escapes);
|
: CountAdditionalEscapeChars<base::uc16>(source, &needs_escapes);
|
||||||
if (!needs_escapes) return source;
|
if (!needs_escapes) return source;
|
||||||
int length = source->length() + additional_escape_chars;
|
int length = source->length() + additional_escape_chars;
|
||||||
if (one_byte) {
|
if (one_byte) {
|
||||||
@ -397,7 +398,7 @@ MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
|
|||||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
|
ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
|
||||||
isolate->factory()->NewRawTwoByteString(length),
|
isolate->factory()->NewRawTwoByteString(length),
|
||||||
String);
|
String);
|
||||||
return WriteEscapedRegExpSource<uc16>(source, result);
|
return WriteEscapedRegExpSource<base::uc16>(source, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "src/base/bits.h"
|
#include "src/base/bits.h"
|
||||||
#include "src/base/memory.h"
|
#include "src/base/memory.h"
|
||||||
|
#include "src/base/numbers/double.h"
|
||||||
#include "src/builtins/builtins.h"
|
#include "src/builtins/builtins.h"
|
||||||
#include "src/common/external-pointer-inl.h"
|
#include "src/common/external-pointer-inl.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
@ -22,7 +23,6 @@
|
|||||||
#include "src/heap/heap-write-barrier-inl.h"
|
#include "src/heap/heap-write-barrier-inl.h"
|
||||||
#include "src/heap/read-only-heap-inl.h"
|
#include "src/heap/read-only-heap-inl.h"
|
||||||
#include "src/numbers/conversions-inl.h"
|
#include "src/numbers/conversions-inl.h"
|
||||||
#include "src/numbers/double.h"
|
|
||||||
#include "src/objects/bigint.h"
|
#include "src/objects/bigint.h"
|
||||||
#include "src/objects/heap-number-inl.h"
|
#include "src/objects/heap-number-inl.h"
|
||||||
#include "src/objects/heap-object.h"
|
#include "src/objects/heap-object.h"
|
||||||
@ -1056,7 +1056,7 @@ Object Object::GetSimpleHash(Object object) {
|
|||||||
if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
|
if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
|
||||||
hash = ComputeUnseededHash(FastD2I(num));
|
hash = ComputeUnseededHash(FastD2I(num));
|
||||||
} else {
|
} else {
|
||||||
hash = ComputeLongHash(double_to_uint64(num));
|
hash = ComputeLongHash(base::double_to_uint64(num));
|
||||||
}
|
}
|
||||||
return Smi::FromInt(hash & Smi::kMaxValue);
|
return Smi::FromInt(hash & Smi::kMaxValue);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/objects/stack-frame-info.h"
|
#include "src/objects/stack-frame-info.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/objects/shared-function-info.h"
|
#include "src/objects/shared-function-info.h"
|
||||||
#include "src/objects/stack-frame-info-inl.h"
|
#include "src/objects/stack-frame-info-inl.h"
|
||||||
#include "src/strings/string-builder-inl.h"
|
#include "src/strings/string-builder-inl.h"
|
||||||
@ -618,7 +619,7 @@ bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uc32 subject_char = subject_reader.Get(subject_index);
|
const base::uc32 subject_char = subject_reader.Get(subject_index);
|
||||||
if (i == pattern_reader.length()) {
|
if (i == pattern_reader.length()) {
|
||||||
if (subject_char != '.') return false;
|
if (subject_char != '.') return false;
|
||||||
} else if (subject_char != pattern_reader.Get(pattern_index)) {
|
} else if (subject_char != pattern_reader.Get(pattern_index)) {
|
||||||
|
@ -300,11 +300,11 @@ bool String::IsOneByteRepresentationUnderneath(String string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uc32 FlatStringReader::Get(int index) const {
|
base::uc32 FlatStringReader::Get(int index) const {
|
||||||
if (is_one_byte_) {
|
if (is_one_byte_) {
|
||||||
return Get<uint8_t>(index);
|
return Get<uint8_t>(index);
|
||||||
} else {
|
} else {
|
||||||
return Get<uc16>(index);
|
return Get<base::uc16>(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ Char FlatStringReader::Get(int index) const {
|
|||||||
if (sizeof(Char) == 1) {
|
if (sizeof(Char) == 1) {
|
||||||
return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
|
return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
|
||||||
} else {
|
} else {
|
||||||
return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
|
return static_cast<Char>(static_cast<const base::uc16*>(start_)[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,7 +766,7 @@ inline base::Vector<const uint8_t> String::GetCharVector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline base::Vector<const uc16> String::GetCharVector(
|
inline base::Vector<const base::uc16> String::GetCharVector(
|
||||||
const DisallowGarbageCollection& no_gc) {
|
const DisallowGarbageCollection& no_gc) {
|
||||||
String::FlatContent flat = GetFlatContent(no_gc);
|
String::FlatContent flat = GetFlatContent(no_gc);
|
||||||
DCHECK(flat.IsTwoByte());
|
DCHECK(flat.IsTwoByte());
|
||||||
@ -813,18 +813,19 @@ Address SeqTwoByteString::GetCharsAddress() const {
|
|||||||
return field_address(kHeaderSize);
|
return field_address(kHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
uc16* SeqTwoByteString::GetChars(const DisallowGarbageCollection& no_gc) const {
|
base::uc16* SeqTwoByteString::GetChars(
|
||||||
|
const DisallowGarbageCollection& no_gc) const {
|
||||||
USE(no_gc);
|
USE(no_gc);
|
||||||
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
|
DCHECK(!SharedStringAccessGuardIfNeeded::IsNeeded(*this));
|
||||||
return reinterpret_cast<uc16*>(GetCharsAddress());
|
return reinterpret_cast<base::uc16*>(GetCharsAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
uc16* SeqTwoByteString::GetChars(
|
base::uc16* SeqTwoByteString::GetChars(
|
||||||
const DisallowGarbageCollection& no_gc,
|
const DisallowGarbageCollection& no_gc,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
const SharedStringAccessGuardIfNeeded& access_guard) const {
|
||||||
USE(no_gc);
|
USE(no_gc);
|
||||||
USE(access_guard);
|
USE(access_guard);
|
||||||
return reinterpret_cast<uc16*>(GetCharsAddress());
|
return reinterpret_cast<base::uc16*>(GetCharsAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SeqTwoByteString::Get(
|
uint16_t SeqTwoByteString::Get(
|
||||||
@ -1193,13 +1194,13 @@ class SubStringRange::iterator final {
|
|||||||
public:
|
public:
|
||||||
using iterator_category = std::forward_iterator_tag;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
using difference_type = int;
|
using difference_type = int;
|
||||||
using value_type = uc16;
|
using value_type = base::uc16;
|
||||||
using pointer = uc16*;
|
using pointer = base::uc16*;
|
||||||
using reference = uc16&;
|
using reference = base::uc16&;
|
||||||
|
|
||||||
iterator(const iterator& other) = default;
|
iterator(const iterator& other) = default;
|
||||||
|
|
||||||
uc16 operator*() { return content_.Get(offset_); }
|
base::uc16 operator*() { return content_.Get(offset_); }
|
||||||
bool operator==(const iterator& other) const {
|
bool operator==(const iterator& other) const {
|
||||||
return content_.UsesSameString(other.content_) && offset_ == other.offset_;
|
return content_.UsesSameString(other.content_) && offset_ == other.offset_;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
|
|||||||
if (FLAG_enable_slow_asserts) {
|
if (FLAG_enable_slow_asserts) {
|
||||||
// Assert that the resource and the string are equivalent.
|
// Assert that the resource and the string are equivalent.
|
||||||
DCHECK(static_cast<size_t>(this->length()) == resource->length());
|
DCHECK(static_cast<size_t>(this->length()) == resource->length());
|
||||||
base::ScopedVector<uc16> smart_chars(this->length());
|
base::ScopedVector<base::uc16> smart_chars(this->length());
|
||||||
String::WriteToFlat(*this, smart_chars.begin(), 0, this->length());
|
String::WriteToFlat(*this, smart_chars.begin(), 0, this->length());
|
||||||
DCHECK_EQ(0, memcmp(smart_chars.begin(), resource->data(),
|
DCHECK_EQ(0, memcmp(smart_chars.begin(), resource->data(),
|
||||||
resource->length() * sizeof(smart_chars[0])));
|
resource->length() * sizeof(smart_chars[0])));
|
||||||
@ -572,7 +572,7 @@ String::FlatContent String::GetFlatContent(
|
|||||||
return FlatContent(start + offset, length, no_gc);
|
return FlatContent(start + offset, length, no_gc);
|
||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(shape.encoding_tag(), kTwoByteStringTag);
|
DCHECK_EQ(shape.encoding_tag(), kTwoByteStringTag);
|
||||||
const uc16* start;
|
const base::uc16* start;
|
||||||
if (shape.representation_tag() == kSeqStringTag) {
|
if (shape.representation_tag() == kSeqStringTag) {
|
||||||
start = SeqTwoByteString::cast(string).GetChars(no_gc);
|
start = SeqTwoByteString::cast(string).GetChars(no_gc);
|
||||||
} else {
|
} else {
|
||||||
@ -654,7 +654,7 @@ void String::WriteToFlat(String source, sinkchar* sink, int from, int to,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case kTwoByteStringTag | kExternalStringTag: {
|
case kTwoByteStringTag | kExternalStringTag: {
|
||||||
const uc16* data = ExternalTwoByteString::cast(source).GetChars();
|
const base::uc16* data = ExternalTwoByteString::cast(source).GetChars();
|
||||||
CopyChars(sink, data + from, to - from);
|
CopyChars(sink, data + from, to - from);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -947,16 +947,16 @@ ComparisonResult String::Compare(Isolate* isolate, Handle<String> x,
|
|||||||
base::Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
|
base::Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
|
||||||
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> y_chars = y_content.ToUC16Vector();
|
base::Vector<const base::uc16> y_chars = y_content.ToUC16Vector();
|
||||||
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> x_chars = x_content.ToUC16Vector();
|
base::Vector<const base::uc16> x_chars = x_content.ToUC16Vector();
|
||||||
if (y_content.IsOneByte()) {
|
if (y_content.IsOneByte()) {
|
||||||
base::Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
|
base::Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
|
||||||
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> y_chars = y_content.ToUC16Vector();
|
base::Vector<const base::uc16> y_chars = y_content.ToUC16Vector();
|
||||||
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
r = CompareChars(x_chars.begin(), y_chars.begin(), prefix_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1043,9 +1043,9 @@ int String::IndexOf(Isolate* isolate, Handle<String> receiver,
|
|||||||
return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
|
return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
|
||||||
start_index);
|
start_index);
|
||||||
}
|
}
|
||||||
base::Vector<const uc16> pat_vector = search_content.ToUC16Vector();
|
base::Vector<const base::uc16> pat_vector = search_content.ToUC16Vector();
|
||||||
return SearchString<const uc16>(isolate, receiver_content, pat_vector,
|
return SearchString<const base::uc16>(isolate, receiver_content, pat_vector,
|
||||||
start_index);
|
start_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
|
MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
|
||||||
@ -1219,7 +1219,7 @@ int StringMatchBackwards(base::Vector<const schar> subject,
|
|||||||
|
|
||||||
if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
|
if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
|
||||||
for (int i = 0; i < pattern_length; i++) {
|
for (int i = 0; i < pattern_length; i++) {
|
||||||
uc16 c = pattern[i];
|
base::uc16 c = pattern[i];
|
||||||
if (c > String::kMaxOneByteCharCode) {
|
if (c > String::kMaxOneByteCharCode) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1304,7 +1304,7 @@ Object String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
|
|||||||
pat_vector, start_index);
|
pat_vector, start_index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base::Vector<const uc16> pat_vector = search_content.ToUC16Vector();
|
base::Vector<const base::uc16> pat_vector = search_content.ToUC16Vector();
|
||||||
if (receiver_content.IsOneByte()) {
|
if (receiver_content.IsOneByte()) {
|
||||||
last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
|
last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
|
||||||
pat_vector, start_index);
|
pat_vector, start_index);
|
||||||
@ -1469,7 +1469,7 @@ void SeqOneByteString::clear_padding() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SeqTwoByteString::clear_padding() {
|
void SeqTwoByteString::clear_padding() {
|
||||||
int data_size = SeqString::kHeaderSize + length() * kUC16Size;
|
int data_size = SeqString::kHeaderSize + length() * base::kUC16Size;
|
||||||
memset(reinterpret_cast<void*>(address() + data_size), 0,
|
memset(reinterpret_cast<void*>(address() + data_size), 0,
|
||||||
SizeFor(length()) - data_size);
|
SizeFor(length()) - data_size);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "src/base/bits.h"
|
#include "src/base/bits.h"
|
||||||
#include "src/base/export-template.h"
|
#include "src/base/export-template.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/objects/instance-type.h"
|
#include "src/objects/instance-type.h"
|
||||||
#include "src/objects/name.h"
|
#include "src/objects/name.h"
|
||||||
#include "src/objects/smi.h"
|
#include "src/objects/smi.h"
|
||||||
@ -124,12 +125,12 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
}
|
}
|
||||||
// Return the two-byte content of the string. Only use if IsTwoByte()
|
// Return the two-byte content of the string. Only use if IsTwoByte()
|
||||||
// returns true.
|
// returns true.
|
||||||
base::Vector<const uc16> ToUC16Vector() const {
|
base::Vector<const base::uc16> ToUC16Vector() const {
|
||||||
DCHECK_EQ(TWO_BYTE, state_);
|
DCHECK_EQ(TWO_BYTE, state_);
|
||||||
return base::Vector<const uc16>(twobyte_start, length_);
|
return base::Vector<const base::uc16>(twobyte_start, length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
uc16 Get(int i) const {
|
base::uc16 Get(int i) const {
|
||||||
DCHECK(i < length_);
|
DCHECK(i < length_);
|
||||||
DCHECK(state_ != NON_FLAT);
|
DCHECK(state_ != NON_FLAT);
|
||||||
if (state_ == ONE_BYTE) return onebyte_start[i];
|
if (state_ == ONE_BYTE) return onebyte_start[i];
|
||||||
@ -150,7 +151,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
length_(length),
|
length_(length),
|
||||||
state_(ONE_BYTE),
|
state_(ONE_BYTE),
|
||||||
no_gc_(no_gc) {}
|
no_gc_(no_gc) {}
|
||||||
FlatContent(const uc16* start, int length,
|
FlatContent(const base::uc16* start, int length,
|
||||||
const DisallowGarbageCollection& no_gc)
|
const DisallowGarbageCollection& no_gc)
|
||||||
: twobyte_start(start),
|
: twobyte_start(start),
|
||||||
length_(length),
|
length_(length),
|
||||||
@ -161,7 +162,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
const uint8_t* onebyte_start;
|
const uint8_t* onebyte_start;
|
||||||
const uc16* twobyte_start;
|
const base::uc16* twobyte_start;
|
||||||
};
|
};
|
||||||
int length_;
|
int length_;
|
||||||
State state_;
|
State state_;
|
||||||
@ -250,7 +251,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
AllocationType allocation = AllocationType::kYoung);
|
AllocationType allocation = AllocationType::kYoung);
|
||||||
|
|
||||||
// Tries to return the content of a flat string as a structure holding either
|
// Tries to return the content of a flat string as a structure holding either
|
||||||
// a flat vector of char or of uc16.
|
// a flat vector of char or of base::uc16.
|
||||||
// If the string isn't flat, and therefore doesn't have flat content, the
|
// If the string isn't flat, and therefore doesn't have flat content, the
|
||||||
// returned structure will report so, and can't provide a vector of either
|
// returned structure will report so, and can't provide a vector of either
|
||||||
// kind.
|
// kind.
|
||||||
@ -432,7 +433,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
|
static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
|
||||||
static const int kMaxUtf16CodeUnit = 0xffff;
|
static const int kMaxUtf16CodeUnit = 0xffff;
|
||||||
static const uint32_t kMaxUtf16CodeUnitU = kMaxUtf16CodeUnit;
|
static const uint32_t kMaxUtf16CodeUnitU = kMaxUtf16CodeUnit;
|
||||||
static const uc32 kMaxCodePoint = 0x10ffff;
|
static const base::uc32 kMaxCodePoint = 0x10ffff;
|
||||||
|
|
||||||
// Maximal string length.
|
// Maximal string length.
|
||||||
// The max length is different on 32 and 64 bit platforms. Max length for
|
// The max length is different on 32 and 64 bit platforms. Max length for
|
||||||
@ -481,8 +482,8 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
return NonAsciiStart(chars, length) >= length;
|
return NonAsciiStart(chars, length) >= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int NonOneByteStart(const uc16* chars, int length) {
|
static inline int NonOneByteStart(const base::uc16* chars, int length) {
|
||||||
DCHECK(IsAligned(reinterpret_cast<Address>(chars), sizeof(uc16)));
|
DCHECK(IsAligned(reinterpret_cast<Address>(chars), sizeof(base::uc16)));
|
||||||
const uint16_t* start = chars;
|
const uint16_t* start = chars;
|
||||||
const uint16_t* limit = chars + length;
|
const uint16_t* limit = chars + length;
|
||||||
|
|
||||||
@ -506,7 +507,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
if (*reinterpret_cast<const uintptr_t*>(chars) & non_one_byte_mask) {
|
if (*reinterpret_cast<const uintptr_t*>(chars) & non_one_byte_mask) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
chars += (sizeof(uintptr_t) / sizeof(uc16));
|
chars += (sizeof(uintptr_t) / sizeof(base::uc16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +522,7 @@ class String : public TorqueGeneratedString<String, Name> {
|
|||||||
return static_cast<int>(chars - start);
|
return static_cast<int>(chars - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsOneByte(const uc16* chars, int length) {
|
static inline bool IsOneByte(const base::uc16* chars, int length) {
|
||||||
return NonOneByteStart(chars, length) >= length;
|
return NonOneByteStart(chars, length) >= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,10 +701,10 @@ class SeqTwoByteString
|
|||||||
// Get a pointer to the characters of the string. May only be called when a
|
// Get a pointer to the characters of the string. May only be called when a
|
||||||
// SharedStringAccessGuard is not needed (i.e. on the main thread or on
|
// SharedStringAccessGuard is not needed (i.e. on the main thread or on
|
||||||
// read-only strings).
|
// read-only strings).
|
||||||
inline uc16* GetChars(const DisallowGarbageCollection& no_gc) const;
|
inline base::uc16* GetChars(const DisallowGarbageCollection& no_gc) const;
|
||||||
|
|
||||||
// Get a pointer to the characters of the string.
|
// Get a pointer to the characters of the string.
|
||||||
inline uc16* GetChars(
|
inline base::uc16* GetChars(
|
||||||
const DisallowGarbageCollection& no_gc,
|
const DisallowGarbageCollection& no_gc,
|
||||||
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
const SharedStringAccessGuardIfNeeded& access_guard) const;
|
||||||
|
|
||||||
@ -958,7 +959,7 @@ class V8_EXPORT_PRIVATE FlatStringReader : public Relocatable {
|
|||||||
public:
|
public:
|
||||||
FlatStringReader(Isolate* isolate, Handle<String> str);
|
FlatStringReader(Isolate* isolate, Handle<String> str);
|
||||||
void PostGarbageCollection() override;
|
void PostGarbageCollection() override;
|
||||||
inline uc32 Get(int index) const;
|
inline base::uc32 Get(int index) const;
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
inline Char Get(int index) const;
|
inline Char Get(int index) const;
|
||||||
int length() { return length_; }
|
int length() { return length_; }
|
||||||
|
@ -315,10 +315,10 @@ void ValueSerializer::WriteOneByteString(base::Vector<const uint8_t> chars) {
|
|||||||
WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t));
|
WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueSerializer::WriteTwoByteString(base::Vector<const uc16> chars) {
|
void ValueSerializer::WriteTwoByteString(base::Vector<const base::uc16> chars) {
|
||||||
// Warning: this uses host endianness.
|
// Warning: this uses host endianness.
|
||||||
WriteVarint<uint32_t>(chars.length() * sizeof(uc16));
|
WriteVarint<uint32_t>(chars.length() * sizeof(base::uc16));
|
||||||
WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16));
|
WriteRawBytes(chars.begin(), chars.length() * sizeof(base::uc16));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueSerializer::WriteBigIntContents(BigInt bigint) {
|
void ValueSerializer::WriteBigIntContents(BigInt bigint) {
|
||||||
@ -497,8 +497,8 @@ void ValueSerializer::WriteString(Handle<String> string) {
|
|||||||
WriteTag(SerializationTag::kOneByteString);
|
WriteTag(SerializationTag::kOneByteString);
|
||||||
WriteOneByteString(chars);
|
WriteOneByteString(chars);
|
||||||
} else if (flat.IsTwoByte()) {
|
} else if (flat.IsTwoByte()) {
|
||||||
base::Vector<const uc16> chars = flat.ToUC16Vector();
|
base::Vector<const base::uc16> chars = flat.ToUC16Vector();
|
||||||
uint32_t byte_length = chars.length() * sizeof(uc16);
|
uint32_t byte_length = chars.length() * sizeof(base::uc16);
|
||||||
// The existing reading code expects 16-byte strings to be aligned.
|
// The existing reading code expects 16-byte strings to be aligned.
|
||||||
if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
|
if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
|
||||||
WriteTag(SerializationTag::kPadding);
|
WriteTag(SerializationTag::kPadding);
|
||||||
@ -1447,7 +1447,7 @@ MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
|
|||||||
if (!ReadVarint<uint32_t>().To(&byte_length) ||
|
if (!ReadVarint<uint32_t>().To(&byte_length) ||
|
||||||
byte_length >
|
byte_length >
|
||||||
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
|
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
|
||||||
byte_length % sizeof(uc16) != 0 ||
|
byte_length % sizeof(base::uc16) != 0 ||
|
||||||
!ReadRawBytes(byte_length).To(&bytes)) {
|
!ReadRawBytes(byte_length).To(&bytes)) {
|
||||||
return MaybeHandle<String>();
|
return MaybeHandle<String>();
|
||||||
}
|
}
|
||||||
@ -1457,7 +1457,7 @@ MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
|
|||||||
if (byte_length == 0) return isolate_->factory()->empty_string();
|
if (byte_length == 0) return isolate_->factory()->empty_string();
|
||||||
Handle<SeqTwoByteString> string;
|
Handle<SeqTwoByteString> string;
|
||||||
if (!isolate_->factory()
|
if (!isolate_->factory()
|
||||||
->NewRawTwoByteString(byte_length / sizeof(uc16))
|
->NewRawTwoByteString(byte_length / sizeof(base::uc16))
|
||||||
.ToHandle(&string)) {
|
.ToHandle(&string)) {
|
||||||
return MaybeHandle<String>();
|
return MaybeHandle<String>();
|
||||||
}
|
}
|
||||||
@ -1496,8 +1496,9 @@ bool ValueDeserializer::ReadExpectedString(Handle<String> expected) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (tag == SerializationTag::kTwoByteString && flat.IsTwoByte()) {
|
} else if (tag == SerializationTag::kTwoByteString && flat.IsTwoByte()) {
|
||||||
base::Vector<const uc16> chars = flat.ToUC16Vector();
|
base::Vector<const base::uc16> chars = flat.ToUC16Vector();
|
||||||
if (byte_length == static_cast<unsigned>(chars.length()) * sizeof(uc16) &&
|
if (byte_length ==
|
||||||
|
static_cast<unsigned>(chars.length()) * sizeof(base::uc16) &&
|
||||||
memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
|
memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "include/v8.h"
|
#include "include/v8.h"
|
||||||
#include "src/base/compiler-specific.h"
|
#include "src/base/compiler-specific.h"
|
||||||
#include "src/base/macros.h"
|
#include "src/base/macros.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
#include "src/common/message-template.h"
|
#include "src/common/message-template.h"
|
||||||
#include "src/handles/maybe-handles.h"
|
#include "src/handles/maybe-handles.h"
|
||||||
@ -106,7 +107,7 @@ class ValueSerializer {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void WriteZigZag(T value);
|
void WriteZigZag(T value);
|
||||||
void WriteOneByteString(base::Vector<const uint8_t> chars);
|
void WriteOneByteString(base::Vector<const uint8_t> chars);
|
||||||
void WriteTwoByteString(base::Vector<const uc16> chars);
|
void WriteTwoByteString(base::Vector<const base::uc16> chars);
|
||||||
void WriteBigIntContents(BigInt bigint);
|
void WriteBigIntContents(BigInt bigint);
|
||||||
Maybe<uint8_t*> ReserveRawBytes(size_t bytes);
|
Maybe<uint8_t*> ReserveRawBytes(size_t bytes);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/parsing/literal-buffer.h"
|
#include "src/parsing/literal-buffer.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/execution/isolate.h"
|
#include "src/execution/isolate.h"
|
||||||
#include "src/execution/local-isolate.h"
|
#include "src/execution/local-isolate.h"
|
||||||
#include "src/heap/factory.h"
|
#include "src/heap/factory.h"
|
||||||
@ -43,7 +44,7 @@ void LiteralBuffer::ExpandBuffer() {
|
|||||||
void LiteralBuffer::ConvertToTwoByte() {
|
void LiteralBuffer::ConvertToTwoByte() {
|
||||||
DCHECK(is_one_byte());
|
DCHECK(is_one_byte());
|
||||||
base::Vector<byte> new_store;
|
base::Vector<byte> new_store;
|
||||||
int new_content_size = position_ * kUC16Size;
|
int new_content_size = position_ * base::kUC16Size;
|
||||||
if (new_content_size >= backing_store_.length()) {
|
if (new_content_size >= backing_store_.length()) {
|
||||||
// Ensure room for all currently read code units as UC16 as well
|
// Ensure room for all currently read code units as UC16 as well
|
||||||
// as the code unit about to be stored.
|
// as the code unit about to be stored.
|
||||||
@ -64,21 +65,21 @@ void LiteralBuffer::ConvertToTwoByte() {
|
|||||||
is_one_byte_ = false;
|
is_one_byte_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiteralBuffer::AddTwoByteChar(uc32 code_unit) {
|
void LiteralBuffer::AddTwoByteChar(base::uc32 code_unit) {
|
||||||
DCHECK(!is_one_byte());
|
DCHECK(!is_one_byte());
|
||||||
if (position_ >= backing_store_.length()) ExpandBuffer();
|
if (position_ >= backing_store_.length()) ExpandBuffer();
|
||||||
if (code_unit <=
|
if (code_unit <=
|
||||||
static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
static_cast<base::uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
||||||
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
|
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
|
||||||
position_ += kUC16Size;
|
position_ += base::kUC16Size;
|
||||||
} else {
|
} else {
|
||||||
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
|
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
|
||||||
unibrow::Utf16::LeadSurrogate(code_unit);
|
unibrow::Utf16::LeadSurrogate(code_unit);
|
||||||
position_ += kUC16Size;
|
position_ += base::kUC16Size;
|
||||||
if (position_ >= backing_store_.length()) ExpandBuffer();
|
if (position_ >= backing_store_.length()) ExpandBuffer();
|
||||||
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
|
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) =
|
||||||
unibrow::Utf16::TrailSurrogate(code_unit);
|
unibrow::Utf16::TrailSurrogate(code_unit);
|
||||||
position_ += kUC16Size;
|
position_ += base::kUC16Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_PARSING_LITERAL_BUFFER_H_
|
#ifndef V8_PARSING_LITERAL_BUFFER_H_
|
||||||
#define V8_PARSING_LITERAL_BUFFER_H_
|
#define V8_PARSING_LITERAL_BUFFER_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
#include "src/strings/unicode-decoder.h"
|
#include "src/strings/unicode-decoder.h"
|
||||||
|
|
||||||
@ -26,9 +27,9 @@ class LiteralBuffer final {
|
|||||||
AddOneByteChar(static_cast<byte>(code_unit));
|
AddOneByteChar(static_cast<byte>(code_unit));
|
||||||
}
|
}
|
||||||
|
|
||||||
V8_INLINE void AddChar(uc32 code_unit) {
|
V8_INLINE void AddChar(base::uc32 code_unit) {
|
||||||
if (is_one_byte()) {
|
if (is_one_byte()) {
|
||||||
if (code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) {
|
if (code_unit <= static_cast<base::uc32>(unibrow::Latin1::kMaxChar)) {
|
||||||
AddOneByteChar(static_cast<byte>(code_unit));
|
AddOneByteChar(static_cast<byte>(code_unit));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,7 +92,7 @@ class LiteralBuffer final {
|
|||||||
position_ += kOneByteSize;
|
position_ += kOneByteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTwoByteChar(uc32 code_unit);
|
void AddTwoByteChar(base::uc32 code_unit);
|
||||||
int NewCapacity(int min_capacity);
|
int NewCapacity(int min_capacity);
|
||||||
void ExpandBuffer();
|
void ExpandBuffer();
|
||||||
void ConvertToTwoByte();
|
void ConvertToTwoByte();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "include/v8.h"
|
#include "include/v8.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/handles/handles.h"
|
#include "src/handles/handles.h"
|
||||||
#include "src/logging/runtime-call-stats-scope.h"
|
#include "src/logging/runtime-call-stats-scope.h"
|
||||||
@ -278,7 +279,7 @@ class BufferedCharacterStream : public Utf16CharacterStream {
|
|||||||
: byte_stream_(other.byte_stream_) {}
|
: byte_stream_(other.byte_stream_) {}
|
||||||
|
|
||||||
static const size_t kBufferSize = 512;
|
static const size_t kBufferSize = 512;
|
||||||
uc16 buffer_[kBufferSize];
|
base::uc16 buffer_[kBufferSize];
|
||||||
ByteStream<uint8_t> byte_stream_;
|
ByteStream<uint8_t> byte_stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -392,7 +393,7 @@ class BufferedUtf16CharacterStream : public Utf16CharacterStream {
|
|||||||
|
|
||||||
// Fixed sized buffer that this class reads from.
|
// Fixed sized buffer that this class reads from.
|
||||||
// The base class' buffer_start_ should always point to buffer_.
|
// The base class' buffer_start_ should always point to buffer_.
|
||||||
uc16 buffer_[kBufferSize];
|
base::uc16 buffer_[kBufferSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
BufferedUtf16CharacterStream::BufferedUtf16CharacterStream()
|
BufferedUtf16CharacterStream::BufferedUtf16CharacterStream()
|
||||||
@ -418,7 +419,7 @@ bool BufferedUtf16CharacterStream::ReadBlock() {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const uc16 kWindows1252ToUC16[256] = {
|
static const base::uc16 kWindows1252ToUC16[256] = {
|
||||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, // 00-07
|
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, // 00-07
|
||||||
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, // 08-0F
|
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, // 08-0F
|
||||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, // 10-17
|
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, // 10-17
|
||||||
@ -504,7 +505,7 @@ class Windows1252CharacterStream final : public Utf16CharacterStream {
|
|||||||
V8_NOEXCEPT : byte_stream_(other.byte_stream_) {}
|
V8_NOEXCEPT : byte_stream_(other.byte_stream_) {}
|
||||||
|
|
||||||
static const size_t kBufferSize = 512;
|
static const size_t kBufferSize = 512;
|
||||||
uc16 buffer_[kBufferSize];
|
base::uc16 buffer_[kBufferSize];
|
||||||
ChunkedStream<uint8_t> byte_stream_;
|
ChunkedStream<uint8_t> byte_stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -653,7 +654,7 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() {
|
|||||||
unibrow::uchar t = unibrow::Utf8::ValueOfIncrementalFinish(&state);
|
unibrow::uchar t = unibrow::Utf8::ValueOfIncrementalFinish(&state);
|
||||||
if (t != unibrow::Utf8::kBufferEmpty) {
|
if (t != unibrow::Utf8::kBufferEmpty) {
|
||||||
DCHECK_EQ(t, unibrow::Utf8::kBadChar);
|
DCHECK_EQ(t, unibrow::Utf8::kBadChar);
|
||||||
*output_cursor = static_cast<uc16>(t);
|
*output_cursor = static_cast<base::uc16>(t);
|
||||||
buffer_end_++;
|
buffer_end_++;
|
||||||
current_.pos.chars++;
|
current_.pos.chars++;
|
||||||
current_.pos.incomplete_char = 0;
|
current_.pos.incomplete_char = 0;
|
||||||
@ -672,13 +673,14 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() {
|
|||||||
unibrow::uchar t =
|
unibrow::uchar t =
|
||||||
unibrow::Utf8::ValueOfIncremental(&cursor, &state, &incomplete_char);
|
unibrow::Utf8::ValueOfIncremental(&cursor, &state, &incomplete_char);
|
||||||
if (V8_LIKELY(t < kUtf8Bom)) {
|
if (V8_LIKELY(t < kUtf8Bom)) {
|
||||||
*(output_cursor++) = static_cast<uc16>(t); // The most frequent case.
|
*(output_cursor++) =
|
||||||
|
static_cast<base::uc16>(t); // The most frequent case.
|
||||||
} else if (t == unibrow::Utf8::kIncomplete) {
|
} else if (t == unibrow::Utf8::kIncomplete) {
|
||||||
continue;
|
continue;
|
||||||
} else if (t == kUtf8Bom) {
|
} else if (t == kUtf8Bom) {
|
||||||
// BOM detected at beginning of the stream. Don't copy it.
|
// BOM detected at beginning of the stream. Don't copy it.
|
||||||
} else if (t <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
|
} else if (t <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
|
||||||
*(output_cursor++) = static_cast<uc16>(t);
|
*(output_cursor++) = static_cast<base::uc16>(t);
|
||||||
} else {
|
} else {
|
||||||
*(output_cursor++) = unibrow::Utf16::LeadSurrogate(t);
|
*(output_cursor++) = unibrow::Utf16::LeadSurrogate(t);
|
||||||
*(output_cursor++) = unibrow::Utf16::TrailSurrogate(t);
|
*(output_cursor++) = unibrow::Utf16::TrailSurrogate(t);
|
||||||
@ -692,7 +694,8 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() {
|
|||||||
unibrow::uchar t =
|
unibrow::uchar t =
|
||||||
unibrow::Utf8::ValueOfIncremental(&cursor, &state, &incomplete_char);
|
unibrow::Utf8::ValueOfIncremental(&cursor, &state, &incomplete_char);
|
||||||
if (V8_LIKELY(t <= unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
if (V8_LIKELY(t <= unibrow::Utf16::kMaxNonSurrogateCharCode)) {
|
||||||
*(output_cursor++) = static_cast<uc16>(t); // The most frequent case.
|
*(output_cursor++) =
|
||||||
|
static_cast<base::uc16>(t); // The most frequent case.
|
||||||
} else if (t == unibrow::Utf8::kIncomplete) {
|
} else if (t == unibrow::Utf8::kIncomplete) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -251,7 +251,7 @@ static constexpr const uint8_t character_scan_flags[128] = {
|
|||||||
#undef CALL_GET_SCAN_FLAGS
|
#undef CALL_GET_SCAN_FLAGS
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool CharCanBeKeyword(uc32 c) {
|
inline bool CharCanBeKeyword(base::uc32 c) {
|
||||||
return static_cast<uint32_t>(c) < arraysize(character_scan_flags) &&
|
return static_cast<uint32_t>(c) < arraysize(character_scan_flags) &&
|
||||||
CanBeKeyword(character_scan_flags[c]);
|
CanBeKeyword(character_scan_flags[c]);
|
||||||
}
|
}
|
||||||
@ -273,7 +273,7 @@ V8_INLINE Token::Value Scanner::ScanIdentifierOrKeywordInner() {
|
|||||||
// Otherwise we'll fall into the slow path after scanning the identifier.
|
// Otherwise we'll fall into the slow path after scanning the identifier.
|
||||||
DCHECK(!IdentifierNeedsSlowPath(scan_flags));
|
DCHECK(!IdentifierNeedsSlowPath(scan_flags));
|
||||||
AddLiteralChar(static_cast<char>(c0_));
|
AddLiteralChar(static_cast<char>(c0_));
|
||||||
AdvanceUntil([this, &scan_flags](uc32 c0) {
|
AdvanceUntil([this, &scan_flags](base::uc32 c0) {
|
||||||
if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
|
if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
|
||||||
// A non-ascii character means we need to drop through to the slow
|
// A non-ascii character means we need to drop through to the slow
|
||||||
// path.
|
// path.
|
||||||
@ -305,7 +305,7 @@ V8_INLINE Token::Value Scanner::ScanIdentifierOrKeywordInner() {
|
|||||||
} else {
|
} else {
|
||||||
// Special case for escapes at the start of an identifier.
|
// Special case for escapes at the start of an identifier.
|
||||||
escaped = true;
|
escaped = true;
|
||||||
uc32 c = ScanIdentifierUnicodeEscape();
|
base::uc32 c = ScanIdentifierUnicodeEscape();
|
||||||
DCHECK(!IsIdentifierStart(Invalid()));
|
DCHECK(!IsIdentifierStart(Invalid()));
|
||||||
if (c == '\\' || !IsIdentifierStart(c)) {
|
if (c == '\\' || !IsIdentifierStart(c)) {
|
||||||
return Token::ILLEGAL;
|
return Token::ILLEGAL;
|
||||||
@ -454,7 +454,7 @@ V8_INLINE Token::Value Scanner::ScanSingleToken() {
|
|||||||
// / // /* /=
|
// / // /* /=
|
||||||
Advance();
|
Advance();
|
||||||
if (c0_ == '/') {
|
if (c0_ == '/') {
|
||||||
uc32 c = Peek();
|
base::uc32 c = Peek();
|
||||||
if (c == '#' || c == '@') {
|
if (c == '#' || c == '@') {
|
||||||
Advance();
|
Advance();
|
||||||
Advance();
|
Advance();
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "src/ast/ast-value-factory.h"
|
#include "src/ast/ast-value-factory.h"
|
||||||
#include "src/base/platform/wrappers.h"
|
#include "src/base/platform/wrappers.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/numbers/conversions-inl.h"
|
#include "src/numbers/conversions-inl.h"
|
||||||
#include "src/objects/bigint.h"
|
#include "src/objects/bigint.h"
|
||||||
#include "src/parsing/parse-info.h"
|
#include "src/parsing/parse-info.h"
|
||||||
@ -109,19 +110,19 @@ void Scanner::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool Scanner::IsInvalid(uc32 c) {
|
bool Scanner::IsInvalid(base::uc32 c) {
|
||||||
DCHECK(c == Invalid() || base::IsInRange(c, 0u, String::kMaxCodePoint));
|
DCHECK(c == Invalid() || base::IsInRange(c, 0u, String::kMaxCodePoint));
|
||||||
return c == Scanner::Invalid();
|
return c == Scanner::Invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool capture_raw, bool unicode>
|
template <bool capture_raw, bool unicode>
|
||||||
uc32 Scanner::ScanHexNumber(int expected_length) {
|
base::uc32 Scanner::ScanHexNumber(int expected_length) {
|
||||||
DCHECK_LE(expected_length, 4); // prevent overflow
|
DCHECK_LE(expected_length, 4); // prevent overflow
|
||||||
|
|
||||||
int begin = source_pos() - 2;
|
int begin = source_pos() - 2;
|
||||||
uc32 x = 0;
|
base::uc32 x = 0;
|
||||||
for (int i = 0; i < expected_length; i++) {
|
for (int i = 0; i < expected_length; i++) {
|
||||||
int d = HexValue(c0_);
|
int d = base::HexValue(c0_);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
ReportScannerError(Location(begin, begin + expected_length + 2),
|
ReportScannerError(Location(begin, begin + expected_length + 2),
|
||||||
unicode
|
unicode
|
||||||
@ -137,9 +138,10 @@ uc32 Scanner::ScanHexNumber(int expected_length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
uc32 Scanner::ScanUnlimitedLengthHexNumber(uc32 max_value, int beg_pos) {
|
base::uc32 Scanner::ScanUnlimitedLengthHexNumber(base::uc32 max_value,
|
||||||
uc32 x = 0;
|
int beg_pos) {
|
||||||
int d = HexValue(c0_);
|
base::uc32 x = 0;
|
||||||
|
int d = base::HexValue(c0_);
|
||||||
if (d < 0) return Invalid();
|
if (d < 0) return Invalid();
|
||||||
|
|
||||||
while (d >= 0) {
|
while (d >= 0) {
|
||||||
@ -150,7 +152,7 @@ uc32 Scanner::ScanUnlimitedLengthHexNumber(uc32 max_value, int beg_pos) {
|
|||||||
return Invalid();
|
return Invalid();
|
||||||
}
|
}
|
||||||
Advance<capture_raw>();
|
Advance<capture_raw>();
|
||||||
d = HexValue(c0_);
|
d = base::HexValue(c0_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
@ -209,7 +211,7 @@ Token::Value Scanner::SkipSingleLineComment() {
|
|||||||
// separately by the lexical grammar and becomes part of the
|
// separately by the lexical grammar and becomes part of the
|
||||||
// stream of input elements for the syntactic grammar (see
|
// stream of input elements for the syntactic grammar (see
|
||||||
// ECMA-262, section 7.4).
|
// ECMA-262, section 7.4).
|
||||||
AdvanceUntil([](uc32 c0_) { return unibrow::IsLineTerminator(c0_); });
|
AdvanceUntil([](base::uc32 c0_) { return unibrow::IsLineTerminator(c0_); });
|
||||||
|
|
||||||
return Token::WHITESPACE;
|
return Token::WHITESPACE;
|
||||||
}
|
}
|
||||||
@ -276,7 +278,7 @@ Token::Value Scanner::SkipMultiLineComment() {
|
|||||||
// Until we see the first newline, check for * and newline characters.
|
// Until we see the first newline, check for * and newline characters.
|
||||||
if (!next().after_line_terminator) {
|
if (!next().after_line_terminator) {
|
||||||
do {
|
do {
|
||||||
AdvanceUntil([](uc32 c0) {
|
AdvanceUntil([](base::uc32 c0) {
|
||||||
if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
|
if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
|
||||||
return unibrow::IsLineTerminator(c0);
|
return unibrow::IsLineTerminator(c0);
|
||||||
}
|
}
|
||||||
@ -301,7 +303,7 @@ Token::Value Scanner::SkipMultiLineComment() {
|
|||||||
|
|
||||||
// After we've seen newline, simply try to find '*/'.
|
// After we've seen newline, simply try to find '*/'.
|
||||||
while (c0_ != kEndOfInput) {
|
while (c0_ != kEndOfInput) {
|
||||||
AdvanceUntil([](uc32 c0) { return c0 == '*'; });
|
AdvanceUntil([](base::uc32 c0) { return c0 == '*'; });
|
||||||
|
|
||||||
while (c0_ == '*') {
|
while (c0_ == '*') {
|
||||||
Advance();
|
Advance();
|
||||||
@ -369,7 +371,7 @@ void Scanner::SeekForward(int pos) {
|
|||||||
|
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
bool Scanner::ScanEscape() {
|
bool Scanner::ScanEscape() {
|
||||||
uc32 c = c0_;
|
base::uc32 c = c0_;
|
||||||
Advance<capture_raw>();
|
Advance<capture_raw>();
|
||||||
|
|
||||||
// Skip escaped newlines.
|
// Skip escaped newlines.
|
||||||
@ -425,9 +427,9 @@ bool Scanner::ScanEscape() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
|
base::uc32 Scanner::ScanOctalEscape(base::uc32 c, int length) {
|
||||||
DCHECK('0' <= c && c <= '7');
|
DCHECK('0' <= c && c <= '7');
|
||||||
uc32 x = c - '0';
|
base::uc32 x = c - '0';
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < length; i++) {
|
for (; i < length; i++) {
|
||||||
int d = c0_ - '0';
|
int d = c0_ - '0';
|
||||||
@ -451,11 +453,11 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token::Value Scanner::ScanString() {
|
Token::Value Scanner::ScanString() {
|
||||||
uc32 quote = c0_;
|
base::uc32 quote = c0_;
|
||||||
|
|
||||||
next().literal_chars.Start();
|
next().literal_chars.Start();
|
||||||
while (true) {
|
while (true) {
|
||||||
AdvanceUntil([this](uc32 c0) {
|
AdvanceUntil([this](base::uc32 c0) {
|
||||||
if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
|
if (V8_UNLIKELY(static_cast<uint32_t>(c0) > kMaxAscii)) {
|
||||||
if (V8_UNLIKELY(unibrow::IsStringLiteralLineTerminator(c0))) {
|
if (V8_UNLIKELY(unibrow::IsStringLiteralLineTerminator(c0))) {
|
||||||
return true;
|
return true;
|
||||||
@ -531,7 +533,7 @@ Token::Value Scanner::ScanTemplateSpan() {
|
|||||||
next().raw_literal_chars.Start();
|
next().raw_literal_chars.Start();
|
||||||
const bool capture_raw = true;
|
const bool capture_raw = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
uc32 c = c0_;
|
base::uc32 c = c0_;
|
||||||
if (c == '`') {
|
if (c == '`') {
|
||||||
Advance(); // Consume '`'
|
Advance(); // Consume '`'
|
||||||
result = Token::TEMPLATE_TAIL;
|
result = Token::TEMPLATE_TAIL;
|
||||||
@ -547,7 +549,7 @@ Token::Value Scanner::ScanTemplateSpan() {
|
|||||||
if (unibrow::IsLineTerminator(c0_)) {
|
if (unibrow::IsLineTerminator(c0_)) {
|
||||||
// The TV of LineContinuation :: \ LineTerminatorSequence is the empty
|
// The TV of LineContinuation :: \ LineTerminatorSequence is the empty
|
||||||
// code unit sequence.
|
// code unit sequence.
|
||||||
uc32 lastChar = c0_;
|
base::uc32 lastChar = c0_;
|
||||||
Advance();
|
Advance();
|
||||||
if (lastChar == '\r') {
|
if (lastChar == '\r') {
|
||||||
// Also skip \n.
|
// Also skip \n.
|
||||||
@ -610,7 +612,7 @@ Handle<String> Scanner::SourceMappingUrl(IsolateT* isolate) const {
|
|||||||
template Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const;
|
template Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const;
|
||||||
template Handle<String> Scanner::SourceMappingUrl(LocalIsolate* isolate) const;
|
template Handle<String> Scanner::SourceMappingUrl(LocalIsolate* isolate) const;
|
||||||
|
|
||||||
bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch),
|
bool Scanner::ScanDigitsWithNumericSeparators(bool (*predicate)(base::uc32 ch),
|
||||||
bool is_check_first_digit) {
|
bool is_check_first_digit) {
|
||||||
// we must have at least one digit after 'x'/'b'/'o'
|
// we must have at least one digit after 'x'/'b'/'o'
|
||||||
if (is_check_first_digit && !predicate(c0_)) return false;
|
if (is_check_first_digit && !predicate(c0_)) return false;
|
||||||
@ -670,7 +672,7 @@ bool Scanner::ScanDecimalAsSmiWithNumericSeparators(uint64_t* value) {
|
|||||||
}
|
}
|
||||||
separator_seen = false;
|
separator_seen = false;
|
||||||
*value = 10 * *value + (c0_ - '0');
|
*value = 10 * *value + (c0_ - '0');
|
||||||
uc32 first_char = c0_;
|
base::uc32 first_char = c0_;
|
||||||
Advance();
|
Advance();
|
||||||
AddLiteralChar(first_char);
|
AddLiteralChar(first_char);
|
||||||
}
|
}
|
||||||
@ -691,7 +693,7 @@ bool Scanner::ScanDecimalAsSmi(uint64_t* value, bool allow_numeric_separator) {
|
|||||||
|
|
||||||
while (IsDecimalDigit(c0_)) {
|
while (IsDecimalDigit(c0_)) {
|
||||||
*value = 10 * *value + (c0_ - '0');
|
*value = 10 * *value + (c0_ - '0');
|
||||||
uc32 first_char = c0_;
|
base::uc32 first_char = c0_;
|
||||||
Advance();
|
Advance();
|
||||||
AddLiteralChar(first_char);
|
AddLiteralChar(first_char);
|
||||||
}
|
}
|
||||||
@ -869,7 +871,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
|
|||||||
return is_bigint ? Token::BIGINT : Token::NUMBER;
|
return is_bigint ? Token::BIGINT : Token::NUMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
uc32 Scanner::ScanIdentifierUnicodeEscape() {
|
base::uc32 Scanner::ScanIdentifierUnicodeEscape() {
|
||||||
Advance();
|
Advance();
|
||||||
if (c0_ != 'u') return Invalid();
|
if (c0_ != 'u') return Invalid();
|
||||||
Advance();
|
Advance();
|
||||||
@ -877,13 +879,13 @@ uc32 Scanner::ScanIdentifierUnicodeEscape() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
uc32 Scanner::ScanUnicodeEscape() {
|
base::uc32 Scanner::ScanUnicodeEscape() {
|
||||||
// Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
|
// Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
|
||||||
// hex digits between { } is arbitrary. \ and u have already been read.
|
// hex digits between { } is arbitrary. \ and u have already been read.
|
||||||
if (c0_ == '{') {
|
if (c0_ == '{') {
|
||||||
int begin = source_pos() - 2;
|
int begin = source_pos() - 2;
|
||||||
Advance<capture_raw>();
|
Advance<capture_raw>();
|
||||||
uc32 cp =
|
base::uc32 cp =
|
||||||
ScanUnlimitedLengthHexNumber<capture_raw>(String::kMaxCodePoint, begin);
|
ScanUnlimitedLengthHexNumber<capture_raw>(String::kMaxCodePoint, begin);
|
||||||
if (cp == kInvalidSequence || c0_ != '}') {
|
if (cp == kInvalidSequence || c0_ != '}') {
|
||||||
ReportScannerError(source_pos(),
|
ReportScannerError(source_pos(),
|
||||||
@ -902,7 +904,7 @@ Token::Value Scanner::ScanIdentifierOrKeywordInnerSlow(bool escaped,
|
|||||||
while (true) {
|
while (true) {
|
||||||
if (c0_ == '\\') {
|
if (c0_ == '\\') {
|
||||||
escaped = true;
|
escaped = true;
|
||||||
uc32 c = ScanIdentifierUnicodeEscape();
|
base::uc32 c = ScanIdentifierUnicodeEscape();
|
||||||
// Only allow legal identifier part characters.
|
// Only allow legal identifier part characters.
|
||||||
// TODO(verwaest): Make this true.
|
// TODO(verwaest): Make this true.
|
||||||
// DCHECK(!IsIdentifierPart('\'));
|
// DCHECK(!IsIdentifierPart('\'));
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "include/v8.h"
|
#include "include/v8.h"
|
||||||
#include "src/base/logging.h"
|
#include "src/base/logging.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
#include "src/common/message-template.h"
|
#include "src/common/message-template.h"
|
||||||
#include "src/parsing/literal-buffer.h"
|
#include "src/parsing/literal-buffer.h"
|
||||||
@ -39,7 +40,7 @@ class Zone;
|
|||||||
// or one part of a surrogate pair that make a single 21 bit code point.
|
// or one part of a surrogate pair that make a single 21 bit code point.
|
||||||
class Utf16CharacterStream {
|
class Utf16CharacterStream {
|
||||||
public:
|
public:
|
||||||
static constexpr uc32 kEndOfInput = static_cast<uc32>(-1);
|
static constexpr base::uc32 kEndOfInput = static_cast<base::uc32>(-1);
|
||||||
|
|
||||||
virtual ~Utf16CharacterStream() = default;
|
virtual ~Utf16CharacterStream() = default;
|
||||||
|
|
||||||
@ -50,11 +51,11 @@ class Utf16CharacterStream {
|
|||||||
V8_INLINE void reset_parser_error_flag() { has_parser_error_ = false; }
|
V8_INLINE void reset_parser_error_flag() { has_parser_error_ = false; }
|
||||||
V8_INLINE bool has_parser_error() const { return has_parser_error_; }
|
V8_INLINE bool has_parser_error() const { return has_parser_error_; }
|
||||||
|
|
||||||
inline uc32 Peek() {
|
inline base::uc32 Peek() {
|
||||||
if (V8_LIKELY(buffer_cursor_ < buffer_end_)) {
|
if (V8_LIKELY(buffer_cursor_ < buffer_end_)) {
|
||||||
return static_cast<uc32>(*buffer_cursor_);
|
return static_cast<base::uc32>(*buffer_cursor_);
|
||||||
} else if (ReadBlockChecked()) {
|
} else if (ReadBlockChecked()) {
|
||||||
return static_cast<uc32>(*buffer_cursor_);
|
return static_cast<base::uc32>(*buffer_cursor_);
|
||||||
} else {
|
} else {
|
||||||
return kEndOfInput;
|
return kEndOfInput;
|
||||||
}
|
}
|
||||||
@ -62,8 +63,8 @@ class Utf16CharacterStream {
|
|||||||
|
|
||||||
// Returns and advances past the next UTF-16 code unit in the input
|
// Returns and advances past the next UTF-16 code unit in the input
|
||||||
// stream. If there are no more code units it returns kEndOfInput.
|
// stream. If there are no more code units it returns kEndOfInput.
|
||||||
inline uc32 Advance() {
|
inline base::uc32 Advance() {
|
||||||
uc32 result = Peek();
|
base::uc32 result = Peek();
|
||||||
buffer_cursor_++;
|
buffer_cursor_++;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -72,11 +73,11 @@ class Utf16CharacterStream {
|
|||||||
// that meets the checks requirement. If there are no more code units it
|
// that meets the checks requirement. If there are no more code units it
|
||||||
// returns kEndOfInput.
|
// returns kEndOfInput.
|
||||||
template <typename FunctionType>
|
template <typename FunctionType>
|
||||||
V8_INLINE uc32 AdvanceUntil(FunctionType check) {
|
V8_INLINE base::uc32 AdvanceUntil(FunctionType check) {
|
||||||
while (true) {
|
while (true) {
|
||||||
auto next_cursor_pos =
|
auto next_cursor_pos =
|
||||||
std::find_if(buffer_cursor_, buffer_end_, [&check](uint16_t raw_c0_) {
|
std::find_if(buffer_cursor_, buffer_end_, [&check](uint16_t raw_c0_) {
|
||||||
uc32 c0_ = static_cast<uc32>(raw_c0_);
|
base::uc32 c0_ = static_cast<base::uc32>(raw_c0_);
|
||||||
return check(c0_);
|
return check(c0_);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ class Utf16CharacterStream {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer_cursor_ = next_cursor_pos + 1;
|
buffer_cursor_ = next_cursor_pos + 1;
|
||||||
return static_cast<uc32>(*next_cursor_pos);
|
return static_cast<base::uc32>(*next_cursor_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,11 +268,11 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// -1 is outside of the range of any real source code.
|
// -1 is outside of the range of any real source code.
|
||||||
static constexpr uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput;
|
static constexpr base::uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput;
|
||||||
static constexpr uc32 kInvalidSequence = static_cast<uc32>(-1);
|
static constexpr base::uc32 kInvalidSequence = static_cast<base::uc32>(-1);
|
||||||
|
|
||||||
static constexpr uc32 Invalid() { return Scanner::kInvalidSequence; }
|
static constexpr base::uc32 Invalid() { return Scanner::kInvalidSequence; }
|
||||||
static bool IsInvalid(uc32 c);
|
static bool IsInvalid(base::uc32 c);
|
||||||
|
|
||||||
explicit Scanner(Utf16CharacterStream* source, UnoptimizedCompileFlags flags);
|
explicit Scanner(Utf16CharacterStream* source, UnoptimizedCompileFlags flags);
|
||||||
|
|
||||||
@ -471,7 +472,7 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
|
|
||||||
// Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
|
// Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
uc32 ScanOctalEscape(uc32 c, int length);
|
base::uc32 ScanOctalEscape(base::uc32 c, int length);
|
||||||
|
|
||||||
// Call this after setting source_ to the input.
|
// Call this after setting source_ to the input.
|
||||||
void Init() {
|
void Init() {
|
||||||
@ -502,11 +503,13 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
// Seek to the next_ token at the given position.
|
// Seek to the next_ token at the given position.
|
||||||
void SeekNext(size_t position);
|
void SeekNext(size_t position);
|
||||||
|
|
||||||
V8_INLINE void AddLiteralChar(uc32 c) { next().literal_chars.AddChar(c); }
|
V8_INLINE void AddLiteralChar(base::uc32 c) {
|
||||||
|
next().literal_chars.AddChar(c);
|
||||||
|
}
|
||||||
|
|
||||||
V8_INLINE void AddLiteralChar(char c) { next().literal_chars.AddChar(c); }
|
V8_INLINE void AddLiteralChar(char c) { next().literal_chars.AddChar(c); }
|
||||||
|
|
||||||
V8_INLINE void AddRawLiteralChar(uc32 c) {
|
V8_INLINE void AddRawLiteralChar(base::uc32 c) {
|
||||||
next().raw_literal_chars.AddChar(c);
|
next().raw_literal_chars.AddChar(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +535,7 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
bool CombineSurrogatePair() {
|
bool CombineSurrogatePair() {
|
||||||
DCHECK(!unibrow::Utf16::IsLeadSurrogate(kEndOfInput));
|
DCHECK(!unibrow::Utf16::IsLeadSurrogate(kEndOfInput));
|
||||||
if (unibrow::Utf16::IsLeadSurrogate(c0_)) {
|
if (unibrow::Utf16::IsLeadSurrogate(c0_)) {
|
||||||
uc32 c1 = source_->Advance();
|
base::uc32 c1 = source_->Advance();
|
||||||
DCHECK(!unibrow::Utf16::IsTrailSurrogate(kEndOfInput));
|
DCHECK(!unibrow::Utf16::IsTrailSurrogate(kEndOfInput));
|
||||||
if (unibrow::Utf16::IsTrailSurrogate(c1)) {
|
if (unibrow::Utf16::IsTrailSurrogate(c1)) {
|
||||||
c0_ = unibrow::Utf16::CombineSurrogatePair(c0_, c1);
|
c0_ = unibrow::Utf16::CombineSurrogatePair(c0_, c1);
|
||||||
@ -543,21 +546,22 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushBack(uc32 ch) {
|
void PushBack(base::uc32 ch) {
|
||||||
DCHECK(IsInvalid(c0_) ||
|
DCHECK(IsInvalid(c0_) ||
|
||||||
base::IsInRange(c0_, 0u, unibrow::Utf16::kMaxNonSurrogateCharCode));
|
base::IsInRange(c0_, 0u, unibrow::Utf16::kMaxNonSurrogateCharCode));
|
||||||
source_->Back();
|
source_->Back();
|
||||||
c0_ = ch;
|
c0_ = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
uc32 Peek() const { return source_->Peek(); }
|
base::uc32 Peek() const { return source_->Peek(); }
|
||||||
|
|
||||||
inline Token::Value Select(Token::Value tok) {
|
inline Token::Value Select(Token::Value tok) {
|
||||||
Advance();
|
Advance();
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) {
|
inline Token::Value Select(base::uc32 next, Token::Value then,
|
||||||
|
Token::Value else_) {
|
||||||
Advance();
|
Advance();
|
||||||
if (c0_ == next) {
|
if (c0_ == next) {
|
||||||
Advance();
|
Advance();
|
||||||
@ -622,12 +626,12 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool capture_raw, bool unicode = false>
|
template <bool capture_raw, bool unicode = false>
|
||||||
uc32 ScanHexNumber(int expected_length);
|
base::uc32 ScanHexNumber(int expected_length);
|
||||||
// Scan a number of any length but not bigger than max_value. For example, the
|
// Scan a number of any length but not bigger than max_value. For example, the
|
||||||
// number can be 000000001, so it's very long in characters but its value is
|
// number can be 000000001, so it's very long in characters but its value is
|
||||||
// small.
|
// small.
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
uc32 ScanUnlimitedLengthHexNumber(uc32 max_value, int beg_pos);
|
base::uc32 ScanUnlimitedLengthHexNumber(base::uc32 max_value, int beg_pos);
|
||||||
|
|
||||||
// Scans a single JavaScript token.
|
// Scans a single JavaScript token.
|
||||||
V8_INLINE Token::Value ScanSingleToken();
|
V8_INLINE Token::Value ScanSingleToken();
|
||||||
@ -647,7 +651,7 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
// Scans a possible HTML comment -- begins with '<!'.
|
// Scans a possible HTML comment -- begins with '<!'.
|
||||||
Token::Value ScanHtmlComment();
|
Token::Value ScanHtmlComment();
|
||||||
|
|
||||||
bool ScanDigitsWithNumericSeparators(bool (*predicate)(uc32 ch),
|
bool ScanDigitsWithNumericSeparators(bool (*predicate)(base::uc32 ch),
|
||||||
bool is_check_first_digit);
|
bool is_check_first_digit);
|
||||||
bool ScanDecimalDigits(bool allow_numeric_separator);
|
bool ScanDecimalDigits(bool allow_numeric_separator);
|
||||||
// Optimized function to scan decimal number as Smi.
|
// Optimized function to scan decimal number as Smi.
|
||||||
@ -676,10 +680,10 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
|
|
||||||
// Decodes a Unicode escape-sequence which is part of an identifier.
|
// Decodes a Unicode escape-sequence which is part of an identifier.
|
||||||
// If the escape sequence cannot be decoded the result is kBadChar.
|
// If the escape sequence cannot be decoded the result is kBadChar.
|
||||||
uc32 ScanIdentifierUnicodeEscape();
|
base::uc32 ScanIdentifierUnicodeEscape();
|
||||||
// Helper for the above functions.
|
// Helper for the above functions.
|
||||||
template <bool capture_raw>
|
template <bool capture_raw>
|
||||||
uc32 ScanUnicodeEscape();
|
base::uc32 ScanUnicodeEscape();
|
||||||
|
|
||||||
Token::Value ScanTemplateSpan();
|
Token::Value ScanTemplateSpan();
|
||||||
|
|
||||||
@ -718,7 +722,7 @@ class V8_EXPORT_PRIVATE Scanner {
|
|||||||
Utf16CharacterStream* const source_;
|
Utf16CharacterStream* const source_;
|
||||||
|
|
||||||
// One Unicode character look-ahead; c0_ < 0 at the end of the input.
|
// One Unicode character look-ahead; c0_ < 0 at the end of the input.
|
||||||
uc32 c0_;
|
base::uc32 c0_;
|
||||||
|
|
||||||
TokenDesc token_storage_[3];
|
TokenDesc token_storage_[3];
|
||||||
|
|
||||||
|
@ -191,8 +191,8 @@ void RegExpMacroAssemblerARM::CheckCharacter(uint32_t c, Label* on_equal) {
|
|||||||
BranchOrBacktrack(eq, on_equal);
|
BranchOrBacktrack(eq, on_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM::CheckCharacterGT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) {
|
Label* on_greater) {
|
||||||
__ cmp(current_character(), Operand(limit));
|
__ cmp(current_character(), Operand(limit));
|
||||||
BranchOrBacktrack(gt, on_greater);
|
BranchOrBacktrack(gt, on_greater);
|
||||||
}
|
}
|
||||||
@ -214,13 +214,12 @@ void RegExpMacroAssemblerARM::CheckNotAtStart(int cp_offset,
|
|||||||
BranchOrBacktrack(ne, on_not_at_start);
|
BranchOrBacktrack(ne, on_not_at_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM::CheckCharacterLT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) {
|
Label* on_less) {
|
||||||
__ cmp(current_character(), Operand(limit));
|
__ cmp(current_character(), Operand(limit));
|
||||||
BranchOrBacktrack(lt, on_less);
|
BranchOrBacktrack(lt, on_less);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) {
|
void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) {
|
||||||
__ ldr(r0, MemOperand(backtrack_stackpointer(), 0));
|
__ ldr(r0, MemOperand(backtrack_stackpointer(), 0));
|
||||||
__ cmp(current_input_offset(), r0);
|
__ cmp(current_input_offset(), r0);
|
||||||
@ -458,12 +457,8 @@ void RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(unsigned c,
|
|||||||
BranchOrBacktrack(ne, on_not_equal);
|
BranchOrBacktrack(ne, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
|
void RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c,
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
uc16 minus,
|
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal) {
|
|
||||||
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
||||||
__ sub(r0, current_character(), Operand(minus));
|
__ sub(r0, current_character(), Operand(minus));
|
||||||
__ and_(r0, r0, Operand(mask));
|
__ and_(r0, r0, Operand(mask));
|
||||||
@ -471,27 +466,22 @@ void RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
|
|||||||
BranchOrBacktrack(ne, on_not_equal);
|
BranchOrBacktrack(ne, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM::CheckCharacterInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerARM::CheckCharacterInRange(
|
base::uc16 to,
|
||||||
uc16 from,
|
Label* on_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range) {
|
|
||||||
__ sub(r0, current_character(), Operand(from));
|
__ sub(r0, current_character(), Operand(from));
|
||||||
__ cmp(r0, Operand(to - from));
|
__ cmp(r0, Operand(to - from));
|
||||||
BranchOrBacktrack(ls, on_in_range); // Unsigned lower-or-same condition.
|
BranchOrBacktrack(ls, on_in_range); // Unsigned lower-or-same condition.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM::CheckCharacterNotInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerARM::CheckCharacterNotInRange(
|
base::uc16 to,
|
||||||
uc16 from,
|
Label* on_not_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range) {
|
|
||||||
__ sub(r0, current_character(), Operand(from));
|
__ sub(r0, current_character(), Operand(from));
|
||||||
__ cmp(r0, Operand(to - from));
|
__ cmp(r0, Operand(to - from));
|
||||||
BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition.
|
BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM::CheckBitInTable(
|
void RegExpMacroAssemblerARM::CheckBitInTable(
|
||||||
Handle<ByteArray> table,
|
Handle<ByteArray> table,
|
||||||
Label* on_bit_set) {
|
Label* on_bit_set) {
|
||||||
@ -509,8 +499,7 @@ void RegExpMacroAssemblerARM::CheckBitInTable(
|
|||||||
BranchOrBacktrack(ne, on_bit_set);
|
BranchOrBacktrack(ne, on_bit_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(base::uc16 type,
|
||||||
bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type,
|
|
||||||
Label* on_no_match) {
|
Label* on_no_match) {
|
||||||
// Range checks (c in min..max) are generally implemented by an unsigned
|
// Range checks (c in min..max) are generally implemented by an unsigned
|
||||||
// (c - min) <= (max - min) check
|
// (c - min) <= (max - min) check
|
||||||
@ -625,7 +614,6 @@ bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM::Fail() {
|
void RegExpMacroAssemblerARM::Fail() {
|
||||||
__ mov(r0, Operand(FAILURE));
|
__ mov(r0, Operand(FAILURE));
|
||||||
__ jmp(&exit_label_);
|
__ jmp(&exit_label_);
|
||||||
@ -828,8 +816,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
|
|||||||
// Advance current position after a zero-length match.
|
// Advance current position after a zero-length match.
|
||||||
Label advance;
|
Label advance;
|
||||||
__ bind(&advance);
|
__ bind(&advance);
|
||||||
__ add(current_input_offset(),
|
__ add(current_input_offset(), current_input_offset(),
|
||||||
current_input_offset(),
|
|
||||||
Operand((mode_ == UC16) ? 2 : 1));
|
Operand((mode_ == UC16) ? 2 : 1));
|
||||||
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
#ifndef V8_REGEXP_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
||||||
#define V8_REGEXP_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
#define V8_REGEXP_ARM_REGEXP_MACRO_ASSEMBLER_ARM_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/codegen/arm/assembler-arm.h"
|
#include "src/codegen/arm/assembler-arm.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
@ -28,8 +29,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
|
|||||||
virtual void CheckCharacterAfterAnd(unsigned c,
|
virtual void CheckCharacterAfterAnd(unsigned c,
|
||||||
unsigned mask,
|
unsigned mask,
|
||||||
Label* on_equal);
|
Label* on_equal);
|
||||||
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
virtual void CheckCharacterGT(base::uc16 limit, Label* on_greater);
|
||||||
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
virtual void CheckCharacterLT(base::uc16 limit, Label* on_less);
|
||||||
// A "greedy loop" is a loop that is both greedy and with a simple
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
// body. It has a particularly simple implementation.
|
// body. It has a particularly simple implementation.
|
||||||
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
@ -43,23 +44,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
|
|||||||
virtual void CheckNotCharacterAfterAnd(unsigned c,
|
virtual void CheckNotCharacterAfterAnd(unsigned c,
|
||||||
unsigned mask,
|
unsigned mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
|
virtual void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
uc16 minus,
|
base::uc16 mask,
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckCharacterInRange(uc16 from,
|
virtual void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range);
|
Label* on_in_range);
|
||||||
virtual void CheckCharacterNotInRange(uc16 from,
|
virtual void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range);
|
Label* on_not_in_range);
|
||||||
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
||||||
|
|
||||||
// Checks whether the given offset from the current position is before
|
// Checks whether the given offset from the current position is before
|
||||||
// the end of the string.
|
// the end of the string.
|
||||||
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
virtual bool CheckSpecialCharacterClass(uc16 type,
|
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
|
||||||
Label* on_no_match);
|
|
||||||
virtual void Fail();
|
virtual void Fail();
|
||||||
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
||||||
virtual void GoTo(Label* label);
|
virtual void GoTo(Label* label);
|
||||||
|
@ -231,8 +231,7 @@ void RegExpMacroAssemblerARM64::CheckCharacter(uint32_t c, Label* on_equal) {
|
|||||||
CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal);
|
CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM64::CheckCharacterGT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerARM64::CheckCharacterGT(uc16 limit,
|
|
||||||
Label* on_greater) {
|
Label* on_greater) {
|
||||||
CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater);
|
CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater);
|
||||||
}
|
}
|
||||||
@ -253,15 +252,14 @@ void RegExpMacroAssemblerARM64::CheckNotAtStart(int cp_offset,
|
|||||||
BranchOrBacktrack(ne, on_not_at_start);
|
BranchOrBacktrack(ne, on_not_at_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM64::CheckCharacterLT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerARM64::CheckCharacterLT(uc16 limit, Label* on_less) {
|
Label* on_less) {
|
||||||
CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less);
|
CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM64::CheckCharacters(base::Vector<const uc16> str,
|
void RegExpMacroAssemblerARM64::CheckCharacters(
|
||||||
int cp_offset,
|
base::Vector<const base::uc16> str, int cp_offset, Label* on_failure,
|
||||||
Label* on_failure,
|
bool check_end_of_string) {
|
||||||
bool check_end_of_string) {
|
|
||||||
// This method is only ever called from the cctests.
|
// This method is only ever called from the cctests.
|
||||||
|
|
||||||
if (check_end_of_string) {
|
if (check_end_of_string) {
|
||||||
@ -557,39 +555,29 @@ void RegExpMacroAssemblerARM64::CheckNotCharacterAfterAnd(unsigned c,
|
|||||||
CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal);
|
CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd(
|
void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c,
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
uc16 minus,
|
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal) {
|
|
||||||
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
||||||
__ Sub(w10, current_character(), minus);
|
__ Sub(w10, current_character(), minus);
|
||||||
__ And(w10, w10, mask);
|
__ And(w10, w10, mask);
|
||||||
CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal);
|
CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerARM64::CheckCharacterInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerARM64::CheckCharacterInRange(
|
base::uc16 to,
|
||||||
uc16 from,
|
Label* on_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range) {
|
|
||||||
__ Sub(w10, current_character(), from);
|
__ Sub(w10, current_character(), from);
|
||||||
// Unsigned lower-or-same condition.
|
// Unsigned lower-or-same condition.
|
||||||
CompareAndBranchOrBacktrack(w10, to - from, ls, on_in_range);
|
CompareAndBranchOrBacktrack(w10, to - from, ls, on_in_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM64::CheckCharacterNotInRange(
|
void RegExpMacroAssemblerARM64::CheckCharacterNotInRange(
|
||||||
uc16 from,
|
base::uc16 from, base::uc16 to, Label* on_not_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range) {
|
|
||||||
__ Sub(w10, current_character(), from);
|
__ Sub(w10, current_character(), from);
|
||||||
// Unsigned higher condition.
|
// Unsigned higher condition.
|
||||||
CompareAndBranchOrBacktrack(w10, to - from, hi, on_not_in_range);
|
CompareAndBranchOrBacktrack(w10, to - from, hi, on_not_in_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM64::CheckBitInTable(
|
void RegExpMacroAssemblerARM64::CheckBitInTable(
|
||||||
Handle<ByteArray> table,
|
Handle<ByteArray> table,
|
||||||
Label* on_bit_set) {
|
Label* on_bit_set) {
|
||||||
@ -604,8 +592,7 @@ void RegExpMacroAssemblerARM64::CheckBitInTable(
|
|||||||
CompareAndBranchOrBacktrack(w11, 0, ne, on_bit_set);
|
CompareAndBranchOrBacktrack(w11, 0, ne, on_bit_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(base::uc16 type,
|
||||||
bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(uc16 type,
|
|
||||||
Label* on_no_match) {
|
Label* on_no_match) {
|
||||||
// Range checks (c in min..max) are generally implemented by an unsigned
|
// Range checks (c in min..max) are generally implemented by an unsigned
|
||||||
// (c - min) <= (max - min) check
|
// (c - min) <= (max - min) check
|
||||||
@ -708,7 +695,6 @@ bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(uc16 type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerARM64::Fail() {
|
void RegExpMacroAssemblerARM64::Fail() {
|
||||||
__ Mov(w0, FAILURE);
|
__ Mov(w0, FAILURE);
|
||||||
__ B(&exit_label_);
|
__ B(&exit_label_);
|
||||||
@ -1016,8 +1002,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
|
|||||||
// Advance current position after a zero-length match.
|
// Advance current position after a zero-length match.
|
||||||
Label advance;
|
Label advance;
|
||||||
__ bind(&advance);
|
__ bind(&advance);
|
||||||
__ Add(current_input_offset(),
|
__ Add(current_input_offset(), current_input_offset(),
|
||||||
current_input_offset(),
|
|
||||||
Operand((mode_ == UC16) ? 2 : 1));
|
Operand((mode_ == UC16) ? 2 : 1));
|
||||||
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_ARM64_REGEXP_MACRO_ASSEMBLER_ARM64_H_
|
#ifndef V8_REGEXP_ARM64_REGEXP_MACRO_ASSEMBLER_ARM64_H_
|
||||||
#define V8_REGEXP_ARM64_REGEXP_MACRO_ASSEMBLER_ARM64_H_
|
#define V8_REGEXP_ARM64_REGEXP_MACRO_ASSEMBLER_ARM64_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/codegen/arm64/assembler-arm64.h"
|
#include "src/codegen/arm64/assembler-arm64.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
@ -29,10 +30,11 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
|
|||||||
virtual void CheckCharacterAfterAnd(unsigned c,
|
virtual void CheckCharacterAfterAnd(unsigned c,
|
||||||
unsigned mask,
|
unsigned mask,
|
||||||
Label* on_equal);
|
Label* on_equal);
|
||||||
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
virtual void CheckCharacterGT(base::uc16 limit, Label* on_greater);
|
||||||
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
virtual void CheckCharacterLT(base::uc16 limit, Label* on_less);
|
||||||
virtual void CheckCharacters(base::Vector<const uc16> str, int cp_offset,
|
virtual void CheckCharacters(base::Vector<const base::uc16> str,
|
||||||
Label* on_failure, bool check_end_of_string);
|
int cp_offset, Label* on_failure,
|
||||||
|
bool check_end_of_string);
|
||||||
// A "greedy loop" is a loop that is both greedy and with a simple
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
// body. It has a particularly simple implementation.
|
// body. It has a particularly simple implementation.
|
||||||
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
@ -46,23 +48,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
|
|||||||
virtual void CheckNotCharacterAfterAnd(unsigned c,
|
virtual void CheckNotCharacterAfterAnd(unsigned c,
|
||||||
unsigned mask,
|
unsigned mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
|
virtual void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
uc16 minus,
|
base::uc16 mask,
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckCharacterInRange(uc16 from,
|
virtual void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range);
|
Label* on_in_range);
|
||||||
virtual void CheckCharacterNotInRange(uc16 from,
|
virtual void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range);
|
Label* on_not_in_range);
|
||||||
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
||||||
|
|
||||||
// Checks whether the given offset from the current position is before
|
// Checks whether the given offset from the current position is before
|
||||||
// the end of the string.
|
// the end of the string.
|
||||||
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
virtual bool CheckSpecialCharacterClass(uc16 type,
|
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
|
||||||
Label* on_no_match);
|
|
||||||
virtual void BindJumpTarget(Label* label = nullptr);
|
virtual void BindJumpTarget(Label* label = nullptr);
|
||||||
virtual void Fail();
|
virtual void Fail();
|
||||||
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
||||||
|
@ -11,7 +11,7 @@ namespace internal {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::ostream& PrintAsciiOrHex(std::ostream& os, uc16 c) {
|
std::ostream& PrintAsciiOrHex(std::ostream& os, base::uc16 c) {
|
||||||
if (c < 128 && std::isprint(c)) {
|
if (c < 128 && std::isprint(c)) {
|
||||||
os << static_cast<char>(c);
|
os << static_cast<char>(c);
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/base/vector.h"
|
#include "src/base/vector.h"
|
||||||
#include "src/regexp/regexp-ast.h"
|
#include "src/regexp/regexp-ast.h"
|
||||||
|
|
||||||
@ -102,11 +103,11 @@ struct RegExpInstruction {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Uc16Range {
|
struct Uc16Range {
|
||||||
uc16 min; // Inclusive.
|
base::uc16 min; // Inclusive.
|
||||||
uc16 max; // Inclusive.
|
base::uc16 max; // Inclusive.
|
||||||
};
|
};
|
||||||
|
|
||||||
static RegExpInstruction ConsumeRange(uc16 min, uc16 max) {
|
static RegExpInstruction ConsumeRange(base::uc16 min, base::uc16 max) {
|
||||||
RegExpInstruction result;
|
RegExpInstruction result;
|
||||||
result.opcode = CONSUME_RANGE;
|
result.opcode = CONSUME_RANGE;
|
||||||
result.payload.consume_range = Uc16Range{min, max};
|
result.payload.consume_range = Uc16Range{min, max};
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/regexp/experimental/experimental-compiler.h"
|
#include "src/regexp/experimental/experimental-compiler.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/regexp/experimental/experimental.h"
|
#include "src/regexp/experimental/experimental.h"
|
||||||
#include "src/zone/zone-list-inl.h"
|
#include "src/zone/zone-list-inl.h"
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ namespace {
|
|||||||
|
|
||||||
// TODO(mbid, v8:10765): Currently the experimental engine doesn't support
|
// TODO(mbid, v8:10765): Currently the experimental engine doesn't support
|
||||||
// UTF-16, but this shouldn't be too hard to implement.
|
// UTF-16, but this shouldn't be too hard to implement.
|
||||||
constexpr uc32 kMaxSupportedCodepoint = 0xFFFFu;
|
constexpr base::uc32 kMaxSupportedCodepoint = 0xFFFFu;
|
||||||
|
|
||||||
class CanBeHandledVisitor final : private RegExpVisitor {
|
class CanBeHandledVisitor final : private RegExpVisitor {
|
||||||
// Visitor to implement `ExperimentalRegExp::CanBeHandled`.
|
// Visitor to implement `ExperimentalRegExp::CanBeHandled`.
|
||||||
@ -229,7 +230,7 @@ class BytecodeAssembler {
|
|||||||
code_.Add(RegExpInstruction::ClearRegister(register_index), zone_);
|
code_.Add(RegExpInstruction::ClearRegister(register_index), zone_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsumeRange(uc16 from, uc16 to) {
|
void ConsumeRange(base::uc16 from, base::uc16 to) {
|
||||||
code_.Add(RegExpInstruction::ConsumeRange(from, to), zone_);
|
code_.Add(RegExpInstruction::ConsumeRange(from, to), zone_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,16 +403,18 @@ class CompileVisitor : private RegExpVisitor {
|
|||||||
|
|
||||||
CompileDisjunction(ranges->length(), [&](int i) {
|
CompileDisjunction(ranges->length(), [&](int i) {
|
||||||
// We don't support utf16 for now, so only ranges that can be specified
|
// We don't support utf16 for now, so only ranges that can be specified
|
||||||
// by (complements of) ranges with uc16 bounds.
|
// by (complements of) ranges with base::uc16 bounds.
|
||||||
STATIC_ASSERT(kMaxSupportedCodepoint <= std::numeric_limits<uc16>::max());
|
STATIC_ASSERT(kMaxSupportedCodepoint <=
|
||||||
|
std::numeric_limits<base::uc16>::max());
|
||||||
|
|
||||||
uc32 from = (*ranges)[i].from();
|
base::uc32 from = (*ranges)[i].from();
|
||||||
DCHECK_LE(from, kMaxSupportedCodepoint);
|
DCHECK_LE(from, kMaxSupportedCodepoint);
|
||||||
uc16 from_uc16 = static_cast<uc16>(from);
|
base::uc16 from_uc16 = static_cast<base::uc16>(from);
|
||||||
|
|
||||||
uc32 to = (*ranges)[i].to();
|
base::uc32 to = (*ranges)[i].to();
|
||||||
DCHECK_IMPLIES(to > kMaxSupportedCodepoint, to == String::kMaxCodePoint);
|
DCHECK_IMPLIES(to > kMaxSupportedCodepoint, to == String::kMaxCodePoint);
|
||||||
uc16 to_uc16 = static_cast<uc16>(std::min(to, kMaxSupportedCodepoint));
|
base::uc16 to_uc16 =
|
||||||
|
static_cast<base::uc16>(std::min(to, kMaxSupportedCodepoint));
|
||||||
|
|
||||||
assembler_.ConsumeRange(from_uc16, to_uc16);
|
assembler_.ConsumeRange(from_uc16, to_uc16);
|
||||||
});
|
});
|
||||||
@ -419,7 +422,7 @@ class CompileVisitor : private RegExpVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* VisitAtom(RegExpAtom* node, void*) override {
|
void* VisitAtom(RegExpAtom* node, void*) override {
|
||||||
for (uc16 c : node->data()) {
|
for (base::uc16 c : node->data()) {
|
||||||
assembler_.ConsumeRange(c, c);
|
assembler_.ConsumeRange(c, c);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "src/regexp/experimental/experimental-interpreter.h"
|
#include "src/regexp/experimental/experimental-interpreter.h"
|
||||||
|
|
||||||
#include "src/base/optional.h"
|
#include "src/base/optional.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/assert-scope.h"
|
#include "src/common/assert-scope.h"
|
||||||
#include "src/objects/fixed-array-inl.h"
|
#include "src/objects/fixed-array-inl.h"
|
||||||
#include "src/objects/string-inl.h"
|
#include "src/objects/string-inl.h"
|
||||||
@ -76,7 +77,7 @@ base::Vector<const uint8_t> ToCharacterVector<uint8_t>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
base::Vector<const uc16> ToCharacterVector<uc16>(
|
base::Vector<const base::uc16> ToCharacterVector<base::uc16>(
|
||||||
String str, const DisallowGarbageCollection& no_gc) {
|
String str, const DisallowGarbageCollection& no_gc) {
|
||||||
DCHECK(str.IsFlat());
|
DCHECK(str.IsFlat());
|
||||||
String::FlatContent content = str.GetFlatContent(no_gc);
|
String::FlatContent content = str.GetFlatContent(no_gc);
|
||||||
@ -87,8 +88,8 @@ base::Vector<const uc16> ToCharacterVector<uc16>(
|
|||||||
template <class Character>
|
template <class Character>
|
||||||
class NfaInterpreter {
|
class NfaInterpreter {
|
||||||
// Executes a bytecode program in breadth-first mode, without backtracking.
|
// Executes a bytecode program in breadth-first mode, without backtracking.
|
||||||
// `Character` can be instantiated with `uint8_t` or `uc16` for one byte or
|
// `Character` can be instantiated with `uint8_t` or `base::uc16` for one byte
|
||||||
// two byte input strings.
|
// or two byte input strings.
|
||||||
//
|
//
|
||||||
// In contrast to the backtracking implementation, this has linear time
|
// In contrast to the backtracking implementation, this has linear time
|
||||||
// complexity in the length of the input string. Breadth-first mode means
|
// complexity in the length of the input string. Breadth-first mode means
|
||||||
@ -343,7 +344,7 @@ class NfaInterpreter {
|
|||||||
while (input_index_ != input_.length() &&
|
while (input_index_ != input_.length() &&
|
||||||
!(FoundMatch() && blocked_threads_.is_empty())) {
|
!(FoundMatch() && blocked_threads_.is_empty())) {
|
||||||
DCHECK(active_threads_.is_empty());
|
DCHECK(active_threads_.is_empty());
|
||||||
uc16 input_char = input_[input_index_];
|
base::uc16 input_char = input_[input_index_];
|
||||||
++input_index_;
|
++input_index_;
|
||||||
|
|
||||||
static constexpr int kTicksBetweenInterruptHandling = 64;
|
static constexpr int kTicksBetweenInterruptHandling = 64;
|
||||||
@ -439,7 +440,7 @@ class NfaInterpreter {
|
|||||||
// Unblock all blocked_threads_ by feeding them an `input_char`. Should only
|
// Unblock all blocked_threads_ by feeding them an `input_char`. Should only
|
||||||
// be called with `input_index_` pointing to the character *after*
|
// be called with `input_index_` pointing to the character *after*
|
||||||
// `input_char` so that `pc_last_input_index_` is updated correctly.
|
// `input_char` so that `pc_last_input_index_` is updated correctly.
|
||||||
void FlushBlockedThreads(uc16 input_char) {
|
void FlushBlockedThreads(base::uc16 input_char) {
|
||||||
// The threads in blocked_threads_ are sorted from high to low priority,
|
// The threads in blocked_threads_ are sorted from high to low priority,
|
||||||
// but active_threads_ needs to be sorted from low to high priority, so we
|
// but active_threads_ needs to be sorted from low to high priority, so we
|
||||||
// need to activate blocked threads in reverse order.
|
// need to activate blocked threads in reverse order.
|
||||||
@ -568,9 +569,9 @@ int ExperimentalRegExpInterpreter::FindMatches(
|
|||||||
return interpreter.FindMatches(output_registers, output_register_count);
|
return interpreter.FindMatches(output_registers, output_register_count);
|
||||||
} else {
|
} else {
|
||||||
DCHECK(input.GetFlatContent(no_gc).IsTwoByte());
|
DCHECK(input.GetFlatContent(no_gc).IsTwoByte());
|
||||||
NfaInterpreter<uc16> interpreter(isolate, call_origin, bytecode,
|
NfaInterpreter<base::uc16> interpreter(isolate, call_origin, bytecode,
|
||||||
register_count_per_match, input,
|
register_count_per_match, input,
|
||||||
start_index, zone);
|
start_index, zone);
|
||||||
return interpreter.FindMatches(output_registers, output_register_count);
|
return interpreter.FindMatches(output_registers, output_register_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/regexp/special-case.h"
|
#include "src/regexp/special-case.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
static const uc32 kSurrogateStart = 0xd800;
|
static const base::uc32 kSurrogateStart = 0xd800;
|
||||||
static const uc32 kSurrogateEnd = 0xdfff;
|
static const base::uc32 kSurrogateEnd = 0xdfff;
|
||||||
static const uc32 kNonBmpStart = 0x10000;
|
static const base::uc32 kNonBmpStart = 0x10000;
|
||||||
|
|
||||||
// The following code generates "src/regexp/special-case.cc".
|
// The following code generates "src/regexp/special-case.cc".
|
||||||
void PrintSet(std::ofstream& out, const char* name,
|
void PrintSet(std::ofstream& out, const char* name,
|
||||||
|
@ -176,8 +176,8 @@ void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
|
|||||||
BranchOrBacktrack(equal, on_equal);
|
BranchOrBacktrack(equal, on_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerIA32::CheckCharacterGT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
|
Label* on_greater) {
|
||||||
__ cmp(current_character(), limit);
|
__ cmp(current_character(), limit);
|
||||||
BranchOrBacktrack(greater, on_greater);
|
BranchOrBacktrack(greater, on_greater);
|
||||||
}
|
}
|
||||||
@ -195,13 +195,12 @@ void RegExpMacroAssemblerIA32::CheckNotAtStart(int cp_offset,
|
|||||||
BranchOrBacktrack(not_equal, on_not_at_start);
|
BranchOrBacktrack(not_equal, on_not_at_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerIA32::CheckCharacterLT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
|
Label* on_less) {
|
||||||
__ cmp(current_character(), limit);
|
__ cmp(current_character(), limit);
|
||||||
BranchOrBacktrack(less, on_less);
|
BranchOrBacktrack(less, on_less);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
|
void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
|
||||||
Label fallthrough;
|
Label fallthrough;
|
||||||
__ cmp(edi, Operand(backtrack_stackpointer(), 0));
|
__ cmp(edi, Operand(backtrack_stackpointer(), 0));
|
||||||
@ -481,12 +480,8 @@ void RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
|
|||||||
BranchOrBacktrack(not_equal, on_not_equal);
|
BranchOrBacktrack(not_equal, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
|
void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c,
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
uc16 minus,
|
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal) {
|
|
||||||
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
||||||
__ lea(eax, Operand(current_character(), -minus));
|
__ lea(eax, Operand(current_character(), -minus));
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
@ -498,27 +493,21 @@ void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
|
|||||||
BranchOrBacktrack(not_equal, on_not_equal);
|
BranchOrBacktrack(not_equal, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerIA32::CheckCharacterInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerIA32::CheckCharacterInRange(
|
base::uc16 to,
|
||||||
uc16 from,
|
Label* on_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range) {
|
|
||||||
__ lea(eax, Operand(current_character(), -from));
|
__ lea(eax, Operand(current_character(), -from));
|
||||||
__ cmp(eax, to - from);
|
__ cmp(eax, to - from);
|
||||||
BranchOrBacktrack(below_equal, on_in_range);
|
BranchOrBacktrack(below_equal, on_in_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
|
void RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
|
||||||
uc16 from,
|
base::uc16 from, base::uc16 to, Label* on_not_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range) {
|
|
||||||
__ lea(eax, Operand(current_character(), -from));
|
__ lea(eax, Operand(current_character(), -from));
|
||||||
__ cmp(eax, to - from);
|
__ cmp(eax, to - from);
|
||||||
BranchOrBacktrack(above, on_not_in_range);
|
BranchOrBacktrack(above, on_not_in_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::CheckBitInTable(
|
void RegExpMacroAssemblerIA32::CheckBitInTable(
|
||||||
Handle<ByteArray> table,
|
Handle<ByteArray> table,
|
||||||
Label* on_bit_set) {
|
Label* on_bit_set) {
|
||||||
@ -534,8 +523,7 @@ void RegExpMacroAssemblerIA32::CheckBitInTable(
|
|||||||
BranchOrBacktrack(not_equal, on_bit_set);
|
BranchOrBacktrack(not_equal, on_bit_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(base::uc16 type,
|
||||||
bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
|
|
||||||
Label* on_no_match) {
|
Label* on_no_match) {
|
||||||
// Range checks (c in min..max) are generally implemented by an unsigned
|
// Range checks (c in min..max) are generally implemented by an unsigned
|
||||||
// (c - min) <= (max - min) check
|
// (c - min) <= (max - min) check
|
||||||
@ -659,7 +647,6 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerIA32::Fail() {
|
void RegExpMacroAssemblerIA32::Fail() {
|
||||||
STATIC_ASSERT(FAILURE == 0); // Return value for failure is zero.
|
STATIC_ASSERT(FAILURE == 0); // Return value for failure is zero.
|
||||||
if (!global()) {
|
if (!global()) {
|
||||||
@ -1263,11 +1250,11 @@ void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
|
|||||||
DCHECK(mode_ == UC16);
|
DCHECK(mode_ == UC16);
|
||||||
if (characters == 2) {
|
if (characters == 2) {
|
||||||
__ mov(current_character(),
|
__ mov(current_character(),
|
||||||
Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
|
Operand(esi, edi, times_1, cp_offset * sizeof(base::uc16)));
|
||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(1, characters);
|
DCHECK_EQ(1, characters);
|
||||||
__ movzx_w(current_character(),
|
__ movzx_w(current_character(),
|
||||||
Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
|
Operand(esi, edi, times_1, cp_offset * sizeof(base::uc16)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
|
#ifndef V8_REGEXP_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
|
||||||
#define V8_REGEXP_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
|
#define V8_REGEXP_IA32_REGEXP_MACRO_ASSEMBLER_IA32_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/codegen/ia32/assembler-ia32.h"
|
#include "src/codegen/ia32/assembler-ia32.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
@ -28,8 +29,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
|
|||||||
virtual void CheckCharacterAfterAnd(uint32_t c,
|
virtual void CheckCharacterAfterAnd(uint32_t c,
|
||||||
uint32_t mask,
|
uint32_t mask,
|
||||||
Label* on_equal);
|
Label* on_equal);
|
||||||
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
virtual void CheckCharacterGT(base::uc16 limit, Label* on_greater);
|
||||||
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
virtual void CheckCharacterLT(base::uc16 limit, Label* on_less);
|
||||||
// A "greedy loop" is a loop that is both greedy and with a simple
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
// body. It has a particularly simple implementation.
|
// body. It has a particularly simple implementation.
|
||||||
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
@ -43,22 +44,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
|
|||||||
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
||||||
uint32_t mask,
|
uint32_t mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
|
virtual void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
uc16 minus,
|
base::uc16 mask,
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckCharacterInRange(uc16 from,
|
virtual void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range);
|
Label* on_in_range);
|
||||||
virtual void CheckCharacterNotInRange(uc16 from,
|
virtual void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range);
|
Label* on_not_in_range);
|
||||||
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
||||||
|
|
||||||
// Checks whether the given offset from the current position is before
|
// Checks whether the given offset from the current position is before
|
||||||
// the end of the string.
|
// the end of the string.
|
||||||
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
virtual bool CheckSpecialCharacterClass(uc16 type, Label* on_no_match);
|
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
|
||||||
virtual void Fail();
|
virtual void Fail();
|
||||||
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
||||||
virtual void GoTo(Label* label);
|
virtual void GoTo(Label* label);
|
||||||
|
@ -192,12 +192,11 @@ void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) {
|
|||||||
BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
|
BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerMIPS::CheckCharacterGT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) {
|
Label* on_greater) {
|
||||||
BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
|
BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckAtStart(int cp_offset, Label* on_at_start) {
|
void RegExpMacroAssemblerMIPS::CheckAtStart(int cp_offset, Label* on_at_start) {
|
||||||
__ lw(a1, MemOperand(frame_pointer(), kStringStartMinusOne));
|
__ lw(a1, MemOperand(frame_pointer(), kStringStartMinusOne));
|
||||||
__ Addu(a0, current_input_offset(),
|
__ Addu(a0, current_input_offset(),
|
||||||
@ -214,12 +213,11 @@ void RegExpMacroAssemblerMIPS::CheckNotAtStart(int cp_offset,
|
|||||||
BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
|
BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerMIPS::CheckCharacterLT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) {
|
Label* on_less) {
|
||||||
BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
|
BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
|
void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
|
||||||
Label backtrack_non_equal;
|
Label backtrack_non_equal;
|
||||||
__ lw(a0, MemOperand(backtrack_stackpointer(), 0));
|
__ lw(a0, MemOperand(backtrack_stackpointer(), 0));
|
||||||
@ -462,39 +460,29 @@ void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
|
|||||||
BranchOrBacktrack(on_not_equal, ne, a0, rhs);
|
BranchOrBacktrack(on_not_equal, ne, a0, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
|
void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c,
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
uc16 minus,
|
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal) {
|
|
||||||
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
||||||
__ Subu(a0, current_character(), Operand(minus));
|
__ Subu(a0, current_character(), Operand(minus));
|
||||||
__ And(a0, a0, Operand(mask));
|
__ And(a0, a0, Operand(mask));
|
||||||
BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
|
BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerMIPS::CheckCharacterInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterInRange(
|
base::uc16 to,
|
||||||
uc16 from,
|
Label* on_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range) {
|
|
||||||
__ Subu(a0, current_character(), Operand(from));
|
__ Subu(a0, current_character(), Operand(from));
|
||||||
// Unsigned lower-or-same condition.
|
// Unsigned lower-or-same condition.
|
||||||
BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
|
BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
|
void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
|
||||||
uc16 from,
|
base::uc16 from, base::uc16 to, Label* on_not_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range) {
|
|
||||||
__ Subu(a0, current_character(), Operand(from));
|
__ Subu(a0, current_character(), Operand(from));
|
||||||
// Unsigned higher condition.
|
// Unsigned higher condition.
|
||||||
BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
|
BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
||||||
Handle<ByteArray> table,
|
Handle<ByteArray> table,
|
||||||
Label* on_bit_set) {
|
Label* on_bit_set) {
|
||||||
@ -510,8 +498,7 @@ void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
|||||||
BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
|
BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(base::uc16 type,
|
||||||
bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
|
|
||||||
Label* on_no_match) {
|
Label* on_no_match) {
|
||||||
// Range checks (c in min..max) are generally implemented by an unsigned
|
// Range checks (c in min..max) are generally implemented by an unsigned
|
||||||
// (c - min) <= (max - min) check.
|
// (c - min) <= (max - min) check.
|
||||||
@ -615,7 +602,6 @@ bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::Fail() {
|
void RegExpMacroAssemblerMIPS::Fail() {
|
||||||
__ li(v0, Operand(FAILURE));
|
__ li(v0, Operand(FAILURE));
|
||||||
__ jmp(&exit_label_);
|
__ jmp(&exit_label_);
|
||||||
@ -827,8 +813,7 @@ Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) {
|
|||||||
// Advance current position after a zero-length match.
|
// Advance current position after a zero-length match.
|
||||||
Label advance;
|
Label advance;
|
||||||
__ bind(&advance);
|
__ bind(&advance);
|
||||||
__ Addu(current_input_offset(),
|
__ Addu(current_input_offset(), current_input_offset(),
|
||||||
current_input_offset(),
|
|
||||||
Operand((mode_ == UC16) ? 2 : 1));
|
Operand((mode_ == UC16) ? 2 : 1));
|
||||||
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
|
#ifndef V8_REGEXP_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
|
||||||
#define V8_REGEXP_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
|
#define V8_REGEXP_MIPS_REGEXP_MACRO_ASSEMBLER_MIPS_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
#include "src/codegen/mips/assembler-mips.h"
|
#include "src/codegen/mips/assembler-mips.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
@ -28,8 +29,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerMIPS
|
|||||||
virtual void CheckCharacterAfterAnd(uint32_t c,
|
virtual void CheckCharacterAfterAnd(uint32_t c,
|
||||||
uint32_t mask,
|
uint32_t mask,
|
||||||
Label* on_equal);
|
Label* on_equal);
|
||||||
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
virtual void CheckCharacterGT(base::uc16 limit, Label* on_greater);
|
||||||
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
virtual void CheckCharacterLT(base::uc16 limit, Label* on_less);
|
||||||
// A "greedy loop" is a loop that is both greedy and with a simple
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
// body. It has a particularly simple implementation.
|
// body. It has a particularly simple implementation.
|
||||||
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
@ -43,23 +44,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerMIPS
|
|||||||
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
||||||
uint32_t mask,
|
uint32_t mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
|
virtual void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
uc16 minus,
|
base::uc16 mask,
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckCharacterInRange(uc16 from,
|
virtual void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range);
|
Label* on_in_range);
|
||||||
virtual void CheckCharacterNotInRange(uc16 from,
|
virtual void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range);
|
Label* on_not_in_range);
|
||||||
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
||||||
|
|
||||||
// Checks whether the given offset from the current position is before
|
// Checks whether the given offset from the current position is before
|
||||||
// the end of the string.
|
// the end of the string.
|
||||||
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
virtual bool CheckSpecialCharacterClass(uc16 type,
|
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
|
||||||
Label* on_no_match);
|
|
||||||
virtual void Fail();
|
virtual void Fail();
|
||||||
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
||||||
virtual void GoTo(Label* label);
|
virtual void GoTo(Label* label);
|
||||||
|
@ -228,12 +228,11 @@ void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) {
|
|||||||
BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
|
BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerMIPS::CheckCharacterGT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) {
|
Label* on_greater) {
|
||||||
BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
|
BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckAtStart(int cp_offset, Label* on_at_start) {
|
void RegExpMacroAssemblerMIPS::CheckAtStart(int cp_offset, Label* on_at_start) {
|
||||||
__ Ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne));
|
__ Ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne));
|
||||||
__ Daddu(a0, current_input_offset(),
|
__ Daddu(a0, current_input_offset(),
|
||||||
@ -250,12 +249,11 @@ void RegExpMacroAssemblerMIPS::CheckNotAtStart(int cp_offset,
|
|||||||
BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
|
BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerMIPS::CheckCharacterLT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) {
|
Label* on_less) {
|
||||||
BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
|
BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
|
void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
|
||||||
Label backtrack_non_equal;
|
Label backtrack_non_equal;
|
||||||
__ Lw(a0, MemOperand(backtrack_stackpointer(), 0));
|
__ Lw(a0, MemOperand(backtrack_stackpointer(), 0));
|
||||||
@ -492,39 +490,29 @@ void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
|
|||||||
BranchOrBacktrack(on_not_equal, ne, a0, rhs);
|
BranchOrBacktrack(on_not_equal, ne, a0, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
|
void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c,
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
uc16 minus,
|
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal) {
|
|
||||||
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
||||||
__ Dsubu(a0, current_character(), Operand(minus));
|
__ Dsubu(a0, current_character(), Operand(minus));
|
||||||
__ And(a0, a0, Operand(mask));
|
__ And(a0, a0, Operand(mask));
|
||||||
BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
|
BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerMIPS::CheckCharacterInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterInRange(
|
base::uc16 to,
|
||||||
uc16 from,
|
Label* on_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range) {
|
|
||||||
__ Dsubu(a0, current_character(), Operand(from));
|
__ Dsubu(a0, current_character(), Operand(from));
|
||||||
// Unsigned lower-or-same condition.
|
// Unsigned lower-or-same condition.
|
||||||
BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
|
BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
|
void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
|
||||||
uc16 from,
|
base::uc16 from, base::uc16 to, Label* on_not_in_range) {
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range) {
|
|
||||||
__ Dsubu(a0, current_character(), Operand(from));
|
__ Dsubu(a0, current_character(), Operand(from));
|
||||||
// Unsigned higher condition.
|
// Unsigned higher condition.
|
||||||
BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
|
BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
||||||
Handle<ByteArray> table,
|
Handle<ByteArray> table,
|
||||||
Label* on_bit_set) {
|
Label* on_bit_set) {
|
||||||
@ -540,8 +528,7 @@ void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
|||||||
BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
|
BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(base::uc16 type,
|
||||||
bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
|
|
||||||
Label* on_no_match) {
|
Label* on_no_match) {
|
||||||
// Range checks (c in min..max) are generally implemented by an unsigned
|
// Range checks (c in min..max) are generally implemented by an unsigned
|
||||||
// (c - min) <= (max - min) check.
|
// (c - min) <= (max - min) check.
|
||||||
@ -645,7 +632,6 @@ bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerMIPS::Fail() {
|
void RegExpMacroAssemblerMIPS::Fail() {
|
||||||
__ li(v0, Operand(FAILURE));
|
__ li(v0, Operand(FAILURE));
|
||||||
__ jmp(&exit_label_);
|
__ jmp(&exit_label_);
|
||||||
@ -863,9 +849,8 @@ Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) {
|
|||||||
// Advance current position after a zero-length match.
|
// Advance current position after a zero-length match.
|
||||||
Label advance;
|
Label advance;
|
||||||
__ bind(&advance);
|
__ bind(&advance);
|
||||||
__ Daddu(current_input_offset(),
|
__ Daddu(current_input_offset(), current_input_offset(),
|
||||||
current_input_offset(),
|
Operand((mode_ == UC16) ? 2 : 1));
|
||||||
Operand((mode_ == UC16) ? 2 : 1));
|
|
||||||
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_MIPS64_REGEXP_MACRO_ASSEMBLER_MIPS64_H_
|
#ifndef V8_REGEXP_MIPS64_REGEXP_MACRO_ASSEMBLER_MIPS64_H_
|
||||||
#define V8_REGEXP_MIPS64_REGEXP_MACRO_ASSEMBLER_MIPS64_H_
|
#define V8_REGEXP_MIPS64_REGEXP_MACRO_ASSEMBLER_MIPS64_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
#include "src/codegen/mips64/assembler-mips64.h"
|
#include "src/codegen/mips64/assembler-mips64.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
@ -28,8 +29,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerMIPS
|
|||||||
virtual void CheckCharacterAfterAnd(uint32_t c,
|
virtual void CheckCharacterAfterAnd(uint32_t c,
|
||||||
uint32_t mask,
|
uint32_t mask,
|
||||||
Label* on_equal);
|
Label* on_equal);
|
||||||
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
virtual void CheckCharacterGT(base::uc16 limit, Label* on_greater);
|
||||||
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
virtual void CheckCharacterLT(base::uc16 limit, Label* on_less);
|
||||||
// A "greedy loop" is a loop that is both greedy and with a simple
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
// body. It has a particularly simple implementation.
|
// body. It has a particularly simple implementation.
|
||||||
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
@ -43,23 +44,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerMIPS
|
|||||||
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
virtual void CheckNotCharacterAfterAnd(uint32_t c,
|
||||||
uint32_t mask,
|
uint32_t mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
|
virtual void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
uc16 minus,
|
base::uc16 mask,
|
||||||
uc16 mask,
|
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckCharacterInRange(uc16 from,
|
virtual void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_in_range);
|
Label* on_in_range);
|
||||||
virtual void CheckCharacterNotInRange(uc16 from,
|
virtual void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
uc16 to,
|
|
||||||
Label* on_not_in_range);
|
Label* on_not_in_range);
|
||||||
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
||||||
|
|
||||||
// Checks whether the given offset from the current position is before
|
// Checks whether the given offset from the current position is before
|
||||||
// the end of the string.
|
// the end of the string.
|
||||||
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
virtual bool CheckSpecialCharacterClass(uc16 type,
|
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
|
||||||
Label* on_no_match);
|
|
||||||
virtual void Fail();
|
virtual void Fail();
|
||||||
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
||||||
virtual void GoTo(Label* label);
|
virtual void GoTo(Label* label);
|
||||||
|
@ -206,8 +206,8 @@ void RegExpMacroAssemblerPPC::CheckCharacter(uint32_t c, Label* on_equal) {
|
|||||||
BranchOrBacktrack(eq, on_equal);
|
BranchOrBacktrack(eq, on_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerPPC::CheckCharacterGT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerPPC::CheckCharacterGT(uc16 limit, Label* on_greater) {
|
Label* on_greater) {
|
||||||
__ Cmpli(current_character(), Operand(limit), r0);
|
__ Cmpli(current_character(), Operand(limit), r0);
|
||||||
BranchOrBacktrack(gt, on_greater);
|
BranchOrBacktrack(gt, on_greater);
|
||||||
}
|
}
|
||||||
@ -229,13 +229,12 @@ void RegExpMacroAssemblerPPC::CheckNotAtStart(int cp_offset,
|
|||||||
BranchOrBacktrack(ne, on_not_at_start);
|
BranchOrBacktrack(ne, on_not_at_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerPPC::CheckCharacterLT(base::uc16 limit,
|
||||||
void RegExpMacroAssemblerPPC::CheckCharacterLT(uc16 limit, Label* on_less) {
|
Label* on_less) {
|
||||||
__ Cmpli(current_character(), Operand(limit), r0);
|
__ Cmpli(current_character(), Operand(limit), r0);
|
||||||
BranchOrBacktrack(lt, on_less);
|
BranchOrBacktrack(lt, on_less);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) {
|
void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) {
|
||||||
Label backtrack_non_equal;
|
Label backtrack_non_equal;
|
||||||
__ LoadU64(r3, MemOperand(backtrack_stackpointer(), 0));
|
__ LoadU64(r3, MemOperand(backtrack_stackpointer(), 0));
|
||||||
@ -488,9 +487,8 @@ void RegExpMacroAssemblerPPC::CheckNotCharacterAfterAnd(unsigned c,
|
|||||||
BranchOrBacktrack(ne, on_not_equal, cr0);
|
BranchOrBacktrack(ne, on_not_equal, cr0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerPPC::CheckNotCharacterAfterMinusAnd(
|
void RegExpMacroAssemblerPPC::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c, uc16 minus, uc16 mask, Label* on_not_equal) {
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
|
||||||
__ subi(r3, current_character(), Operand(minus));
|
__ subi(r3, current_character(), Operand(minus));
|
||||||
__ mov(r0, Operand(mask));
|
__ mov(r0, Operand(mask));
|
||||||
@ -499,8 +497,8 @@ void RegExpMacroAssemblerPPC::CheckNotCharacterAfterMinusAnd(
|
|||||||
BranchOrBacktrack(ne, on_not_equal);
|
BranchOrBacktrack(ne, on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerPPC::CheckCharacterInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerPPC::CheckCharacterInRange(uc16 from, uc16 to,
|
base::uc16 to,
|
||||||
Label* on_in_range) {
|
Label* on_in_range) {
|
||||||
__ mov(r0, Operand(from));
|
__ mov(r0, Operand(from));
|
||||||
__ sub(r3, current_character(), r0);
|
__ sub(r3, current_character(), r0);
|
||||||
@ -508,8 +506,8 @@ void RegExpMacroAssemblerPPC::CheckCharacterInRange(uc16 from, uc16 to,
|
|||||||
BranchOrBacktrack(le, on_in_range); // Unsigned lower-or-same condition.
|
BranchOrBacktrack(le, on_in_range); // Unsigned lower-or-same condition.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegExpMacroAssemblerPPC::CheckCharacterNotInRange(base::uc16 from,
|
||||||
void RegExpMacroAssemblerPPC::CheckCharacterNotInRange(uc16 from, uc16 to,
|
base::uc16 to,
|
||||||
Label* on_not_in_range) {
|
Label* on_not_in_range) {
|
||||||
__ mov(r0, Operand(from));
|
__ mov(r0, Operand(from));
|
||||||
__ sub(r3, current_character(), r0);
|
__ sub(r3, current_character(), r0);
|
||||||
@ -517,7 +515,6 @@ void RegExpMacroAssemblerPPC::CheckCharacterNotInRange(uc16 from, uc16 to,
|
|||||||
BranchOrBacktrack(gt, on_not_in_range); // Unsigned higher condition.
|
BranchOrBacktrack(gt, on_not_in_range); // Unsigned higher condition.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerPPC::CheckBitInTable(Handle<ByteArray> table,
|
void RegExpMacroAssemblerPPC::CheckBitInTable(Handle<ByteArray> table,
|
||||||
Label* on_bit_set) {
|
Label* on_bit_set) {
|
||||||
__ mov(r3, Operand(table));
|
__ mov(r3, Operand(table));
|
||||||
@ -533,8 +530,7 @@ void RegExpMacroAssemblerPPC::CheckBitInTable(Handle<ByteArray> table,
|
|||||||
BranchOrBacktrack(ne, on_bit_set);
|
BranchOrBacktrack(ne, on_bit_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RegExpMacroAssemblerPPC::CheckSpecialCharacterClass(base::uc16 type,
|
||||||
bool RegExpMacroAssemblerPPC::CheckSpecialCharacterClass(uc16 type,
|
|
||||||
Label* on_no_match) {
|
Label* on_no_match) {
|
||||||
// Range checks (c in min..max) are generally implemented by an unsigned
|
// Range checks (c in min..max) are generally implemented by an unsigned
|
||||||
// (c - min) <= (max - min) check
|
// (c - min) <= (max - min) check
|
||||||
@ -651,7 +647,6 @@ bool RegExpMacroAssemblerPPC::CheckSpecialCharacterClass(uc16 type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RegExpMacroAssemblerPPC::Fail() {
|
void RegExpMacroAssemblerPPC::Fail() {
|
||||||
__ li(r3, Operand(FAILURE));
|
__ li(r3, Operand(FAILURE));
|
||||||
__ b(&exit_label_);
|
__ b(&exit_label_);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
|
#ifndef V8_REGEXP_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
|
||||||
#define V8_REGEXP_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
|
#define V8_REGEXP_PPC_REGEXP_MACRO_ASSEMBLER_PPC_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/codegen/macro-assembler.h"
|
#include "src/codegen/macro-assembler.h"
|
||||||
#include "src/codegen/ppc/assembler-ppc.h"
|
#include "src/codegen/ppc/assembler-ppc.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
@ -27,8 +28,8 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerPPC
|
|||||||
virtual void CheckCharacter(unsigned c, Label* on_equal);
|
virtual void CheckCharacter(unsigned c, Label* on_equal);
|
||||||
virtual void CheckCharacterAfterAnd(unsigned c, unsigned mask,
|
virtual void CheckCharacterAfterAnd(unsigned c, unsigned mask,
|
||||||
Label* on_equal);
|
Label* on_equal);
|
||||||
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
|
virtual void CheckCharacterGT(base::uc16 limit, Label* on_greater);
|
||||||
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
|
virtual void CheckCharacterLT(base::uc16 limit, Label* on_less);
|
||||||
// A "greedy loop" is a loop that is both greedy and with a simple
|
// A "greedy loop" is a loop that is both greedy and with a simple
|
||||||
// body. It has a particularly simple implementation.
|
// body. It has a particularly simple implementation.
|
||||||
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
|
||||||
@ -41,17 +42,19 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerPPC
|
|||||||
virtual void CheckNotCharacter(unsigned c, Label* on_not_equal);
|
virtual void CheckNotCharacter(unsigned c, Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
|
virtual void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckNotCharacterAfterMinusAnd(uc16 c, uc16 minus, uc16 mask,
|
virtual void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
|
base::uc16 mask,
|
||||||
Label* on_not_equal);
|
Label* on_not_equal);
|
||||||
virtual void CheckCharacterInRange(uc16 from, uc16 to, Label* on_in_range);
|
virtual void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
virtual void CheckCharacterNotInRange(uc16 from, uc16 to,
|
Label* on_in_range);
|
||||||
|
virtual void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
Label* on_not_in_range);
|
Label* on_not_in_range);
|
||||||
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
|
||||||
|
|
||||||
// Checks whether the given offset from the current position is before
|
// Checks whether the given offset from the current position is before
|
||||||
// the end of the string.
|
// the end of the string.
|
||||||
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
|
||||||
virtual bool CheckSpecialCharacterClass(uc16 type, Label* on_no_match);
|
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
|
||||||
virtual void Fail();
|
virtual void Fail();
|
||||||
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
virtual Handle<HeapObject> GetCode(Handle<String> source);
|
||||||
virtual void GoTo(Label* label);
|
virtual void GoTo(Label* label);
|
||||||
|
@ -42,7 +42,7 @@ const generateData = (property) => {
|
|||||||
buffer.push(' ' + codePoints.join(', ') + ', 0,');
|
buffer.push(' ' + codePoints.join(', ') + ', 0,');
|
||||||
}
|
}
|
||||||
const output =
|
const output =
|
||||||
`const uc32 UnicodePropertySequences::k${ id }[] = {\n` +
|
`const base::uc32 UnicodePropertySequences::k${ id }[] = {\n` +
|
||||||
`${ buffer.join('\n') }\n 0 // null-terminating the list\n};\n`;
|
`${ buffer.join('\n') }\n 0 // null-terminating the list\n};\n`;
|
||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
@ -60,7 +60,7 @@ for (const property of properties) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const uc32 UnicodePropertySequences::kEmojiFlagSequences[] = {
|
const base::uc32 UnicodePropertySequences::kEmojiFlagSequences[] = {
|
||||||
0x01F1E6, 0x01F1E8, 0,
|
0x01F1E6, 0x01F1E8, 0,
|
||||||
0x01F1FF, 0x01F1FC, 0,
|
0x01F1FF, 0x01F1FC, 0,
|
||||||
0x01F1E6, 0x01F1EA, 0,
|
0x01F1E6, 0x01F1EA, 0,
|
||||||
@ -322,14 +322,14 @@ const uc32 UnicodePropertySequences::kEmojiFlagSequences[] = {
|
|||||||
0 // null-terminating the list
|
0 // null-terminating the list
|
||||||
};
|
};
|
||||||
|
|
||||||
const uc32 UnicodePropertySequences::kEmojiTagSequences[] = {
|
const base::uc32 UnicodePropertySequences::kEmojiTagSequences[] = {
|
||||||
0x01F3F4, 0x0E0067, 0x0E0062, 0x0E0065, 0x0E006E, 0x0E0067, 0x0E007F, 0,
|
0x01F3F4, 0x0E0067, 0x0E0062, 0x0E0065, 0x0E006E, 0x0E0067, 0x0E007F, 0,
|
||||||
0x01F3F4, 0x0E0067, 0x0E0062, 0x0E0073, 0x0E0063, 0x0E0074, 0x0E007F, 0,
|
0x01F3F4, 0x0E0067, 0x0E0062, 0x0E0073, 0x0E0063, 0x0E0074, 0x0E007F, 0,
|
||||||
0x01F3F4, 0x0E0067, 0x0E0062, 0x0E0077, 0x0E006C, 0x0E0073, 0x0E007F, 0,
|
0x01F3F4, 0x0E0067, 0x0E0062, 0x0E0077, 0x0E006C, 0x0E0073, 0x0E007F, 0,
|
||||||
0 // null-terminating the list
|
0 // null-terminating the list
|
||||||
};
|
};
|
||||||
|
|
||||||
const uc32 UnicodePropertySequences::kEmojiZWJSequences[] = {
|
const base::uc32 UnicodePropertySequences::kEmojiZWJSequences[] = {
|
||||||
0x01F468, 0x00200D, 0x002764, 0x00FE0F, 0x00200D, 0x01F468, 0,
|
0x01F468, 0x00200D, 0x002764, 0x00FE0F, 0x00200D, 0x01F468, 0,
|
||||||
0x01F441, 0x00FE0F, 0x00200D, 0x01F5E8, 0x00FE0F, 0,
|
0x01F441, 0x00FE0F, 0x00200D, 0x01F5E8, 0x00FE0F, 0,
|
||||||
0x01F468, 0x00200D, 0x01F466, 0,
|
0x01F468, 0x00200D, 0x01F466, 0,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#ifdef V8_INTL_SUPPORT
|
#ifdef V8_INTL_SUPPORT
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -14,9 +15,9 @@ namespace internal {
|
|||||||
|
|
||||||
class UnicodePropertySequences : public AllStatic {
|
class UnicodePropertySequences : public AllStatic {
|
||||||
public:
|
public:
|
||||||
static const uc32 kEmojiFlagSequences[];
|
static const base::uc32 kEmojiFlagSequences[];
|
||||||
static const uc32 kEmojiTagSequences[];
|
static const base::uc32 kEmojiTagSequences[];
|
||||||
static const uc32 kEmojiZWJSequences[];
|
static const base::uc32 kEmojiZWJSequences[];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -219,7 +219,7 @@ void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
|
|||||||
|
|
||||||
void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
|
void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
|
||||||
os_ << "'";
|
os_ << "'";
|
||||||
base::Vector<const uc16> chardata = that->data();
|
base::Vector<const base::uc16> chardata = that->data();
|
||||||
for (int i = 0; i < chardata.length(); i++) {
|
for (int i = 0; i < chardata.length(); i++) {
|
||||||
os_ << AsUC16(chardata[i]);
|
os_ << AsUC16(chardata[i]);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_REGEXP_AST_H_
|
#ifndef V8_REGEXP_REGEXP_AST_H_
|
||||||
#define V8_REGEXP_REGEXP_AST_H_
|
#define V8_REGEXP_REGEXP_AST_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/objects/js-regexp.h"
|
#include "src/objects/js-regexp.h"
|
||||||
#include "src/objects/objects.h"
|
#include "src/objects/objects.h"
|
||||||
#include "src/objects/string.h"
|
#include "src/objects/string.h"
|
||||||
@ -92,10 +93,10 @@ class CharacterRange {
|
|||||||
char type, ZoneList<CharacterRange>* ranges,
|
char type, ZoneList<CharacterRange>* ranges,
|
||||||
bool add_unicode_case_equivalents, Zone* zone);
|
bool add_unicode_case_equivalents, Zone* zone);
|
||||||
static base::Vector<const int> GetWordBounds();
|
static base::Vector<const int> GetWordBounds();
|
||||||
static inline CharacterRange Singleton(uc32 value) {
|
static inline CharacterRange Singleton(base::uc32 value) {
|
||||||
return CharacterRange(value, value);
|
return CharacterRange(value, value);
|
||||||
}
|
}
|
||||||
static inline CharacterRange Range(uc32 from, uc32 to) {
|
static inline CharacterRange Range(base::uc32 from, base::uc32 to) {
|
||||||
DCHECK(0 <= from && to <= String::kMaxCodePoint);
|
DCHECK(0 <= from && to <= String::kMaxCodePoint);
|
||||||
DCHECK(static_cast<uint32_t>(from) <= static_cast<uint32_t>(to));
|
DCHECK(static_cast<uint32_t>(from) <= static_cast<uint32_t>(to));
|
||||||
return CharacterRange(from, to);
|
return CharacterRange(from, to);
|
||||||
@ -110,13 +111,13 @@ class CharacterRange {
|
|||||||
list->Add(range, zone);
|
list->Add(range, zone);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
bool Contains(uc32 i) { return from_ <= i && i <= to_; }
|
bool Contains(base::uc32 i) { return from_ <= i && i <= to_; }
|
||||||
uc32 from() const { return from_; }
|
base::uc32 from() const { return from_; }
|
||||||
void set_from(uc32 value) { from_ = value; }
|
void set_from(base::uc32 value) { from_ = value; }
|
||||||
uc32 to() const { return to_; }
|
base::uc32 to() const { return to_; }
|
||||||
void set_to(uc32 value) { to_ = value; }
|
void set_to(base::uc32 value) { to_ = value; }
|
||||||
bool is_valid() { return from_ <= to_; }
|
bool is_valid() { return from_ <= to_; }
|
||||||
bool IsEverything(uc32 max) { return from_ == 0 && to_ >= max; }
|
bool IsEverything(base::uc32 max) { return from_ == 0 && to_ >= max; }
|
||||||
bool IsSingleton() { return (from_ == to_); }
|
bool IsSingleton() { return (from_ == to_); }
|
||||||
V8_EXPORT_PRIVATE static void AddCaseEquivalents(
|
V8_EXPORT_PRIVATE static void AddCaseEquivalents(
|
||||||
Isolate* isolate, Zone* zone, ZoneList<CharacterRange>* ranges,
|
Isolate* isolate, Zone* zone, ZoneList<CharacterRange>* ranges,
|
||||||
@ -136,21 +137,21 @@ class CharacterRange {
|
|||||||
static const int kPayloadMask = (1 << 24) - 1;
|
static const int kPayloadMask = (1 << 24) - 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CharacterRange(uc32 from, uc32 to) : from_(from), to_(to) {}
|
CharacterRange(base::uc32 from, base::uc32 to) : from_(from), to_(to) {}
|
||||||
|
|
||||||
uc32 from_;
|
base::uc32 from_;
|
||||||
uc32 to_;
|
base::uc32 to_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CharacterSet final {
|
class CharacterSet final {
|
||||||
public:
|
public:
|
||||||
explicit CharacterSet(uc16 standard_set_type)
|
explicit CharacterSet(base::uc16 standard_set_type)
|
||||||
: ranges_(nullptr), standard_set_type_(standard_set_type) {}
|
: ranges_(nullptr), standard_set_type_(standard_set_type) {}
|
||||||
explicit CharacterSet(ZoneList<CharacterRange>* ranges)
|
explicit CharacterSet(ZoneList<CharacterRange>* ranges)
|
||||||
: ranges_(ranges), standard_set_type_(0) {}
|
: ranges_(ranges), standard_set_type_(0) {}
|
||||||
ZoneList<CharacterRange>* ranges(Zone* zone);
|
ZoneList<CharacterRange>* ranges(Zone* zone);
|
||||||
uc16 standard_set_type() const { return standard_set_type_; }
|
base::uc16 standard_set_type() const { return standard_set_type_; }
|
||||||
void set_standard_set_type(uc16 special_set_type) {
|
void set_standard_set_type(base::uc16 special_set_type) {
|
||||||
standard_set_type_ = special_set_type;
|
standard_set_type_ = special_set_type;
|
||||||
}
|
}
|
||||||
bool is_standard() { return standard_set_type_ != 0; }
|
bool is_standard() { return standard_set_type_ != 0; }
|
||||||
@ -160,7 +161,7 @@ class CharacterSet final {
|
|||||||
ZoneList<CharacterRange>* ranges_;
|
ZoneList<CharacterRange>* ranges_;
|
||||||
// If non-zero, the value represents a standard set (e.g., all whitespace
|
// If non-zero, the value represents a standard set (e.g., all whitespace
|
||||||
// characters) without having to expand the ranges.
|
// characters) without having to expand the ranges.
|
||||||
uc16 standard_set_type_;
|
base::uc16 standard_set_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextElement final {
|
class TextElement final {
|
||||||
@ -322,7 +323,7 @@ class RegExpCharacterClass final : public RegExpTree {
|
|||||||
character_class_flags_ ^= NEGATED;
|
character_class_flags_ ^= NEGATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegExpCharacterClass(uc16 type, JSRegExp::Flags flags)
|
RegExpCharacterClass(base::uc16 type, JSRegExp::Flags flags)
|
||||||
: set_(type),
|
: set_(type),
|
||||||
flags_(flags),
|
flags_(flags),
|
||||||
character_class_flags_(CharacterClassFlags()) {}
|
character_class_flags_(CharacterClassFlags()) {}
|
||||||
@ -352,7 +353,7 @@ class RegExpCharacterClass final : public RegExpTree {
|
|||||||
// D : non-ASCII digit
|
// D : non-ASCII digit
|
||||||
// . : non-newline
|
// . : non-newline
|
||||||
// * : All characters, for advancing unanchored regexp
|
// * : All characters, for advancing unanchored regexp
|
||||||
uc16 standard_type() const { return set_.standard_set_type(); }
|
base::uc16 standard_type() const { return set_.standard_set_type(); }
|
||||||
ZoneList<CharacterRange>* ranges(Zone* zone) { return set_.ranges(zone); }
|
ZoneList<CharacterRange>* ranges(Zone* zone) { return set_.ranges(zone); }
|
||||||
bool is_negated() const { return (character_class_flags_ & NEGATED) != 0; }
|
bool is_negated() const { return (character_class_flags_ & NEGATED) != 0; }
|
||||||
JSRegExp::Flags flags() const { return flags_; }
|
JSRegExp::Flags flags() const { return flags_; }
|
||||||
@ -369,7 +370,8 @@ class RegExpCharacterClass final : public RegExpTree {
|
|||||||
|
|
||||||
class RegExpAtom final : public RegExpTree {
|
class RegExpAtom final : public RegExpTree {
|
||||||
public:
|
public:
|
||||||
explicit RegExpAtom(base::Vector<const uc16> data, JSRegExp::Flags flags)
|
explicit RegExpAtom(base::Vector<const base::uc16> data,
|
||||||
|
JSRegExp::Flags flags)
|
||||||
: data_(data), flags_(flags) {}
|
: data_(data), flags_(flags) {}
|
||||||
void* Accept(RegExpVisitor* visitor, void* data) override;
|
void* Accept(RegExpVisitor* visitor, void* data) override;
|
||||||
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
|
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
|
||||||
@ -379,13 +381,13 @@ class RegExpAtom final : public RegExpTree {
|
|||||||
int min_match() override { return data_.length(); }
|
int min_match() override { return data_.length(); }
|
||||||
int max_match() override { return data_.length(); }
|
int max_match() override { return data_.length(); }
|
||||||
void AppendToText(RegExpText* text, Zone* zone) override;
|
void AppendToText(RegExpText* text, Zone* zone) override;
|
||||||
base::Vector<const uc16> data() { return data_; }
|
base::Vector<const base::uc16> data() { return data_; }
|
||||||
int length() { return data_.length(); }
|
int length() { return data_.length(); }
|
||||||
JSRegExp::Flags flags() const { return flags_; }
|
JSRegExp::Flags flags() const { return flags_; }
|
||||||
bool ignore_case() const { return (flags_ & JSRegExp::kIgnoreCase) != 0; }
|
bool ignore_case() const { return (flags_ & JSRegExp::kIgnoreCase) != 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::Vector<const uc16> data_;
|
base::Vector<const base::uc16> data_;
|
||||||
const JSRegExp::Flags flags_;
|
const JSRegExp::Flags flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -486,8 +488,8 @@ class RegExpCapture final : public RegExpTree {
|
|||||||
max_match_ = body->max_match();
|
max_match_ = body->max_match();
|
||||||
}
|
}
|
||||||
int index() const { return index_; }
|
int index() const { return index_; }
|
||||||
const ZoneVector<uc16>* name() const { return name_; }
|
const ZoneVector<base::uc16>* name() const { return name_; }
|
||||||
void set_name(const ZoneVector<uc16>* name) { name_ = name; }
|
void set_name(const ZoneVector<base::uc16>* name) { name_ = name; }
|
||||||
static int StartRegister(int index) { return index * 2; }
|
static int StartRegister(int index) { return index * 2; }
|
||||||
static int EndRegister(int index) { return index * 2 + 1; }
|
static int EndRegister(int index) { return index * 2 + 1; }
|
||||||
|
|
||||||
@ -496,7 +498,7 @@ class RegExpCapture final : public RegExpTree {
|
|||||||
int index_;
|
int index_;
|
||||||
int min_match_;
|
int min_match_;
|
||||||
int max_match_;
|
int max_match_;
|
||||||
const ZoneVector<uc16>* name_;
|
const ZoneVector<base::uc16>* name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegExpGroup final : public RegExpTree {
|
class RegExpGroup final : public RegExpTree {
|
||||||
@ -593,12 +595,12 @@ class RegExpBackReference final : public RegExpTree {
|
|||||||
int index() { return capture_->index(); }
|
int index() { return capture_->index(); }
|
||||||
RegExpCapture* capture() { return capture_; }
|
RegExpCapture* capture() { return capture_; }
|
||||||
void set_capture(RegExpCapture* capture) { capture_ = capture; }
|
void set_capture(RegExpCapture* capture) { capture_ = capture; }
|
||||||
const ZoneVector<uc16>* name() const { return name_; }
|
const ZoneVector<base::uc16>* name() const { return name_; }
|
||||||
void set_name(const ZoneVector<uc16>* name) { name_ = name; }
|
void set_name(const ZoneVector<base::uc16>* name) { name_ = name; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RegExpCapture* capture_;
|
RegExpCapture* capture_;
|
||||||
const ZoneVector<uc16>* name_;
|
const ZoneVector<base::uc16>* name_;
|
||||||
const JSRegExp::Flags flags_;
|
const JSRegExp::Flags flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -220,12 +220,14 @@ void RegExpBytecodeGenerator::LoadCurrentCharacterImpl(int cp_offset,
|
|||||||
if (check_bounds) EmitOrLink(on_failure);
|
if (check_bounds) EmitOrLink(on_failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegExpBytecodeGenerator::CheckCharacterLT(uc16 limit, Label* on_less) {
|
void RegExpBytecodeGenerator::CheckCharacterLT(base::uc16 limit,
|
||||||
|
Label* on_less) {
|
||||||
Emit(BC_CHECK_LT, limit);
|
Emit(BC_CHECK_LT, limit);
|
||||||
EmitOrLink(on_less);
|
EmitOrLink(on_less);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegExpBytecodeGenerator::CheckCharacterGT(uc16 limit, Label* on_greater) {
|
void RegExpBytecodeGenerator::CheckCharacterGT(base::uc16 limit,
|
||||||
|
Label* on_greater) {
|
||||||
Emit(BC_CHECK_GT, limit);
|
Emit(BC_CHECK_GT, limit);
|
||||||
EmitOrLink(on_greater);
|
EmitOrLink(on_greater);
|
||||||
}
|
}
|
||||||
@ -288,14 +290,15 @@ void RegExpBytecodeGenerator::CheckNotCharacterAfterAnd(uint32_t c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RegExpBytecodeGenerator::CheckNotCharacterAfterMinusAnd(
|
void RegExpBytecodeGenerator::CheckNotCharacterAfterMinusAnd(
|
||||||
uc16 c, uc16 minus, uc16 mask, Label* on_not_equal) {
|
base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
|
||||||
Emit(BC_MINUS_AND_CHECK_NOT_CHAR, c);
|
Emit(BC_MINUS_AND_CHECK_NOT_CHAR, c);
|
||||||
Emit16(minus);
|
Emit16(minus);
|
||||||
Emit16(mask);
|
Emit16(mask);
|
||||||
EmitOrLink(on_not_equal);
|
EmitOrLink(on_not_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegExpBytecodeGenerator::CheckCharacterInRange(uc16 from, uc16 to,
|
void RegExpBytecodeGenerator::CheckCharacterInRange(base::uc16 from,
|
||||||
|
base::uc16 to,
|
||||||
Label* on_in_range) {
|
Label* on_in_range) {
|
||||||
Emit(BC_CHECK_CHAR_IN_RANGE, 0);
|
Emit(BC_CHECK_CHAR_IN_RANGE, 0);
|
||||||
Emit16(from);
|
Emit16(from);
|
||||||
@ -303,7 +306,8 @@ void RegExpBytecodeGenerator::CheckCharacterInRange(uc16 from, uc16 to,
|
|||||||
EmitOrLink(on_in_range);
|
EmitOrLink(on_in_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegExpBytecodeGenerator::CheckCharacterNotInRange(uc16 from, uc16 to,
|
void RegExpBytecodeGenerator::CheckCharacterNotInRange(base::uc16 from,
|
||||||
|
base::uc16 to,
|
||||||
Label* on_not_in_range) {
|
Label* on_not_in_range) {
|
||||||
Emit(BC_CHECK_CHAR_NOT_IN_RANGE, 0);
|
Emit(BC_CHECK_CHAR_NOT_IN_RANGE, 0);
|
||||||
Emit16(from);
|
Emit16(from);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef V8_REGEXP_REGEXP_BYTECODE_GENERATOR_H_
|
#ifndef V8_REGEXP_REGEXP_BYTECODE_GENERATOR_H_
|
||||||
#define V8_REGEXP_REGEXP_BYTECODE_GENERATOR_H_
|
#define V8_REGEXP_REGEXP_BYTECODE_GENERATOR_H_
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/regexp/regexp-macro-assembler.h"
|
#include "src/regexp/regexp-macro-assembler.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -52,18 +53,20 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGenerator : public RegExpMacroAssembler {
|
|||||||
void CheckCharacter(unsigned c, Label* on_equal) override;
|
void CheckCharacter(unsigned c, Label* on_equal) override;
|
||||||
void CheckCharacterAfterAnd(unsigned c, unsigned mask,
|
void CheckCharacterAfterAnd(unsigned c, unsigned mask,
|
||||||
Label* on_equal) override;
|
Label* on_equal) override;
|
||||||
void CheckCharacterGT(uc16 limit, Label* on_greater) override;
|
void CheckCharacterGT(base::uc16 limit, Label* on_greater) override;
|
||||||
void CheckCharacterLT(uc16 limit, Label* on_less) override;
|
void CheckCharacterLT(base::uc16 limit, Label* on_less) override;
|
||||||
void CheckGreedyLoop(Label* on_tos_equals_current_position) override;
|
void CheckGreedyLoop(Label* on_tos_equals_current_position) override;
|
||||||
void CheckAtStart(int cp_offset, Label* on_at_start) override;
|
void CheckAtStart(int cp_offset, Label* on_at_start) override;
|
||||||
void CheckNotAtStart(int cp_offset, Label* on_not_at_start) override;
|
void CheckNotAtStart(int cp_offset, Label* on_not_at_start) override;
|
||||||
void CheckNotCharacter(unsigned c, Label* on_not_equal) override;
|
void CheckNotCharacter(unsigned c, Label* on_not_equal) override;
|
||||||
void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
|
void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
|
||||||
Label* on_not_equal) override;
|
Label* on_not_equal) override;
|
||||||
void CheckNotCharacterAfterMinusAnd(uc16 c, uc16 minus, uc16 mask,
|
void CheckNotCharacterAfterMinusAnd(base::uc16 c, base::uc16 minus,
|
||||||
|
base::uc16 mask,
|
||||||
Label* on_not_equal) override;
|
Label* on_not_equal) override;
|
||||||
void CheckCharacterInRange(uc16 from, uc16 to, Label* on_in_range) override;
|
void CheckCharacterInRange(base::uc16 from, base::uc16 to,
|
||||||
void CheckCharacterNotInRange(uc16 from, uc16 to,
|
Label* on_in_range) override;
|
||||||
|
void CheckCharacterNotInRange(base::uc16 from, base::uc16 to,
|
||||||
Label* on_not_in_range) override;
|
Label* on_not_in_range) override;
|
||||||
void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set) override;
|
void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set) override;
|
||||||
void CheckNotBackReference(int start_reg, bool read_backward,
|
void CheckNotBackReference(int start_reg, bool read_backward,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "src/base/bounds.h"
|
#include "src/base/bounds.h"
|
||||||
#include "src/base/macros.h"
|
#include "src/base/macros.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/common/globals.h"
|
#include "src/common/globals.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -87,12 +88,14 @@ STATIC_ASSERT(1 << BYTECODE_SHIFT > BYTECODE_MASK);
|
|||||||
/* 0x10 - 0x1F: Character to match against (after mask aplied) */ \
|
/* 0x10 - 0x1F: Character to match against (after mask aplied) */ \
|
||||||
/* 0x20 - 0x3F: Bitmask bitwise and combined with current character */ \
|
/* 0x20 - 0x3F: Bitmask bitwise and combined with current character */ \
|
||||||
/* 0x40 - 0x5F: Address of bytecode when matched */ \
|
/* 0x40 - 0x5F: Address of bytecode when matched */ \
|
||||||
V(AND_CHECK_CHAR, 28, 12) /* bc8 pad8 uint16 uint32 addr32 */ \
|
V(AND_CHECK_CHAR, 28, 12) /* bc8 pad8 uint16 uint32 addr32 */ \
|
||||||
V(AND_CHECK_NOT_4_CHARS, 29, 16) /* bc8 pad24 uint32 uint32 addr32 */ \
|
V(AND_CHECK_NOT_4_CHARS, 29, 16) /* bc8 pad24 uint32 uint32 addr32 */ \
|
||||||
V(AND_CHECK_NOT_CHAR, 30, 12) /* bc8 pad8 uint16 uint32 addr32 */ \
|
V(AND_CHECK_NOT_CHAR, 30, 12) /* bc8 pad8 uint16 uint32 addr32 */ \
|
||||||
V(MINUS_AND_CHECK_NOT_CHAR, 31, 12) /* bc8 pad8 uc16 uc16 uc16 addr32 */ \
|
V(MINUS_AND_CHECK_NOT_CHAR, 31, \
|
||||||
V(CHECK_CHAR_IN_RANGE, 32, 12) /* bc8 pad24 uc16 uc16 addr32 */ \
|
12) /* bc8 pad8 base::uc16 base::uc16 base::uc16 addr32 */ \
|
||||||
V(CHECK_CHAR_NOT_IN_RANGE, 33, 12) /* bc8 pad24 uc16 uc16 addr32 */ \
|
V(CHECK_CHAR_IN_RANGE, 32, 12) /* bc8 pad24 base::uc16 base::uc16 addr32 */ \
|
||||||
|
V(CHECK_CHAR_NOT_IN_RANGE, 33, \
|
||||||
|
12) /* bc8 pad24 base::uc16 base::uc16 addr32 */ \
|
||||||
/* Checks if the current character matches any of the characters encoded */ \
|
/* Checks if the current character matches any of the characters encoded */ \
|
||||||
/* in a bit table. Similar to/inspired by boyer moore string search */ \
|
/* in a bit table. Similar to/inspired by boyer moore string search */ \
|
||||||
/* Bit Layout: */ \
|
/* Bit Layout: */ \
|
||||||
@ -101,8 +104,8 @@ STATIC_ASSERT(1 << BYTECODE_SHIFT > BYTECODE_MASK);
|
|||||||
/* 0x20 - 0x3F: Address of bytecode when bit is set */ \
|
/* 0x20 - 0x3F: Address of bytecode when bit is set */ \
|
||||||
/* 0x40 - 0xBF: Bit table */ \
|
/* 0x40 - 0xBF: Bit table */ \
|
||||||
V(CHECK_BIT_IN_TABLE, 34, 24) /* bc8 pad24 addr32 bits128 */ \
|
V(CHECK_BIT_IN_TABLE, 34, 24) /* bc8 pad24 addr32 bits128 */ \
|
||||||
V(CHECK_LT, 35, 8) /* bc8 pad8 uc16 addr32 */ \
|
V(CHECK_LT, 35, 8) /* bc8 pad8 base::uc16 addr32 */ \
|
||||||
V(CHECK_GT, 36, 8) /* bc8 pad8 uc16 addr32 */ \
|
V(CHECK_GT, 36, 8) /* bc8 pad8 base::uc16 addr32 */ \
|
||||||
V(CHECK_NOT_BACK_REF, 37, 8) /* bc8 reg_idx24 addr32 */ \
|
V(CHECK_NOT_BACK_REF, 37, 8) /* bc8 reg_idx24 addr32 */ \
|
||||||
V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32 */ \
|
V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32 */ \
|
||||||
V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 39, 8) \
|
V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 39, 8) \
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "src/zone/zone-list-inl.h"
|
#include "src/zone/zone-list-inl.h"
|
||||||
|
|
||||||
#ifdef V8_INTL_SUPPORT
|
#ifdef V8_INTL_SUPPORT
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "unicode/locid.h"
|
#include "unicode/locid.h"
|
||||||
#include "unicode/uniset.h"
|
#include "unicode/uniset.h"
|
||||||
#include "unicode/utypes.h"
|
#include "unicode/utypes.h"
|
||||||
@ -56,11 +57,11 @@ static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < length; i += 2) {
|
for (int i = 0; i < length; i += 2) {
|
||||||
if (static_cast<uc32>(special_class[i]) != (range.to() + 1)) {
|
if (static_cast<base::uc32>(special_class[i]) != (range.to() + 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
range = ranges->at((i >> 1) + 1);
|
range = ranges->at((i >> 1) + 1);
|
||||||
if (static_cast<uc32>(special_class[i + 1]) != range.from()) {
|
if (static_cast<base::uc32>(special_class[i + 1]) != range.from()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,8 +80,8 @@ static bool CompareRanges(ZoneList<CharacterRange>* ranges,
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < length; i += 2) {
|
for (int i = 0; i < length; i += 2) {
|
||||||
CharacterRange range = ranges->at(i >> 1);
|
CharacterRange range = ranges->at(i >> 1);
|
||||||
if (range.from() != static_cast<uc32>(special_class[i]) ||
|
if (range.from() != static_cast<base::uc32>(special_class[i]) ||
|
||||||
range.to() != static_cast<uc32>(special_class[i + 1] - 1)) {
|
range.to() != static_cast<base::uc32>(special_class[i + 1] - 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,10 +139,10 @@ UnicodeRangeSplitter::UnicodeRangeSplitter(ZoneList<CharacterRange>* base) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UnicodeRangeSplitter::AddRange(CharacterRange range) {
|
void UnicodeRangeSplitter::AddRange(CharacterRange range) {
|
||||||
static constexpr uc32 kBmp1Start = 0;
|
static constexpr base::uc32 kBmp1Start = 0;
|
||||||
static constexpr uc32 kBmp1End = kLeadSurrogateStart - 1;
|
static constexpr base::uc32 kBmp1End = kLeadSurrogateStart - 1;
|
||||||
static constexpr uc32 kBmp2Start = kTrailSurrogateEnd + 1;
|
static constexpr base::uc32 kBmp2Start = kTrailSurrogateEnd + 1;
|
||||||
static constexpr uc32 kBmp2End = kNonBmpStart - 1;
|
static constexpr base::uc32 kBmp2End = kNonBmpStart - 1;
|
||||||
|
|
||||||
// Ends are all inclusive.
|
// Ends are all inclusive.
|
||||||
STATIC_ASSERT(kBmp1Start == 0);
|
STATIC_ASSERT(kBmp1Start == 0);
|
||||||
@ -155,12 +156,12 @@ void UnicodeRangeSplitter::AddRange(CharacterRange range) {
|
|||||||
STATIC_ASSERT(kBmp2End + 1 == kNonBmpStart);
|
STATIC_ASSERT(kBmp2End + 1 == kNonBmpStart);
|
||||||
STATIC_ASSERT(kNonBmpStart < kNonBmpEnd);
|
STATIC_ASSERT(kNonBmpStart < kNonBmpEnd);
|
||||||
|
|
||||||
static constexpr uc32 kStarts[] = {
|
static constexpr base::uc32 kStarts[] = {
|
||||||
kBmp1Start, kLeadSurrogateStart, kTrailSurrogateStart,
|
kBmp1Start, kLeadSurrogateStart, kTrailSurrogateStart,
|
||||||
kBmp2Start, kNonBmpStart,
|
kBmp2Start, kNonBmpStart,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uc32 kEnds[] = {
|
static constexpr base::uc32 kEnds[] = {
|
||||||
kBmp1End, kLeadSurrogateEnd, kTrailSurrogateEnd, kBmp2End, kNonBmpEnd,
|
kBmp1End, kLeadSurrogateEnd, kTrailSurrogateEnd, kBmp2End, kNonBmpEnd,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,8 +175,8 @@ void UnicodeRangeSplitter::AddRange(CharacterRange range) {
|
|||||||
|
|
||||||
for (int i = 0; i < kCount; i++) {
|
for (int i = 0; i < kCount; i++) {
|
||||||
if (kStarts[i] > range.to()) break;
|
if (kStarts[i] > range.to()) break;
|
||||||
const uc32 from = std::max(kStarts[i], range.from());
|
const base::uc32 from = std::max(kStarts[i], range.from());
|
||||||
const uc32 to = std::min(kEnds[i], range.to());
|
const base::uc32 to = std::min(kEnds[i], range.to());
|
||||||
if (from > to) continue;
|
if (from > to) continue;
|
||||||
kTargets[i]->emplace_back(CharacterRange::Range(from, to));
|
kTargets[i]->emplace_back(CharacterRange::Range(from, to));
|
||||||
}
|
}
|
||||||
@ -224,12 +225,12 @@ void AddNonBmpSurrogatePairs(RegExpCompiler* compiler, ChoiceNode* result,
|
|||||||
// \ud800[\udc05-\udfff]|
|
// \ud800[\udc05-\udfff]|
|
||||||
// [\ud801-\ud803][\udc00-\udfff]|
|
// [\ud801-\ud803][\udc00-\udfff]|
|
||||||
// \ud804[\udc00-\udc05]
|
// \ud804[\udc00-\udc05]
|
||||||
uc32 from = non_bmp->at(i).from();
|
base::uc32 from = non_bmp->at(i).from();
|
||||||
uc32 to = non_bmp->at(i).to();
|
base::uc32 to = non_bmp->at(i).to();
|
||||||
uc16 from_l = unibrow::Utf16::LeadSurrogate(from);
|
base::uc16 from_l = unibrow::Utf16::LeadSurrogate(from);
|
||||||
uc16 from_t = unibrow::Utf16::TrailSurrogate(from);
|
base::uc16 from_t = unibrow::Utf16::TrailSurrogate(from);
|
||||||
uc16 to_l = unibrow::Utf16::LeadSurrogate(to);
|
base::uc16 to_l = unibrow::Utf16::LeadSurrogate(to);
|
||||||
uc16 to_t = unibrow::Utf16::TrailSurrogate(to);
|
base::uc16 to_t = unibrow::Utf16::TrailSurrogate(to);
|
||||||
if (from_l == to_l) {
|
if (from_l == to_l) {
|
||||||
// The lead surrogate is the same.
|
// The lead surrogate is the same.
|
||||||
result->AddAlternative(
|
result->AddAlternative(
|
||||||
@ -447,8 +448,8 @@ RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
|
|||||||
int CompareFirstChar(RegExpTree* const* a, RegExpTree* const* b) {
|
int CompareFirstChar(RegExpTree* const* a, RegExpTree* const* b) {
|
||||||
RegExpAtom* atom1 = (*a)->AsAtom();
|
RegExpAtom* atom1 = (*a)->AsAtom();
|
||||||
RegExpAtom* atom2 = (*b)->AsAtom();
|
RegExpAtom* atom2 = (*b)->AsAtom();
|
||||||
uc16 character1 = atom1->data().at(0);
|
base::uc16 character1 = atom1->data().at(0);
|
||||||
uc16 character2 = atom2->data().at(0);
|
base::uc16 character2 = atom2->data().at(0);
|
||||||
if (character1 < character2) return -1;
|
if (character1 < character2) return -1;
|
||||||
if (character1 > character2) return 1;
|
if (character1 > character2) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1060,7 +1061,7 @@ static void AddClassNegated(const int* elmv, int elmc,
|
|||||||
DCHECK_EQ(kRangeEndMarker, elmv[elmc]);
|
DCHECK_EQ(kRangeEndMarker, elmv[elmc]);
|
||||||
DCHECK_NE(0x0000, elmv[0]);
|
DCHECK_NE(0x0000, elmv[0]);
|
||||||
DCHECK_NE(String::kMaxCodePoint, elmv[elmc - 1]);
|
DCHECK_NE(String::kMaxCodePoint, elmv[elmc - 1]);
|
||||||
uc16 last = 0x0000;
|
base::uc16 last = 0x0000;
|
||||||
for (int i = 0; i < elmc; i += 2) {
|
for (int i = 0; i < elmc; i += 2) {
|
||||||
DCHECK(last <= elmv[i] - 1);
|
DCHECK(last <= elmv[i] - 1);
|
||||||
DCHECK(elmv[i] < elmv[i + 1]);
|
DCHECK(elmv[i] < elmv[i + 1]);
|
||||||
@ -1148,9 +1149,9 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
|
|||||||
icu::UnicodeSet others;
|
icu::UnicodeSet others;
|
||||||
for (int i = 0; i < range_count; i++) {
|
for (int i = 0; i < range_count; i++) {
|
||||||
CharacterRange range = ranges->at(i);
|
CharacterRange range = ranges->at(i);
|
||||||
uc32 from = range.from();
|
base::uc32 from = range.from();
|
||||||
if (from > String::kMaxUtf16CodeUnit) continue;
|
if (from > String::kMaxUtf16CodeUnit) continue;
|
||||||
uc32 to = std::min({range.to(), String::kMaxUtf16CodeUnitU});
|
base::uc32 to = std::min({range.to(), String::kMaxUtf16CodeUnitU});
|
||||||
// Nothing to be done for surrogates.
|
// Nothing to be done for surrogates.
|
||||||
if (from >= kLeadSurrogateStart && to <= kTrailSurrogateEnd) continue;
|
if (from >= kLeadSurrogateStart && to <= kTrailSurrogateEnd) continue;
|
||||||
if (is_one_byte && !RangeContainsLatin1Equivalents(range)) {
|
if (is_one_byte && !RangeContainsLatin1Equivalents(range)) {
|
||||||
@ -1191,9 +1192,9 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
|
|||||||
#else
|
#else
|
||||||
for (int i = 0; i < range_count; i++) {
|
for (int i = 0; i < range_count; i++) {
|
||||||
CharacterRange range = ranges->at(i);
|
CharacterRange range = ranges->at(i);
|
||||||
uc32 bottom = range.from();
|
base::uc32 bottom = range.from();
|
||||||
if (bottom > String::kMaxUtf16CodeUnit) continue;
|
if (bottom > String::kMaxUtf16CodeUnit) continue;
|
||||||
uc32 top = std::min({range.to(), String::kMaxUtf16CodeUnitU});
|
base::uc32 top = std::min({range.to(), String::kMaxUtf16CodeUnitU});
|
||||||
// Nothing to be done for surrogates.
|
// Nothing to be done for surrogates.
|
||||||
if (bottom >= kLeadSurrogateStart && top <= kTrailSurrogateEnd) continue;
|
if (bottom >= kLeadSurrogateStart && top <= kTrailSurrogateEnd) continue;
|
||||||
if (is_one_byte && !RangeContainsLatin1Equivalents(range)) {
|
if (is_one_byte && !RangeContainsLatin1Equivalents(range)) {
|
||||||
@ -1205,7 +1206,7 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
|
|||||||
// If this is a singleton we just expand the one character.
|
// If this is a singleton we just expand the one character.
|
||||||
int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars);
|
int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars);
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
uc32 chr = chars[i];
|
base::uc32 chr = chars[i];
|
||||||
if (chr != bottom) {
|
if (chr != bottom) {
|
||||||
ranges->Add(CharacterRange::Singleton(chars[i]), zone);
|
ranges->Add(CharacterRange::Singleton(chars[i]), zone);
|
||||||
}
|
}
|
||||||
@ -1228,11 +1229,11 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
|
|||||||
// block we do this for all the blocks covered by the range (handling
|
// block we do this for all the blocks covered by the range (handling
|
||||||
// characters that is not in a block as a "singleton block").
|
// characters that is not in a block as a "singleton block").
|
||||||
unibrow::uchar equivalents[unibrow::Ecma262UnCanonicalize::kMaxWidth];
|
unibrow::uchar equivalents[unibrow::Ecma262UnCanonicalize::kMaxWidth];
|
||||||
uc32 pos = bottom;
|
base::uc32 pos = bottom;
|
||||||
while (pos <= top) {
|
while (pos <= top) {
|
||||||
int length =
|
int length =
|
||||||
isolate->jsregexp_canonrange()->get(pos, '\0', equivalents);
|
isolate->jsregexp_canonrange()->get(pos, '\0', equivalents);
|
||||||
uc32 block_end;
|
base::uc32 block_end;
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
block_end = pos;
|
block_end = pos;
|
||||||
} else {
|
} else {
|
||||||
@ -1243,9 +1244,9 @@ void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
|
|||||||
length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0',
|
length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0',
|
||||||
equivalents);
|
equivalents);
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
uc32 c = equivalents[i];
|
base::uc32 c = equivalents[i];
|
||||||
uc32 range_from = c - (block_end - pos);
|
base::uc32 range_from = c - (block_end - pos);
|
||||||
uc32 range_to = c - (block_end - end);
|
base::uc32 range_to = c - (block_end - end);
|
||||||
if (!(bottom <= range_from && range_to <= top)) {
|
if (!(bottom <= range_from && range_to <= top)) {
|
||||||
ranges->Add(CharacterRange::Range(range_from, range_to), zone);
|
ranges->Add(CharacterRange::Range(range_from, range_to), zone);
|
||||||
}
|
}
|
||||||
@ -1261,7 +1262,7 @@ bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) {
|
|||||||
DCHECK_NOT_NULL(ranges);
|
DCHECK_NOT_NULL(ranges);
|
||||||
int n = ranges->length();
|
int n = ranges->length();
|
||||||
if (n <= 1) return true;
|
if (n <= 1) return true;
|
||||||
uc32 max = ranges->at(0).to();
|
base::uc32 max = ranges->at(0).to();
|
||||||
for (int i = 1; i < n; i++) {
|
for (int i = 1; i < n; i++) {
|
||||||
CharacterRange next_range = ranges->at(i);
|
CharacterRange next_range = ranges->at(i);
|
||||||
if (next_range.from() <= max + 1) return false;
|
if (next_range.from() <= max + 1) return false;
|
||||||
@ -1301,8 +1302,8 @@ static int InsertRangeInCanonicalList(ZoneList<CharacterRange>* list, int count,
|
|||||||
// list[0..count] for the result. Returns the number of resulting
|
// list[0..count] for the result. Returns the number of resulting
|
||||||
// canonicalized ranges. Inserting a range may collapse existing ranges into
|
// canonicalized ranges. Inserting a range may collapse existing ranges into
|
||||||
// fewer ranges, so the return value can be anything in the range 1..count+1.
|
// fewer ranges, so the return value can be anything in the range 1..count+1.
|
||||||
uc32 from = insert.from();
|
base::uc32 from = insert.from();
|
||||||
uc32 to = insert.to();
|
base::uc32 to = insert.to();
|
||||||
int start_pos = 0;
|
int start_pos = 0;
|
||||||
int end_pos = count;
|
int end_pos = count;
|
||||||
for (int i = count - 1; i >= 0; i--) {
|
for (int i = count - 1; i >= 0; i--) {
|
||||||
@ -1362,7 +1363,7 @@ void CharacterRange::Canonicalize(ZoneList<CharacterRange>* character_ranges) {
|
|||||||
// Check whether ranges are already canonical (increasing, non-overlapping,
|
// Check whether ranges are already canonical (increasing, non-overlapping,
|
||||||
// non-adjacent).
|
// non-adjacent).
|
||||||
int n = character_ranges->length();
|
int n = character_ranges->length();
|
||||||
uc32 max = character_ranges->at(0).to();
|
base::uc32 max = character_ranges->at(0).to();
|
||||||
int i = 1;
|
int i = 1;
|
||||||
while (i < n) {
|
while (i < n) {
|
||||||
CharacterRange current = character_ranges->at(i);
|
CharacterRange current = character_ranges->at(i);
|
||||||
@ -1398,7 +1399,7 @@ void CharacterRange::Negate(ZoneList<CharacterRange>* ranges,
|
|||||||
DCHECK(CharacterRange::IsCanonical(ranges));
|
DCHECK(CharacterRange::IsCanonical(ranges));
|
||||||
DCHECK_EQ(0, negated_ranges->length());
|
DCHECK_EQ(0, negated_ranges->length());
|
||||||
int range_count = ranges->length();
|
int range_count = ranges->length();
|
||||||
uc32 from = 0;
|
base::uc32 from = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (range_count > 0 && ranges->at(0).from() == 0) {
|
if (range_count > 0 && ranges->at(0).from() == 0) {
|
||||||
from = ranges->at(0).to() + 1;
|
from = ranges->at(0).to() + 1;
|
||||||
|
@ -176,7 +176,7 @@ using namespace regexp_compiler_constants; // NOLINT(build/namespaces)
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr uc32 MaxCodeUnit(const bool one_byte) {
|
constexpr base::uc32 MaxCodeUnit(const bool one_byte) {
|
||||||
STATIC_ASSERT(String::kMaxOneByteCharCodeU <=
|
STATIC_ASSERT(String::kMaxOneByteCharCodeU <=
|
||||||
std::numeric_limits<uint16_t>::max());
|
std::numeric_limits<uint16_t>::max());
|
||||||
STATIC_ASSERT(String::kMaxUtf16CodeUnitU <=
|
STATIC_ASSERT(String::kMaxUtf16CodeUnitU <=
|
||||||
@ -751,7 +751,7 @@ bool ContainsOnlyUtf16CodeUnits(unibrow::uchar* chars, int length) {
|
|||||||
|
|
||||||
// Returns the number of characters in the equivalence class, omitting those
|
// Returns the number of characters in the equivalence class, omitting those
|
||||||
// that cannot occur in the source string because it is Latin1.
|
// that cannot occur in the source string because it is Latin1.
|
||||||
static int GetCaseIndependentLetters(Isolate* isolate, uc16 character,
|
static int GetCaseIndependentLetters(Isolate* isolate, base::uc16 character,
|
||||||
bool one_byte_subject,
|
bool one_byte_subject,
|
||||||
unibrow::uchar* letters,
|
unibrow::uchar* letters,
|
||||||
int letter_length) {
|
int letter_length) {
|
||||||
@ -815,7 +815,7 @@ static int GetCaseIndependentLetters(Isolate* isolate, uc16 character,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline bool EmitSimpleCharacter(Isolate* isolate,
|
static inline bool EmitSimpleCharacter(Isolate* isolate,
|
||||||
RegExpCompiler* compiler, uc16 c,
|
RegExpCompiler* compiler, base::uc16 c,
|
||||||
Label* on_failure, int cp_offset,
|
Label* on_failure, int cp_offset,
|
||||||
bool check, bool preloaded) {
|
bool check, bool preloaded) {
|
||||||
RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
||||||
@ -831,8 +831,9 @@ static inline bool EmitSimpleCharacter(Isolate* isolate,
|
|||||||
// Only emits non-letters (things that don't have case). Only used for case
|
// Only emits non-letters (things that don't have case). Only used for case
|
||||||
// independent matches.
|
// independent matches.
|
||||||
static inline bool EmitAtomNonLetter(Isolate* isolate, RegExpCompiler* compiler,
|
static inline bool EmitAtomNonLetter(Isolate* isolate, RegExpCompiler* compiler,
|
||||||
uc16 c, Label* on_failure, int cp_offset,
|
base::uc16 c, Label* on_failure,
|
||||||
bool check, bool preloaded) {
|
int cp_offset, bool check,
|
||||||
|
bool preloaded) {
|
||||||
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
|
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
|
||||||
bool one_byte = compiler->one_byte();
|
bool one_byte = compiler->one_byte();
|
||||||
unibrow::uchar chars[4];
|
unibrow::uchar chars[4];
|
||||||
@ -860,27 +861,27 @@ static inline bool EmitAtomNonLetter(Isolate* isolate, RegExpCompiler* compiler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
|
static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
|
||||||
bool one_byte, uc16 c1, uc16 c2,
|
bool one_byte, base::uc16 c1,
|
||||||
Label* on_failure) {
|
base::uc16 c2, Label* on_failure) {
|
||||||
const uint32_t char_mask = CharMask(one_byte);
|
const uint32_t char_mask = CharMask(one_byte);
|
||||||
uc16 exor = c1 ^ c2;
|
base::uc16 exor = c1 ^ c2;
|
||||||
// Check whether exor has only one bit set.
|
// Check whether exor has only one bit set.
|
||||||
if (((exor - 1) & exor) == 0) {
|
if (((exor - 1) & exor) == 0) {
|
||||||
// If c1 and c2 differ only by one bit.
|
// If c1 and c2 differ only by one bit.
|
||||||
// Ecma262UnCanonicalize always gives the highest number last.
|
// Ecma262UnCanonicalize always gives the highest number last.
|
||||||
DCHECK(c2 > c1);
|
DCHECK(c2 > c1);
|
||||||
uc16 mask = char_mask ^ exor;
|
base::uc16 mask = char_mask ^ exor;
|
||||||
macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
|
macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
DCHECK(c2 > c1);
|
DCHECK(c2 > c1);
|
||||||
uc16 diff = c2 - c1;
|
base::uc16 diff = c2 - c1;
|
||||||
if (((diff - 1) & diff) == 0 && c1 >= diff) {
|
if (((diff - 1) & diff) == 0 && c1 >= diff) {
|
||||||
// If the characters differ by 2^n but don't differ by one bit then
|
// If the characters differ by 2^n but don't differ by one bit then
|
||||||
// subtract the difference from the found character, then do the or
|
// subtract the difference from the found character, then do the or
|
||||||
// trick. We avoid the theoretical case where negative numbers are
|
// trick. We avoid the theoretical case where negative numbers are
|
||||||
// involved in order to simplify code generation.
|
// involved in order to simplify code generation.
|
||||||
uc16 mask = char_mask ^ diff;
|
base::uc16 mask = char_mask ^ diff;
|
||||||
macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, diff, mask,
|
macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, diff, mask,
|
||||||
on_failure);
|
on_failure);
|
||||||
return true;
|
return true;
|
||||||
@ -891,8 +892,8 @@ static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
|
|||||||
// Only emits letters (things that have case). Only used for case independent
|
// Only emits letters (things that have case). Only used for case independent
|
||||||
// matches.
|
// matches.
|
||||||
static inline bool EmitAtomLetter(Isolate* isolate, RegExpCompiler* compiler,
|
static inline bool EmitAtomLetter(Isolate* isolate, RegExpCompiler* compiler,
|
||||||
uc16 c, Label* on_failure, int cp_offset,
|
base::uc16 c, Label* on_failure,
|
||||||
bool check, bool preloaded) {
|
int cp_offset, bool check, bool preloaded) {
|
||||||
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
|
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
|
||||||
bool one_byte = compiler->one_byte();
|
bool one_byte = compiler->one_byte();
|
||||||
unibrow::uchar chars[4];
|
unibrow::uchar chars[4];
|
||||||
@ -963,14 +964,14 @@ static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm, int first,
|
|||||||
// even_label is for ranges[i] to ranges[i + 1] where i - start_index is even.
|
// even_label is for ranges[i] to ranges[i + 1] where i - start_index is even.
|
||||||
// odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd.
|
// odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd.
|
||||||
static void EmitUseLookupTable(RegExpMacroAssembler* masm,
|
static void EmitUseLookupTable(RegExpMacroAssembler* masm,
|
||||||
ZoneList<uc32>* ranges, uint32_t start_index,
|
ZoneList<base::uc32>* ranges,
|
||||||
uint32_t end_index, uc32 min_char,
|
uint32_t start_index, uint32_t end_index,
|
||||||
Label* fall_through, Label* even_label,
|
base::uc32 min_char, Label* fall_through,
|
||||||
Label* odd_label) {
|
Label* even_label, Label* odd_label) {
|
||||||
static const uint32_t kSize = RegExpMacroAssembler::kTableSize;
|
static const uint32_t kSize = RegExpMacroAssembler::kTableSize;
|
||||||
static const uint32_t kMask = RegExpMacroAssembler::kTableMask;
|
static const uint32_t kMask = RegExpMacroAssembler::kTableMask;
|
||||||
|
|
||||||
uc32 base = (min_char & ~kMask);
|
base::uc32 base = (min_char & ~kMask);
|
||||||
USE(base);
|
USE(base);
|
||||||
|
|
||||||
// Assert that everything is on one kTableSize page.
|
// Assert that everything is on one kTableSize page.
|
||||||
@ -1017,10 +1018,10 @@ static void EmitUseLookupTable(RegExpMacroAssembler* masm,
|
|||||||
if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
|
if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CutOutRange(RegExpMacroAssembler* masm, ZoneList<uc32>* ranges,
|
static void CutOutRange(RegExpMacroAssembler* masm,
|
||||||
uint32_t start_index, uint32_t end_index,
|
ZoneList<base::uc32>* ranges, uint32_t start_index,
|
||||||
uint32_t cut_index, Label* even_label,
|
uint32_t end_index, uint32_t cut_index,
|
||||||
Label* odd_label) {
|
Label* even_label, Label* odd_label) {
|
||||||
bool odd = (((cut_index - start_index) & 1) == 1);
|
bool odd = (((cut_index - start_index) & 1) == 1);
|
||||||
Label* in_range_label = odd ? odd_label : even_label;
|
Label* in_range_label = odd ? odd_label : even_label;
|
||||||
Label dummy;
|
Label dummy;
|
||||||
@ -1041,14 +1042,14 @@ static void CutOutRange(RegExpMacroAssembler* masm, ZoneList<uc32>* ranges,
|
|||||||
|
|
||||||
// Unicode case. Split the search space into kSize spaces that are handled
|
// Unicode case. Split the search space into kSize spaces that are handled
|
||||||
// with recursion.
|
// with recursion.
|
||||||
static void SplitSearchSpace(ZoneList<uc32>* ranges, uint32_t start_index,
|
static void SplitSearchSpace(ZoneList<base::uc32>* ranges, uint32_t start_index,
|
||||||
uint32_t end_index, uint32_t* new_start_index,
|
uint32_t end_index, uint32_t* new_start_index,
|
||||||
uint32_t* new_end_index, uc32* border) {
|
uint32_t* new_end_index, base::uc32* border) {
|
||||||
static const uint32_t kSize = RegExpMacroAssembler::kTableSize;
|
static const uint32_t kSize = RegExpMacroAssembler::kTableSize;
|
||||||
static const uint32_t kMask = RegExpMacroAssembler::kTableMask;
|
static const uint32_t kMask = RegExpMacroAssembler::kTableMask;
|
||||||
|
|
||||||
uc32 first = ranges->at(start_index);
|
base::uc32 first = ranges->at(start_index);
|
||||||
uc32 last = ranges->at(end_index) - 1;
|
base::uc32 last = ranges->at(end_index) - 1;
|
||||||
|
|
||||||
*new_start_index = start_index;
|
*new_start_index = start_index;
|
||||||
*border = (ranges->at(start_index) & ~kMask) + kSize;
|
*border = (ranges->at(start_index) & ~kMask) + kSize;
|
||||||
@ -1107,15 +1108,16 @@ static void SplitSearchSpace(ZoneList<uc32>* ranges, uint32_t start_index,
|
|||||||
// know that the character is in the range of min_char to max_char inclusive.
|
// know that the character is in the range of min_char to max_char inclusive.
|
||||||
// Either label can be nullptr indicating backtracking. Either label can also
|
// Either label can be nullptr indicating backtracking. Either label can also
|
||||||
// be equal to the fall_through label.
|
// be equal to the fall_through label.
|
||||||
static void GenerateBranches(RegExpMacroAssembler* masm, ZoneList<uc32>* ranges,
|
static void GenerateBranches(RegExpMacroAssembler* masm,
|
||||||
uint32_t start_index, uint32_t end_index,
|
ZoneList<base::uc32>* ranges, uint32_t start_index,
|
||||||
uc32 min_char, uc32 max_char, Label* fall_through,
|
uint32_t end_index, base::uc32 min_char,
|
||||||
|
base::uc32 max_char, Label* fall_through,
|
||||||
Label* even_label, Label* odd_label) {
|
Label* even_label, Label* odd_label) {
|
||||||
DCHECK_LE(min_char, String::kMaxUtf16CodeUnit);
|
DCHECK_LE(min_char, String::kMaxUtf16CodeUnit);
|
||||||
DCHECK_LE(max_char, String::kMaxUtf16CodeUnit);
|
DCHECK_LE(max_char, String::kMaxUtf16CodeUnit);
|
||||||
|
|
||||||
uc32 first = ranges->at(start_index);
|
base::uc32 first = ranges->at(start_index);
|
||||||
uc32 last = ranges->at(end_index) - 1;
|
base::uc32 last = ranges->at(end_index) - 1;
|
||||||
|
|
||||||
DCHECK_LT(min_char, first);
|
DCHECK_LT(min_char, first);
|
||||||
|
|
||||||
@ -1175,7 +1177,7 @@ static void GenerateBranches(RegExpMacroAssembler* masm, ZoneList<uc32>* ranges,
|
|||||||
|
|
||||||
uint32_t new_start_index = 0;
|
uint32_t new_start_index = 0;
|
||||||
uint32_t new_end_index = 0;
|
uint32_t new_end_index = 0;
|
||||||
uc32 border = 0;
|
base::uc32 border = 0;
|
||||||
|
|
||||||
SplitSearchSpace(ranges, start_index, end_index, &new_start_index,
|
SplitSearchSpace(ranges, start_index, end_index, &new_start_index,
|
||||||
&new_end_index, &border);
|
&new_end_index, &border);
|
||||||
@ -1225,7 +1227,7 @@ static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
|
|||||||
ZoneList<CharacterRange>* ranges = cc->ranges(zone);
|
ZoneList<CharacterRange>* ranges = cc->ranges(zone);
|
||||||
CharacterRange::Canonicalize(ranges);
|
CharacterRange::Canonicalize(ranges);
|
||||||
|
|
||||||
const uc32 max_char = MaxCodeUnit(one_byte);
|
const base::uc32 max_char = MaxCodeUnit(one_byte);
|
||||||
int range_count = ranges->length();
|
int range_count = ranges->length();
|
||||||
|
|
||||||
int last_valid_range = range_count - 1;
|
int last_valid_range = range_count - 1;
|
||||||
@ -1272,8 +1274,8 @@ static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
|
|||||||
// entry at zero which goes to the failure label, but if there
|
// entry at zero which goes to the failure label, but if there
|
||||||
// was already one there we fall through for success on that entry.
|
// was already one there we fall through for success on that entry.
|
||||||
// Subsequent entries have alternating meaning (success/failure).
|
// Subsequent entries have alternating meaning (success/failure).
|
||||||
ZoneList<uc32>* range_boundaries =
|
ZoneList<base::uc32>* range_boundaries =
|
||||||
zone->New<ZoneList<uc32>>(last_valid_range, zone);
|
zone->New<ZoneList<base::uc32>>(last_valid_range, zone);
|
||||||
|
|
||||||
bool zeroth_entry_is_failure = !cc->is_negated();
|
bool zeroth_entry_is_failure = !cc->is_negated();
|
||||||
|
|
||||||
@ -1579,11 +1581,11 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
|||||||
for (int k = 0; k < elements()->length(); k++) {
|
for (int k = 0; k < elements()->length(); k++) {
|
||||||
TextElement elm = elements()->at(k);
|
TextElement elm = elements()->at(k);
|
||||||
if (elm.text_type() == TextElement::ATOM) {
|
if (elm.text_type() == TextElement::ATOM) {
|
||||||
base::Vector<const uc16> quarks = elm.atom()->data();
|
base::Vector<const base::uc16> quarks = elm.atom()->data();
|
||||||
for (int i = 0; i < characters && i < quarks.length(); i++) {
|
for (int i = 0; i < characters && i < quarks.length(); i++) {
|
||||||
QuickCheckDetails::Position* pos =
|
QuickCheckDetails::Position* pos =
|
||||||
details->positions(characters_filled_in);
|
details->positions(characters_filled_in);
|
||||||
uc16 c = quarks[i];
|
base::uc16 c = quarks[i];
|
||||||
if (elm.atom()->ignore_case()) {
|
if (elm.atom()->ignore_case()) {
|
||||||
unibrow::uchar chars[4];
|
unibrow::uchar chars[4];
|
||||||
int length = GetCaseIndependentLetters(
|
int length = GetCaseIndependentLetters(
|
||||||
@ -1664,8 +1666,9 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CharacterRange range = ranges->at(first_range);
|
CharacterRange range = ranges->at(first_range);
|
||||||
const uc32 first_from = range.from();
|
const base::uc32 first_from = range.from();
|
||||||
const uc32 first_to = (range.to() > char_mask) ? char_mask : range.to();
|
const base::uc32 first_to =
|
||||||
|
(range.to() > char_mask) ? char_mask : range.to();
|
||||||
const uint32_t differing_bits = (first_from ^ first_to);
|
const uint32_t differing_bits = (first_from ^ first_to);
|
||||||
// A mask and compare is only perfect if the differing bits form a
|
// A mask and compare is only perfect if the differing bits form a
|
||||||
// number like 00011111 with one single block of trailing 1s.
|
// number like 00011111 with one single block of trailing 1s.
|
||||||
@ -1677,9 +1680,10 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
|||||||
uint32_t bits = (first_from & common_bits);
|
uint32_t bits = (first_from & common_bits);
|
||||||
for (int i = first_range + 1; i < ranges->length(); i++) {
|
for (int i = first_range + 1; i < ranges->length(); i++) {
|
||||||
CharacterRange range = ranges->at(i);
|
CharacterRange range = ranges->at(i);
|
||||||
const uc32 from = range.from();
|
const base::uc32 from = range.from();
|
||||||
if (from > char_mask) continue;
|
if (from > char_mask) continue;
|
||||||
const uc32 to = (range.to() > char_mask) ? char_mask : range.to();
|
const base::uc32 to =
|
||||||
|
(range.to() > char_mask) ? char_mask : range.to();
|
||||||
// Here we are combining more ranges into the mask and compare
|
// Here we are combining more ranges into the mask and compare
|
||||||
// value. With each new range the mask becomes more sparse and
|
// value. With each new range the mask becomes more sparse and
|
||||||
// so the chances of a false positive rise. A character class
|
// so the chances of a false positive rise. A character class
|
||||||
@ -1851,15 +1855,15 @@ RegExpNode* TextNode::FilterOneByte(int depth) {
|
|||||||
for (int i = 0; i < element_count; i++) {
|
for (int i = 0; i < element_count; i++) {
|
||||||
TextElement elm = elements()->at(i);
|
TextElement elm = elements()->at(i);
|
||||||
if (elm.text_type() == TextElement::ATOM) {
|
if (elm.text_type() == TextElement::ATOM) {
|
||||||
base::Vector<const uc16> quarks = elm.atom()->data();
|
base::Vector<const base::uc16> quarks = elm.atom()->data();
|
||||||
for (int j = 0; j < quarks.length(); j++) {
|
for (int j = 0; j < quarks.length(); j++) {
|
||||||
uc16 c = quarks[j];
|
base::uc16 c = quarks[j];
|
||||||
if (elm.atom()->ignore_case()) {
|
if (elm.atom()->ignore_case()) {
|
||||||
c = unibrow::Latin1::TryConvertToLatin1(c);
|
c = unibrow::Latin1::TryConvertToLatin1(c);
|
||||||
}
|
}
|
||||||
if (c > unibrow::Latin1::kMaxChar) return set_replacement(nullptr);
|
if (c > unibrow::Latin1::kMaxChar) return set_replacement(nullptr);
|
||||||
// Replace quark in case we converted to Latin-1.
|
// Replace quark in case we converted to Latin-1.
|
||||||
uc16* writable_quarks = const_cast<uc16*>(quarks.begin());
|
base::uc16* writable_quarks = const_cast<base::uc16*>(quarks.begin());
|
||||||
writable_quarks[j] = c;
|
writable_quarks[j] = c;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2314,11 +2318,11 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler, TextEmitPassType pass,
|
|||||||
int cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset;
|
int cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset;
|
||||||
if (elm.text_type() == TextElement::ATOM) {
|
if (elm.text_type() == TextElement::ATOM) {
|
||||||
if (SkipPass(pass, elm.atom()->ignore_case())) continue;
|
if (SkipPass(pass, elm.atom()->ignore_case())) continue;
|
||||||
base::Vector<const uc16> quarks = elm.atom()->data();
|
base::Vector<const base::uc16> quarks = elm.atom()->data();
|
||||||
for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
|
for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
|
||||||
if (first_element_checked && i == 0 && j == 0) continue;
|
if (first_element_checked && i == 0 && j == 0) continue;
|
||||||
if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue;
|
if (DeterminedAlready(quick_check, elm.cp_offset() + j)) continue;
|
||||||
uc16 quark = quarks[j];
|
base::uc16 quark = quarks[j];
|
||||||
if (elm.atom()->ignore_case()) {
|
if (elm.atom()->ignore_case()) {
|
||||||
// Everywhere else we assume that a non-Latin-1 character cannot match
|
// Everywhere else we assume that a non-Latin-1 character cannot match
|
||||||
// a Latin-1 character. Avoid the cases where this is assumption is
|
// a Latin-1 character. Avoid the cases where this is assumption is
|
||||||
@ -2523,7 +2527,7 @@ RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
|
|||||||
return ranges->length() == 0 ? on_success() : nullptr;
|
return ranges->length() == 0 ? on_success() : nullptr;
|
||||||
}
|
}
|
||||||
if (ranges->length() != 1) return nullptr;
|
if (ranges->length() != 1) return nullptr;
|
||||||
const uc32 max_char = MaxCodeUnit(compiler->one_byte());
|
const base::uc32 max_char = MaxCodeUnit(compiler->one_byte());
|
||||||
return ranges->at(0).IsEverything(max_char) ? on_success() : nullptr;
|
return ranges->at(0).IsEverything(max_char) ? on_success() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3803,7 +3807,7 @@ void TextNode::FillInBMInfo(Isolate* isolate, int initial_offset, int budget,
|
|||||||
if (initial_offset == 0) set_bm_info(not_at_start, bm);
|
if (initial_offset == 0) set_bm_info(not_at_start, bm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uc16 character = atom->data()[j];
|
base::uc16 character = atom->data()[j];
|
||||||
if (IgnoreCase(atom->flags())) {
|
if (IgnoreCase(atom->flags())) {
|
||||||
unibrow::uchar chars[4];
|
unibrow::uchar chars[4];
|
||||||
int length = GetCaseIndependentLetters(
|
int length = GetCaseIndependentLetters(
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#include "src/base/small-vector.h"
|
#include "src/base/small-vector.h"
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/regexp/regexp-nodes.h"
|
#include "src/regexp/regexp-nodes.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
@ -21,7 +22,7 @@ namespace regexp_compiler_constants {
|
|||||||
// The '2' variant is has inclusive from and exclusive to.
|
// The '2' variant is has inclusive from and exclusive to.
|
||||||
// This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
|
// This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
|
||||||
// which include WhiteSpace (7.2) or LineTerminator (7.3) values.
|
// which include WhiteSpace (7.2) or LineTerminator (7.3) values.
|
||||||
constexpr uc32 kRangeEndMarker = 0x110000;
|
constexpr base::uc32 kRangeEndMarker = 0x110000;
|
||||||
constexpr int kSpaceRanges[] = {
|
constexpr int kSpaceRanges[] = {
|
||||||
'\t', '\r' + 1, ' ', ' ' + 1, 0x00A0, 0x00A1, 0x1680,
|
'\t', '\r' + 1, ' ', ' ' + 1, 0x00A0, 0x00A1, 0x1680,
|
||||||
0x1681, 0x2000, 0x200B, 0x2028, 0x202A, 0x202F, 0x2030,
|
0x1681, 0x2000, 0x200B, 0x2028, 0x202A, 0x202F, 0x2030,
|
||||||
@ -96,8 +97,8 @@ class QuickCheckDetails {
|
|||||||
void set_cannot_match() { cannot_match_ = true; }
|
void set_cannot_match() { cannot_match_ = true; }
|
||||||
struct Position {
|
struct Position {
|
||||||
Position() : mask(0), value(0), determines_perfectly(false) {}
|
Position() : mask(0), value(0), determines_perfectly(false) {}
|
||||||
uc32 mask;
|
base::uc32 mask;
|
||||||
uc32 value;
|
base::uc32 value;
|
||||||
bool determines_perfectly;
|
bool determines_perfectly;
|
||||||
};
|
};
|
||||||
int characters() { return characters_; }
|
int characters() { return characters_; }
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/regexp/regexp-dotprinter.h"
|
#include "src/regexp/regexp-dotprinter.h"
|
||||||
|
|
||||||
|
#include "src/base/strings.h"
|
||||||
#include "src/regexp/regexp-compiler.h"
|
#include "src/regexp/regexp-compiler.h"
|
||||||
#include "src/utils/ostreams.h"
|
#include "src/utils/ostreams.h"
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ void DotPrinterImpl::VisitText(TextNode* that) {
|
|||||||
TextElement elm = that->elements()->at(i);
|
TextElement elm = that->elements()->at(i);
|
||||||
switch (elm.text_type()) {
|
switch (elm.text_type()) {
|
||||||
case TextElement::ATOM: {
|
case TextElement::ATOM: {
|
||||||
base::Vector<const uc16> data = elm.atom()->data();
|
base::Vector<const base::uc16> data = elm.atom()->data();
|
||||||
for (int i = 0; i < data.length(); i++) {
|
for (int i = 0; i < data.length(); i++) {
|
||||||
os_ << static_cast<char>(data[i]);
|
os_ << static_cast<char>(data[i]);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user