!3893 Add function apply builtins ir

Merge pull request !3893 from wpy111/master
This commit is contained in:
openharmony_ci 2023-04-24 15:24:46 +00:00 committed by Gitee
commit 0140f8f663
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
26 changed files with 892 additions and 61 deletions

View File

@ -449,7 +449,8 @@ void Builtins::InitializeFunction(const JSHandle<GlobalEnv> &env, const JSHandle
// Function.prototype method
// 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
SetFunction(env, funcFuncPrototypeObj, "apply", Function::FunctionPrototypeApply, FunctionLength::TWO);
SetFunction(env, funcFuncPrototypeObj, "apply", Function::FunctionPrototypeApply, FunctionLength::TWO,
BUILTINS_STUB_ID(FunctionPrototypeApply));
// 19.2.3.2 Function.prototype.bind ( thisArg , ...args)
SetFunction(env, funcFuncPrototypeObj, "bind", Function::FunctionPrototypeBind, FunctionLength::ONE);
// 19.2.3.3 Function.prototype.call (thisArg , ...args)

View File

@ -107,6 +107,7 @@ int AssemblerModule::GetArgcFromJSCallMode(JSCallMode mode)
case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::CALL_ENTRY:
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return -1;
case JSCallMode::CALL_GETTER:
return 0;
@ -142,6 +143,7 @@ bool AssemblerModule::IsCallNew(JSCallMode mode)
case JSCallMode::CALL_ENTRY:
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return false;
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
@ -180,6 +182,7 @@ bool AssemblerModule::JSModeHaveThisArg(JSCallMode mode)
case JSCallMode::CALL_GETTER:
case JSCallMode::CALL_SETTER:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return true;
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
@ -209,6 +212,7 @@ bool AssemblerModule::JSModeHaveNewTargetArg(JSCallMode mode)
case JSCallMode::CALL_THIS_ARG1:
case JSCallMode::CALL_THIS_ARG2:
case JSCallMode::CALL_THIS_ARG3:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return false;
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
@ -249,6 +253,7 @@ bool AssemblerModule::IsJumpToCallCommonEntry(JSCallMode mode)
case JSCallMode::CALL_ENTRY:
case JSCallMode::CALL_GENERATOR:
case JSCallMode::CALL_FROM_AOT:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return false;
default:
LOG_ECMA(FATAL) << "this branch is unreachable";

View File

@ -50,6 +50,7 @@ namespace panda::ecmascript::kungfu {
V(ListForEach) \
V(ArrayListForEach) \
V(ArrayListReplaceAllElements) \
V(FunctionPrototypeApply) \
#define BUILTINS_CONSTRUCTOR_STUB_LIST(V) \
V(BooleanConstructor) \

View File

@ -107,7 +107,7 @@ GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, Gate
Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, &notcallThis1);
Bind(&callThis1);
{
GateRef arg0 = GetCallArg0();
GateRef arg0 = GetCallArg0(numArgs);
result =
CallBuiltinRuntime(glue, { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 });
Jump(&exit);
@ -117,17 +117,17 @@ GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, Gate
Branch(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2
Bind(&callThis2);
{
GateRef arg0 = GetCallArg0();
GateRef arg1 = GetCallArg1();
GateRef arg0 = GetCallArg0(numArgs);
GateRef arg1 = GetCallArg1(numArgs);
result = CallBuiltinRuntime(glue,
{ nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 });
Jump(&exit);
}
Bind(&callThis3);
{
GateRef arg0 = GetCallArg0();
GateRef arg1 = GetCallArg1();
GateRef arg2 = GetCallArg2();
GateRef arg0 = GetCallArg0(numArgs);
GateRef arg1 = GetCallArg1(numArgs);
GateRef arg2 = GetCallArg2(numArgs);
result = CallBuiltinRuntime(glue,
{ nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 });
Jump(&exit);
@ -172,7 +172,7 @@ DECLARE_BUILTINS(CharCodeAt)
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
Bind(&posTagNotUndefined);
{
GateRef posTag = GetCallArg0();
GateRef posTag = GetCallArg0(numArgs);
Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
Bind(&posTagIsInt);
pos = GetInt32OfTInt(posTag);
@ -238,7 +238,7 @@ DECLARE_BUILTINS(IndexOf)
Branch(IsString(thisValue), &isString, &slowPath);
Bind(&isString);
{
GateRef searchTag = GetCallArg0();
GateRef searchTag = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(searchTag), &searchTagIsHeapObject, &slowPath);
Bind(&searchTagIsHeapObject);
Branch(IsString(searchTag), &isSearchString, &slowPath);
@ -248,7 +248,7 @@ DECLARE_BUILTINS(IndexOf)
Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &next, &posTagNotUndefined);
Bind(&posTagNotUndefined);
{
GateRef posTag = GetCallArg1();
GateRef posTag = GetCallArg1(numArgs);
Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
Bind(&posTagIsInt);
pos = GetInt32OfTInt(posTag);
@ -356,7 +356,7 @@ DECLARE_BUILTINS(Substring)
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &startTagNotUndefined);
Bind(&startTagNotUndefined);
{
GateRef startTag = GetCallArg0();
GateRef startTag = GetCallArg0(numArgs);
Branch(TaggedIsInt(startTag), &posTagIsInt, &posTagNotInt);
Bind(&posTagIsInt);
start = GetInt32OfTInt(startTag);
@ -377,7 +377,7 @@ DECLARE_BUILTINS(Substring)
}
Bind(&endTagNotUndefined);
{
GateRef endTag = GetCallArg1();
GateRef endTag = GetCallArg1(numArgs);
Branch(TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt);
Bind(&endTagIsInt);
end = GetInt32OfTInt(endTag);
@ -504,7 +504,7 @@ DECLARE_BUILTINS(CharAt)
Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
Bind(&posTagNotUndefined);
{
GateRef posTag = GetCallArg0();
GateRef posTag = GetCallArg0(numArgs);
Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
Bind(&posTagIsInt);
pos = GetInt32OfTInt(posTag);
@ -826,6 +826,102 @@ DECLARE_BUILTINS(ArrayListReplaceAllElements)
Return(*res);
}
DECLARE_BUILTINS(FunctionPrototypeApply)
{
auto env = GetEnvironment();
DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
Label exit(env);
Label slowPath(env);
Label targetIsCallable(env);
Label targetIsUndefined(env);
Label targetNotUndefined(env);
Label isHeapObject(env);
//1. If IsCallable(func) is false, throw a TypeError exception
Branch(TaggedIsHeapObject(thisValue), &isHeapObject, &slowPath);
Bind(&isHeapObject);
{
Branch(IsCallable(thisValue), &targetIsCallable, &slowPath);
Bind(&targetIsCallable);
{
GateRef thisArg = GetCallArg0(numArgs);
GateRef arrayObj = GetCallArg1(numArgs);
// 2. If argArray is null or undefined, then
Branch(TaggedIsUndefined(arrayObj), &targetIsUndefined, &targetNotUndefined);
Bind(&targetIsUndefined);
{
// a. Return Call(func, thisArg).
res = JSCallDispatch(glue, thisValue, Int32(0), 0, Circuit::NullGate(),
JSCallMode::CALL_GETTER, { thisArg });
Jump(&exit);
}
Bind(&targetNotUndefined);
{
// 3. Let argList be CreateListFromArrayLike(argArray).
GateRef elements = BuildArgumentsListFastElements(glue, arrayObj);
Label targetIsHole(env);
Label targetNotHole(env);
Branch(TaggedIsHole(elements), &targetIsHole, &targetNotHole);
Bind(&targetIsHole);
{
GateRef argList = CreateListFromArrayLike(glue, arrayObj);
// 4. ReturnIfAbrupt(argList).
Label isPendingException(env);
Label noPendingException(env);
Branch(HasPendingException(glue), &isPendingException, &noPendingException);
Bind(&isPendingException);
{
Jump(&slowPath);
}
Bind(&noPendingException);
{
GateRef argsLength = GetLengthOfTaggedArray(argList);
GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(),
JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, argv, thisArg });
Jump(&exit);
}
}
Bind(&targetNotHole);
{
// 6. Return Call(func, thisArg, argList).
Label taggedIsStableJsArg(env);
Label taggedNotStableJsArg(env);
Branch(IsStableJSArguments(glue, arrayObj), &taggedIsStableJsArg, &taggedNotStableJsArg);
Bind(&taggedIsStableJsArg);
{
GateRef hClass = LoadHClass(arrayObj);
GateRef PropertyInlinedPropsOffset = IntPtr(JSArguments::LENGTH_INLINE_PROPERTY_INDEX);
GateRef result = GetPropertyInlinedProps(arrayObj, hClass, PropertyInlinedPropsOffset);
GateRef length = TaggedGetInt(result);
GateRef argsLength = MakeArgListWithHole(glue, elements, length);
GateRef elementArgv = PtrAdd(elements, IntPtr(TaggedArray::DATA_OFFSET));
res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(),
JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg });
Jump(&exit);
}
Bind(&taggedNotStableJsArg);
{
GateRef length = GetLengthOfJsArray(glue, arrayObj);
GateRef argsLength = MakeArgListWithHole(glue, elements, length);
GateRef elementArgv = PtrAdd(elements, IntPtr(TaggedArray::DATA_OFFSET));
res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(),
JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg });
Jump(&exit);
}
}
}
}
}
Bind(&slowPath);
{
res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
Jump(&exit);
}
Bind(&exit);
Return(*res);
}
DECLARE_BUILTINS(BooleanConstructor)
{
auto env = GetEnvironment();
@ -965,7 +1061,7 @@ DECLARE_BUILTINS(ArrayConstructor)
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
Branch(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath);
Branch(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath);
Bind(&fastGetHclass);
GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0));

