mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
!7407 IR Number.toString()
Merge pull request !7407 from maojunwei/toString
This commit is contained in:
commit
fea1d192c9
@ -64,7 +64,7 @@
|
|||||||
/* Number.prototype.toPrecision ( precision ) */ \
|
/* Number.prototype.toPrecision ( precision ) */ \
|
||||||
V("toPrecision", ToPrecision, 1, INVALID) \
|
V("toPrecision", ToPrecision, 1, INVALID) \
|
||||||
/* Number.prototype.toString ( [ radix ] ) */ \
|
/* Number.prototype.toString ( [ radix ] ) */ \
|
||||||
V("toString", ToString, 1, INVALID) \
|
V("toString", ToString, 1, NumberToString) \
|
||||||
/* Number.prototype.valueOf ( ) */ \
|
/* Number.prototype.valueOf ( ) */ \
|
||||||
V("valueOf", ValueOf, 0, INVALID)
|
V("valueOf", ValueOf, 0, INVALID)
|
||||||
|
|
||||||
|
@ -138,7 +138,8 @@ namespace panda::ecmascript::kungfu {
|
|||||||
V(PrototypeApply, Function, Undefined())
|
V(PrototypeApply, Function, Undefined())
|
||||||
|
|
||||||
#define BUILTINS_WITH_NUMBER_STUB_BUILDER(V) \
|
#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) \
|
#define BUILTINS_WITH_TYPEDARRAY_STUB_BUILDER(V) \
|
||||||
V(Reverse, TypedArray, Undefined()) \
|
V(Reverse, TypedArray, Undefined()) \
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "ecmascript/compiler/builtins/builtins_number_stub_builder.h"
|
#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/new_object_stub_builder.h"
|
||||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||||
#include "ecmascript/js_arguments.h"
|
#include "ecmascript/js_arguments.h"
|
||||||
@ -123,4 +124,171 @@ void BuiltinsNumberStubBuilder::GenNumberConstructor(GateRef nativeCode, GateRef
|
|||||||
Bind(&exit);
|
Bind(&exit);
|
||||||
Return(*res);
|
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, ¬ThrowError);
|
||||||
|
Bind(&throwError);
|
||||||
|
{
|
||||||
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InvalidRadixLength));
|
||||||
|
CallRuntime(glue_, RTSTUB_ID(ThrowRangeError), { IntToTaggedInt(taggedId) });
|
||||||
|
Jump(exit);
|
||||||
|
}
|
||||||
|
Bind(¬ThrowError);
|
||||||
|
{
|
||||||
|
*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
|
} // namespace panda::ecmascript::kungfu
|
||||||
|
@ -34,6 +34,7 @@ BUILTINS_WITH_NUMBER_STUB_BUILDER(DECLARE_BUILTINS_NUMBER_STUB_BUILDER)
|
|||||||
#undef DECLARE_BUILTINS_NUMBER_STUB_BUILDER
|
#undef DECLARE_BUILTINS_NUMBER_STUB_BUILDER
|
||||||
|
|
||||||
void GenNumberConstructor(GateRef nativeCode, GateRef func, GateRef newTarget);
|
void GenNumberConstructor(GateRef nativeCode, GateRef func, GateRef newTarget);
|
||||||
|
GateRef NumberToString(GateRef number, GateRef radix);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GateRef glue_ { Circuit::NullGate() };
|
GateRef glue_ { Circuit::NullGate() };
|
||||||
|
@ -9732,6 +9732,34 @@ GateRef StubBuilder::AppendSkipHole(GateRef glue, GateRef first, GateRef second,
|
|||||||
return ret;
|
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, ¬LessThanTen); // 10: means number
|
||||||
|
Bind(&lessThanTen);
|
||||||
|
{
|
||||||
|
result = Int32Add(Int32('0'), *result);
|
||||||
|
Jump(&exit);
|
||||||
|
}
|
||||||
|
Bind(¬LessThanTen);
|
||||||
|
{
|
||||||
|
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)
|
GateRef StubBuilder::IntToEcmaString(GateRef glue, GateRef number)
|
||||||
{
|
{
|
||||||
auto env = GetEnvironment();
|
auto env = GetEnvironment();
|
||||||
|
@ -870,6 +870,7 @@ public:
|
|||||||
GateRef CalArrayRelativePos(GateRef index, GateRef arrayLen);
|
GateRef CalArrayRelativePos(GateRef index, GateRef arrayLen);
|
||||||
GateRef AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength);
|
GateRef AppendSkipHole(GateRef glue, GateRef first, GateRef second, GateRef copyLength);
|
||||||
GateRef IntToEcmaString(GateRef glue, GateRef number);
|
GateRef IntToEcmaString(GateRef glue, GateRef number);
|
||||||
|
GateRef ToCharCode(GateRef number);
|
||||||
GateRef NumberToString(GateRef glue, GateRef number);
|
GateRef NumberToString(GateRef glue, GateRef number);
|
||||||
inline GateRef GetViewedArrayBuffer(GateRef dataView);
|
inline GateRef GetViewedArrayBuffer(GateRef dataView);
|
||||||
inline GateRef GetByteOffset(GateRef dataView);
|
inline GateRef GetByteOffset(GateRef dataView);
|
||||||
|
@ -60,7 +60,8 @@ namespace panda::ecmascript {
|
|||||||
V(InvalidStringLength, "Invalid string length") \
|
V(InvalidStringLength, "Invalid string length") \
|
||||||
V(InvalidNewTarget, "new.target is not an object") \
|
V(InvalidNewTarget, "new.target is not an object") \
|
||||||
V(ObjIsNotCallable, "obj is not Callable") \
|
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) \
|
#define DEBUG_CHECK_MESSAGE_STRING_LIST(V) \
|
||||||
V(IsCallable) \
|
V(IsCallable) \
|
||||||
|
@ -102,3 +102,18 @@
|
|||||||
-12
|
-12
|
||||||
-1.2e+3
|
-1.2e+3
|
||||||
-1.235e+4
|
-1.235e+4
|
||||||
|
0
|
||||||
|
1
|
||||||
|
-9
|
||||||
|
1234567
|
||||||
|
-1234567
|
||||||
|
10000
|
||||||
|
67345
|
||||||
|
0
|
||||||
|
9
|
||||||
|
5a
|
||||||
|
0
|
||||||
|
-5a
|
||||||
|
5yc1z
|
||||||
|
3lnj8l
|
||||||
|
-3lnj8l
|
||||||
|
@ -133,4 +133,26 @@ testToPrecision(Number(-.00012345), (2));
|
|||||||
testToPrecision(Number(-1.2345), (2));
|
testToPrecision(Number(-1.2345), (2));
|
||||||
testToPrecision(Number(-12.345), (2));
|
testToPrecision(Number(-12.345), (2));
|
||||||
testToPrecision(Number(-1234.5), (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));
|
Loading…
Reference in New Issue
Block a user