mirror of
https://github.com/openharmony/ark_js_runtime.git
synced 2026-07-22 07:35:27 -04:00
50ee964a21
Signed-off-by: wupengyong <wupengyong@huawei.com> Change-Id: I085d81d00b00a0b49daa0d28af591b83dc1c9759
1188 lines
45 KiB
C++
1188 lines
45 KiB
C++
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "fast_stub.h"
|
|
#include "ecmascript/base/number_helper.h"
|
|
#include "ecmascript/js_array.h"
|
|
#include "ecmascript/message_string.h"
|
|
#include "ecmascript/tagged_hash_table-inl.h"
|
|
#include "llvm_ir_builder.h"
|
|
|
|
namespace kungfu {
|
|
using namespace panda::ecmascript;
|
|
void FastArrayLoadElementStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift aVal = Int64Argument(0);
|
|
AddrShift indexVal = Int32Argument(1);
|
|
|
|
// load a.length
|
|
AddrShift lengthOffset = GetInteger32Constant(JSArray::GetArrayLengthOffset());
|
|
if (PtrValueCode() == ValueCode::INT64) {
|
|
lengthOffset = SExtInt32ToInt64(lengthOffset);
|
|
} else if (PtrValueCode() == ValueCode::INT32) {
|
|
aVal = TruncInt64ToInt32(aVal);
|
|
}
|
|
AddrShift taggedLength = Load(MachineType::TAGGED_TYPE, aVal, lengthOffset);
|
|
AddrShift intLength = TaggedCastToInt32(taggedLength);
|
|
// if index < length
|
|
Label ifTrue(env);
|
|
Label ifFalse(env);
|
|
Branch(Int32LessThan(indexVal, intLength), &ifTrue, &ifFalse);
|
|
Bind(&ifTrue);
|
|
Return(LoadFromObject(MachineType::TAGGED_TYPE, aVal, indexVal));
|
|
Bind(&ifFalse);
|
|
Return(GetUndefinedConstant());
|
|
}
|
|
|
|
void FastAddStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift x = Int64Argument(0);
|
|
AddrShift y = Int64Argument(1);
|
|
DEFVARIABLE(intX, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(intY, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0);
|
|
DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0);
|
|
Label xIsNumber(env);
|
|
Label xNotNumberOryNotNumber(env);
|
|
Label xIsNumberAndyIsNumber(env);
|
|
Label xIsDoubleAndyIsDouble(env);
|
|
Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&xIsNumber);
|
|
{
|
|
Label yIsNumber(env);
|
|
// if right.IsNumber()
|
|
Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&yIsNumber);
|
|
{
|
|
Label xIsInt(env);
|
|
Label xNotInt(env);
|
|
Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
|
|
Bind(&xIsInt);
|
|
{
|
|
intX = TaggedCastToInt32(x);
|
|
doubleX = CastInt32ToFloat64(*intX);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
Bind(&xNotInt);
|
|
{
|
|
doubleX = TaggedCastToDouble(x);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
}
|
|
}
|
|
Bind(&xNotNumberOryNotNumber);
|
|
Return(GetHoleConstant());
|
|
Label yIsInt(env);
|
|
Label yNotInt(env);
|
|
Bind(&xIsNumberAndyIsNumber);
|
|
{
|
|
Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
|
|
Bind(&yIsInt);
|
|
{
|
|
intY = TaggedCastToInt32(y);
|
|
doubleY = CastInt32ToFloat64(*intY);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
Bind(&yNotInt);
|
|
{
|
|
doubleY = TaggedCastToDouble(y);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
}
|
|
Bind(&xIsDoubleAndyIsDouble);
|
|
doubleX = DoubleAdd(*doubleX, *doubleY);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
}
|
|
|
|
void FastSubStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift x = Int64Argument(0);
|
|
AddrShift y = Int64Argument(1);
|
|
DEFVARIABLE(intX, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(intY, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0);
|
|
DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0);
|
|
Label xIsNumber(env);
|
|
Label xNotNumberOryNotNumber(env);
|
|
Label xNotIntOryNotInt(env);
|
|
Label xIsIntAndyIsInt(env);
|
|
// if x is number
|
|
Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&xIsNumber);
|
|
{
|
|
Label yIsNumber(env);
|
|
// if y is number
|
|
Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
|
|
{
|
|
Bind(&yIsNumber);
|
|
{
|
|
Label xIsInt(env);
|
|
Label xNotInt(env);
|
|
Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
|
|
Bind(&xIsInt);
|
|
{
|
|
intX = TaggedCastToInt32(x);
|
|
Label yIsInt(env);
|
|
Label yNotInt(env);
|
|
Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
|
|
Bind(&yIsInt);
|
|
{
|
|
intY = TaggedCastToInt32(y);
|
|
intX = Int32Sub(*intX, *intY);
|
|
Jump(&xIsIntAndyIsInt);
|
|
}
|
|
Bind(&yNotInt);
|
|
{
|
|
doubleY = TaggedCastToDouble(y);
|
|
doubleX = CastInt32ToFloat64(*intX);
|
|
Jump(&xNotIntOryNotInt);
|
|
}
|
|
}
|
|
Bind(&xNotInt);
|
|
{
|
|
Label yIsInt(env);
|
|
Label yNotInt(env);
|
|
doubleX = TaggedCastToDouble(x);
|
|
Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
|
|
Bind(&yIsInt);
|
|
{
|
|
intY = TaggedCastToInt32(y);
|
|
doubleY = CastInt32ToFloat64(*intY);
|
|
Jump(&xNotIntOryNotInt);
|
|
}
|
|
Bind(&yNotInt);
|
|
{
|
|
doubleY = TaggedCastToDouble(y);
|
|
Jump(&xNotIntOryNotInt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Bind(&xNotNumberOryNotNumber);
|
|
Return(GetHoleConstant());
|
|
Bind(&xNotIntOryNotInt);
|
|
doubleX = DoubleSub(*doubleX, *doubleY);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
Bind(&xIsIntAndyIsInt);
|
|
Return(IntBuildTagged(*intX));
|
|
}
|
|
|
|
void FastMulStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift x = Int64Argument(0);
|
|
AddrShift y = Int64Argument(1);
|
|
DEFVARIABLE(intX, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(intY, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0);
|
|
DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0);
|
|
Label xIsNumber(env);
|
|
Label xNotNumberOryNotNumber(env);
|
|
Label xIsNumberAndyIsNumber(env);
|
|
Label xIsDoubleAndyIsDouble(env);
|
|
Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&xIsNumber);
|
|
{
|
|
Label yIsNumber(env);
|
|
// if right.IsNumber()
|
|
Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&yIsNumber);
|
|
{
|
|
Label xIsInt(env);
|
|
Label xNotInt(env);
|
|
Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
|
|
Bind(&xIsInt);
|
|
{
|
|
intX = TaggedCastToInt32(x);
|
|
doubleX = CastInt32ToFloat64(*intX);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
Bind(&xNotInt);
|
|
{
|
|
doubleX = TaggedCastToDouble(x);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
}
|
|
}
|
|
Bind(&xNotNumberOryNotNumber);
|
|
Return(GetHoleConstant());
|
|
Label yIsInt(env);
|
|
Label yNotInt(env);
|
|
Bind(&xIsNumberAndyIsNumber);
|
|
{
|
|
Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
|
|
Bind(&yIsInt);
|
|
{
|
|
intY = TaggedCastToInt32(y);
|
|
doubleY = CastInt32ToFloat64(*intY);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
Bind(&yNotInt);
|
|
{
|
|
doubleY = TaggedCastToDouble(y);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
}
|
|
Bind(&xIsDoubleAndyIsDouble);
|
|
doubleX = DoubleMul(*doubleX, *doubleY);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
}
|
|
|
|
void FastDivStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift x = Int64Argument(0);
|
|
AddrShift y = Int64Argument(1);
|
|
DEFVARIABLE(intX, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(intY, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0);
|
|
DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0);
|
|
Label xIsNumber(env);
|
|
Label xNotNumberOryNotNumber(env);
|
|
Label xIsNumberAndyIsNumber(env);
|
|
Label xIsDoubleAndyIsDouble(env);
|
|
Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&xIsNumber);
|
|
{
|
|
Label yIsNumber(env);
|
|
// if right.IsNumber()
|
|
Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&yIsNumber);
|
|
{
|
|
Label xIsInt(env);
|
|
Label xNotInt(env);
|
|
Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
|
|
Bind(&xIsInt);
|
|
{
|
|
intX = TaggedCastToInt32(x);
|
|
doubleX = CastInt32ToFloat64(*intX);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
Bind(&xNotInt);
|
|
{
|
|
doubleX = TaggedCastToDouble(x);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
}
|
|
}
|
|
Bind(&xNotNumberOryNotNumber);
|
|
Return(GetHoleConstant());
|
|
Label yIsInt(env);
|
|
Label yNotInt(env);
|
|
Bind(&xIsNumberAndyIsNumber);
|
|
Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
|
|
Bind(&yIsInt);
|
|
{
|
|
intY = TaggedCastToInt32(y);
|
|
doubleY = CastInt32ToFloat64(*intY);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
Bind(&yNotInt);
|
|
{
|
|
doubleY = TaggedCastToDouble(y);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
Bind(&xIsDoubleAndyIsDouble);
|
|
{
|
|
Label divisorIsZero(env);
|
|
Label divisorNotZero(env);
|
|
Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &divisorIsZero, &divisorNotZero);
|
|
Bind(&divisorIsZero);
|
|
{
|
|
Label xIsZeroOrNan(env);
|
|
Label xNeiZeroOrNan(env);
|
|
Label xIsZero(env);
|
|
Label xNotZero(env);
|
|
// dLeft == 0.0 || std::isnan(dLeft)
|
|
Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsZero, &xNotZero);
|
|
Bind(&xIsZero);
|
|
Jump(&xIsZeroOrNan);
|
|
Bind(&xNotZero);
|
|
{
|
|
Label xIsNan(env);
|
|
Label xNotNan(env);
|
|
Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan);
|
|
Bind(&xIsNan);
|
|
Jump(&xIsZeroOrNan);
|
|
Bind(&xNotNan);
|
|
Jump(&xNeiZeroOrNan);
|
|
}
|
|
Bind(&xIsZeroOrNan);
|
|
Return(DoubleBuildTagged(GetDoubleConstant(base::NAN_VALUE)));
|
|
Bind(&xNeiZeroOrNan);
|
|
{
|
|
AddrShift intXTmp = CastDoubleToInt64(*doubleX);
|
|
AddrShift intYtmp = CastDoubleToInt64(*doubleY);
|
|
intXTmp = Word64And(Word64Xor(intXTmp, intYtmp), GetWord64Constant(base::DOUBLE_SIGN_MASK));
|
|
intXTmp = Word64Xor(intXTmp, CastDoubleToInt64(GetDoubleConstant(base::POSITIVE_INFINITY)));
|
|
doubleX = CastInt64ToFloat64(intXTmp);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
}
|
|
}
|
|
Bind(&divisorNotZero);
|
|
{
|
|
doubleX = DoubleDiv(*doubleX, *doubleY);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
}
|
|
}
|
|
}
|
|
|
|
void FindOwnElementStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift obj = PtrArgument(1);
|
|
AddrShift index = Int32Argument(2); // 2: 3rd parameter - index
|
|
|
|
Label notDict(env);
|
|
Label isDict(env);
|
|
Label invalidValue(env);
|
|
Label end(env);
|
|
AddrShift elements = Load(POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET));
|
|
|
|
Branch(IsDictionaryMode(elements), &isDict, ¬Dict);
|
|
Bind(¬Dict);
|
|
{
|
|
Label outOfArray(env);
|
|
Label notOutOfArray(env);
|
|
AddrShift arrayLength = Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset()));
|
|
Branch(Int32LessThanOrEqual(arrayLength, index), &outOfArray, ¬OutOfArray);
|
|
Bind(&outOfArray);
|
|
Jump(&invalidValue);
|
|
Bind(¬OutOfArray);
|
|
{
|
|
AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize()));
|
|
AddrShift dataIndex = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset()));
|
|
AddrShift value = Load(TAGGED_TYPE, elements, dataIndex);
|
|
Label isHole1(env);
|
|
Label notHole1(env);
|
|
Branch(TaggedIsHole(value), &isHole1, ¬Hole1);
|
|
Bind(&isHole1);
|
|
Jump(&invalidValue);
|
|
Bind(¬Hole1);
|
|
Return(value);
|
|
}
|
|
Bind(&invalidValue);
|
|
Return(GetHoleConstant());
|
|
}
|
|
// IsDictionary
|
|
Bind(&isDict);
|
|
{
|
|
AddrShift taggedIndex = IntBuildTagged(index);
|
|
AddrShift entry = FindElementFromNumberDictionary(thread, elements, taggedIndex);
|
|
Label notNegtiveOne(env);
|
|
Label negtiveOne(env);
|
|
Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne);
|
|
Bind(¬NegtiveOne);
|
|
{
|
|
Return(GetValueFromDictionary(elements, entry));
|
|
}
|
|
Bind(&negtiveOne);
|
|
Jump(&end);
|
|
}
|
|
Bind(&end);
|
|
Return(GetHoleConstant());
|
|
}
|
|
|
|
void GetElementStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift receiver = Int64Argument(1);
|
|
AddrShift index = Int64Argument(2); // 2: 3rd parameter - index
|
|
Label isHole(env);
|
|
Label notHole(env);
|
|
Label loopHead(env);
|
|
Label loopEnd(env);
|
|
Label afterLoop(env);
|
|
Label notHeapObj(env);
|
|
|
|
Jump(&loopHead);
|
|
LoopBegin(&loopHead);
|
|
AddrShift objPtr = ChangeInt64ToPointer(receiver);
|
|
auto findOwnElementDescriptor = GET_STUBDESCRIPTOR(FindOwnElement);
|
|
AddrShift callFindOwnElementVal =
|
|
CallStub(findOwnElementDescriptor, GetWord64Constant(FAST_STUB_ID(FindOwnElement)), {thread, objPtr, index});
|
|
Branch(TaggedIsHole(callFindOwnElementVal), &isHole, ¬Hole);
|
|
Bind(¬Hole);
|
|
Return(callFindOwnElementVal);
|
|
Bind(&isHole);
|
|
receiver = Load(TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET));
|
|
Branch(TaggedIsHeapObject(receiver), &loopEnd, ¬HeapObj);
|
|
Bind(¬HeapObj);
|
|
Return(GetUndefinedConstant());
|
|
Bind(&loopEnd);
|
|
LoopEnd(&loopHead);
|
|
}
|
|
|
|
void FindOwnElement2Stub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift elements = PtrArgument(1);
|
|
AddrShift index = Int32Argument(2); // 2 : 3rd parameter
|
|
AddrShift isDict = Int32Argument(3); // 3 : 4th parameter
|
|
AddrShift attr = PtrArgument(4); // 4 : 5th parameter
|
|
AddrShift indexOrEntry = PtrArgument(5); // 5 : 6rd parameter
|
|
isDict = ZExtInt1ToInt32(isDict);
|
|
Label notDictionary(env);
|
|
Label isDictionary(env);
|
|
Label end(env);
|
|
Branch(Word32Equal(isDict, GetInteger32Constant(0)), ¬Dictionary, &isDictionary);
|
|
Bind(¬Dictionary);
|
|
{
|
|
AddrShift elementsLength =
|
|
Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset()));
|
|
Label outOfElements(env);
|
|
Label notOutOfElements(env);
|
|
Branch(Int32LessThanOrEqual(elementsLength, index), &outOfElements, ¬OutOfElements);
|
|
Bind(&outOfElements);
|
|
{
|
|
Return(GetHoleConstant());
|
|
}
|
|
Bind(¬OutOfElements);
|
|
{
|
|
AddrShift value = GetValueFromTaggedArray(elements, index);
|
|
Label isHole(env);
|
|
Label notHole(env);
|
|
Branch(TaggedIsHole(value), &isHole, ¬Hole);
|
|
Bind(&isHole);
|
|
Jump(&end);
|
|
Bind(¬Hole);
|
|
{
|
|
Store(UINT32_TYPE, attr, GetPtrConstant(0),
|
|
GetInteger32Constant(PropertyAttributes::GetDefaultAttributes()));
|
|
Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), index);
|
|
Return(value);
|
|
}
|
|
}
|
|
}
|
|
Bind(&isDictionary);
|
|
{
|
|
AddrShift entry = FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index));
|
|
Label notNegtiveOne(env);
|
|
Label negtiveOne(env);
|
|
Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne);
|
|
Bind(¬NegtiveOne);
|
|
{
|
|
Store(UINT32_TYPE, attr, GetPtrConstant(0), GetAttributesFromDictionary(elements, entry));
|
|
Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry);
|
|
Return(GetValueFromDictionary(elements, entry));
|
|
}
|
|
Bind(&negtiveOne);
|
|
Jump(&end);
|
|
}
|
|
Bind(&end);
|
|
Return(GetHoleConstant());
|
|
}
|
|
|
|
void SetElementStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift receiver = PtrArgument(1);
|
|
DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver);
|
|
AddrShift index = Int32Argument(2); // 2 : 3rd argument
|
|
AddrShift value = Int64Argument(3); // 3 : 4th argument
|
|
AddrShift mayThrow = Int32Argument(4); // 4 : 5th argument
|
|
DEFVARIABLE(onPrototype, MachineType::BOOL_TYPE, FalseConstant());
|
|
|
|
AddrShift pattr = Alloca(static_cast<int>(MachineRep::K_WORD32));
|
|
AddrShift pindexOrEntry = Alloca(static_cast<int>(MachineRep::K_WORD32));
|
|
Label loopHead(env);
|
|
Label loopEnd(env);
|
|
Jump(&loopHead);
|
|
LoopBegin(&loopHead);
|
|
{
|
|
AddrShift elements = GetElements(*holder);
|
|
AddrShift isDictionary = IsDictionaryMode(elements);
|
|
StubDescriptor *findOwnElemnt2 = GET_STUBDESCRIPTOR(FindOwnElement2);
|
|
AddrShift val = CallStub(findOwnElemnt2, GetWord64Constant(FAST_STUB_ID(FindOwnElement2)),
|
|
{thread, elements, index, isDictionary, pattr, pindexOrEntry});
|
|
Label notHole(env);
|
|
Label isHole(env);
|
|
Branch(TaggedIsNotHole(val), ¬Hole, &isHole);
|
|
Bind(¬Hole);
|
|
{
|
|
Label isOnProtoType(env);
|
|
Label notOnProtoType(env);
|
|
Label afterOnProtoType(env);
|
|
Branch(*onPrototype, &isOnProtoType, ¬OnProtoType);
|
|
Bind(¬OnProtoType);
|
|
Jump(&afterOnProtoType);
|
|
Bind(&isOnProtoType);
|
|
{
|
|
Label isExtensible(env);
|
|
Label notExtensible(env);
|
|
Label nextExtensible(env);
|
|
Branch(IsExtensible(receiver), &isExtensible, ¬Extensible);
|
|
Bind(&isExtensible);
|
|
Jump(&nextExtensible);
|
|
Bind(¬Extensible);
|
|
{
|
|
Label isThrow(env);
|
|
Label notThrow(env);
|
|
Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw);
|
|
Bind(&isThrow);
|
|
ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant());
|
|
Bind(¬Throw);
|
|
Return(FalseConstant());
|
|
}
|
|
Bind(&nextExtensible);
|
|
StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal);
|
|
Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)),
|
|
{thread, receiver, index, value,
|
|
GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())}));
|
|
}
|
|
Bind(&afterOnProtoType);
|
|
{
|
|
AddrShift attr = Load(INT32_TYPE, pattr);
|
|
Label isAccessor(env);
|
|
Label notAccessor(env);
|
|
Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
|
|
Bind(¬Accessor);
|
|
{
|
|
Label isWritable(env);
|
|
Label notWritable(env);
|
|
Branch(IsWritable(attr), &isWritable, ¬Writable);
|
|
Bind(&isWritable);
|
|
{
|
|
AddrShift elements = GetElements(receiver);
|
|
Label isDict(env);
|
|
Label notDict(env);
|
|
AddrShift indexOrEntry = Load(INT32_TYPE, pindexOrEntry);
|
|
Branch(isDictionary, &isDict, ¬Dict);
|
|
Bind(¬Dict);
|
|
{
|
|
StoreElement(elements, indexOrEntry, value);
|
|
UpdateRepresention(LoadHClass(receiver), value);
|
|
Return(TrueConstant());
|
|
}
|
|
Bind(&isDict);
|
|
{
|
|
UpdateValueAndAttributes(elements, indexOrEntry, value, attr);
|
|
Return(TrueConstant());
|
|
}
|
|
}
|
|
Bind(¬Writable);
|
|
{
|
|
Label isThrow(env);
|
|
Label notThrow(env);
|
|
Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw);
|
|
Bind(&isThrow);
|
|
ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), FalseConstant());
|
|
Bind(¬Throw);
|
|
Return(FalseConstant());
|
|
}
|
|
}
|
|
Bind(&isAccessor);
|
|
{
|
|
StubDescriptor *callsetter = GET_STUBDESCRIPTOR(CallSetter);
|
|
AddrShift setter = GetSetterFromAccessor(val);
|
|
Return(CallRuntime(callsetter, thread, GetWord64Constant(FAST_STUB_ID(CallSetter)),
|
|
{thread, setter, receiver, value, TruncInt32ToInt1(mayThrow)}));
|
|
}
|
|
}
|
|
}
|
|
Bind(&isHole);
|
|
{
|
|
// holder equals to
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
Label isHeapObj(env);
|
|
Label notHeapObj(env);
|
|
Branch(TaggedIsObject(*holder), &isHeapObj, ¬HeapObj);
|
|
Bind(¬HeapObj);
|
|
{
|
|
Label isExtensible(env);
|
|
Label notExtensible(env);
|
|
Label nextExtensible(env);
|
|
Branch(IsExtensible(receiver), &isExtensible, ¬Extensible);
|
|
Bind(&isExtensible);
|
|
Jump(&nextExtensible);
|
|
Bind(¬Extensible);
|
|
{
|
|
Label isThrow(env);
|
|
Label notThrow(env);
|
|
Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw);
|
|
Bind(&isThrow);
|
|
ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant());
|
|
Bind(¬Throw);
|
|
Return(FalseConstant());
|
|
}
|
|
Bind(&nextExtensible);
|
|
{
|
|
StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal);
|
|
Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)),
|
|
{thread, receiver, index, value,
|
|
GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())}));
|
|
}
|
|
}
|
|
Bind(&isHeapObj);
|
|
{
|
|
Label isJsProxy(env);
|
|
Label notJsProxy(env);
|
|
Branch(IsJsProxy(*holder), &isJsProxy, ¬JsProxy);
|
|
Bind(&isJsProxy);
|
|
{
|
|
StubDescriptor *setProperty = GET_STUBDESCRIPTOR(JSProxySetProperty);
|
|
Return(CallRuntime(
|
|
setProperty, thread, GetWord64Constant(FAST_STUB_ID(JSProxySetProperty)),
|
|
{thread, *holder, IntBuildTagged(index), value, receiver, TruncInt32ToInt1(mayThrow)}));
|
|
}
|
|
Bind(¬JsProxy);
|
|
onPrototype = TrueConstant();
|
|
Jump(&loopEnd);
|
|
}
|
|
}
|
|
}
|
|
Bind(&loopEnd);
|
|
LoopEnd(&loopHead);
|
|
}
|
|
|
|
void GetPropertyByIndexStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift receiver = PtrArgument(1);
|
|
AddrShift index = Int32Argument(2); /* 2 : 3rd parameter is index */
|
|
|
|
DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver);
|
|
Label loopHead(env);
|
|
Label loopEnd(env);
|
|
Label loopExit(env);
|
|
Label afterLoop(env);
|
|
Jump(&loopHead);
|
|
LoopBegin(&loopHead);
|
|
{
|
|
AddrShift hclass = LoadHClass(*holder);
|
|
AddrShift jsType = GetObjectType(hclass);
|
|
Label isSpecialIndexed(env);
|
|
Label notSpecialIndexed(env);
|
|
Label loopEnd(env);
|
|
Branch(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed);
|
|
Bind(&isSpecialIndexed);
|
|
{
|
|
Return(GetHoleConstant());
|
|
}
|
|
Bind(¬SpecialIndexed);
|
|
{
|
|
AddrShift elements = GetElements(*holder);
|
|
Label isDictionaryElement(env);
|
|
Label notDictionaryElement(env);
|
|
Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
|
|
Bind(¬DictionaryElement);
|
|
{
|
|
Label lessThanLength(env);
|
|
Label notLessThanLength(env);
|
|
Branch(Word32LessThan(index, GetLengthofElements(elements)), &lessThanLength, ¬LessThanLength);
|
|
Bind(&lessThanLength);
|
|
{
|
|
Label notHole(env);
|
|
Label isHole(env);
|
|
AddrShift value = GetValueFromTaggedArray(elements, index);
|
|
Branch(TaggedIsNotHole(value), ¬Hole, &isHole);
|
|
Bind(¬Hole);
|
|
{
|
|
Return(value);
|
|
}
|
|
Bind(&isHole);
|
|
{
|
|
Jump(&loopExit);
|
|
}
|
|
}
|
|
Bind(¬LessThanLength);
|
|
{
|
|
Return(GetHoleConstant());
|
|
}
|
|
}
|
|
Bind(&isDictionaryElement);
|
|
{
|
|
AddrShift entry =
|
|
FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index));
|
|
Label notNegtiveOne(env);
|
|
Label negtiveOne(env);
|
|
Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne);
|
|
Bind(¬NegtiveOne);
|
|
{
|
|
AddrShift attr = GetAttributesFromDictionary(elements, entry);
|
|
AddrShift value = GetValueFromDictionary(elements, entry);
|
|
Label isAccessor(env);
|
|
Label notAccessor(env);
|
|
Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
|
|
Bind(&isAccessor);
|
|
{
|
|
Label isInternal(env);
|
|
Label notInternal(env);
|
|
Branch(IsAccessorInternal(value), &isInternal, ¬Internal);
|
|
Bind(&isInternal);
|
|
{
|
|
StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter);
|
|
Return(CallRuntime(callAccessorGetter, thread,
|
|
GetWord64Constant(FAST_STUB_ID(AccessorGetter)),
|
|
{thread, *holder, value}));
|
|
}
|
|
Bind(¬Internal);
|
|
{
|
|
StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter);
|
|
Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)),
|
|
{thread, receiver, value}));
|
|
}
|
|
}
|
|
Bind(¬Accessor);
|
|
{
|
|
Return(value);
|
|
}
|
|
}
|
|
Bind(&negtiveOne);
|
|
Jump(&loopExit);
|
|
}
|
|
Bind(&loopExit);
|
|
{
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
|
}
|
|
}
|
|
Bind(&loopEnd);
|
|
LoopEnd(&loopHead);
|
|
Bind(&afterLoop);
|
|
{
|
|
Return(GetUndefinedConstant());
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetPropertyByIndexStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift receiver = PtrArgument(1);
|
|
AddrShift index = Int32Argument(2); /* 2 : 3rd parameter is index */
|
|
AddrShift value = Int64Argument(3); /* 3 : 4th parameter is value */
|
|
|
|
DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver);
|
|
Label loopHead(env);
|
|
Label loopEnd(env);
|
|
Label loopExit(env);
|
|
Label afterLoop(env);
|
|
Jump(&loopHead);
|
|
LoopBegin(&loopHead);
|
|
{
|
|
AddrShift hclass = LoadHClass(*holder);
|
|
AddrShift jsType = GetObjectType(hclass);
|
|
Label isSpecialIndex(env);
|
|
Label notSpecialIndex(env);
|
|
Branch(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
|
|
Bind(&isSpecialIndex);
|
|
Return(GetHoleConstant());
|
|
Bind(¬SpecialIndex);
|
|
{
|
|
AddrShift elements = GetElements(*holder);
|
|
Label isDictionaryElement(env);
|
|
Label notDictionaryElement(env);
|
|
Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
|
|
Bind(¬DictionaryElement);
|
|
{
|
|
Label isReceiver(env);
|
|
Label notReceiver(env);
|
|
Branch(Word64Equal(*holder, receiver), &isReceiver, ¬Receiver);
|
|
Bind(&isReceiver);
|
|
{
|
|
AddrShift length = GetLengthofElements(elements);
|
|
Label inRange(env);
|
|
Branch(Word64LessThan(index, length), &inRange, &loopExit);
|
|
Bind(&inRange);
|
|
{
|
|
AddrShift value1 = GetValueFromTaggedArray(elements, index);
|
|
Label notHole(env);
|
|
Branch(Word64NotEqual(value1, GetHoleConstant()), ¬Hole, &loopExit);
|
|
Bind(¬Hole);
|
|
{
|
|
StoreElement(elements, index, value);
|
|
Return(GetUndefinedConstant());
|
|
}
|
|
}
|
|
}
|
|
Bind(¬Receiver);
|
|
Jump(&afterLoop);
|
|
}
|
|
Bind(&isDictionaryElement);
|
|
Return(GetHoleConstant());
|
|
}
|
|
Bind(&loopExit);
|
|
{
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
|
}
|
|
}
|
|
Bind(&loopEnd);
|
|
LoopEnd(&loopHead);
|
|
Bind(&afterLoop);
|
|
{
|
|
Label isExtensible(env);
|
|
Label notExtensible(env);
|
|
Branch(IsExtensible(receiver), &isExtensible, ¬Extensible);
|
|
Bind(&isExtensible);
|
|
{
|
|
StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal);
|
|
AddrShift result = CallRuntime(addElementInternal, thread,
|
|
GetWord64Constant(FAST_STUB_ID(AddElementInternal)),
|
|
{thread, receiver, index, value,
|
|
GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())});
|
|
Label success(env);
|
|
Label failed(env);
|
|
Branch(result, &success, &failed);
|
|
Bind(&success);
|
|
Return(GetUndefinedConstant());
|
|
Bind(&failed);
|
|
Return(GetExceptionConstant());
|
|
}
|
|
Bind(¬Extensible);
|
|
{
|
|
ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), GetExceptionConstant());
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetPropertyByNameStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift receiver = Int64Argument(1);
|
|
AddrShift key = Int64Argument(2); // 2 : 3rd para
|
|
DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver);
|
|
Label loopHead(env);
|
|
Label loopEnd(env);
|
|
Label loopExit(env);
|
|
Label afterLoop(env);
|
|
// a do-while loop
|
|
Jump(&loopHead);
|
|
LoopBegin(&loopHead);
|
|
{
|
|
// auto *hclass = holder.GetTaggedObject()->GetClass()
|
|
// JSType jsType = hclass->GetObjectType()
|
|
AddrShift hClass = LoadHClass(*holder);
|
|
AddrShift jsType = GetObjectType(hClass);
|
|
Label isSIndexObj(env);
|
|
Label notSIndexObj(env);
|
|
// if branch condition : IsSpecialIndexedObj(jsType)
|
|
Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
|
|
Bind(&isSIndexObj);
|
|
{
|
|
Return(GetHoleConstant());
|
|
}
|
|
Bind(¬SIndexObj);
|
|
{
|
|
Label isDicMode(env);
|
|
Label notDicMode(env);
|
|
// if branch condition : LIKELY(!hclass->IsDictionaryMode())
|
|
Branch(IsDictionaryElement(hClass), &isDicMode, ¬DicMode);
|
|
Bind(¬DicMode);
|
|
{
|
|
// LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject())
|
|
AddrShift layOutInfo = GetAttributesFromHclass(hClass);
|
|
// int propsNumber = hclass->GetPropertiesNumber()
|
|
AddrShift propsNum = ChangeInt64ToInt32(GetPropertiesNumberFromHClass(hClass));
|
|
// int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
|
|
StubDescriptor *findElemWithCache = GET_STUBDESCRIPTOR(FindElementWithCache);
|
|
AddrShift entry = CallRuntime(findElemWithCache, thread,
|
|
GetWord64Constant(FAST_STUB_ID(FindElementWithCache)),
|
|
{thread, hClass, key, propsNum});
|
|
Label hasEntry(env);
|
|
Label noEntry(env);
|
|
// if branch condition : entry != -1
|
|
Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), &hasEntry, &noEntry);
|
|
Bind(&hasEntry);
|
|
{
|
|
// PropertyAttributes attr(layoutInfo->GetAttr(entry))
|
|
AddrShift propAttr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
|
|
AddrShift attr = TaggedCastToInt32(propAttr);
|
|
// auto value = JSObject::Cast(holder)->GetProperty(hclass, attr)
|
|
AddrShift value = JSObjectGetProperty(*holder, hClass, attr);
|
|
Label isAccessor(env);
|
|
Label notAccessor(env);
|
|
Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
|
|
Bind(&isAccessor);
|
|
{
|
|
Label isInternal(env);
|
|
Label notInternal(env);
|
|
Branch(IsAccessorInternal(value), &isInternal, ¬Internal);
|
|
Bind(&isInternal);
|
|
{
|
|
StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter);
|
|
Return(CallRuntime(callAccessorGetter, thread,
|
|
GetWord64Constant(FAST_STUB_ID(AccessorGetter)),
|
|
{thread, *holder, value}));
|
|
}
|
|
Bind(¬Internal);
|
|
{
|
|
StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter);
|
|
Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)),
|
|
{thread, receiver, value}));
|
|
}
|
|
}
|
|
Bind(¬Accessor);
|
|
{
|
|
Return(value);
|
|
}
|
|
}
|
|
Bind(&noEntry);
|
|
{
|
|
Jump(&loopExit);
|
|
}
|
|
}
|
|
Bind(&isDicMode);
|
|
{
|
|
// TaggedArray *array = TaggedArray::Cast(JSObject::Cast(holder)->GetProperties().GetTaggedObject())
|
|
AddrShift array = GetProperties(*holder);
|
|
// int entry = dict->FindEntry(key)
|
|
AddrShift entry = FindEntryFromNameDictionary(thread, array, key);
|
|
Label notNegtiveOne(env);
|
|
Label negtiveOne(env);
|
|
// if branch condition : entry != -1
|
|
Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne);
|
|
Bind(¬NegtiveOne);
|
|
{
|
|
// auto value = dict->GetValue(entry)
|
|
AddrShift attr = GetAttributesFromDictionary(array, entry);
|
|
// auto attr = dict->GetAttributes(entry)
|
|
AddrShift value = GetValueFromDictionary(array, entry);
|
|
Label isAccessor1(env);
|
|
Label notAccessor1(env);
|
|
// if branch condition : UNLIKELY(attr.IsAccessor())
|
|
Branch(IsAccessor(attr), &isAccessor1, ¬Accessor1);
|
|
Bind(&isAccessor1);
|
|
{
|
|
Label isInternal1(env);
|
|
Label notInternal1(env);
|
|
Branch(IsAccessorInternal(value), &isInternal1, ¬Internal1);
|
|
Bind(&isInternal1);
|
|
{
|
|
StubDescriptor *callAccessorGetter1 = GET_STUBDESCRIPTOR(AccessorGetter);
|
|
Return(CallRuntime(callAccessorGetter1, thread,
|
|
GetWord64Constant(FAST_STUB_ID(AccessorGetter)),
|
|
{thread, *holder, value}));
|
|
}
|
|
Bind(¬Internal1);
|
|
{
|
|
StubDescriptor *callGetter1 = GET_STUBDESCRIPTOR(CallGetter);
|
|
Return(CallRuntime(callGetter1, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)),
|
|
{thread, receiver, value}));
|
|
}
|
|
}
|
|
Bind(¬Accessor1);
|
|
{
|
|
Return(value);
|
|
}
|
|
}
|
|
Bind(&negtiveOne);
|
|
Jump(&loopExit);
|
|
}
|
|
Bind(&loopExit);
|
|
{
|
|
// holder = hclass->GetPrototype()
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
// loop condition for a do-while loop
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
|
}
|
|
}
|
|
Bind(&loopEnd);
|
|
LoopEnd(&loopHead);
|
|
Bind(&afterLoop);
|
|
{
|
|
Return(GetUndefinedConstant());
|
|
}
|
|
}
|
|
}
|
|
|
|
void FastModStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift x = Int64Argument(0);
|
|
AddrShift y = Int64Argument(1);
|
|
DEFVARIABLE(intX, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(intY, MachineType::INT32_TYPE, 0);
|
|
DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0);
|
|
DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0);
|
|
Label xIsInt(env);
|
|
Label xNotIntOryNotInt(env);
|
|
Branch(TaggedIsInt(x), &xIsInt, &xNotIntOryNotInt);
|
|
Bind(&xIsInt);
|
|
{
|
|
Label yIsInt(env);
|
|
Label xIsIntAndyIsInt(env);
|
|
// if right.IsInt()
|
|
Branch(TaggedIsInt(y), &yIsInt, &xNotIntOryNotInt);
|
|
Bind(&yIsInt);
|
|
{
|
|
intX = TaggedCastToInt32(x);
|
|
intY = TaggedCastToInt32(y);
|
|
Jump(&xIsIntAndyIsInt);
|
|
}
|
|
Bind(&xIsIntAndyIsInt);
|
|
{
|
|
Label xGtZero(env);
|
|
Label xGtZeroAndyGtZero(env);
|
|
Branch(Int32GreaterThan(*intX, GetInteger32Constant(0)), &xGtZero, &xNotIntOryNotInt);
|
|
Bind(&xGtZero);
|
|
{
|
|
Branch(Int32GreaterThan(*intY, GetInteger32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt);
|
|
Bind(&xGtZeroAndyGtZero);
|
|
{
|
|
intX = Int32Mod(*intX, *intY);
|
|
Return(IntBuildTagged(*intX));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Bind(&xNotIntOryNotInt);
|
|
{
|
|
Label xIsNumber(env);
|
|
Label xNotNumberOryNotNumber(env);
|
|
Label xIsNumberAndyIsNumber(env);
|
|
Label xIsDoubleAndyIsDouble(env);
|
|
Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&xIsNumber);
|
|
{
|
|
Label yIsNumber(env);
|
|
// if right.IsNumber()
|
|
Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
|
|
Bind(&yIsNumber);
|
|
{
|
|
Label xIfInt(env);
|
|
Label xIfNotInt(env);
|
|
Branch(TaggedIsInt(x), &xIfInt, &xIfNotInt);
|
|
Bind(&xIfInt);
|
|
{
|
|
intX = TaggedCastToInt32(x);
|
|
doubleX = CastInt32ToFloat64(*intX);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
Bind(&xIfNotInt);
|
|
{
|
|
doubleX = TaggedCastToDouble(x);
|
|
Jump(&xIsNumberAndyIsNumber);
|
|
}
|
|
}
|
|
}
|
|
Bind(&xNotNumberOryNotNumber);
|
|
Return(GetHoleConstant());
|
|
Label yIfInt(env);
|
|
Label yIfNotInt(env);
|
|
Bind(&xIsNumberAndyIsNumber);
|
|
Branch(TaggedIsInt(y), &yIfInt, &yIfNotInt);
|
|
Bind(&yIfInt);
|
|
{
|
|
intY = TaggedCastToInt32(y);
|
|
doubleY = CastInt32ToFloat64(*intY);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
Bind(&yIfNotInt);
|
|
{
|
|
doubleY = TaggedCastToDouble(y);
|
|
Jump(&xIsDoubleAndyIsDouble);
|
|
}
|
|
Bind(&xIsDoubleAndyIsDouble);
|
|
{
|
|
Label yIsZero(env);
|
|
Label yNotZero(env);
|
|
Label yIsZeroOrNanOrxIsNanOrInf(env);
|
|
Label yNeiZeroOrNanAndxNeiNanOrInf(env);
|
|
// dRight == 0.0 or std::isnan(dRight) or std::isnan(dLeft) or std::isinf(dLeft)
|
|
Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &yIsZero, &yNotZero);
|
|
Bind(&yIsZero);
|
|
Jump(&yIsZeroOrNanOrxIsNanOrInf);
|
|
Bind(&yNotZero);
|
|
{
|
|
Label yIsNan(env);
|
|
Label yNotNan(env);
|
|
Branch(DoubleIsNAN(*doubleY), &yIsNan, &yNotNan);
|
|
Bind(&yIsNan);
|
|
Jump(&yIsZeroOrNanOrxIsNanOrInf);
|
|
Bind(&yNotNan);
|
|
{
|
|
Label xIsNan(env);
|
|
Label xNotNan(env);
|
|
Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan);
|
|
Bind(&xIsNan);
|
|
Jump(&yIsZeroOrNanOrxIsNanOrInf);
|
|
Bind(&xNotNan);
|
|
{
|
|
Label xIsInf(env);
|
|
Label xNotInf(env);
|
|
Branch(DoubleIsINF(*doubleX), &xIsInf, &xNotInf);
|
|
Bind(&xIsInf);
|
|
Jump(&yIsZeroOrNanOrxIsNanOrInf);
|
|
Bind(&xNotInf);
|
|
Jump(&yNeiZeroOrNanAndxNeiNanOrInf);
|
|
}
|
|
}
|
|
}
|
|
Bind(&yIsZeroOrNanOrxIsNanOrInf);
|
|
Return(DoubleBuildTagged(GetDoubleConstant(base::NAN_VALUE)));
|
|
Bind(&yNeiZeroOrNanAndxNeiNanOrInf);
|
|
{
|
|
Label xIsFloatZero(env);
|
|
Label xIsZeroOryIsInf(env);
|
|
Label xNotZeroAndyNotInf(env);
|
|
Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsFloatZero, &xNotZeroAndyNotInf);
|
|
Bind(&xIsFloatZero);
|
|
Jump(&xIsZeroOryIsInf);
|
|
Label yIsInf(env);
|
|
Label yNotInf(env);
|
|
Bind(&xNotZeroAndyNotInf);
|
|
Branch(DoubleIsINF(*doubleY), &yIsInf, &yNotInf);
|
|
Bind(&yIsInf);
|
|
Jump(&xIsZeroOryIsInf);
|
|
Bind(&yNotInf);
|
|
{
|
|
doubleX = DoubleMod(*doubleX, *doubleY);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
}
|
|
Bind(&xIsZeroOryIsInf);
|
|
Return(DoubleBuildTagged(*doubleX));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FunctionCallInternalStub::GenerateCircuit()
|
|
{
|
|
auto env = GetEnvironment();
|
|
AddrShift thread = PtrArgument(0);
|
|
AddrShift func = PtrArgument(1);
|
|
AddrShift thisArg = Int64Argument(2); /* 2 : 3rd parameter is value */
|
|
AddrShift argc = Int32Argument(3); /* 3 : 4th parameter is value */
|
|
AddrShift argv = PtrArgument(4); /* 4 : 5th parameter is ptr */
|
|
Label funcNotBuiltinsConstructor(env);
|
|
Label funcIsBuiltinsConstructorOrFuncNotClassConstructor(env);
|
|
Label funcIsClassConstructor(env);
|
|
Branch(NotBuiltinsConstructor(func), &funcNotBuiltinsConstructor,
|
|
&funcIsBuiltinsConstructorOrFuncNotClassConstructor);
|
|
Bind(&funcNotBuiltinsConstructor);
|
|
{
|
|
Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor);
|
|
Bind(&funcIsClassConstructor);
|
|
ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), FalseConstant());
|
|
}
|
|
Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor);
|
|
StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute);
|
|
Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)),
|
|
{thread, func, thisArg, argc, argv}));
|
|
}
|
|
} // namespace kungfu
|