View File

@ -64,19 +64,65 @@ public:
return Load(VariableType::JS_ANY(), info, thisOffset);
}
inline GateRef GetCallArg0()
inline GateRef GetCallArg0(GateRef numArg)
{
return TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG0_OR_ARGV));
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
Label isValid(env);
Label exit(env);
Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(0)), &isValid, &exit);
Bind(&isValid);
{
result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG0_OR_ARGV));
Jump(&exit);
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
inline GateRef GetCallArg1()
inline GateRef GetCallArg1(GateRef numArg)
{
return TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG1));
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
Label isValid(env);
Label exit(env);
Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(1)), &isValid, &exit);
Bind(&isValid);
{
result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG1));
Jump(&exit);
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
inline GateRef GetCallArg2()
inline GateRef GetCallArg2(GateRef numArg)
{
return TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG2));
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
Label isValid(env);
Label exit(env);
// 2: 2 args
Branch(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(2)), &isValid, &exit);
Bind(&isValid);
{
result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG2));
Jump(&exit);
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
inline GateRef GetArgv()

View File

@ -70,7 +70,7 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV
Label isCall(env);
Label notCall(env);
Label isHeapObj(env);
callbackFnHandle = GetCallArg0();
callbackFnHandle = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath);
Bind(&isHeapObj);
Branch(IsCallable(callbackFnHandle), &isCall, &notCall);
@ -82,7 +82,7 @@ void ContainersStubBuilder::ContainersCommonFuncCall(GateRef glue, GateRef thisV
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
thisArg = GetCallArg1(numArgs);
Jump(&nextCount);
}
}
@ -188,7 +188,7 @@ void ContainersStubBuilder::QueueCommonFuncCall(GateRef glue, GateRef thisValue,
Label isCall(env);
Label notCall(env);
Label isHeapObj(env);
callbackFnHandle = GetCallArg0();
callbackFnHandle = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath);
Bind(&isHeapObj);
Branch(IsCallable(callbackFnHandle), &isCall, &notCall);
@ -200,7 +200,7 @@ void ContainersStubBuilder::QueueCommonFuncCall(GateRef glue, GateRef thisValue,
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
thisArg = GetCallArg1(numArgs);
Jump(&nextCount);
}
}
@ -294,7 +294,7 @@ void ContainersStubBuilder::DequeCommonFuncCall(GateRef glue, GateRef thisValue,
Label isCall(env);
Label notCall(env);
Label isHeapObj(env);
callbackFnHandle = GetCallArg0();
callbackFnHandle = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath);
Bind(&isHeapObj);
Branch(IsCallable(callbackFnHandle), &isCall, &notCall);
@ -306,7 +306,7 @@ void ContainersStubBuilder::DequeCommonFuncCall(GateRef glue, GateRef thisValue,
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
thisArg = GetCallArg1(numArgs);
Jump(&nextCount);
}
}
@ -402,7 +402,7 @@ void ContainersStubBuilder::ContainersLightWeightCall(GateRef glue, GateRef this
Label isCall(env);
Label notCall(env);
Label isHeapObj(env);
callbackFnHandle = GetCallArg0();
callbackFnHandle = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, slowPath);
Bind(&isHeapObj);
Branch(IsCallable(callbackFnHandle), &isCall, &notCall);
@ -414,7 +414,7 @@ void ContainersStubBuilder::ContainersLightWeightCall(GateRef glue, GateRef this
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
thisArg = GetCallArg1(numArgs);
Jump(&nextCount);
}
}
@ -514,7 +514,7 @@ void ContainersStubBuilder::ContainersHashCall(GateRef glue, GateRef thisValue,
Label isCall(env);
Label notCall(env);
Label isHeapObj(env);
callbackFnHandle = GetCallArg0();
callbackFnHandle = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, &notCall);
Bind(&isHeapObj);
Branch(IsCallable(callbackFnHandle), &isCall, &notCall);
@ -526,7 +526,7 @@ void ContainersStubBuilder::ContainersHashCall(GateRef glue, GateRef thisValue,
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
thisArg = GetCallArg1(numArgs);
Jump(&nextCount);
}
}
@ -646,7 +646,7 @@ void ContainersStubBuilder::ContainersLinkedListCall(GateRef glue, GateRef thisV
Label isCall(env);
Label notCall(env);
Label isHeapObj(env);
callbackFnHandle = GetCallArg0();
callbackFnHandle = GetCallArg0(numArgs);
Branch(TaggedIsHeapObject(callbackFnHandle), &isHeapObj, &notCall);
Bind(&isHeapObj);
Branch(IsCallable(callbackFnHandle), &isCall, &notCall);
@ -658,7 +658,7 @@ void ContainersStubBuilder::ContainersLinkedListCall(GateRef glue, GateRef thisV
Bind(&thisArgUndefined);
Jump(&nextCount);
Bind(&thisArgNotUndefined);
thisArg = GetCallArg1();
thisArg = GetCallArg1(numArgs);
Jump(&nextCount);
}
}

