Commit c4e944cb authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

[torque] Port ToInteger to Torque

Bug: v8:10155
Change-Id: I032b27ad7c71d240453e33bef33a447a1530ace9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2060005
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66387}
parent 86a6ce45
......@@ -63,7 +63,8 @@ namespace array {
// else let n be len - 1.
const n: Number = arguments.length < 2 ?
length - 1 :
ToInteger_Inline(arguments[1], kTruncateMinusZero);
ToInteger_Inline(
arguments[1], ToIntegerTruncationMode::kTruncateMinusZero);
// 5. If n >= 0, then.
let k: Number = SmiConstant(0);
......
......@@ -177,9 +177,6 @@ type Callable = JSFunction|JSBoundFunction|CallableJSProxy|CallableApiObject;
type WriteBarrierMode
generates 'TNode<Int32T>' constexpr 'WriteBarrierMode';
type ToIntegerTruncationMode
constexpr 'CodeStubAssembler::ToIntegerTruncationMode';
extern enum UnicodeEncoding { UTF16, UTF32 }
// Promise constants
......@@ -345,9 +342,11 @@ const kSloppyArgumentsContextIndex: constexpr int31
const kSloppyArgumentsParameterMapStart: constexpr int31
generates 'SloppyArgumentsElements::kParameterMapStart';
const kTruncateMinusZero: constexpr ToIntegerTruncationMode
generates 'CodeStubAssembler::ToIntegerTruncationMode::kTruncateMinusZero'
;
extern enum ToIntegerTruncationMode extends int32
constexpr 'compiler::CodeAssembler::ToIntegerTruncationMode' {
kNoTruncation,
kTruncateMinusZero
}
extern enum PrimitiveType { kString, kBoolean, kSymbol, kNumber }
......@@ -433,10 +432,71 @@ extern macro Comment(constexpr string);
extern macro StaticAssert(bool);
extern macro Print(Object);
extern macro DebugBreak();
extern transitioning macro ToInteger_Inline(implicit context: Context)(JSAny):
Number;
extern transitioning macro ToInteger_Inline(implicit context: Context)(
JSAny, constexpr ToIntegerTruncationMode): Number;
// ES6 7.1.4 ToInteger ( argument )
transitioning macro ToIntegerImpl(implicit context: Context)(
input: Object, mode: constexpr ToIntegerTruncationMode): Number {
let input = input;
while (true) {
typeswitch (input) {
case (s: Smi): {
return s;
}
case (hn: HeapNumber): {
let value = Convert<float64>(hn);
if (Float64IsNaN(value)) return SmiConstant(0);
value = math::Float64Trunc(value);
if constexpr (mode == ToIntegerTruncationMode::kTruncateMinusZero) {
if (value == 0.0) return SmiConstant(0);
}
const result = ChangeFloat64ToTagged(value);
if constexpr (mode == ToIntegerTruncationMode::kTruncateMinusZero) {
assert(IsNumberNormalized(result));
}
return result;
}
case (ho: HeapObject): {
input = math::NonNumberToNumber(ho);
}
}
}
unreachable;
}
transitioning builtin ToInteger(implicit context: Context)(input: Object):
Number {
return ToIntegerImpl(input, ToIntegerTruncationMode::kNoTruncation);
}
transitioning builtin ToInteger_TruncateMinusZero(implicit context: Context)(
input: Object): Number {
return ToIntegerImpl(input, ToIntegerTruncationMode::kTruncateMinusZero);
}
@export
transitioning macro ToInteger_Inline(implicit context: Context)(input: Object):
Number {
return ToInteger_Inline(input, ToIntegerTruncationMode::kNoTruncation);
}
@export
transitioning macro ToInteger_Inline(implicit context: Context)(
input: Object, mode: constexpr ToIntegerTruncationMode): Number {
typeswitch (input) {
case (s: Smi): {
return s;
}
case (ho: HeapObject): {
if constexpr (mode == ToIntegerTruncationMode::kTruncateMinusZero) {
return ToInteger_TruncateMinusZero(ho);
} else {
return ToInteger(ho);
}
}
}
}
extern transitioning macro ToLength_Inline(implicit context: Context)(JSAny):
Number;
extern transitioning macro ToNumber_Inline(implicit context: Context)(JSAny):
......@@ -724,6 +784,10 @@ ConstexprInt31NotEqual(constexpr int31, constexpr int31): constexpr bool;
extern operator '>=' macro
ConstexprInt31GreaterThanEqual(
constexpr int31, constexpr int31): constexpr bool;
extern operator '==' macro ConstexprInt32Equal(
constexpr int32, constexpr int32): constexpr bool;
extern operator '!=' macro ConstexprInt32NotEqual(
constexpr int32, constexpr int32): constexpr bool;
extern operator '==' macro Word32Equal(int32, int32): bool;
extern operator '==' macro Word32Equal(uint32, uint32): bool;
......@@ -1206,7 +1270,8 @@ macro ChangeSafeIntegerNumberToUintPtr(value: Number):
transitioning macro ToUintPtr(implicit context: Context)(value: JSAny):
uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
if (value == Undefined) return 0;
const indexNumber = ToInteger_Inline(value, kTruncateMinusZero);
const indexNumber =
ToInteger_Inline(value, ToIntegerTruncationMode::kTruncateMinusZero);
return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
otherwise IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow;
}
......@@ -1220,7 +1285,8 @@ transitioning macro ToUintPtr(implicit context: Context)(value: JSAny):
transitioning macro ToIndex(implicit context: Context)(value: JSAny):
uintptr labels IfRangeError {
if (value == Undefined) return 0;
const indexNumber = ToInteger_Inline(value, kTruncateMinusZero);
const indexNumber =
ToInteger_Inline(value, ToIntegerTruncationMode::kTruncateMinusZero);
// Less than 0 case, uintptr range overflow and safe integer range overflow
// imply IfRangeError.
return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
......@@ -1293,7 +1359,8 @@ extern macro IsOneByteStringInstanceType(InstanceType): bool;
@export
transitioning macro ConvertToRelativeIndex(implicit context: Context)(
index: JSAny, length: uintptr): uintptr {
const indexNumber: Number = ToInteger_Inline(index, kTruncateMinusZero);
const indexNumber: Number =
ToInteger_Inline(index, ToIntegerTruncationMode::kTruncateMinusZero);
return ConvertToRelativeIndex(indexNumber, length);
}
......@@ -1340,7 +1407,8 @@ macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr {
@export
transitioning macro ClampToIndexRange(implicit context: Context)(
index: JSAny, limit: uintptr): uintptr {
const indexNumber: Number = ToInteger_Inline(index, kTruncateMinusZero);
const indexNumber: Number =
ToInteger_Inline(index, ToIntegerTruncationMode::kTruncateMinusZero);
return ClampToIndexRange(indexNumber, limit);
}
......
......@@ -376,20 +376,6 @@ TF_BUILTIN(ToLength, CodeStubAssembler) {
}
}
TF_BUILTIN(ToInteger, CodeStubAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
Return(ToInteger(context, input, kNoTruncation));
}
TF_BUILTIN(ToInteger_TruncateMinusZero, CodeStubAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
Return(ToInteger(context, input, kTruncateMinusZero));
}
// ES6 section 7.1.13 ToObject (argument)
TF_BUILTIN(ToObject, CodeStubAssembler) {
Label if_smi(this, Label::kDeferred), if_jsreceiver(this),
......
......@@ -200,8 +200,6 @@ namespace internal {
TFC(ToNumberConvertBigInt, TypeConversion) \
TFC(ToNumeric, TypeConversion) \
TFC(NumberToString, TypeConversion) \
TFC(ToInteger, TypeConversion) \
TFC(ToInteger_TruncateMinusZero, TypeConversion) \
TFC(ToLength, TypeConversion) \
TFC(Typeof, Typeof) \
TFC(GetSuperConstructor, Typeof) \
......
......@@ -68,7 +68,8 @@ namespace string {
const string: String = ToThisString(receiver, methodName);
// 3. Let position be ? ToInteger(pos).
const indexNumber: Number = ToInteger_Inline(position, kTruncateMinusZero);
const indexNumber: Number =
ToInteger_Inline(position, ToIntegerTruncationMode::kTruncateMinusZero);
// Convert the {position} to a uintptr and check that it's in bounds of
// the {string}.
......
......@@ -33,8 +33,9 @@ namespace number {
// 3. Else if radix is undefined, let radixNumber be 10.
// 4. Else, let radixNumber be ? ToInteger(radix).
const radix: JSAny = arguments[0];
const radixNumber: Number =
radix == Undefined ? 10 : ToInteger_Inline(radix, kTruncateMinusZero);
const radixNumber: Number = radix == Undefined ?
10 :
ToInteger_Inline(radix, ToIntegerTruncationMode::kTruncateMinusZero);
// 5. If radixNumber < 2 or radixNumber > 36, throw a RangeError exception.
if (radixNumber < 2 || radixNumber > 36) {
......
......@@ -36,7 +36,8 @@ namespace string {
try {
// 3. Let n be ? ToInteger(count).
typeswitch (ToInteger_Inline(count, kTruncateMinusZero)) {
typeswitch (ToInteger_Inline(
count, ToIntegerTruncationMode::kTruncateMinusZero)) {
case (n: Smi): {
// 4. If n < 0, throw a RangeError exception.
if (n < 0) goto InvalidCount;
......
......@@ -7243,82 +7243,6 @@ TNode<Number> CodeStubAssembler::ToLength_Inline(SloppyTNode<Context> context,
[=] { return CAST(CallBuiltin(Builtins::kToLength, context, input)); });
}
TNode<Number> CodeStubAssembler::ToInteger_Inline(
SloppyTNode<Context> context, SloppyTNode<Object> input,
ToIntegerTruncationMode mode) {
Builtins::Name builtin = (mode == kNoTruncation)
? Builtins::kToInteger
: Builtins::kToInteger_TruncateMinusZero;
return Select<Number>(
TaggedIsSmi(input), [=] { return CAST(input); },
[=] { return CAST(CallBuiltin(builtin, context, input)); });
}
TNode<Number> CodeStubAssembler::ToInteger(SloppyTNode<Context> context,
SloppyTNode<Object> input,
ToIntegerTruncationMode mode) {
// We might need to loop once for ToNumber conversion.
TVARIABLE(Object, var_arg, input);
Label loop(this, &var_arg), out(this);
Goto(&loop);
BIND(&loop);
{
// Shared entry points.
Label return_zero(this, Label::kDeferred);
// Load the current {arg} value.
TNode<Object> arg = var_arg.value();
// Check if {arg} is a Smi.
GotoIf(TaggedIsSmi(arg), &out);
// Check if {arg} is a HeapNumber.
Label if_argisheapnumber(this),
if_argisnotheapnumber(this, Label::kDeferred);
Branch(IsHeapNumber(CAST(arg)), &if_argisheapnumber,
&if_argisnotheapnumber);
BIND(&if_argisheapnumber);
{
TNode<HeapNumber> arg_hn = CAST(arg);
// Load the floating-point value of {arg}.
TNode<Float64T> arg_value = LoadHeapNumberValue(arg_hn);
// Check if {arg} is NaN.
GotoIfNot(Float64Equal(arg_value, arg_value), &return_zero);
// Truncate {arg} towards zero.
TNode<Float64T> value = Float64Trunc(arg_value);
if (mode == kTruncateMinusZero) {
// Truncate -0.0 to 0.
GotoIf(Float64Equal(value, Float64Constant(0.0)), &return_zero);
}
var_arg = ChangeFloat64ToTagged(value);
Goto(&out);
}
BIND(&if_argisnotheapnumber);
{
// Need to convert {arg} to a Number first.
var_arg = UncheckedCast<Object>(
CallBuiltin(Builtins::kNonNumberToNumber, context, arg));
Goto(&loop);
}
BIND(&return_zero);
var_arg = SmiConstant(0);
Goto(&out);
}
BIND(&out);
if (mode == kTruncateMinusZero) {
CSA_ASSERT(this, IsNumberNormalized(CAST(var_arg.value())));
}
return CAST(var_arg.value());
}
TNode<Uint32T> CodeStubAssembler::DecodeWord32(SloppyTNode<Word32T> word32,
uint32_t shift, uint32_t mask) {
DCHECK_EQ((mask >> shift) << shift, mask);
......
......@@ -2732,23 +2732,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<JSReceiver> ToObject_Inline(TNode<Context> context,
TNode<Object> input);
enum ToIntegerTruncationMode {
kNoTruncation,
kTruncateMinusZero,
};
// ES6 7.1.15 ToLength, but with inlined fast path.
TNode<Number> ToLength_Inline(SloppyTNode<Context> context,
SloppyTNode<Object> input);
// ES6 7.1.4 ToInteger ( argument )
TNode<Number> ToInteger_Inline(SloppyTNode<Context> context,
SloppyTNode<Object> input,
ToIntegerTruncationMode mode = kNoTruncation);
TNode<Number> ToInteger(SloppyTNode<Context> context,
SloppyTNode<Object> input,
ToIntegerTruncationMode mode = kNoTruncation);
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word32|. Returns result as an uint32 node.
template <typename BitField>
......@@ -3660,6 +3647,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
bool ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; }
bool ConstexprInt31NotEqual(int31_t a, int31_t b) { return a != b; }
bool ConstexprInt31GreaterThanEqual(int31_t a, int31_t b) { return a >= b; }
bool ConstexprInt32Equal(int32_t a, int32_t b) { return a == b; }
bool ConstexprInt32NotEqual(int32_t a, int32_t b) { return a != b; }
bool ConstexprInt32GreaterThanEqual(int32_t a, int32_t b) { return a >= b; }
uint32_t ConstexprUint32Add(uint32_t a, uint32_t b) { return a + b; }
int31_t ConstexprInt31Add(int31_t a, int31_t b) {
......
......@@ -371,6 +371,11 @@ TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
// a CodeAssemblerState instance.
class V8_EXPORT_PRIVATE CodeAssembler {
public:
enum ToIntegerTruncationMode {
kNoTruncation,
kTruncateMinusZero,
};
explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
~CodeAssembler();
......
......@@ -222,7 +222,7 @@ bool IsUpperCamelCase(const std::string& s) {
if (s.empty()) return false;
size_t start = 0;
if (s[0] == '_') start = 1;
return isupper(s[start]) && !ContainsUnderscore(s.substr(1));
return isupper(s[start]);
}
bool IsSnakeCase(const std::string& s) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment