!7407 IR Number.toString()

Merge pull request !7407 from maojunwei/toString
This commit is contained in:
openharmony_ci 2024-05-21 04:46:40 +00:00 committed by Gitee
commit fea1d192c9
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 241 additions and 4 deletions

View File

@ -64,7 +64,7 @@
/* Number.prototype.toPrecision ( precision ) */ \
V("toPrecision", ToPrecision, 1, INVALID) \
/* Number.prototype.toString ( [ radix ] ) */ \
V("toString", ToString, 1, INVALID) \
V("toString", ToString, 1, NumberToString) \
/* Number.prototype.valueOf ( ) */ \
V("valueOf", ValueOf, 0, INVALID)

View File

@ -138,7 +138,8 @@ namespace panda::ecmascript::kungfu {
V(PrototypeApply, Function, Undefined())
#define BUILTINS_WITH_NUMBER_STUB_BUILDER(V) \
V(ParseFloat, Number, Undefined())
V(ParseFloat, Number, Undefined()) \
V(ToString, Number, Undefined())
#define BUILTINS_WITH_TYPEDARRAY_STUB_BUILDER(V) \
V(Reverse, TypedArray, Undefined()) \

View File

@ -15,6 +15,7 @@
#include "ecmascript/compiler/builtins/builtins_number_stub_builder.h"
#include "ecmascript/builtins/builtins_number.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
#include "ecmascript/compiler/stub_builder-inl.h"
#include "ecmascript/js_arguments.h"
@ -123,4 +124,171 @@ void BuiltinsNumberStubBuilder::GenNumberConstructor(GateRef nativeCode, GateRef
Bind(&exit);
Return(*res);
}
void BuiltinsNumberStubBuilder::ToString(Variable *result, Label *exit, Label *slowPath)
{
auto env = GetEnvironment();
Label definedMsg(env);
Label undefinedMsg(env);
Label thisIsInt(env);
Label msgIsInt(env);
BRANCH(TaggedIsInt(thisValue_), &thisIsInt, slowPath);
Bind(&thisIsInt);
GateRef thisValueInt = GetInt32OfTInt(thisValue_);
GateRef msg = GetCallArg0(numArgs_);
BRANCH(TaggedIsUndefined(msg), &undefinedMsg, &definedMsg);
Bind(&undefinedMsg);
{
*result = NumberToString(thisValueInt, Int32(10)); // 10: means radix
Jump(exit);
}
Bind(&definedMsg);
BRANCH(TaggedIsInt(msg), &msgIsInt, slowPath);
Bind(&msgIsInt);
{
Label throwError(env);
Label notThrowError(env);
GateRef msgValue = GetInt32OfTInt(msg);
GateRef outOfRange = BoolOr(Int32LessThan(msgValue, Int32(base::MIN_RADIX)),
Int32GreaterThan(msgValue, Int32(base::MAX_RADIX)));
BRANCH(outOfRange, &throwError, &notThrowError);
Bind(&throwError);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InvalidRadixLength));
CallRuntime(glue_, RTSTUB_ID(ThrowRangeError), { IntToTaggedInt(taggedId) });
Jump(exit);
}
Bind(&notThrowError);
{
*result = NumberToString(thisValueInt, msgValue);
Jump(exit);
}
}
}
GateRef BuiltinsNumberStubBuilder::NumberToString(GateRef number, GateRef radix)
{
auto env = GetEnvironment();
DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
DEFVARIABLE(n, VariableType::INT32(), number);
Label exit(env);
Label numIsNegative(env);
Label numNotNegative(env);
Label afterFast(env);
Label afterNew(env);
GateRef isNegative = Int32LessThan(number, Int32(0));
BRANCH(isNegative, &numIsNegative, &numNotNegative);
Bind(&numIsNegative);
{
n = Int32Sub(Int32(0), *n);
Jump(&afterFast);
}
Bind(&numNotNegative);
{
Label thisIsZero(env);
Label thisNotZero(env);
Label thisIsSingle(env);
Label thisNotSingle(env);
BRANCH(Int32Equal(number, Int32(0)), &thisIsZero, &thisNotZero);
Bind(&thisIsZero);
{
result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ZERO_INDEX);
Jump(&exit);
}
Bind(&thisNotZero);
{
BRANCH(Int32LessThan(number, radix), &thisIsSingle, &afterFast);
Bind(&thisIsSingle);
GateRef singleCharTable = GetSingleCharTable(glue_);
GateRef index = ToCharCode(number);
result = GetValueFromTaggedArray(singleCharTable, index);
Jump(&exit);
}
}
Bind(&afterFast);
{
DEFVARIABLE(temp, VariableType::INT32(), *n);
DEFVARIABLE(length, VariableType::INT32(), Int32(0));
Label lenAddOne(env);
Label lenNotAddOne(env);
BRANCH(isNegative, &lenAddOne, &lenNotAddOne);
Bind(&lenAddOne);
{
length = Int32Add(*length, Int32(1));
Jump(&lenNotAddOne);
}
Bind(&lenNotAddOne);
{
Label loopHead(env);
Label loopEnd(env);
Label next(env);
Label loopExit(env);
Jump(&loopHead);
LoopBegin(&loopHead);
{
BRANCH(Int32GreaterThan(*temp, Int32(0)), &next, &loopExit);
Bind(&next);
{
temp = Int32Div(*temp, radix);
length = Int32Add(*length, Int32(1));
Jump(&loopEnd);
}
}
Bind(&loopEnd);
LoopEnd(&loopHead, env, glue_);
Bind(&loopExit);
{
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue_, 0);
newBuilder.AllocLineStringObject(&result, &afterNew, *length, true);
Bind(&afterNew);
{
GateRef dst = ChangeTaggedPointerToInt64(PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET)));
DEFVARIABLE(cursor, VariableType::INT32(), Int32Sub(*length, Int32(1)));
DEFVARIABLE(digit, VariableType::INT32(), Int32(0));
DEFVARIABLE(dstTmp, VariableType::NATIVE_POINTER(), dst);
dstTmp = PtrAdd(*dstTmp, PtrMul(ZExtInt32ToPtr(*cursor), IntPtr(sizeof(uint8_t))));
Label loopHead1(env);
Label loopEnd1(env);
Label next1(env);
Label loopExit1(env);
Jump(&loopHead1);
LoopBegin(&loopHead1);
{
BRANCH(Int32GreaterThan(*n, Int32(0)), &next1, &loopExit1);
Bind(&next1);
{
digit = Int32Mod(*n, radix);
n = Int32Div(*n, radix);
GateRef digitChar = ToCharCode(*digit);
Store(VariableType::INT8(), glue_, *dstTmp, IntPtr(0), TruncInt32ToInt8(digitChar));
cursor = Int32Sub(*cursor, Int32(1));
Jump(&loopEnd1);
}
}
Bind(&loopEnd1);
dstTmp = PtrSub(*dstTmp, IntPtr(sizeof(uint8_t)));
LoopEnd(&loopHead1, env, glue_);
Bind(&loopExit1);
{
Label strInsertSign(env);
Label strNotInsertSign(env);
BRANCH(isNegative, &strInsertSign, &exit);
Bind(&strInsertSign);
{
dstTmp = PtrSub(*dstTmp, IntPtr(sizeof(uint8_t)));
Store(VariableType::INT8(), glue_, dst, IntPtr(0), Int8(45)); // 45: means '-'
Jump(&exit);
}
}
}
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
} // namespace panda::ecmascript::kungfu

View File

@ -34,6 +34,7 @@ BUILTINS_WITH_NUMBER_STUB_BUILDER(DECLARE_BUILTINS_NUMBER_STUB_BUILDER)
#undef DECLARE_BUILTINS_NUMBER_STUB_BUILDER
void GenNumberConstructor(GateRef nativeCode, GateRef func, GateRef newTarget);
GateRef NumberToString(GateRef number, GateRef radix);
private:
GateRef glue_ { Circuit::NullGate() };

View File

@ -9732,6 +9732,34 @@ GateRef StubBuilder::AppendSkipHole(GateRef glue, GateRef first, GateRef second,
return ret;
}
GateRef StubBuilder::ToCharCode(GateRef number)
{
auto env = GetEnvironment();
Label subEntry(env);
env->SubCfgEntry(&subEntry);
Label exit(env);
DEFVARIABLE(result, VariableType::INT32(), number);
Label lessThanTen(env);
Label notLessThanTen(env);
BRANCH(Int32LessThan(number, Int32(10)), &lessThanTen, &notLessThanTen); // 10: means number
Bind(&lessThanTen);
{
result = Int32Add(Int32('0'), *result);
Jump(&exit);
}
Bind(&notLessThanTen);
{
result = Int32Sub(*result, Int32(10)); // 10: means number
result = Int32Add(Int32('a'), *result);
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::IntToEcmaString(GateRef glue, GateRef number)
{
auto env = GetEnvironment();

View File

@ -870,6 +870,7 @@ public:
GateRef CalArrayRelativePos(GateRef index, GateRef arrayLen);
GateRef AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength);
GateRef IntToEcmaString(GateRef glue, GateRef number);
GateRef ToCharCode(GateRef number);
GateRef NumberToString(GateRef glue, GateRef number);
inline GateRef GetViewedArrayBuffer(GateRef dataView);
inline GateRef GetByteOffset(GateRef dataView);

View File

@ -60,7 +60,8 @@ namespace panda::ecmascript {
V(InvalidStringLength, "Invalid string length") \
V(InvalidNewTarget, "new.target is not an object") \
V(ObjIsNotCallable, "obj is not Callable") \
V(SharedObjectRefersLocalObject, "shared object refers a local object")
V(SharedObjectRefersLocalObject, "shared object refers a local object") \
V(InvalidRadixLength, "radix must be 2 to 36")
#define DEBUG_CHECK_MESSAGE_STRING_LIST(V) \
V(IsCallable) \

View File

@ -102,3 +102,18 @@
-12
-1.2e+3
-1.235e+4
0
1
-9
1234567
-1234567
10000
67345
0
9
5a
0
-5a
5yc1z
3lnj8l
-3lnj8l

View File

@ -133,4 +133,26 @@ testToPrecision(Number(-.00012345), (2));
testToPrecision(Number(-1.2345), (2));
testToPrecision(Number(-12.345), (2));
testToPrecision(Number(-1234.5), (2));
testToPrecision(Number(-12345.67), (4));
testToPrecision(Number(-12345.67), (4));
// toString, Only Test InttoString
function testToString(a, b) {
print(a.toString(b));
}
print((-0).toString());
print((1).toString());
print((-9).toString());
print((1234567).toString());
print((-1234567).toString());
print((10000).toString());
print((67345).toString());
testToString((0), (16));
testToString((9), (16));
testToString((90), (16));
testToString((-0), (16));
testToString((-90), (16));
testToString((10000007), (36));
testToString((123456789), (32));
testToString((-123456789), (32));