View File

@ -1205,21 +1205,26 @@ DEF_CALL_SIGNATURE(CallContainersArgs3)
PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallContainersArgs3)
}
DEF_CALL_SIGNATURE(CallReturnWithArgv)
{
PUSH_CALL_ARGS_AND_DISPATCH_NATIVE_RANGE_SIGNATURE(CallReturnWithArgv)
}
DEF_CALL_SIGNATURE(JSCallWithArgV)
{
// 6 : 6 input parameters
CallSignature jSCallWithArgV("JSCallWithArgV", 0, 6,
// 5 : 5 input parameters
CallSignature jSCallWithArgV("JSCallWithArgV", 0, 5,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = jSCallWithArgV;
// 6 : 6 input parameters
std::array<VariableType, 6> params = {
// 5 : 5 input parameters
std::array<VariableType, 5> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::INT64(), // actualNumArgs
VariableType::JS_ANY(), // jsfunc
VariableType::JS_ANY(), // newTarget
VariableType::JS_ANY(), // this
VariableType::NATIVE_POINTER(), // argV
};
callSign->SetVariadicArgs(true);
callSign->SetParameters(params.data());
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
callSign->SetCallConv(CallSignature::CallConv::CCallConv);

View File

@ -439,6 +439,7 @@ private:
V(JSCallNewWithArgV) \
V(TimeClip) \
V(SetDateValues) \
V(CallReturnWithArgv) \
TEST_STUB_SIGNATRUE_LIST(V)
#define DECL_CALL_SIGNATURE(name) \

View File

@ -378,6 +378,15 @@ GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x)
return LogicAnd(isHeapObj, isAsyncGeneratorObj);
}
GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef x)
{
GateRef isHeapObj = TaggedIsHeapObject(x);
GateRef objType = GetObjectType(LoadHClass(x));
GateRef isGlobal = Equal(objType,
Int32(static_cast<int32_t>(JSType::JS_GLOBAL_OBJECT)));
return LogicAnd(isHeapObj, isGlobal);
}
GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x)
{
GateRef isHeapObj = TaggedIsHeapObject(x);
@ -639,6 +648,32 @@ GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass)
Int32(0));
}
GateRef CircuitBuilder::IsStableElements(GateRef hClass)
{
GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
return NotEqual(Int32And(Int32LSR(bitfield,
Int32(JSHClass::IsStableElementsBit::START_BIT)),
Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)),
Int32(0));
}
GateRef CircuitBuilder::IsStableArguments(GateRef hClass)
{
GateRef objectType = GetObjectType(hClass);
GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARGUMENTS)));
GateRef isStableElements = IsStableElements(hClass);
return BoolAnd(isStableElements, isJsArguments);
}
GateRef CircuitBuilder::IsStableArray(GateRef hClass)
{
GateRef objectType = GetObjectType(hClass);
GateRef isJsArray = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
GateRef isStableElements = IsStableElements(hClass);
return BoolAnd(isStableElements, isJsArray);
}
GateRef CircuitBuilder::IsClassConstructor(GateRef object)
{
GateRef hClass = LoadHClass(object);

View File

@ -402,6 +402,7 @@ public:
inline GateRef TaggedIsSpecial(GateRef x);
inline GateRef TaggedIsHeapObject(GateRef x);
inline GateRef TaggedIsAsyncGeneratorObject(GateRef x);
inline GateRef TaggedIsJSGlobalObject(GateRef x);
inline GateRef TaggedIsGeneratorObject(GateRef x);
inline GateRef TaggedIsPropertyBox(GateRef x);
inline GateRef TaggedIsWeak(GateRef x);
@ -493,6 +494,9 @@ public:
inline GateRef GetObjectType(GateRef hClass);
inline GateRef IsDictionaryModeByHClass(GateRef hClass);
inline GateRef IsIsStableElementsByHClass(GateRef hClass);
inline GateRef IsStableElements(GateRef hClass);
inline GateRef IsStableArguments(GateRef hClass);
inline GateRef IsStableArray(GateRef hClass);
inline GateRef DoubleIsINF(GateRef x);
inline GateRef IsDictionaryElement(GateRef hClass);
inline GateRef IsClassConstructor(GateRef object);

View File

@ -608,6 +608,10 @@ inline GateRef StubBuilder::TaggedIsAsyncGeneratorObject(GateRef x)
return env_->GetBuilder()->TaggedIsAsyncGeneratorObject(x);
}
inline GateRef StubBuilder::TaggedIsJSGlobalObject(GateRef x)
{
return env_->GetBuilder()->TaggedIsJSGlobalObject(x);
}
inline GateRef StubBuilder::TaggedIsWeak(GateRef x)
{
@ -2226,5 +2230,28 @@ inline void StubBuilder::Comment(GateRef glue, const std::string &str)
{
CallNGCRuntime(glue, RTSTUB_ID(Comment), { StringPtr(str) });
}
inline GateRef StubBuilder::IsStableElements(GateRef hClass)
{
return env_->GetBuilder()->IsStableElements(hClass);
}
inline GateRef StubBuilder::IsStableArguments(GateRef hClass)
{
return env_->GetBuilder()->IsStableArguments(hClass);
}
inline GateRef StubBuilder::IsStableArray(GateRef hClass)
{
return env_->GetBuilder()->IsStableArray(hClass);
}
inline GateRef StubBuilder::IsTypedArray(GateRef obj)
{
GateRef jsHclass = LoadHClass(obj);
GateRef jsType = GetObjectType(jsHclass);
return BoolAnd(Int32GreaterThan(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), jsType));
}
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_STUB_INL_H

View File

@ -19,11 +19,13 @@
#include "ecmascript/compiler/access_object_stub_builder.h"
#include "ecmascript/compiler/interpreter_stub.h"
#include "ecmascript/compiler/llvm_ir_builder.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/typed_array_stub_builder.h"
#include "ecmascript/js_api/js_api_arraylist.h"
#include "ecmascript/js_api/js_api_vector.h"
#include "ecmascript/js_object.h"
#include "ecmascript/js_arguments.h"
#include "ecmascript/mem/remembered_set.h"
#include "ecmascript/message_string.h"
#include "ecmascript/pgo_profiler/pgo_profiler_type.h"
@ -3268,6 +3270,35 @@ GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef ke
return ret;
}
GateRef StubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef obj, GateRef index)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
Label fastPath(env);
Label slowPath(env);
Branch(TaggedIsHeapObject(obj), &fastPath, &slowPath);
Bind(&fastPath);
{
result = GetPropertyByIndex(glue, obj, index);
Label notHole(env);
Branch(TaggedIsHole(*result), &slowPath, &exit);
}
Bind(&slowPath);
{
result = CallRuntime(glue, RTSTUB_ID(LdObjByIndex),
{ obj, IntToTaggedInt(index), TaggedFalse(), Undefined() });
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
{
auto env = GetEnvironment();
@ -4402,6 +4433,121 @@ GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpo
ConstPoolType::OBJECT_LITERAL);
}
// return elements
GateRef StubBuilder::BuildArgumentsListFastElements(GateRef glue, GateRef arrayObj)
{
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
Label exit(env);
Label hasStableElements(env);
Label targetIsStableJSArguments(env);
Label targetNotStableJSArguments(env);
Label targetIsInt(env);
Label hClassEqual(env);
Label targetIsStableJSArray(env);
Label targetNotStableJSArray(env);
Branch(HasStableElements(glue, arrayObj), &hasStableElements, &exit);
Bind(&hasStableElements);
{
Branch(IsStableJSArguments(glue, arrayObj), &targetIsStableJSArguments, &targetNotStableJSArguments);
Bind(&targetIsStableJSArguments);
{
GateRef hClass = LoadHClass(arrayObj);
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
GateRef argmentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
GlobalEnv::ARGUMENTS_CLASS);
Branch(Int32Equal(hClass, argmentsClass), &hClassEqual, &exit);
Bind(&hClassEqual);
{
GateRef PropertyInlinedPropsOffset = IntPtr(JSArguments::LENGTH_INLINE_PROPERTY_INDEX);
GateRef result = GetPropertyInlinedProps(arrayObj, hClass, PropertyInlinedPropsOffset);
Branch(TaggedIsInt(result), &targetIsInt, &exit);
Bind(&targetIsInt);
{
res = GetElementsArray(arrayObj);
Jump(&exit);
}
}
}
Bind(&targetNotStableJSArguments);
{
Branch(IsStableJSArray(glue, arrayObj), &targetIsStableJSArray, &targetNotStableJSArray);
Bind(&targetIsStableJSArray);
{
res = GetElementsArray(arrayObj);
Jump(&exit);
}
Bind(&targetNotStableJSArray);
{
FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
Jump(&exit);
}
}
}
Bind(&exit);
auto ret = *res;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::MakeArgListWithHole(GateRef glue, GateRef argv, GateRef length)
{
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(res, VariableType::INT32(), length);
DEFVARIABLE(i, VariableType::INT32(), Int32(0));
Label exit(env);
GateRef argsLength = GetLengthOfTaggedArray(argv);
Label lengthGreaterThanArgsLength(env);
Label lengthLessThanArgsLength(env);
Branch(Int32GreaterThan(length, argsLength), &lengthGreaterThanArgsLength, &lengthLessThanArgsLength);
Bind(&lengthGreaterThanArgsLength);
{
res = argsLength;
Jump(&lengthLessThanArgsLength);
}
Bind(&lengthLessThanArgsLength);
{
Label loopHead(env);
Label loopEnd(env);
Label afterLoop(env);
Label targetIsHole(env);
Label targetNotHole(env);
Branch(Int32UnsignedLessThan(*i, *res), &loopHead, &afterLoop);
LoopBegin(&loopHead);
{
GateRef value = GetValueFromTaggedArray(argv, *i);
Branch(TaggedIsHole(value), &targetIsHole, &targetNotHole);
Bind(&targetIsHole);
{
SetValueToTaggedArray(VariableType::JS_ANY(), glue, argv, *i, Undefined());
Jump(&targetNotHole);
}
Bind(&targetNotHole);
i = Int32Add(*i, Int32(1));
Branch(Int32UnsignedLessThan(*i, *res), &loopEnd, &afterLoop);
}
Bind(&loopEnd);
LoopEnd(&loopHead);
Bind(&afterLoop);
{
res = length;
Jump(&exit);
}
}
Bind(&exit);
auto ret = *res;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
{
auto env = GetEnvironment();
@ -4670,6 +4816,7 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
newTarget, thisValue, data[0], data[1], data[2] }); // 2: args2
break;
case JSCallMode::CALL_THIS_WITH_ARGV:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV: {
thisValue = data[2]; // 2: this input
[[fallthrough]];
@ -4774,6 +4921,7 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
Jump(&exit);
break;
case JSCallMode::CALL_THIS_WITH_ARGV:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
thisValue = data[2]; // 2: this input
[[fallthrough]];
@ -4893,6 +5041,11 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
{ glue, func, method, callField, data[1], data[2], data[3], data[0] });
Jump(&exit);
break;
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
result = CallNGCRuntime(glue, RTSTUB_ID(CallReturnWithArgv),
{ glue, func, method, callField, data[0], data[1], data[2] });
Jump(&exit);
break;
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
@ -4909,27 +5062,27 @@ void StubBuilder::CallFastPath(GateRef glue, GateRef nativeCode, GateRef func, G
std::initializer_list<GateRef> args, JSCallMode mode)
{
auto env = GetEnvironment();
Label isFastBuiltins(env);
auto data = std::begin(args);
Label isFastBuiltins(env);
GateRef numArgs = ZExtInt32ToPtr(actualNumArgs);
GateRef isFastBuiltinsMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsFastBuiltinBit::START_BIT);
Branch(Int64NotEqual(Int64And(callField, isFastBuiltinsMask), Int64(0)),
&isFastBuiltins, notFastBuiltins);
Branch(Int64NotEqual(Int64And(callField, isFastBuiltinsMask), Int64(0)), &isFastBuiltins, notFastBuiltins);
Bind(&isFastBuiltins);
{
GateRef builtinId = GetBuiltinId(method);
GateRef ret;
switch (mode) {
case JSCallMode::CALL_THIS_ARG0:
ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, numArgs });
ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue, numArgs,
Undefined(), Undefined(), Undefined()});
break;
case JSCallMode::CALL_THIS_ARG1:
ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(),
thisValue, numArgs, data[0] });
thisValue, numArgs, data[0], Undefined(), Undefined() });
break;
case JSCallMode::CALL_THIS_ARG2:
ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue,
numArgs, data[0], data[1] });
numArgs, data[0], data[1], Undefined() });
break;
case JSCallMode::CALL_THIS_ARG3:
ret = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, Undefined(), thisValue,
@ -5284,4 +5437,358 @@ GateRef StubBuilder::ToNumber(GateRef glue, GateRef tagged)
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::GetLengthOfJsArray(GateRef glue, GateRef array)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
Label isInt(env);
Label notInt(env);
Label notDouble(env);
Label isDouble(env);
DEFVARIABLE(result, VariableType::INT32(), Int32(0));
GateRef len = Load(VariableType::JS_ANY(), array, IntPtr(JSArray::LENGTH_OFFSET));
Branch(TaggedIsInt(len), &isInt, &notInt);
Bind(&isInt);
{
result = TaggedGetInt(len);
Jump(&exit);
}
Bind(&notInt);
{
Branch(TaggedIsDouble(len), &isDouble, &notDouble);
Bind(&isDouble);
{
result = DoubleToInt(glue, GetDoubleOfTDouble(len));
Jump(&exit);
}
Bind(&notDouble);
{
FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::CreateListFromArrayLike(GateRef glue, GateRef arrayObj)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
DEFVARIABLE(index, VariableType::INT32(), Int32(0));
Label exit(env);
// 3. If Type(obj) is Object, throw a TypeError exception.
Label targetIsHeapObject(env);
Label targetIsEcmaObject(env);
Label targetNotEcmaObject(env);
Branch(TaggedIsHeapObject(arrayObj), &targetIsHeapObject, &targetNotEcmaObject);
Bind(&targetIsHeapObject);
Branch(TaggedObjectIsEcmaObject(arrayObj), &targetIsEcmaObject, &targetNotEcmaObject);
Bind(&targetNotEcmaObject);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
Jump(&exit);
}
Bind(&targetIsEcmaObject);
{
// 4. Let len be ToLength(Get(obj, "length")).
GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::LENGTH_STRING_INDEX);
GateRef value = FastGetPropertyByName(glue, arrayObj, lengthString);
GateRef number = ToLength(glue, value);
// 5. ReturnIfAbrupt(len).
Label isPendingException1(env);
Label noPendingException1(env);
Branch(HasPendingException(glue), &isPendingException1, &noPendingException1);
Bind(&isPendingException1);
{
Jump(&exit);
}
Bind(&noPendingException1);
{
Label indexInRange(env);
Label indexOutRange(env);
GateRef doubleLen = GetDoubleOfTNumber(number);
Branch(DoubleGreaterThan(doubleLen, Double(JSObject::MAX_ELEMENT_INDEX)), &indexOutRange, &indexInRange);
Bind(&indexOutRange);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
Jump(&exit);
}
Bind(&indexInRange);
{
GateRef int32Len = DoubleToInt(glue, doubleLen);
// 6. Let list be an empty List.
NewObjectStubBuilder newBuilder(this);
GateRef array = newBuilder.NewTaggedArray(glue, int32Len);
Label targetIsTypeArray(env);
Label targetNotTypeArray(env);
Branch(IsTypedArray(arrayObj), &targetIsTypeArray, &targetNotTypeArray);
Bind(&targetIsTypeArray);
{
TypedArrayStubBuilder arrayStubBuilder(this);
arrayStubBuilder.FastCopyElementToArray(glue, arrayObj, array);
// c. ReturnIfAbrupt(next).
Label isPendingException2(env);
Label noPendingException2(env);
Branch(HasPendingException(glue), &isPendingException2, &noPendingException2);
Bind(&isPendingException2);
{
Jump(&exit);
}
Bind(&noPendingException2);
{
res = array;
Jump(&exit);
}
}
Bind(&targetNotTypeArray);
// 8. Repeat while index < len
Label loopHead(env);
Label loopEnd(env);
Label afterLoop(env);
Label isPendingException3(env);
Label noPendingException3(env);
Label storeValue(env);
Jump(&loopHead);
LoopBegin(&loopHead);
{
Branch(Int32UnsignedLessThan(*index, int32Len), &storeValue, &afterLoop);
Bind(&storeValue);
{
GateRef next = FastGetPropertyByIndex(glue, arrayObj, *index);
// c. ReturnIfAbrupt(next).
Branch(HasPendingException(glue), &isPendingException3, &noPendingException3);
Bind(&isPendingException3);
{
Jump(&exit);
}
Bind(&noPendingException3);
SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, next);
index = Int32Add(*index, Int32(1));
Jump(&loopEnd);
}
}
Bind(&loopEnd);
LoopEnd(&loopHead);
Bind(&afterLoop);
{
res = array;
Jump(&exit);
}
}
}
}
Bind(&exit);
GateRef ret = *res;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::ToLength(GateRef glue, GateRef target)
{
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
Label exit(env);
GateRef number = ToNumber(glue, target);
Label isPendingException(env);
Label noPendingException(env);
Branch(HasPendingException(glue), &isPendingException, &noPendingException);
Bind(&isPendingException);
{
Jump(&exit);
}
Bind(&noPendingException);
{
GateRef num = GetDoubleOfTNumber(number);
Label targetLessThanZero(env);
Label targetGreaterThanZero(env);
Label targetLessThanSafeNumber(env);
Label targetGreaterThanSafeNumber(env);
Branch(DoubleLessThan(num, Double(0.0)), &targetLessThanZero, &targetGreaterThanZero);
Bind(&targetLessThanZero);
{
res = DoubleToTaggedDoublePtr(Double(0.0));
Jump(&exit);
}
Bind(&targetGreaterThanZero);
Branch(DoubleGreaterThan(num, Double(SAFE_NUMBER)), &targetGreaterThanSafeNumber, &targetLessThanSafeNumber);
Bind(&targetGreaterThanSafeNumber);
{
res = DoubleToTaggedDoublePtr(Double(SAFE_NUMBER));
Jump(&exit);
}
Bind(&targetLessThanSafeNumber);
{
res = number;
Jump(&exit);
}
}
Bind(&exit);
auto ret = *res;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::TaggedGetNumber(GateRef x)
{
auto env = GetEnvironment();
Label subentry(env);
Label exit(env);
env->SubCfgEntry(&subentry);
Label targetIsInt(env);
Label targetIsDouble(env);
DEFVAlUE(number, env_, VariableType::FLOAT64(), Double(0));
Branch(TaggedIsInt(x), &targetIsInt, &targetIsDouble);
Bind(&targetIsInt);
{
number = ChangeInt32ToFloat64(TaggedGetInt(x));
Jump(&exit);
}
Bind(&targetIsDouble);
{
number = GetDoubleOfTDouble(x);
Jump(&exit);
}
Bind(&exit);
GateRef ret = *number;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::HasStableElements(GateRef glue, GateRef obj)
{
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(result, VariableType::BOOL(), False());
Label exit(env);
Label targetIsHeapObject(env);
Label targetIsStableElements(env);
Branch(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
Bind(&targetIsHeapObject);
{
GateRef jsHclass = LoadHClass(obj);
Branch(IsStableElements(jsHclass), &targetIsStableElements, &exit);
Bind(&targetIsStableElements);
{
GateRef guardiansOffset = IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
GateRef guardians = Load(VariableType::JS_ANY(), glue, guardiansOffset);
Label targetIsTaggedTrue(env);
Label targetIsTaggedFalse(env);
Branch(TaggedIsTrue(guardians), &targetIsTaggedTrue, &targetIsTaggedFalse);
Bind(&targetIsTaggedTrue);
{
result = True();
Jump(&exit);
}
Bind(&targetIsTaggedFalse);
{
result = False();
Jump(&exit);
}
}
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
GateRef StubBuilder::IsStableJSArguments(GateRef glue, GateRef obj)
{
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(result, VariableType::BOOL(), False());
Label exit(env);
Label targetIsHeapObject(env);
Label targetIsStableArguments(env);
Branch(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
Bind(&targetIsHeapObject);
{
GateRef jsHclass = LoadHClass(obj);
Branch(IsStableArguments(jsHclass), &targetIsStableArguments, &exit);
Bind(&targetIsStableArguments);
{
GateRef guardiansOffset = IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
GateRef guardians = Load(VariableType::JS_ANY(), glue, guardiansOffset);
Label targetIsTaggedTrue(env);
Label targetIsTaggedFalse(env);
Branch(TaggedIsTrue(guardians), &targetIsTaggedTrue, &targetIsTaggedFalse);
Bind(&targetIsTaggedTrue);
{
result = True();
Jump(&exit);
}
Bind(&targetIsTaggedFalse);
{
result = False();
Jump(&exit);
}
}
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
GateRef StubBuilder::IsStableJSArray(GateRef glue, GateRef obj)
{
auto env = GetEnvironment();
Label subentry(env);
env->SubCfgEntry(&subentry);
DEFVARIABLE(result, VariableType::BOOL(), False());
Label exit(env);
Label targetIsHeapObject(env);
Label targetIsStableArray(env);
Branch(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
Bind(&targetIsHeapObject);
{
GateRef jsHclass = LoadHClass(obj);
Branch(IsStableArray(jsHclass), &targetIsStableArray, &exit);
Bind(&targetIsStableArray);
{
GateRef guardiansOffset = IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(env->Is32Bit()));
GateRef guardians = Load(VariableType::JS_ANY(), glue, guardiansOffset);
Label targetIsTaggedTrue(env);
Label targetIsTaggedFalse(env);
Branch(TaggedIsTrue(guardians), &targetIsTaggedTrue, &targetIsTaggedFalse);
Bind(&targetIsTaggedTrue);
{
result = True();
Jump(&exit);
}
Bind(&targetIsTaggedFalse);
{
result = False();
Jump(&exit);
}
}
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
} // namespace panda::ecmascript::kungfu

View File

@ -226,6 +226,7 @@ public:
GateRef InYoungGeneration(GateRef region);
GateRef TaggedIsGeneratorObject(GateRef x);
GateRef TaggedIsAsyncGeneratorObject(GateRef x);
GateRef TaggedIsJSGlobalObject(GateRef x);
GateRef TaggedIsWeak(GateRef x);
GateRef TaggedIsPrototypeHandler(GateRef x);
GateRef TaggedIsStoreTSHandler(GateRef x);
@ -243,6 +244,7 @@ public:
GateRef TaggedIsFalse(GateRef x);
GateRef TaggedIsBoolean(GateRef x);
GateRef TaggedGetInt(GateRef x);
GateRef TaggedGetNumber(GateRef x);
GateRef Int8ToTaggedInt(GateRef x);
GateRef Int16ToTaggedInt(GateRef x);
GateRef IntToTaggedPtr(GateRef x);
@ -282,6 +284,8 @@ public:
GateRef ChangeInt64ToIntPtr(GateRef val);
GateRef ZExtInt32ToPtr(GateRef val);
GateRef ChangeIntPtrToInt32(GateRef val);
GateRef ToLength(GateRef glue, GateRef target);
// math operation
GateRef Sqrt(GateRef x);
GateRef GetSetterFromAccessor(GateRef accessor);
@ -292,6 +296,7 @@ public:
void SetPropertiesArray(VariableType type, GateRef glue, GateRef object, GateRef propsArray);
void SetHash(GateRef glue, GateRef object, GateRef hash);
GateRef GetLengthOfTaggedArray(GateRef array);
GateRef GetLengthOfJsArray(GateRef glue, GateRef array);
// object operation
GateRef IsJSHClass(GateRef obj);
GateRef LoadHClass(GateRef object);
@ -301,6 +306,7 @@ public:
GateRef IsDictionaryMode(GateRef object);
GateRef IsDictionaryModeByHClass(GateRef hClass);
GateRef IsDictionaryElement(GateRef hClass);
GateRef IsStableElements(GateRef hClass);
GateRef IsClassConstructorFromBitField(GateRef bitfield);
GateRef IsClassConstructor(GateRef object);
GateRef IsClassPrototype(GateRef object);
@ -371,7 +377,12 @@ public:
void TryFastHasInstance(GateRef glue, GateRef instof, GateRef target, GateRef object, Label *fastPath,
Label *exit, Variable *result);
GateRef SameValue(GateRef glue, GateRef left, GateRef right);
GateRef HasStableElements(GateRef glue, GateRef obj);
GateRef IsStableJSArguments(GateRef glue, GateRef obj);
GateRef IsStableJSArray(GateRef glue, GateRef obj);
GateRef IsTypedArray(GateRef obj);
GateRef IsStableArguments(GateRef hClass);
GateRef IsStableArray(GateRef hClass);
// SetDictionaryOrder func in property_attribute.h
GateRef SetDictionaryOrderFieldInPropAttr(GateRef attr, GateRef value);
GateRef GetPrototypeFromHClass(GateRef hClass);
@ -510,6 +521,7 @@ public:
GateRef GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index);
GateRef GetPropertyByName(GateRef glue, GateRef receiver, GateRef key);
GateRef FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key);
GateRef FastGetPropertyByIndex(GateRef glue, GateRef obj, GateRef index);
GateRef GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue);
GateRef SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn);
GateRef SetPropertyByName(GateRef glue, GateRef receiver, GateRef key,
@ -538,6 +550,9 @@ public:
GateRef GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index);
GateRef GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module);
GateRef GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module);
GateRef CreateListFromArrayLike(GateRef glue, GateRef arrayObj);
GateRef BuildArgumentsListFastElements(GateRef glue, GateRef arrayObj);
GateRef MakeArgListWithHole(GateRef glue, GateRef argv, GateRef length);
void SetExtensibleToBitfield(GateRef glue, GateRef obj, bool isExtensible);
// fast path

View File

@ -326,6 +326,7 @@ Register AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCal
case JSCallMode::CALL_THIS_ARG2:
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
case JSCallMode::CALL_THIS_WITH_ARGV:
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
case JSCallMode::CALL_THIS_ARG3:
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
@ -521,7 +522,7 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c
Register frameType(X11);
__ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
__ Mov(spRegister, temp);
__ Mov(frameType, Immediate(static_cast<int32_t>(FrameType::BUILTIN_FRAME_WITH_ARGV)));
__ Mov(frameType, Immediate(static_cast<int32_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME)));
// 2: frame type and argc
__ Stp(Register(Zero), frameType, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
__ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED));
@ -529,8 +530,6 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c
__ Stp(temp, temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
// 2: fill func&align slots
__ Stp(Register(Zero), temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
__ Mov(temp, spRegister);
__ Add(Register(FP), temp, Immediate(48)); // 48: skip frame type, numArgs, func, newTarget, this and align
Register runtimeId(X11);
Register trampoline(X12);
@ -614,14 +613,10 @@ void AsmInterpreterCall::PushBuiltinFrame(ExtendedAssembler *assembler, Register
// 16: type & next
__ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE)); // 16: skip next and frame type
} else if (type == FrameType::BUILTIN_ENTRY_FRAME) {
} else {
// 16: type & next
__ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
__ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE)); // 16: skip next and frame type
} else {
ASSERT(type == FrameType::BUILTIN_FRAME_WITH_ARGV);
// 16: type & next
__ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
}
}
@ -882,6 +877,28 @@ void AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler)
}
}
// c++ calling convention
// X0 - glue
// X1 - callTarget
// X2 - method
// X3 - callField
// X4 - arg0(argc)
// X5 - arg1(arglist)
// X6 - arg3(argthis)
void AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallReturnWithArgv));
Label target;
PushAsmInterpBridgeFrame(assembler);
__ Bl(&target);
PopAsmInterpBridgeFrame(assembler);
__ Ret();
__ Bind(&target);
{
JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
}
}
// Generate code for generator re-entering asm interpreter
// c++ calling convention
// Input: %X0 - glue

View File

@ -171,6 +171,8 @@ public:
static void CallContainersArgs3(ExtendedAssembler *assembler);
static void CallReturnWithArgv([[maybe_unused]]ExtendedAssembler *assembler);
private:
static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode, Label *stackOverflow);

View File

@ -568,6 +568,9 @@ Register AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCal
}
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
return __ CppJSCallAvailableRegister2();
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN: {
return __ CppJSCallAvailableRegister1();
}
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
@ -816,13 +819,12 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c
__ Bind(&stackOverflow);
{
Label aligneThrow;
__ Movq(rsp, Operand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
__ Pushq(static_cast<int32_t>(FrameType::BUILTIN_FRAME_WITH_ARGV)); // frame type
__ Movq(static_cast<int32_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME),
Operand(rsp, FRAME_SLOT_SIZE));
__ Pushq(0); // argc
__ Pushq(JSTaggedValue::VALUE_UNDEFINED); // this
__ Pushq(JSTaggedValue::VALUE_UNDEFINED); // newTarget
__ Pushq(JSTaggedValue::VALUE_UNDEFINED); // callTarget
__ Leaq(Operand(rsp, 5 * FRAME_SLOT_SIZE), rbp); // 40: skip frame type, numArgs, func, newTarget and this
__ Testq(0xf, rsp); // 0xf: 0x1111
__ Jz(&aligneThrow, Distance::Near);
@ -922,9 +924,7 @@ void AsmInterpreterCall::PushBuiltinFrame(ExtendedAssembler *assembler,
__ Pushq(rbp);
__ Movq(rsp, Operand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
__ Pushq(static_cast<int32_t>(type));
if (type != FrameType::BUILTIN_FRAME_WITH_ARGV) {
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // 8: skip frame type
}
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp); // 8: skip frame type
}
void AsmInterpreterCall::CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode)
@ -1071,6 +1071,29 @@ void AsmInterpreterCall::CallSetter(ExtendedAssembler *assembler)
JSCallCommonEntry(assembler, JSCallMode::CALL_SETTER);
}
// Input: glue - %rdi
// callTarget - %rsi
// method - %rdx
// callField - %rcx
// arg0(argc) - %r8
// arg1(arglist) - %r9
// argthis - stack
void AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallReturnWithArgv));
Label target;
PushAsmInterpBridgeFrame(assembler);
Register r13 = __ CppJSCallAvailableRegister1();
__ Movq(Operand(rbp, FRAME_SLOT_SIZE), r13);
__ Callq(&target);
PopAsmInterpBridgeFrame(assembler);
__ Ret();
__ Bind(&target);
{
JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
}
}
void AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler)
{
__ BindAssemblerStub(RTSTUB_ID(CallContainersArgs3));

View File

@ -137,6 +137,8 @@ public:
static void CallContainersArgs3(ExtendedAssembler *assembler);
static void CallReturnWithArgv(ExtendedAssembler *assembler);
static void ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler);
static void ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler);

View File

@ -89,6 +89,7 @@ JSTaggedValue FrameIterator::GetFunction() const
auto *frame = OptimizedBuiltinLeaveFrame::GetFrameFromSp(GetSp());
return JSTaggedValue(*(frame->GetArgv()));
}
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
case FrameType::OPTIMIZED_FRAME:
case FrameType::OPTIMIZED_ENTRY_FRAME:
case FrameType::ASM_BRIDGE_FRAME:
@ -260,6 +261,16 @@ void FrameIterator::Advance()
current_ = frame->GetPrevFrameFp();
break;
}
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME : {
auto frame = GetFrame<BuiltinWithArgvFrame>();
if constexpr (GCVisit == GCVisitedFlag::VISITED) {
optimizedReturnAddr_ = frame->GetReturnAddr();
optimizedCallSiteSp_ = GetPrevFrameCallSiteSp();
needCalCallSiteInfo = true;
}
current_ = frame->GetPrevFrameFp();
break;
}
case FrameType::INTERPRETER_ENTRY_FRAME : {
auto frame = GetFrame<InterpretedEntryFrame>();
if constexpr (GCVisit == GCVisitedFlag::VISITED) {
@ -329,6 +340,10 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
auto frame = GetFrame<BuiltinWithArgvFrame>();
return frame->GetCallSiteSp();
}
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME: {
auto frame = GetFrame<BuiltinWithArgvFrame>();
return frame->GetCallSiteSp();
}
case FrameType::BUILTIN_FRAME: {
auto frame = GetFrame<BuiltinFrame>();
return frame->GetCallSiteSp();
@ -777,6 +792,10 @@ bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typ
typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type);
prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp);
break;
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME:
typeOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, type);
prevOffset = MEMBER_OFFSET(BuiltinWithArgvFrame, prevFp);
break;
case FrameType::INTERPRETER_ENTRY_FRAME:
typeOffset = MEMBER_OFFSET(InterpretedEntryFrame, base) +
MEMBER_OFFSET(InterpretedFrameBase, type);

View File

@ -131,6 +131,7 @@ enum class FrameType: uintptr_t {
ASM_INTERPRETER_BRIDGE_FRAME,
OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME,
OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME,
FRAME_TYPE_FIRST = OPTIMIZED_FRAME,
FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
@ -162,6 +163,7 @@ enum class JSCallMode : uintptr_t {
CALL_GETTER,
CALL_SETTER,
CALL_THIS_ARG3_WITH_RETURN,
CALL_THIS_ARGV_WITH_RETURN,
CALL_ENTRY,
CALL_GENERATOR,
CALL_FROM_AOT,

View File

@ -187,6 +187,7 @@ JSTaggedValue FrameHandler::GetFunction() const
auto *frame = OptimizedJSFunctionFrame::GetFrameFromSp(sp_);
return frame->GetFunction();
}
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
case FrameType::INTERPRETER_FRAME:
case FrameType::INTERPRETER_FAST_NEW_FRAME:
case FrameType::INTERPRETER_ENTRY_FRAME:
@ -298,6 +299,7 @@ ARK_INLINE uintptr_t FrameHandler::GetInterpretedFrameEnd(JSTaggedType *prevSp)
end = ToUintPtr(frame);
break;
}
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME :
case FrameType::BUILTIN_FRAME_WITH_ARGV:
case FrameType::BUILTIN_ENTRY_FRAME:
case FrameType::BUILTIN_FRAME:
@ -426,6 +428,7 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &vis
frame->GCIterate(it, visitor, rangeVisitor);
break;
}
case FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME:
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
case FrameType::OPTIMIZED_ENTRY_FRAME:

View File

@ -39,7 +39,6 @@
namespace panda::ecmascript {
// ecma6 7.1 Type Conversion
static constexpr double SAFE_NUMBER = 9007199254740991LL;
static constexpr uint32_t MAX_ELEMENT_INDEX_LEN = 10;
inline bool JSTaggedValue::ToBoolean() const

View File

@ -35,6 +35,8 @@ class OperationResult;
class EcmaString;
class JSThread;
static constexpr double SAFE_NUMBER = 9007199254740991LL;
// Don't switch the order!
enum PreferredPrimitiveType : uint8_t { PREFER_NUMBER = 0, PREFER_STRING, NO_PREFERENCE };

View File

@ -36,7 +36,13 @@ namespace panda::ecmascript {
V(INT32_VALUE, "value: %ld") \
V(TargetTypeNotObject, "Type of target is not Object") \
V(CanNotGetNotEcmaObject, "Can not get Prototype on non ECMA Object") \
V(InstanceOfErrorTargetNotCallable, "InstanceOf error when target is not Callable")
V(InstanceOfErrorTargetNotCallable, "InstanceOf error when target is not Callable") \
V(ApplyTargetNotCallable, "apply target is not callable") \
V(TargetNotStableJSArray, "target not stable JSArray") \
V(LenGreaterThanMax, "len is bigger than 2^32 - 1") \
V(ElementTypeNoElementTypes, "CreateListFromArrayLike: not an element of elementTypes") \
V(TargetIsDetachedBuffer, "Is Detached Buffer") \
V(ThisBranchIsUnreachable, "this branch is unreachable")
#define DEBUG_CHECK_MESSAGE_STRING_LIST(V) \
V(IsCallable) \

View File

@ -67,7 +67,8 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, con
V(ResumeUncaughtFrameAndReturn) \
V(CallSetter) \
V(CallGetter) \
V(CallContainersArgs3)
V(CallContainersArgs3) \
V(CallReturnWithArgv)
#define JS_CALL_TRAMPOLINE_LIST(V) \
V(CallRuntime) \

View File

@ -34,4 +34,15 @@ print(str1.indexOf("hjs", 19));
print(str1.indexOf("jk", 3));
print(str1.indexOf(undefined));
print(str1.indexOf(null));
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates"
}
var a = new Uint32Array([1,2]);
print(person.fullName.apply(person1, a));
print("builtins ir end");

View File

@ -30,6 +30,7 @@ NaN
5
-1
-1
Bill Gates,1,2
builtins ir end
builtins number start
parseInt result = 16947500000