!7206 Inline some builtins of Object Function Reflect

Merge pull request !7206 from dingding/aot_inline
This commit is contained in:
openharmony_ci 2024-05-23 04:30:24 +00:00 committed by Gitee
commit 2d317fa7c1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
63 changed files with 1988 additions and 344 deletions

View File

@ -645,7 +645,8 @@ void Builtins::InitializeFunctionPrototype(const JSHandle<GlobalEnv> &env, JSHan
SetInlineFunction(env, funcFuncPrototypeObj, thread_->GlobalConstants()->GetHandledToStringString(),
Function::FunctionPrototypeToString, fieldIndex++, FunctionLength::ZERO);
SetInlineFunction(env, funcFuncPrototypeObj, "[Symbol.hasInstance]",
Function::FunctionPrototypeHasInstance, fieldIndex++, FunctionLength::ONE);
Function::FunctionPrototypeHasInstance, fieldIndex++, FunctionLength::ONE,
BUILTINS_STUB_ID(FunctionPrototypeHasInstance));
}
void Builtins::InitializeFunction(const JSHandle<GlobalEnv> &env, JSHandle<JSTaggedValue> &objFuncPrototypeVal) const
@ -720,6 +721,9 @@ void Builtins::InitializeObject(const JSHandle<GlobalEnv> &env, const JSHandle<J
JSHandle<JSTaggedValue> protoSetter = CreateSetter(env, Object::ProtoSetter, "__proto__", FunctionLength::ONE);
SetAccessor(objFuncPrototype, protoKey, protoGetter, protoSetter);
GlobalEnvConstants *globalConst = const_cast<GlobalEnvConstants *>(thread_->GlobalConstants());
globalConst->SetConstant(ConstantIndex::OBJECT_GET_PROTO_INDEX, protoGetter);
GlobalIndex globalIndex;
globalIndex.UpdateGlobalEnvId(static_cast<size_t>(GlobalEnvField::OBJECT_FUNCTION_INDEX));
thread_->SetInitialBuiltinGlobalHClass(objFunc->GetJSHClass(), globalIndex);
@ -1021,6 +1025,7 @@ void Builtins::InitializeBoolean(const JSHandle<GlobalEnv> &env, const JSHandle<
Boolean::BooleanPrototypeValueOf, FunctionLength::ZERO);
env->SetBooleanFunction(thread_, booleanFunction);
env->SetBooleanPrototype(thread_, booleanFuncPrototype);
}
void Builtins::InitializeProxy(const JSHandle<GlobalEnv> &env)
@ -1857,7 +1862,7 @@ void Builtins::InitializeIterator(const JSHandle<GlobalEnv> &env, const JSHandle
thread_->SetInitialBuiltinHClass(BuiltinTypeId::ITERATOR, nullptr,
*iteratorFuncClass, iteratorPrototype->GetJSHClass());
// iteratorPrototype hclass
JSHandle<JSHClass> iteratorPrototypeHClass(thread_, iteratorPrototype->GetJSHClass());

View File

@ -122,22 +122,30 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeApply(EcmaRuntimeCallInfo *argv
BUILTINS_API_TRACE(thread, Function, PrototypeApply);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> func = GetThis(argv);
JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> arrayObj = GetCallArg(argv, 1);
return FunctionPrototypeApplyInternal(thread, func, thisArg, arrayObj);
}
JSTaggedValue BuiltinsFunction::FunctionPrototypeApplyInternal(JSThread *thread, JSHandle<JSTaggedValue> func,
JSHandle<JSTaggedValue> thisArg,
JSHandle<JSTaggedValue> arrayObj)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. If IsCallable(func) is false, throw a TypeError exception.
if (!GetThis(argv)->IsCallable()) {
if (!func->IsCallable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "apply target is not callable", JSTaggedValue::Exception());
}
JSHandle<JSTaggedValue> func = GetThis(argv);
JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
// 2. If argArray is null or undefined, then
if (GetCallArg(argv, 1)->IsUndefined()) { // null will also get undefined
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
if (arrayObj->IsUndefined()) { // null will also get undefined
// a. Return Call(func, thisArg).
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, 0);
return JSFunction::Call(info);
}
// 3. Let argList be CreateListFromArrayLike(argArray).
JSHandle<JSTaggedValue> arrayObj = GetCallArg(argv, 1);
std::pair<TaggedArray*, size_t> argumentsList = BuildArgumentsListFast(thread, arrayObj);
if (!argumentsList.first) {
JSHandle<JSTaggedValue> num = JSObject::CreateListFromArrayLike(thread, arrayObj);
@ -170,10 +178,6 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeBind(EcmaRuntimeCallInfo *argv)
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// 1. Let Target be the this value.
JSHandle<JSTaggedValue> target = GetThis(argv);
// 2. If IsCallable(Target) is false, throw a TypeError exception.
if (!target->IsCallable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "bind target is not callable", JSTaggedValue::Exception());
}
JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 0);
uint32_t argsLength = 0;
@ -187,6 +191,22 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeBind(EcmaRuntimeCallInfo *argv)
for (uint32_t index = 0; index < argsLength; ++index) {
argsArray->Set(thread, index, GetCallArg(argv, index + 1));
}
return FunctionPrototypeBindInternal(thread, target, thisArg, argsArray);
}
JSTaggedValue BuiltinsFunction::FunctionPrototypeBindInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<JSTaggedValue> thisArg,
JSHandle<TaggedArray> argsArray)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// 2. If IsCallable(Target) is false, throw a TypeError exception.
if (!target->IsCallable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "bind target is not callable", JSTaggedValue::Exception());
}
// 4. Let F be BoundFunctionCreate(Target, thisArg, args).
JSHandle<JSBoundFunction> boundFunction = factory->NewJSBoundFunction(target, thisArg, argsArray);
// 5. ReturnIfAbrupt(F)
@ -230,7 +250,7 @@ JSTaggedValue BuiltinsFunction::FunctionPrototypeBind(EcmaRuntimeCallInfo *argv)
// argv include thisArg
lengthValue =
std::max(0.0, JSTaggedValue::ToNumber(thread, targetLen).GetNumber() -
static_cast<double>(argsLength));
static_cast<double>(argsArray->GetLength()));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
}

View File

@ -23,9 +23,9 @@
/* Function.prototype.apply ( thisArg, argArray ) */ \
V("apply", FunctionPrototypeApply, 2, FunctionPrototypeApply) \
/* Function.prototype.bind ( thisArg , ...args) */ \
V("bind", FunctionPrototypeBind, 1, INVALID) \
V("bind", FunctionPrototypeBind, 1, FunctionPrototypeBind) \
/* Function.prototype.call (thisArg , ...args) */ \
V("call", FunctionPrototypeCall, 1, INVALID)
V("call", FunctionPrototypeCall, 1, FunctionPrototypeCall)
namespace panda::ecmascript::builtins {
using BuiltinsPropertyConfig = base::BuiltinsPropertyConfig;
@ -39,9 +39,15 @@ public:
// ecma 19.2.3.1 Function.prototype.apply (thisArg, argArray)
static JSTaggedValue FunctionPrototypeApply(EcmaRuntimeCallInfo *argv);
static JSTaggedValue FunctionPrototypeApplyInternal(JSThread *thread, JSHandle<JSTaggedValue> func,
JSHandle<JSTaggedValue> thisArg,
JSHandle<JSTaggedValue> arrayObj);
// ecma 19.2.3.2 Function.prototype.bind (thisArg , ...args)
static JSTaggedValue FunctionPrototypeBind(EcmaRuntimeCallInfo *argv);
static JSTaggedValue FunctionPrototypeBindInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<JSTaggedValue> thisArg,
JSHandle<TaggedArray> argsArray);
// ecma 19.2.3.3 Function.prototype.call (thisArg , ...args)
static JSTaggedValue FunctionPrototypeCall(EcmaRuntimeCallInfo *argv);

View File

@ -782,10 +782,15 @@ JSTaggedValue BuiltinsObject::HasOwnProperty(EcmaRuntimeCallInfo *argv)
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Object, HasOwnProperty);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let P be ToPropertyKey(V).
JSHandle<JSTaggedValue> thisValue = GetThis(argv);
JSHandle<JSTaggedValue> prop = GetCallArg(argv, 0);
return HasOwnPropertyInternal(thread, thisValue, prop);
}
JSTaggedValue BuiltinsObject::HasOwnPropertyInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue,
JSHandle<JSTaggedValue> prop)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
std::pair<JSTaggedValue, bool> result = ObjectFastOperator::HasOwnProperty(thread, thisValue.GetTaggedValue(),
prop.GetTaggedValue());
if (!result.first.IsHole()) {
@ -794,6 +799,7 @@ JSTaggedValue BuiltinsObject::HasOwnProperty(EcmaRuntimeCallInfo *argv)
return GetTaggedBoolean(false);
}
// 1. Let P be ToPropertyKey(V).
JSHandle<JSTaggedValue> property = JSTaggedValue::ToPropertyKey(thread, prop);
// 2. ReturnIfAbrupt(P).
@ -833,11 +839,12 @@ JSTaggedValue BuiltinsObject::IsPrototypeOf(EcmaRuntimeCallInfo *argv)
// c. If SameValue(O, V) is true, return true.
JSMutableHandle<JSTaggedValue> msgValueHandle(thread, msg.GetTaggedValue());
while (!msgValueHandle->IsNull()) {
msgValueHandle.Update(JSTaggedValue::GetPrototype(thread, msgValueHandle));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (JSTaggedValue::SameValue(object.GetTaggedValue(), msgValueHandle.GetTaggedValue())) {
return GetTaggedBoolean(true);
}
msgValueHandle.Update(JSTaggedValue::GetPrototype(thread, msgValueHandle));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
return GetTaggedBoolean(false);
}

View File

@ -54,7 +54,7 @@
/* Object.hasOwn ( O, P ) */ \
V("hasOwn", HasOwn, 2, INVALID) \
/* Object.is ( value1, value2 ) */ \
V("is", Is, 2, INVALID) \
V("is", Is, 2, ObjectIs) \
/* Object.isExtensible ( O ) */ \
V("isExtensible", IsExtensible, 1, INVALID) \
/* Object.isFrozen ( O ) */ \
@ -80,7 +80,7 @@
/* Object.prototype.hasOwnProperty ( V ) */ \
V("hasOwnProperty", HasOwnProperty, 1, ObjectHasOwnProperty) \
/* Object.prototype.isPrototypeOf ( V ) */ \
V("isPrototypeOf", IsPrototypeOf, 1, INVALID) \
V("isPrototypeOf", IsPrototypeOf, 1, ObjectIsPrototypeOf) \
/* Object.prototype.propertyIsEnumerable ( V ) */ \
V("propertyIsEnumerable", PropertyIsEnumerable, 1, INVALID) \
/* Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */ \
@ -137,11 +137,13 @@ public:
static JSTaggedValue Seal(EcmaRuntimeCallInfo *argv);
// 19.1.2.18 Object.setPrototypeOf(O, proto)
static JSTaggedValue SetPrototypeOf(EcmaRuntimeCallInfo *argv);
static JSTaggedValue GetOwnPropertyDescriptors(EcmaRuntimeCallInfo *argv);
// 19.1.3.2 Object.prototype.hasOwnProperty(V)
static JSTaggedValue HasOwnProperty(EcmaRuntimeCallInfo *argv);
static JSTaggedValue HasOwnPropertyInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue,
JSHandle<JSTaggedValue> prop);
// 19.1.3.3 Object.prototype.isPrototypeOf(V)
static JSTaggedValue IsPrototypeOf(EcmaRuntimeCallInfo *argv);
// 19.1.3.4 Object.prototype.propertyIsEnumerable(V)
@ -190,7 +192,7 @@ public:
{
return Span<const std::pair<std::string_view, bool>>(OBJECT_PROPERTIES);
}
private:
#define BUILTIN_OBJECT_FUNCTION_ENTRY(name, func, length, id) \
base::BuiltinFunctionEntry::Create(name, BuiltinsObject::func, length, kungfu::BuiltinsStubCSigns::id),

View File

@ -26,14 +26,22 @@ JSTaggedValue BuiltinsReflect::ReflectApply(EcmaRuntimeCallInfo *argv)
BUILTINS_API_TRACE(argv->GetThread(), Reflect, Apply);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. If IsCallable(target) is false, throw a TypeError exception.
JSHandle<JSTaggedValue> target = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> thisArgument = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> argumentsList = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
return ReflectApplyInternal(thread, target, thisArgument, argumentsList);
}
JSTaggedValue BuiltinsReflect::ReflectApplyInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<JSTaggedValue> thisArgument,
JSHandle<JSTaggedValue> argumentsList)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. If IsCallable(target) is false, throw a TypeError exception.
if (!target->IsCallable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "Reflect.apply target is not callable", JSTaggedValue::Exception());
}
// 2. Let args be ? CreateListFromArrayLike(argumentsList).
JSHandle<JSTaggedValue> thisArgument = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> argumentsList = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
JSHandle<JSTaggedValue> argOrAbrupt = JSObject::CreateListFromArrayLike(thread, argumentsList);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<TaggedArray> args = JSHandle<TaggedArray>::Cast(argOrAbrupt);
@ -74,6 +82,13 @@ JSTaggedValue BuiltinsReflect::ReflectConstruct(EcmaRuntimeCallInfo *argv)
JSHandle<JSTaggedValue> argOrAbrupt = JSObject::CreateListFromArrayLike(thread, argumentsList);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<TaggedArray> args = JSHandle<TaggedArray>::Cast(argOrAbrupt);
return ReflectConstructInternal(thread, target, args, newTarget);
}
JSTaggedValue BuiltinsReflect::ReflectConstructInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<TaggedArray> args, JSHandle<JSTaggedValue> newTarget)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 5. Return ? Construct(target, args, newTarget).
const uint32_t argsLength = args->GetLength();
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
@ -201,16 +216,24 @@ JSTaggedValue BuiltinsReflect::ReflectHas(EcmaRuntimeCallInfo *argv)
BUILTINS_API_TRACE(argv->GetThread(), Reflect, Has);
JSThread *thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. If Type(target) is not Object, throw a TypeError exception.
JSHandle<JSTaggedValue> target = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> key = GetCallArg(argv, 1);
return ReflectHasInternal(thread, target, key);
}
JSTaggedValue BuiltinsReflect::ReflectHasInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<JSTaggedValue> key)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. If Type(target) is not Object, throw a TypeError exception.
if (!target->IsECMAObject()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "Reflect.has target is not object", JSTaggedValue::Exception());
}
// 2. Let key be ? ToPropertyKey(propertyKey).
JSHandle<JSTaggedValue> key = JSTaggedValue::ToPropertyKey(thread, GetCallArg(argv, 1));
JSHandle<JSTaggedValue> propertyKey = JSTaggedValue::ToPropertyKey(thread, key);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 3. Return ? target.[[HasProperty]](key).
return GetTaggedBoolean(JSTaggedValue::HasProperty(thread, target, key));
return GetTaggedBoolean(JSTaggedValue::HasProperty(thread, target, propertyKey));
}
// ecma 26.1.9 Reflect.isExtensible (target)

View File

@ -26,21 +26,21 @@
// kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
#define BUILTIN_REFLECT_FUNCTIONS(V) \
/* Reflect.apply ( target, thisArgument, argumentsList ) */ \
V("apply", ReflectApply, 3, INVALID) \
V("apply", ReflectApply, 3, ReflectApply) \
/* Reflect.construct ( target, argumentsList [ , newTarget ] ) */ \
V("construct", ReflectConstruct, 2, INVALID) \
V("construct", ReflectConstruct, 2, ReflectConstruct) \
/* Reflect.defineProperty ( target, propertyKey, attributes ) */ \
V("defineProperty", ReflectDefineProperty, 3, INVALID) \
/* Reflect.deleteProperty ( target, propertyKey ) */ \
V("deleteProperty", ReflectDeleteProperty, 2, INVALID) \
/* Reflect.get ( target, propertyKey [ , receiver ] ) */ \
V("get", ReflectGet, 2, INVALID) \
V("get", ReflectGet, 2, ReflectGet) \
/* Reflect.getOwnPropertyDescriptor ( target, propertyKey ) */ \
V("getOwnPropertyDescriptor", ReflectGetOwnPropertyDescriptor, 2, INVALID) \
/* Reflect.getPrototypeOf ( target ) */ \
V("getPrototypeOf", ReflectGetPrototypeOf, 1, INVALID) \
V("getPrototypeOf", ReflectGetPrototypeOf, 1, ReflectGetPrototypeOf) \
/* Reflect.has ( target, propertyKey ) */ \
V("has", ReflectHas, 2, INVALID) \
V("has", ReflectHas, 2, ReflectHas) \
/* Reflect.isExtensible ( target ) */ \
V("isExtensible", ReflectIsExtensible, 1, INVALID) \
/* Reflect.ownKeys ( target ) */ \
@ -57,9 +57,14 @@ class BuiltinsReflect : public base::BuiltinsBase {
public:
// ecma 26.1.1
static JSTaggedValue ReflectApply(EcmaRuntimeCallInfo *argv);
static JSTaggedValue ReflectApplyInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<JSTaggedValue> thisArgument,
JSHandle<JSTaggedValue> argumentsList);
// ecma 26.1.2
static JSTaggedValue ReflectConstruct(EcmaRuntimeCallInfo *argv);
static JSTaggedValue ReflectConstructInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<TaggedArray> args, JSHandle<JSTaggedValue> newTarget);
// ecma 26.1.3
static JSTaggedValue ReflectDefineProperty(EcmaRuntimeCallInfo *argv);
@ -78,6 +83,8 @@ public:
// ecma 26.1.8
static JSTaggedValue ReflectHas(EcmaRuntimeCallInfo *argv);
static JSTaggedValue ReflectHasInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
JSHandle<JSTaggedValue> key);
// ecma 26.1.9
static JSTaggedValue ReflectIsExtensible(EcmaRuntimeCallInfo *argv);

View File

@ -279,8 +279,19 @@ namespace panda::ecmascript::kungfu {
V(NumberIsInteger) \
V(NumberIsNaN) \
V(NumberIsSafeInteger) \
V(ObjectIs) \
V(ObjectGetProto) \
V(ObjectIsPrototypeOf) \
V(ReflectGetPrototypeOf) \
V(ReflectGet) \
V(ReflectHas) \
V(ReflectConstruct) \
V(ReflectApply) \
V(FunctionPrototypeBind) \
V(FunctionPrototypeCall) \
V(FunctionPrototypeHasInstance) \
V(TYPED_BUILTINS_INLINE_FIRST = MathAcos) \
V(TYPED_BUILTINS_INLINE_LAST = NumberIsSafeInteger)
V(TYPED_BUILTINS_INLINE_LAST = FunctionPrototypeHasInstance)
class BuiltinsStubCSigns {
public:
@ -373,6 +384,21 @@ public:
case BuiltinsStubCSigns::ID::SetClear:
case BuiltinsStubCSigns::ID::SetAdd:
case BuiltinsStubCSigns::ID::NumberParseFloat:
case BuiltinsStubCSigns::ID::ObjectIs:
case BuiltinsStubCSigns::ID::ObjectGetPrototypeOf:
case BuiltinsStubCSigns::ID::ObjectGetProto:
case BuiltinsStubCSigns::ID::ObjectCreate:
case BuiltinsStubCSigns::ID::ObjectIsPrototypeOf:
case BuiltinsStubCSigns::ID::ObjectHasOwnProperty:
case BuiltinsStubCSigns::ID::ReflectGetPrototypeOf:
case BuiltinsStubCSigns::ID::ReflectGet:
case BuiltinsStubCSigns::ID::ReflectHas:
case BuiltinsStubCSigns::ID::ReflectConstruct:
case BuiltinsStubCSigns::ID::ReflectApply:
case BuiltinsStubCSigns::ID::FunctionPrototypeApply:
case BuiltinsStubCSigns::ID::FunctionPrototypeBind:
case BuiltinsStubCSigns::ID::FunctionPrototypeCall:
case BuiltinsStubCSigns::ID::FunctionPrototypeHasInstance:
return true;
default:
return false;
@ -601,6 +627,36 @@ public:
return ConstantIndex::NUMBER_IS_SAFEINTEGER_INDEX;
case BuiltinsStubCSigns::ID::NumberParseFloat:
return ConstantIndex::NUMBER_PARSE_FLOAT_INDEX;
case BuiltinsStubCSigns::ID::ObjectIs:
return ConstantIndex::OBJECT_IS_INDEX;
case BuiltinsStubCSigns::ID::ObjectGetPrototypeOf:
return ConstantIndex::OBJECT_GET_PROTOTYPE_OF_INDEX;
case BuiltinsStubCSigns::ID::ObjectGetProto:
return ConstantIndex::OBJECT_GET_PROTO_INDEX;
case BuiltinsStubCSigns::ID::ObjectCreate:
return ConstantIndex::OBJECT_CREATE_INDEX;
case BuiltinsStubCSigns::ID::ObjectIsPrototypeOf:
return ConstantIndex::OBJECT_IS_PROTOTYPE_OF_INDEX;
case BuiltinsStubCSigns::ID::ObjectHasOwnProperty:
return ConstantIndex::OBJECT_HAS_OWN_PROPERTY_INDEX;
case BuiltinsStubCSigns::ID::ReflectGetPrototypeOf:
return ConstantIndex::REFLECT_GET_PROTOTYPE_OF_INDEX;
case BuiltinsStubCSigns::ID::ReflectGet:
return ConstantIndex::REFLECT_GET_INDEX;
case BuiltinsStubCSigns::ID::ReflectHas:
return ConstantIndex::REFLECT_HAS_INDEX;
case BuiltinsStubCSigns::ID::ReflectConstruct:
return ConstantIndex::REFLECT_CONSTRUCT_INDEX;
case BuiltinsStubCSigns::ID::ReflectApply:
return ConstantIndex::REFLECT_APPLY_INDEX;
case BuiltinsStubCSigns::ID::FunctionPrototypeApply:
return ConstantIndex::FUNCTION_PROTOTYPE_APPLY_INDEX;
case BuiltinsStubCSigns::ID::FunctionPrototypeBind:
return ConstantIndex::FUNCTION_PROTOTYPE_BIND_INDEX;
case BuiltinsStubCSigns::ID::FunctionPrototypeCall:
return ConstantIndex::FUNCTION_PROTOTYPE_CALL_INDEX;
case BuiltinsStubCSigns::ID::FunctionPrototypeHasInstance:
return ConstantIndex::FUNCTION_PROTOTYPE_HAS_INSTANCE_INDEX;
default:
LOG_COMPILER(INFO) << "GetConstantIndex Invalid Id:" << builtinId;
return ConstantIndex::INVALID;
@ -678,6 +734,21 @@ public:
{StringSubstring, "String.prototype.substring"},
{StringSubStr, "String.prototype.substr"},
{StringSlice, "String.prototype.slice"},
{ObjectIs, "Object.is"},
{ObjectGetPrototypeOf, "Object.getPrototypeOf"},
{ObjectGetProto, "Object.prototype.getProto"},
{ObjectCreate, "Object.create"},
{ObjectIsPrototypeOf, "Object.prototype.isPrototypeOf"},
{ObjectHasOwnProperty, "Object.prototype.hasOwnProperty"},
{ReflectGetPrototypeOf, "Reflect.getPrototypeOf"},
{ReflectGet, "Reflect.get"},
{ReflectHas, "Reflect.has"},
{ReflectConstruct, "Reflect.construct"},
{ReflectApply, "Reflect.apply"},
{FunctionPrototypeApply, "Function.prototype.apply"},
{FunctionPrototypeBind, "Function.prototype.bind"},
{FunctionPrototypeCall, "Function.prototype.call"},
{FunctionPrototypeHasInstance, "Function.prototype.hasInstance"},
};
if (builtinId2Str.count(id) > 0) {
return builtinId2Str.at(id);
@ -737,6 +808,20 @@ public:
{"substring", StringSubstring},
{"substr", StringSubStr},
{"slice", StringSlice},
{"is", ObjectIs},
{"getPrototypeOf", ObjectGetPrototypeOf},
{"create", ObjectCreate},
{"isPrototypeOf", ObjectIsPrototypeOf},
{"hasOwnProperty", ObjectHasOwnProperty},
{"reflectGetPrototypeOf", ReflectGetPrototypeOf},
{"get", ReflectGet},
{"has", ReflectHas},
{"construct", ReflectConstruct},
{"ReflectApply", ReflectApply},
{"apply", FunctionPrototypeApply},
{"bind", FunctionPrototypeBind},
{"call", FunctionPrototypeCall},
{"hasInstance", FunctionPrototypeHasInstance},
};
if (str2BuiltinId.count(idStr) > 0) {
return str2BuiltinId.at(idStr);

View File

@ -219,77 +219,6 @@ void BuiltinsObjectStubBuilder::ToString(Variable *result, Label *exit, Label *s
}
}
GateRef BuiltinsObjectStubBuilder::TransProtoWithoutLayout(GateRef hClass, GateRef proto)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
GateRef key = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
ConstantIndex::PROTOTYPE_STRING_INDEX);
GateRef newClass = CallNGCRuntime(glue_, RTSTUB_ID(JSHClassFindProtoTransitions), { hClass, key, proto });
Label undef(env);
Label find(env);
BRANCH(IntPtrEqual(TaggedCastToIntPtr(newClass), IntPtr(0)), &undef, &find);
Bind(&find);
{
result = newClass;
Jump(&exit);
}
Bind(&undef);
{
result = CallRuntime(glue_, RTSTUB_ID(HClassCloneWithAddProto), { hClass, key, proto });
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef BuiltinsObjectStubBuilder::OrdinaryNewJSObjectCreate(GateRef proto)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
GateRef hClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
ConstantIndex::OBJECT_HCLASS_INDEX);
GateRef newClass = TransProtoWithoutLayout(hClass, proto);
Label exception(env);
Label noexception(env);
BRANCH(TaggedIsException(newClass), &exception, &noexception);
Bind(&exception);
{
result = Exception();
Jump(&exit);
}
Bind(&noexception);
NewObjectStubBuilder newBuilder(this);
GateRef newObj = newBuilder.NewJSObject(glue_, newClass);
Label exceptionNewObj(env);
Label noexceptionNewObj(env);
BRANCH(TaggedIsException(newObj), &exceptionNewObj, &noexceptionNewObj);
Bind(&exceptionNewObj);
{
result = Exception();
Jump(&exit);
}
Bind(&noexceptionNewObj);
{
SetExtensibleToBitfield(glue_, newObj, True());
result = newObj;
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
void BuiltinsObjectStubBuilder::Create(Variable *result, Label *exit, Label *slowPath)
{
@ -309,7 +238,7 @@ void BuiltinsObjectStubBuilder::Create(Variable *result, Label *exit, Label *slo
Bind(&noProperties);
{
// OrdinaryNewJSObjectCreate
*result = OrdinaryNewJSObjectCreate(proto);
*result = OrdinaryNewJSObjectCreate(glue_, proto);
Jump(exit);
}
}
@ -711,15 +640,21 @@ void BuiltinsObjectStubBuilder::Assign(Variable *result, Label *exit, Label *slo
}
void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, Label *slowPath)
{
GateRef prop = GetCallArg0(numArgs_);
HasOwnProperty(result, exit, slowPath, thisValue_, prop);
}
void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, Label *slowPath, GateRef thisValue,
GateRef prop, GateRef hir)
{
auto env = GetEnvironment();
Label keyIsString(env);
Label valid(env);
Label isHeapObject(env);
GateRef prop = GetCallArg0(numArgs_);
BRANCH(TaggedIsHeapObject(thisValue_), &isHeapObject, slowPath);
BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
Bind(&isHeapObject);
BRANCH(TaggedIsRegularObject(thisValue_), &valid, slowPath);
BRANCH(TaggedIsRegularObject(thisValue), &valid, slowPath);
Bind(&valid);
{
Label isIndex(env);
@ -733,7 +668,7 @@ void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, La
{
GateRef index = NumberGetInt(glue_, res);
Label findByIndex(env);
GateRef elements = GetElementsArray(thisValue_);
GateRef elements = GetElementsArray(thisValue);
GateRef len = GetLengthOfTaggedArray(elements);
BRANCH(Int32Equal(len, Int32(0)), exit, &findByIndex);
Bind(&findByIndex);
@ -749,7 +684,7 @@ void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, La
Bind(&lessThanLength);
{
Label notHole(env);
GateRef value = GetTaggedValueWithElementsKind(thisValue_, index);
GateRef value = GetTaggedValueWithElementsKind(thisValue, index);
BRANCH(TaggedIsNotHole(value), &notHole, exit);
Bind(&notHole);
{
@ -779,14 +714,14 @@ void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, La
{
Label isDicMode(env);
Label notDicMode(env);
GateRef hclass = LoadHClass(thisValue_);
GateRef hclass = LoadHClass(thisValue);
BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, &notDicMode);
Bind(&notDicMode);
{
GateRef layOutInfo = GetLayoutFromHClass(hclass);
GateRef propsNum = GetNumberOfPropsFromHClass(hclass);
// int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
GateRef entryA = FindElementWithCache(glue_, layOutInfo, hclass, res, propsNum);
GateRef entryA = FindElementWithCache(glue_, layOutInfo, hclass, res, propsNum, hir);
Label hasEntry(env);
// if branch condition : entry != -1
BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, exit);
@ -798,9 +733,9 @@ void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, La
}
Bind(&isDicMode);
{
GateRef array = GetPropertiesArray(thisValue_);
GateRef array = GetPropertiesArray(thisValue);
// int entry = dict->FindEntry(key)
GateRef entryB = FindEntryFromNameDictionary(glue_, array, res);
GateRef entryB = FindEntryFromNameDictionary(glue_, array, res, hir);
Label notNegtiveOne(env);
// if branch condition : entry != -1
BRANCH(Int32NotEqual(entryB, Int32(-1)), &notNegtiveOne, exit);
@ -944,7 +879,7 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array)
}
Bind(&afterLoop);
Jump(&exit);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();

View File

@ -24,6 +24,8 @@ public:
: BuiltinsStubBuilder(parent) {}
BuiltinsObjectStubBuilder(BuiltinsStubBuilder *parent, GateRef glue, GateRef thisValue, GateRef numArgs)
: BuiltinsStubBuilder(parent), glue_(glue), thisValue_(thisValue), numArgs_(numArgs) {}
BuiltinsObjectStubBuilder(Environment *env, GateRef glue)
: BuiltinsStubBuilder(env), glue_(glue) {}
~BuiltinsObjectStubBuilder() override = default;
NO_MOVE_SEMANTIC(BuiltinsObjectStubBuilder);
NO_COPY_SEMANTIC(BuiltinsObjectStubBuilder);
@ -36,10 +38,10 @@ BUILTINS_WITH_OBJECT_STUB_BUILDER(DECLARE_BUILTINS_OBJECT_STUB_BUILDER)
GateRef CreateListFromArrayLike(GateRef glue, GateRef arrayObj);
GateRef CreateArrayFromList(GateRef glue, GateRef elements);
void HasOwnProperty(Variable *result, Label *exit, Label *slowPath, GateRef thisValue, GateRef prop,
GateRef hir = Circuit::NullGate());
private:
GateRef OrdinaryNewJSObjectCreate(GateRef proto);
GateRef TransProtoWithoutLayout(GateRef hClass, GateRef proto);
GateRef GetNumKeysFromLayoutInfo(GateRef object, GateRef end, GateRef layoutInfo);
GateRef IsUninitializedProperty(GateRef object, GateRef index, GateRef layoutInfo);
GateRef GetNumKeysFromDictionary(GateRef array);

View File

@ -29,6 +29,7 @@ public:
:StubBuilder(parent) {}
BuiltinsStubBuilder(CallSignature *callSignature, Environment *env)
: StubBuilder(callSignature, env) {}
BuiltinsStubBuilder(Environment* env): StubBuilder(env) {}
~BuiltinsStubBuilder() override = default;
NO_MOVE_SEMANTIC(BuiltinsStubBuilder);
NO_COPY_SEMANTIC(BuiltinsStubBuilder);

View File

@ -2776,6 +2776,22 @@ DEF_CALL_SIGNATURE(CreateJSTypedArrayEntries)
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(SameValue)
{
// 3 : 3 input parameters
CallSignature signature("SameValue", 0, 3,
ArgumentsOrder::DEFAULT_ORDER, VariableType::BOOL());
*callSign = signature;
// 3 : 3 input parameters
std::array<VariableType, 3> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::JS_ANY(), // left
VariableType::JS_ANY(), // right
};
callSign->SetParameters(params.data());
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(CreateJSTypedArrayKeys)
{
// 2 : 2 input parameters

View File

@ -580,7 +580,8 @@ private:
V(CallRangeAndCheckToBaselineFromBaseline) \
V(CallNewAndCheckToBaselineFromBaseline) \
V(SuperCallAndCheckToBaselineFromBaseline) \
V(CallThisRangeAndCheckToBaselineFromBaseline)
V(CallThisRangeAndCheckToBaselineFromBaseline) \
V(SameValue)
#define DECL_CALL_SIGNATURE(name) \
class name##CallSignature final { \

View File

@ -21,6 +21,7 @@
#include "ecmascript/compiler/hcr_circuit_builder.h"
#include "ecmascript/compiler/lcr_circuit_builder.h"
#include "ecmascript/compiler/mcr_circuit_builder.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
@ -29,9 +30,11 @@
#include "ecmascript/js_array_iterator.h"
#include "ecmascript/js_for_in_iterator.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_primitive_ref.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/mem/region.h"
#include "ecmascript/message_string.h"
#include "ecmascript/method.h"
#include "ecmascript/sendable_env.h"
@ -1078,6 +1081,247 @@ GateRef CircuitBuilder::GetPropertiesFromLexicalEnv(GateRef object, GateRef inde
return GetValueFromTaggedArray(object, valueIndex);
}
GateRef CircuitBuilder::NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj)
{
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
GateRef protoOrHclass = Load(VariableType::JS_ANY(), func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
NewObjectStubBuilder newBuilder(env_);
GateRef newObj = newBuilder.NewJSObject(glue, protoOrHclass);
GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
Store(VariableType::JS_ANY(), glue, newObj, valueOffset, obj);
return newObj;
}
GateRef CircuitBuilder::ToObject(GateRef glue, GateRef obj)
{
Label entry(env_);
env_->SubCfgEntry(&entry);
Label exit(env_);
DEFVALUE(result, env_, VariableType::JS_ANY(), obj);
DEFVALUE(taggedId, env_, VariableType::INT32(), Int32(0));
Label isNumber(env_);
Label notNumber(env_);
Label isBoolean(env_);
Label notBoolean(env_);
Label isString(env_);
Label notString(env_);
Label isECMAObject(env_);
Label notIsECMAObject(env_);
Label isSymbol(env_);
Label notSymbol(env_);
Label isUndefined(env_);
Label notIsUndefined(env_);
Label isNull(env_);
Label notIsNull(env_);
Label isHole(env_);
Label notIsHole(env_);
Label isBigInt(env_);
Label notIsBigInt(env_);
Label throwError(env_);
BRANCH_CIR2(IsEcmaObject(obj), &isECMAObject, &notIsECMAObject);
Bind(&isECMAObject);
{
result = obj;
Jump(&exit);
}
Bind(&notIsECMAObject);
BRANCH_CIR2(TaggedIsNumber(obj), &isNumber, &notNumber);
Bind(&isNumber);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notNumber);
BRANCH_CIR2(TaggedIsBoolean(obj), &isBoolean, &notBoolean);
Bind(&isBoolean);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notBoolean);
BRANCH_CIR2(TaggedIsString(obj), &isString, &notString);
Bind(&isString);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notString);
BRANCH_CIR2(TaggedIsSymbol(obj), &isSymbol, &notSymbol);
Bind(&isSymbol);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notSymbol);
BRANCH_CIR2(TaggedIsUndefined(obj), &isUndefined, &notIsUndefined);
Bind(&isUndefined);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
Jump(&throwError);
}
Bind(&notIsUndefined);
BRANCH_CIR2(TaggedIsHole(obj), &isHole, &notIsHole);
Bind(&isHole);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
Jump(&throwError);
}
Bind(&notIsHole);
BRANCH_CIR2(TaggedIsNull(obj), &isNull, &notIsNull);
Bind(&isNull);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
Jump(&throwError);
}
Bind(&notIsNull);
BRANCH_CIR2(TaggedIsBigInt(obj), &isBigInt, &notIsBigInt);
Bind(&isBigInt);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notIsBigInt);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
Jump(&throwError);
}
Bind(&throwError);
{
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef, { Int32ToTaggedInt(*taggedId) }, glue);
result = ExceptionConstant();
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env_->SubCfgExit();
return ret;
}
GateRef CircuitBuilder::GetPrototype(GateRef glue, GateRef object)
{
Label entry(env_);
env_->SubCfgEntry(&entry);
DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
Label exit(env_);
Label objectIsHeapObject(env_);
Label objectIsEcmaObject(env_);
Label objectNotEcmaObject(env_);
BRANCH_CIR2(TaggedIsHeapObject(object), &objectIsHeapObject, &objectNotEcmaObject);
Bind(&objectIsHeapObject);
BRANCH_CIR2(TaggedObjectIsEcmaObject(object), &objectIsEcmaObject, &objectNotEcmaObject);
Bind(&objectNotEcmaObject);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef, { Int32ToTaggedInt(taggedId) }, glue);
result = ExceptionConstant();
Jump(&exit);
}
Bind(&objectIsEcmaObject);
{
Label objectIsJsProxy(env_);
Label objectNotIsJsProxy(env_);
BRANCH_CIR2(IsJsProxy(object), &objectIsJsProxy, &objectNotIsJsProxy);
Bind(&objectIsJsProxy);
{
result = CallRuntime(glue, RTSTUB_ID(CallGetPrototype), Gate::InvalidGateRef, { object }, glue);
Jump(&exit);
}
Bind(&objectNotIsJsProxy);
{
result = GetPrototypeFromHClass(LoadHClass(object));
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env_->SubCfgExit();
return ret;
}
GateRef CircuitBuilder::GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index)
{
GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
auto constantIndex = IntPtr(JSTaggedValue::TaggedTypeSize() * static_cast<size_t>(index));
return Load(type, gConstAddr, constantIndex);
}
GateRef CircuitBuilder::TransProtoWithoutLayout(GateRef glue, GateRef hClass, GateRef proto)
{
Label entry(env_);
env_->SubCfgEntry(&entry);
Label exit(env_);
DEFVALUE(result, env_, VariableType::JS_ANY(), Undefined());
GateRef key = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::PROTOTYPE_STRING_INDEX);
GateRef newClass = CallNGCRuntime(glue, RTSTUB_ID(JSHClassFindProtoTransitions), Gate::InvalidGateRef,
{ hClass, key, proto }, glue);
Label undef(env_);
Label find(env_);
BRANCH_CIR2(IntPtrEqual(TaggedCastToIntPtr(newClass), IntPtr(0)), &undef, &find);
Bind(&find);
{
result = newClass;
Jump(&exit);
}
Bind(&undef);
{
result = CallRuntime(glue, RTSTUB_ID(HClassCloneWithAddProto), Gate::InvalidGateRef,
{ hClass, key, proto }, glue);
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env_->SubCfgExit();
return ret;
}
GateRef CircuitBuilder::OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto)
{
Label entry(env_);
env_->SubCfgEntry(&entry);
Label exit(env_);
DEFVALUE(result, env_, VariableType::JS_ANY(), Undefined());
GateRef hClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::OBJECT_HCLASS_INDEX);
GateRef newClass = TransProtoWithoutLayout(glue, hClass, proto);
Label exception(env_);
Label noexception(env_);
BRANCH_CIR2(TaggedIsException(newClass), &exception, &noexception);
Bind(&exception);
{
result = ExceptionConstant();
Jump(&exit);
}
Bind(&noexception);
NewObjectStubBuilder newBuilder(env_);
GateRef newObj = newBuilder.NewJSObject(glue, newClass);
Label exceptionNewObj(env_);
Label noexceptionNewObj(env_);
BRANCH_CIR2(TaggedIsException(newObj), &exceptionNewObj, &noexceptionNewObj);
Bind(&exceptionNewObj);
{
result = ExceptionConstant();
Jump(&exit);
}
Bind(&noexceptionNewObj);
{
SetExtensibleToBitfield(glue, newObj, True());
result = newObj;
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env_->SubCfgExit();
return ret;
}
GateRef CircuitBuilder::GetPropertiesFromSendableEnv(GateRef object, GateRef index)
{
GateRef valueIndex = Int32Add(index, Int32(SendableEnv::SENDABLE_RESERVED_ENV_LENGTH));

View File

@ -558,6 +558,7 @@ public:
GateRef InsertTypedArrayCheck(GateType type, GateRef array);
GateRef ArrayConstructorCheck(GateRef gate);
GateRef ObjectConstructorCheck(GateRef gate);
GateRef BooleanConstructorCheck(GateRef gate);
GateRef InsertTypedBinaryop(GateRef left, GateRef right, TypedBinOp op);
GateRef InsertRangeCheckPredicate(GateRef left, TypedBinOp cond, GateRef right);
GateRef TypedConditionJump(MachineType type, TypedJumpOp jumpOp, uint32_t weight, ParamType paramType,
@ -662,6 +663,13 @@ public:
template<TypedLoadOp Op>
GateRef ConvertJSArrayHoleAsUndefined(GateRef receiver);
GateRef BuildBigIntAsIntN(const GateMetaData* op, std::vector<GateRef> &&args);
GateRef NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj);
GateRef ToObject(GateRef glue, GateRef obj);
GateRef GetPrototype(GateRef glue, GateRef object);
GateRef GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index);
GateRef TransProtoWithoutLayout(GateRef glue, GateRef hClass, GateRef proto);
GateRef OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto);
// bit operation
inline GateRef TaggedIsInt(GateRef x);
@ -739,7 +747,7 @@ public:
GateRef GetLengthFromString(GateRef value);
GateRef Rotl(GateRef word, uint32_t shift);
GateRef CalcHashcodeForInt(GateRef value);
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
GateRef GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir = Circuit::NullGate());
GateRef TryGetHashcodeFromString(GateRef string);
GateRef IsIntegerString(GateRef string);
GateRef IsLiteralString(GateRef string);
@ -798,6 +806,7 @@ public:
inline GateRef IntPtrGreaterThan(GateRef x, GateRef y);
inline GateRef IntPtrAnd(GateRef x, GateRef y);
inline GateRef IntPtrNot(GateRef x);
inline GateRef IntPtrEqual(GateRef x, GateRef y);
GateRef AddWithOverflow(GateRef left, GateRef right);
GateRef SubWithOverflow(GateRef left, GateRef right);
GateRef MulWithOverflow(GateRef left, GateRef right);

View File

@ -1252,6 +1252,15 @@ void JSSetAddStubBuilder::GenerateCircuit()
Return(obj);
}
void SameValueStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
GateRef left = TaggedArgument(1);
GateRef right = TaggedArgument(2U);
GateRef result = SameValue(glue, left, right);
Return(result);
}
CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
void CommonStubCSigns::Initialize()

View File

@ -106,7 +106,8 @@ namespace panda::ecmascript::kungfu {
V(GetSingleCharCodeByIndex) \
V(FastStringEqual) \
V(FastStringAdd) \
V(DeleteObjectProperty)
V(DeleteObjectProperty) \
V(SameValue)
#define COMMON_STUB_ID_LIST(V) \
COMMON_STUB_LIST(V)

View File

@ -89,6 +89,7 @@ GateRef EarlyElimination::VisitGate(GateRef gate)
case OpCode::TYPE_OF_CHECK:
case OpCode::ARRAY_CONSTRUCTOR_CHECK:
case OpCode::OBJECT_CONSTRUCTOR_CHECK:
case OpCode::BOOLEAN_CONSTRUCTOR_CHECK:
case OpCode::PROTO_CHANGE_MARKER_CHECK:
case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
case OpCode::LOAD_BUILTIN_OBJECT:
@ -397,7 +398,8 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs)
break;
}
case OpCode::ARRAY_CONSTRUCTOR_CHECK:
case OpCode::OBJECT_CONSTRUCTOR_CHECK: {
case OpCode::OBJECT_CONSTRUCTOR_CHECK:
case OpCode::BOOLEAN_CONSTRUCTOR_CHECK: {
if (acc_.GetValueIn(lhs) != acc_.GetValueIn(rhs)) {
return false;
}

View File

@ -803,6 +803,16 @@ size_t GateAccessor::GetNumValueIn(GateRef gate) const
return gatePtr->GetInValueCount();
}
std::vector<GateRef> GateAccessor::GetValueIns(GateRef gate) const
{
size_t num = GetNumValueIn(gate);
std::vector<GateRef> valueIns(num);
for (size_t i = 0; i < num; ++i) {
valueIns[i] = GetValueIn(gate, i);
}
return valueIns;
}
bool GateAccessor::IsGCRelated(GateRef gate) const
{
return GetGateType(gate).IsGCRelated();

View File

@ -452,6 +452,7 @@ public:
GateId GetId(GateRef gate) const;
GateRef GetValueIn(GateRef gate, size_t idx = 0) const;
size_t GetNumValueIn(GateRef gate) const;
std::vector<GateRef> GetValueIns(GateRef gate) const;
GateRef GetIn(GateRef gate, size_t idx) const;
GateRef GetState(GateRef gate, size_t idx = 0) const;
GateRef GetDep(GateRef gate, size_t idx = 0) const;

View File

@ -433,13 +433,12 @@ GateRef CircuitBuilder::CallSetter(GateRef hirGate, GateRef receiver, GateRef ho
GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
{
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE || acc_.GetOpCode(hirGate) == OpCode::REFLECT_CONSTRUCT);
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
uint64_t bitfield = args.size();
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
ASSERT(pcOffset != 0);
args.insert(args.begin(), currentDepend);
args.insert(args.begin(), currentControl);
AppendFrameArgs(args, hirGate);
@ -615,6 +614,19 @@ GateRef CircuitBuilder::BuiltinConstructor(BuiltinTypeId id, GateRef gate)
}
break;
}
case BuiltinTypeId::BOOLEAN: {
if (acc_.GetNumValueIn(gate) == 1) {
newGate = GetCircuit()->NewGate(circuit_->BooleanConstructor(1), MachineType::I64,
{ currentControl, currentDepend, acc_.GetValueIn(gate, 0)},
GateType::TaggedValue());
} else {
ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: num value in
newGate = GetCircuit()->NewGate(circuit_->BooleanConstructor(2), MachineType::I64,
{ currentControl, currentDepend, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)},
GateType::TaggedValue());
}
break;
}
default:
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();

View File

@ -38,7 +38,8 @@ namespace panda::ecmascript::kungfu {
V(RuntimeCallWithArgv, RUNTIME_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \
V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value) \
V(ArrayConstructor, ARRAY_CONSTRUCTOR, GateFlags::NONE_FLAG, 1, 1, value) \
V(ObjectConstructor, OBJECT_CONSTRUCTOR, GateFlags::NONE_FLAG, 1, 1, value)
V(ObjectConstructor, OBJECT_CONSTRUCTOR, GateFlags::NONE_FLAG, 1, 1, value) \
V(BooleanConstructor, BOOLEAN_CONSTRUCTOR, GateFlags::NONE_FLAG, 1, 1, value)
#define HCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
V(Construct, CONSTRUCT, GateFlags::HAS_FRAME_STATE, 1, 1, value)

View File

@ -64,6 +64,11 @@ GateRef CircuitBuilder::IntPtrNot(GateRef x)
return env_->Is32Bit() ? Int32Not(x) : Int64Not(x);
}
GateRef CircuitBuilder::IntPtrEqual(GateRef x, GateRef y)
{
return env_->Is32Bit() ? Int32Equal(x, y) : Int64Equal(x, y);
}
GateRef CircuitBuilder::IntPtrLSR(GateRef x, GateRef y)
{
auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
@ -146,8 +151,7 @@ GateRef CircuitBuilder::GetInt32OfTInt(GateRef x)
GateRef CircuitBuilder::TaggedCastToIntPtr(GateRef x)
{
ASSERT(cmpCfg_ != nullptr);
return cmpCfg_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x);
return env_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x);
}
GateRef CircuitBuilder::GetDoubleOfTInt(GateRef x)

View File

@ -1279,9 +1279,8 @@ GateRef CircuitBuilder::CalcHashcodeForInt(GateRef value)
return hash12;
}
GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
Label subentry(env_);
SubCfgEntry(&subentry);
Label noRawHashcode(env_);
@ -1292,7 +1291,7 @@ GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
Bind(&noRawHashcode);
{
hashcode = GetInt32OfTInt(
CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }, Circuit::NullGate()));
CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }, hir));
Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::MIX_HASHCODE_OFFSET), *hashcode);
Jump(&exit);
}
@ -1577,6 +1576,19 @@ GateRef CircuitBuilder::ObjectConstructorCheck(GateRef gate)
return ret;
}
GateRef CircuitBuilder::BooleanConstructorCheck(GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->BooleanConstructorCheck(),
MachineType::I64, {currentControl, currentDepend, gate, frameState}, GateType::IntType());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::MonoLoadPropertyOnProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex)
{
auto currentLabel = env_->GetCurrentLabel();

View File

@ -59,6 +59,7 @@ namespace panda::ecmascript::kungfu {
V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
V(ArrayConstructorCheck, ARRAY_CONSTRUCTOR_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(ObjectConstructorCheck, OBJECT_CONSTRUCTOR_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(BooleanConstructorCheck, BOOLEAN_CONSTRUCTOR_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(MonoLoadPropertyOnProto, MONO_LOAD_PROPERTY_ON_PROTO, GateFlags::CHECKABLE, 1, 1, 4) \
V(StringFromSingleCharCode, STRING_FROM_SINGLE_CHAR_CODE, GateFlags::NO_WRITE, 1, 1, 1) \
@ -146,6 +147,18 @@ namespace panda::ecmascript::kungfu {
V(SetEntries, SET_ENTRIES, GateFlags::NO_WRITE, 1, 1, 1) \
V(MapClear, MAP_CLEAR, GateFlags::NONE_FLAG, 1, 1, 1) \
V(SetClear, SET_CLEAR, GateFlags::NONE_FLAG, 1, 1, 1) \
V(ObjectIs, OBJECT_IS, GateFlags::NO_WRITE, 1, 1, 2) \
V(ObjectGetPrototypeOf, OBJECT_GET_PROTOTYPE_OF, GateFlags::NO_WRITE, 1, 1, 1) \
V(ObjectCreate, OBJECT_CREATE, GateFlags::NO_WRITE, 1, 1, 1) \
V(ObjectIsPrototypeOf, OBJECT_IS_PROTOTYPE_OF, GateFlags::NO_WRITE, 1, 1, 2) \
V(ObjectHasOwnProperty, OBJECT_HAS_OWN_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \
V(ReflectGetPrototypeOf, REFLECT_GET_PROTOTYPE_OF, GateFlags::NO_WRITE, 1, 1, 1) \
V(ReflectGet, REFLECT_GET, GateFlags::NO_WRITE, 1, 1, 2) \
V(ReflectHas, REFLECT_HAS, GateFlags::NO_WRITE, 1, 1, 2) \
V(ReflectConstruct, REFLECT_CONSTRUCT, GateFlags::NO_WRITE, 1, 1, 1) \
V(ReflectApply, REFLECT_APPLY, GateFlags::NO_WRITE, 1, 1, 3) \
V(FunctionPrototypeApply, FUNCTION_PROTOTYPE_APPLY, GateFlags::NO_WRITE, 1, 1, 3) \
V(FunctionPrototypeBind, FUNCTION_PROTOTYPE_BIND, GateFlags::NO_WRITE, 1, 1, 2) \
MCR_BINARY_GATE_META_DATA_CACHE_LIST(V)
#define MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
@ -208,7 +221,8 @@ namespace panda::ecmascript::kungfu {
#define MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(V) \
V(TypedCreateObjWithBuffer, TYPED_CREATE_OBJ_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, value) \
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, value)
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, value) \
V(FunctionPrototypeCall, FUNCTION_PROTOTYPE_CALL, GateFlags::NO_WRITE, 1, 1, value)
#define MCR_GATE_META_DATA_LIST_WITH_SIZE(V) \
MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(V)

View File

@ -299,6 +299,51 @@ void NativeInlineLowering::RunNativeInlineLowering()
case BuiltinsStubCSigns::ID::SetClear:
InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetClear(), skipThis);
break;
case BuiltinsStubCSigns::ID::ObjectIs:
TryInlineObjectIs(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ObjectGetPrototypeOf:
TryInlineObjectGetPrototypeOf(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ObjectGetProto:
TryInlineObjectGetProto(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ObjectCreate:
TryInlineObjectCreate(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ObjectIsPrototypeOf:
TryInlineObjectIsPrototypeOf(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ObjectHasOwnProperty:
TryInlineObjectHasOwnProperty(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ReflectGetPrototypeOf:
TryInlineReflectGetPrototypeOf(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ReflectGet:
TryInlineReflectGet(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ReflectHas:
TryInlineReflectHas(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ReflectConstruct:
TryInlineReflectConstruct(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::ReflectApply:
TryInlineReflectApply(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::FunctionPrototypeApply:
TryInlineFunctionPrototypeApply(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::FunctionPrototypeBind:
TryInlineFunctionPrototypeBind(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::FunctionPrototypeCall:
TryInlineFunctionPrototypeCall(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::FunctionPrototypeHasInstance:
TryInlineFunctionPrototypeHasInstance(gate, argc, id, skipThis);
break;
default:
break;
}
@ -986,4 +1031,361 @@ void NativeInlineLowering::TryInlineDateGetTime(GateRef gate, size_t argc, bool
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
}
void NativeInlineLowering::TryInlineObjectIs(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 2) { // 2: left and right
return;
}
size_t firstParam = skipThis ? 1 : 0;
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef left = acc_.GetValueIn(gate, firstParam);
GateRef right = acc_.GetValueIn(gate, firstParam + 1);
GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIs(), { left, right });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineObjectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 1) {
return;
}
size_t firstParam = skipThis ? 1 : 0;
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef value = acc_.GetValueIn(gate, firstParam);
GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { value });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineObjectGetProto(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
{
if (!skipThis || argc != 0) {
return;
}
Environment env(gate, circuit_, &builder_);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 1), builder_.IntPtr(static_cast<int64_t>(id))); // 1: func
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef thisValue = acc_.GetValueIn(gate, 0);
GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { thisValue });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineObjectCreate(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 1) {
return;
}
size_t firstParam = skipThis ? 1 : 0;
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef proto = acc_.GetValueIn(gate, firstParam);
GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectCreate(), { proto });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineObjectIsPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
if (!skipThis || argc != 1) {
return;
}
Environment env(gate, circuit_, &builder_);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef thisValue = acc_.GetValueIn(gate, 0);
GateRef value = acc_.GetValueIn(gate, 1);
GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIsPrototypeOf(), {thisValue, value});
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineObjectHasOwnProperty(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
if (!skipThis || argc != 1) {
return;
}
Environment env(gate, circuit_, &builder_);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef thisValue = acc_.GetValueIn(gate, 0);
GateRef key = acc_.GetValueIn(gate, 1);
GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectHasOwnProperty(), { thisValue, key });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineReflectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 1) {
return;
}
size_t firstParam = skipThis ? 1 : 0;
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef value = acc_.GetValueIn(gate, firstParam);
GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGetPrototypeOf(), { value });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineReflectGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 2) { // 2: target and key, do not handle receiver argument scene
return;
}
size_t firstParam = skipThis ? 1 : 0;
GateRef key = acc_.GetValueIn(gate, firstParam + 1);
if (!TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, key)) {
return;
}
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef target = acc_.GetValueIn(gate, firstParam);
GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGet(), { target, key });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineReflectHas(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 2) { // 2: target and key
return;
}
size_t firstParam = skipThis ? 1 : 0;
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef target = acc_.GetValueIn(gate, firstParam);
GateRef key = acc_.GetValueIn(gate, firstParam + 1);
GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectHas(), { target, key });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineReflectConstruct(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 2) { // 2: optimize newtarget equal target
return;
}
size_t firstParam = skipThis ? 1 : 0;
GateRef target = acc_.GetValueIn(gate, firstParam);
GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 1);
OpCode op = acc_.GetOpCode(argumentsList);
if (op != OpCode::JS_BYTECODE) {
return;
}
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(argumentsList);
// optimize empty array literal argumentsList
if ((ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM8) && (ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM16)) {
return;
}
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectConstruct(), { target });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineReflectApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (argc != 3) { // 3: target key and argumentsList
return;
}
size_t firstParam = skipThis ? 1 : 0;
GateRef target = acc_.GetValueIn(gate, firstParam);
GateRef thisValue = acc_.GetValueIn(gate, firstParam + 1);
GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 2);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectApply(), { target, thisValue, argumentsList });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineFunctionPrototypeApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (!skipThis || argc == 0) {
return;
}
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef thisFunc = acc_.GetValueIn(gate, 0);
GateRef thisArg = acc_.GetValueIn(gate, 1);
GateRef argArray = (argc == 2) ? (acc_.GetValueIn(gate, 2)) : (builder_.UndefineConstant());
GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeApply(), { thisFunc, thisArg, argArray });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineFunctionPrototypeBind(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (!skipThis || argc != 1) {
return;
}
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef target = acc_.GetValueIn(gate, 0);
GateRef thisArg = acc_.GetValueIn(gate, 1);
GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeBind(), { target, thisArg });
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineFunctionPrototypeCall(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (!skipThis || argc == 0) {
return;
}
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
std::vector<GateRef> args(argc + 1); // 1: thisFunc
for (size_t i = 0; i <= argc; ++i) {
args[i] = acc_.GetValueIn(gate, i);
}
GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeCall(argc + 1), args);
ReplaceGateWithPendingException(gate, ret);
}
void NativeInlineLowering::TryInlineFunctionPrototypeHasInstance(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
bool skipThis)
{
Environment env(gate, circuit_, &builder_);
if (!skipThis || argc != 1) {
return;
}
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func
}
if (EnableTrace()) {
AddTraceLogs(gate, id);
}
GateRef function = acc_.GetValueIn(gate, 0);
GateRef value = acc_.GetValueIn(gate, 1);
GateRef ret = builder_.OrdinaryHasInstance(value, function);
ReplaceGateWithPendingException(gate, ret);
}
} // namespace panda::ecmascript

View File

@ -29,7 +29,7 @@ namespace panda::ecmascript::kungfu {
class NativeInlineLowering {
public:
explicit NativeInlineLowering(Circuit *circuit, CompilationConfig* cmpCfg, PassContext *ctx, bool enableLog,
const std::string& name)
const std::string& name, Chunk *chunk)
: circuit_(circuit),
builder_(circuit, cmpCfg),
acc_(circuit),
@ -38,7 +38,8 @@ public:
methodName_(name),
nocheck_(ctx->GetCompilationEnv()->GetJSOptions().IsCompilerNoCheck()),
traceInline_(ctx->GetCompilationEnv()->GetJSOptions().GetTraceInline()),
compilationEnv_(ctx->GetCompilationEnv()) {}
compilationEnv_(ctx->GetCompilationEnv()),
chunk_(chunk) {}
~NativeInlineLowering() = default;
void RunNativeInlineLowering();
@ -78,6 +79,21 @@ private:
void TryInlineDateGetTime(GateRef gate, size_t argc, bool skipThis);
void TryInlineWhitoutParamBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
const GateMetaData* op, bool skipThis);
void TryInlineObjectIs(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineObjectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineObjectGetProto(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineObjectCreate(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineObjectIsPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineObjectHasOwnProperty(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineReflectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineReflectGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineReflectHas(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineReflectConstruct(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineReflectApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineFunctionPrototypeApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineFunctionPrototypeBind(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineFunctionPrototypeCall(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineFunctionPrototypeHasInstance(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineBigIntConstructor(GateRef gate, size_t argc, bool skipThis);
void ReplaceGateWithPendingException(GateRef hirGate, GateRef value);
@ -113,6 +129,7 @@ private:
bool nocheck_;
bool traceInline_;
const CompilationEnv *compilationEnv_ {nullptr};
Chunk* chunk_ {nullptr};
};
}
#endif // ECMASCRIPT_COMPILER_BUILTIN_INLINE_H

View File

@ -285,6 +285,7 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
case OpCode::TYPE_OF_CHECK:
case OpCode::ARRAY_CONSTRUCTOR:
case OpCode::OBJECT_CONSTRUCTOR:
case OpCode::BOOLEAN_CONSTRUCTOR:
case OpCode::LD_LOCAL_MODULE_VAR:
case OpCode::STORE_MODULE_VAR:
case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
@ -302,6 +303,19 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
case OpCode::SET_ADD:
case OpCode::LOAD_BUILTIN_OBJECT:
case OpCode::CREATE_ARRAY:
case OpCode::OBJECT_IS:
case OpCode::OBJECT_GET_PROTOTYPE_OF:
case OpCode::OBJECT_CREATE:
case OpCode::OBJECT_IS_PROTOTYPE_OF:
case OpCode::OBJECT_HAS_OWN_PROPERTY:
case OpCode::REFLECT_GET_PROTOTYPE_OF:
case OpCode::REFLECT_GET:
case OpCode::REFLECT_HAS:
case OpCode::REFLECT_CONSTRUCT:
case OpCode::REFLECT_APPLY:
case OpCode::FUNCTION_PROTOTYPE_APPLY:
case OpCode::FUNCTION_PROTOTYPE_BIND:
case OpCode::FUNCTION_PROTOTYPE_CALL:
return VisitOthers(gate);
default:
return Circuit::NullGate();

View File

@ -189,7 +189,7 @@ public:
{
return optBCRange_;
}
const CallMethodFlagMap *GetCallMethodFlagMap() const
{
return callMethodFlagMap_;
@ -516,8 +516,8 @@ public:
TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset());
inlining.RunTSInlineLowering();
Chunk chunk(data->GetNativeAreaAllocator());
if (passOptions->EnableLexenvSpecialization()) {
Chunk chunk(data->GetNativeAreaAllocator());
{
CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
GetEnvSpecializationPass getEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk);
@ -538,7 +538,7 @@ public:
if (passOptions->EnableInlineNative()) {
NativeInlineLowering nativeInline(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(),
enableLog, data->GetMethodName());
enableLog, data->GetMethodName(), &chunk);
nativeInline.RunNativeInlineLowering();
}
return true;

View File

@ -112,7 +112,9 @@ enum class TypedCallTargetCheckOp : uint8_t;
V(ProtoTypeChanged2, PROTOTYPECHANGED2) \
V(BuiltinIsHole1, BUILTINISHOLE1) \
V(NewBuiltinCtorFail1, NEWBUILTINCTORFAIL1) \
V(NewBuiltinCtorFail2, NEWBUILTINCTORFAIL2) \
V(NewBuiltinCtorObject, NEWBUILTINCTOROBJECT) \
V(NewBuiltinCtorArray, NEWBUILTINCTORARRAY) \
V(NewBuiltinCtorBoolean, NEWBUILTINCTORBOOLEAN) \
V(IsUndefinedOrHole, ISUNDEFINEDORHOLE) \
V(IsNotUndefinedOrHole, ISNOTUNDEFINEDORHOLE) \
V(BuiltinInliningTypeGuard, BUILTIN_INLINING_TYPE_GUARD) \

View File

@ -384,10 +384,7 @@ inline GateRef StubBuilder::IntPtrAnd(GateRef x, GateRef y)
inline GateRef StubBuilder::IntPtrEqual(GateRef x, GateRef y)
{
if (env_->Is32Bit()) {
return Int32Equal(x, y);
}
return Int64Equal(x, y);
return env_->GetBuilder()->IntPtrEqual(x, y);
}
inline GateRef StubBuilder::Int16Sub(GateRef x, GateRef y)
@ -3099,10 +3096,7 @@ inline GateRef StubBuilder::ComputeTaggedArraySize(GateRef length)
inline GateRef StubBuilder::GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index)
{
GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
auto constantIndex = IntPtr(JSTaggedValue::TaggedTypeSize() * static_cast<size_t>(index));
return Load(type, gConstAddr, constantIndex);
return env_->GetBuilder()->GetGlobalConstantValue(type, glue, index);
}
inline GateRef StubBuilder::GetSingleCharTable(GateRef glue)
@ -3444,9 +3438,10 @@ inline GateRef StubBuilder::GetSortedIndex(GateRef layoutInfo, GateRef index)
return GetSortedIndex(GetAttr(layoutInfo, index));
}
inline void StubBuilder::SetToPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef result)
inline void StubBuilder::SetToPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef result,
GateRef hir)
{
GateRef hash = HashFromHclassAndKey(glue, cls, key);
GateRef hash = HashFromHclassAndKey(glue, cls, key, hir);
GateRef prop =
PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(PropertiesCache::PropertyKey::GetPropertyKeySize())));
StoreWithoutBarrier(VariableType::JS_POINTER(), prop, IntPtr(PropertiesCache::PropertyKey::GetHclassOffset()), cls);
@ -3460,11 +3455,31 @@ inline void StubBuilder::StoreWithoutBarrier(VariableType type, GateRef base, Ga
env_->GetBuilder()->StoreWithoutBarrier(type, addr, value);
}
inline GateRef StubBuilder::HashFromHclassAndKey(GateRef glue, GateRef cls, GateRef key)
inline GateRef StubBuilder::HashFromHclassAndKey(GateRef glue, GateRef cls, GateRef key, GateRef hir)
{
GateRef clsHash = Int32LSR(ChangeIntPtrToInt32(TaggedCastToIntPtr(cls)), Int32(3)); // skip 8bytes
GateRef keyHash = GetKeyHashCode(glue, key);
GateRef keyHash = GetKeyHashCode(glue, key, hir);
return Int32And(Int32Xor(clsHash, keyHash), Int32(PropertiesCache::CACHE_LENGTH_MASK));
}
inline GateRef StubBuilder::OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto)
{
return env_->GetBuilder()->OrdinaryNewJSObjectCreate(glue, proto);
}
inline GateRef StubBuilder::NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj)
{
return env_->GetBuilder()->NewJSPrimitiveRef(glue, index, obj);
}
inline GateRef StubBuilder::ToObject(GateRef glue, GateRef obj)
{
return env_->GetBuilder()->ToObject(glue, obj);
}
inline GateRef StubBuilder::GetPrototype(GateRef glue, GateRef object)
{
return env_->GetBuilder()->GetPrototype(glue, object);
}
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_STUB_INL_H

View File

@ -257,7 +257,7 @@ void StubBuilder::MatchFieldType(GateRef fieldType, GateRef value, Label *execut
// FindElementWithCache in ecmascript/layout_info-inl.h
GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hclass,
GateRef key, GateRef propsNum)
GateRef key, GateRef propsNum, GateRef hir)
{
auto env = GetEnvironment();
Label subEntry(env);
@ -310,14 +310,14 @@ GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, Gate
Label notFind(env);
Label setCache(env);
GateRef cache = GetPropertiesCache(glue);
GateRef index = GetIndexFromPropertiesCache(glue, cache, hclass, key);
GateRef index = GetIndexFromPropertiesCache(glue, cache, hclass, key, hir);
BRANCH(Int32Equal(index, Int32(PropertiesCache::NOT_FOUND)), &notFind, &find);
Bind(&notFind);
{
result = BinarySearch(glue, layoutInfo, key, propsNum);
result = BinarySearch(glue, layoutInfo, key, propsNum, hir);
BRANCH(Int32Equal(*result, Int32(PropertiesCache::NOT_FOUND)), &exit, &setCache);
Bind(&setCache);
SetToPropertiesCache(glue, cache, hclass, key, *result);
SetToPropertiesCache(glue, cache, hclass, key, *result, hir);
Jump(&exit);
}
Bind(&find);
@ -331,7 +331,7 @@ GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, Gate
return ret;
}
GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key)
GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef hir)
{
auto env = GetEnvironment();
Label subentry(env);
@ -340,7 +340,7 @@ GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, Ga
Label exit(env);
Label find(env);
GateRef hash = HashFromHclassAndKey(glue, cls, key);
GateRef hash = HashFromHclassAndKey(glue, cls, key, hir);
GateRef prop =
PtrAdd(cache, PtrMul(ZExtInt32ToPtr(hash), IntPtr(PropertiesCache::PropertyKey::GetPropertyKeySize())));
GateRef propHclass =
@ -360,7 +360,7 @@ GateRef StubBuilder::GetIndexFromPropertiesCache(GateRef glue, GateRef cache, Ga
return ret;
}
GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum)
GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum, GateRef hir)
{
auto env = GetEnvironment();
Label subentry(env);
@ -372,7 +372,7 @@ GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key,
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
DEFVARIABLE(mid, VariableType::INT32(), Int32(-1));
GateRef keyHash = GetKeyHashCode(glue, key);
GateRef keyHash = GetKeyHashCode(glue, key, hir);
Label loopHead(env);
Label loopEnd(env);
Label afterLoop(env);
@ -388,7 +388,7 @@ GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key,
Bind(&next);
mid = Int32Add(*low, Int32Div(Int32Sub(*high, *low), Int32(2))); // 2: half
GateRef midKey = GetSortedKey(layoutInfo, *mid);
GateRef midHash = GetKeyHashCode(glue, midKey);
GateRef midHash = GetKeyHashCode(glue, midKey, hir);
BRANCH(Int32UnsignedGreaterThan(midHash, keyHash), &midGreaterKey, &midnotGreaterKey);
Bind(&midGreaterKey);
{
@ -439,7 +439,8 @@ GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key,
midLeft = Int32Sub(*midLeft, Int32(1));
sortIndex = GetSortedIndex(layoutInfo, *midLeft);
currentKey = GetKey(layoutInfo, *sortIndex);
BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey), keyHash), &hashEqual, &afterLoop1);
BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual,
&afterLoop1);
Bind(&hashEqual);
{
Label retIndex1(env);
@ -476,7 +477,7 @@ GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key,
midRight = Int32Add(*midRight, Int32(1));
sortIndex = GetSortedIndex(layoutInfo, *midRight);
currentKey = GetKey(layoutInfo, *sortIndex);
BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey), keyHash), &hashEqual, &exit);
BRANCH(Int32Equal(GetKeyHashCode(glue, *currentKey, hir), keyHash), &hashEqual, &exit);
Bind(&hashEqual);
{
Label retIndex2(env);
@ -515,7 +516,7 @@ GateRef StubBuilder::BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key,
return ret;
}
GateRef StubBuilder::GetKeyHashCode(GateRef glue, GateRef key)
GateRef StubBuilder::GetKeyHashCode(GateRef glue, GateRef key, GateRef hir)
{
auto env = GetEnvironment();
Label subentry(env);
@ -528,7 +529,7 @@ GateRef StubBuilder::GetKeyHashCode(GateRef glue, GateRef key)
BRANCH(TaggedIsString(key), &isString, &isSymblo);
Bind(&isString);
{
result = GetHashcodeFromString(glue, key);
result = GetHashcodeFromString(glue, key, hir);
Jump(&exit);
}
Bind(&isSymblo);
@ -600,7 +601,7 @@ GateRef StubBuilder::FindElementFromNumberDictionary(GateRef glue, GateRef eleme
}
// int TaggedHashTable<Derived>::FindEntry(const JSTaggedValue &key) in tagged_hash_table.h
GateRef StubBuilder::FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key)
GateRef StubBuilder::FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key, GateRef hir)
{
auto env = GetEnvironment();
Label funcEntry(env);
@ -636,7 +637,7 @@ GateRef StubBuilder::FindEntryFromNameDictionary(GateRef glue, GateRef elements,
BRANCH(IsString(key), &isString, &notString);
Bind(&isString);
{
hash = GetHashcodeFromString(glue, key);
hash = GetHashcodeFromString(glue, key, hir);
Jump(&beforeDefineHash);
}
Bind(&notString);
@ -5060,50 +5061,6 @@ GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef o
return ret;
}
GateRef StubBuilder::GetPrototype(GateRef glue, GateRef object)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
Label objectIsHeapObject(env);
Label objectIsEcmaObject(env);
Label objectNotEcmaObject(env);
BRANCH(TaggedIsHeapObject(object), &objectIsHeapObject, &objectNotEcmaObject);
Bind(&objectIsHeapObject);
BRANCH(TaggedObjectIsEcmaObject(object), &objectIsEcmaObject, &objectNotEcmaObject);
Bind(&objectNotEcmaObject);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
CallRuntime(glue, RTSTUB_ID(Dump), { object });
result = Exception();
Jump(&exit);
}
Bind(&objectIsEcmaObject);
{
Label objectIsJsProxy(env);
Label objectNotIsJsProxy(env);
BRANCH(IsJsProxy(object), &objectIsJsProxy, &objectNotIsJsProxy);
Bind(&objectIsJsProxy);
{
result = CallRuntime(glue, RTSTUB_ID(CallGetPrototype), { object });
Jump(&exit);
}
Bind(&objectNotIsJsProxy);
{
result = GetPrototypeFromHClass(LoadHClass(object));
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();
@ -6693,125 +6650,6 @@ GateRef StubBuilder::GetFunctionPrototype(GateRef glue, size_t index)
return ret;
}
GateRef StubBuilder::ToObject(GateRef glue, GateRef obj)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::JS_ANY(), obj);
DEFVARIABLE(taggedId, VariableType::INT32(), Int32(0));
Label isNumber(env);
Label notNumber(env);
Label isBoolean(env);
Label notBoolean(env);
Label isString(env);
Label notString(env);
Label isECMAObject(env);
Label notIsECMAObject(env);
Label isSymbol(env);
Label notSymbol(env);
Label isUndefined(env);
Label notIsUndefined(env);
Label isNull(env);
Label notIsNull(env);
Label isHole(env);
Label notIsHole(env);
Label isBigInt(env);
Label notIsBigInt(env);
Label throwError(env);
BRANCH(IsEcmaObject(obj), &isECMAObject, &notIsECMAObject);
Bind(&isECMAObject);
{
result = obj;
Jump(&exit);
}
Bind(&notIsECMAObject);
BRANCH(TaggedIsNumber(obj), &isNumber, &notNumber);
Bind(&isNumber);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notNumber);
BRANCH(TaggedIsBoolean(obj), &isBoolean, &notBoolean);
Bind(&isBoolean);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notBoolean);
BRANCH(TaggedIsString(obj), &isString, &notString);
Bind(&isString);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notString);
BRANCH(TaggedIsSymbol(obj), &isSymbol, &notSymbol);
Bind(&isSymbol);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notSymbol);
BRANCH(TaggedIsUndefined(obj), &isUndefined, &notIsUndefined);
Bind(&isUndefined);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
Jump(&throwError);
}
Bind(&notIsUndefined);
BRANCH(TaggedIsHole(obj), &isHole, &notIsHole);
Bind(&isHole);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
Jump(&throwError);
}
Bind(&notIsHole);
BRANCH(TaggedIsNull(obj), &isNull, &notIsNull);
Bind(&isNull);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
Jump(&throwError);
}
Bind(&notIsNull);
BRANCH(TaggedIsBigInt(obj), &isBigInt, &notIsBigInt);
Bind(&isBigInt);
{
result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
Jump(&exit);
}
Bind(&notIsBigInt);
{
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
Jump(&throwError);
}
Bind(&throwError);
{
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(*taggedId) });
result = Exception();
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj)
{
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
GateRef protoOrHclass = Load(VariableType::JS_ANY(), func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
NewObjectStubBuilder newBuilder(env_);
GateRef newObj = newBuilder.NewJSObject(glue, protoOrHclass);
GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
Store(VariableType::JS_ANY(), glue, newObj, valueOffset, obj);
return newObj;
}
GateRef StubBuilder::DeletePropertyOrThrow(GateRef glue, GateRef obj, GateRef value)
{
auto env = GetEnvironment();
@ -7313,9 +7151,9 @@ void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *r
Jump(exit);
}
GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir)
{
return env_->GetBuilder()->GetHashcodeFromString(glue, value);
return env_->GetBuilder()->GetHashcodeFromString(glue, value, hir);
}
GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)

View File

@ -430,7 +430,7 @@ public:
GateRef GetPrototypeHandlerHandlerInfo(GateRef object);
GateRef GetStoreTSHandlerHolder(GateRef object);
GateRef GetStoreTSHandlerHandlerInfo(GateRef object);
GateRef GetPrototype(GateRef glue, GateRef object);
inline GateRef GetPrototype(GateRef glue, GateRef object);
GateRef GetHasChanged(GateRef object);
GateRef HclassIsPrototypeHandler(GateRef hClass);
GateRef HclassIsTransitionHandler(GateRef hClass);
@ -463,7 +463,7 @@ public:
GateRef CalcHashcodeForInt(GateRef value);
void CalcHashcodeForDouble(GateRef value, Variable *res, Label *exit);
void CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit);
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
GateRef GetHashcodeFromString(GateRef glue, GateRef value, GateRef hir = Circuit::NullGate());
inline GateRef IsIntegerString(GateRef string);
inline void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode, GateRef isInteger);
inline GateRef GetRawHashFromString(GateRef value);
@ -542,9 +542,9 @@ public:
GateRef GetKeyFromLayoutInfo(GateRef layout, GateRef entry);
void MatchFieldType(GateRef fieldType, GateRef value, Label *executeSetProp, Label *typeMismatch);
GateRef FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hClass,
GateRef key, GateRef propsNum);
GateRef key, GateRef propsNum, GateRef hir = Circuit::NullGate());
GateRef FindElementFromNumberDictionary(GateRef glue, GateRef elements, GateRef index);
GateRef FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key);
GateRef FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key, GateRef hir = Circuit::NullGate());
GateRef IsMatchInTransitionDictionary(GateRef element, GateRef key, GateRef metaData, GateRef attr);
GateRef FindEntryFromTransitionDictionary(GateRef glue, GateRef elements, GateRef key, GateRef metaData);
GateRef JSObjectGetProperty(GateRef obj, GateRef hClass, GateRef propAttr);
@ -602,9 +602,10 @@ public:
GateRef ChangeFloat64ToInt32(GateRef x);
GateRef TruncDoubleToFloat32(GateRef x);
GateRef DeletePropertyOrThrow(GateRef glue, GateRef obj, GateRef value);
GateRef ToObject(GateRef glue, GateRef obj);
inline GateRef ToObject(GateRef glue, GateRef obj);
GateRef DeleteProperty(GateRef glue, GateRef obj, GateRef value);
GateRef NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj);
inline GateRef OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto);
inline GateRef NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj);
GateRef ModuleNamespaceDeleteProperty(GateRef glue, GateRef obj, GateRef value);
GateRef Int64ToTaggedPtr(GateRef x);
GateRef TruncInt16ToInt8(GateRef x);
@ -883,15 +884,18 @@ public:
GateRef ChangeTaggedPointerToInt64(GateRef x);
GateRef GetLastLeaveFrame(GateRef glue);
inline GateRef GetPropertiesCache(GateRef glue);
GateRef GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key);
inline void SetToPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef result);
GateRef HashFromHclassAndKey(GateRef glue, GateRef cls, GateRef key);
GateRef GetKeyHashCode(GateRef glue, GateRef key);
GateRef GetIndexFromPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key,
GateRef hir = Circuit::NullGate());
inline void SetToPropertiesCache(GateRef glue, GateRef cache, GateRef cls, GateRef key, GateRef result,
GateRef hir = Circuit::NullGate());
GateRef HashFromHclassAndKey(GateRef glue, GateRef cls, GateRef key, GateRef hir = Circuit::NullGate());
GateRef GetKeyHashCode(GateRef glue, GateRef key, GateRef hir = Circuit::NullGate());
inline GateRef GetSortedKey(GateRef layoutInfo, GateRef index);
inline GateRef GetSortedIndex(GateRef layoutInfo, GateRef index);
inline GateRef GetSortedIndex(GateRef attr);
inline void StoreWithoutBarrier(VariableType type, GateRef base, GateRef offset, GateRef value);
GateRef BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum);
GateRef BinarySearch(GateRef glue, GateRef layoutInfo, GateRef key, GateRef propsNum,
GateRef hir = Circuit::NullGate());
private:
using BinaryOperation = std::function<GateRef(Environment*, GateRef, GateRef)>;

View File

@ -224,6 +224,30 @@ bool TypeInfoAccessor::IsTrustedStringType(
return false;
}
bool TypeInfoAccessor::IsTrustedNotSameType(const CompilationEnv *env, Circuit *circuit, Chunk *chunk,
GateAccessor acc, GateRef left, GateRef right)
{
bool leftIsBoolean = IsTrustedBooleanType(acc, left);
bool rightIsBoolean = IsTrustedBooleanType(acc, right);
bool leftIsNumber = IsTrustedNumberType(acc, left);
bool rightIsNumber = IsTrustedNumberType(acc, right);
bool leftIsString = IsTrustedStringType(env, circuit, chunk, acc, left);
bool rightIsString = IsTrustedStringType(env, circuit, chunk, acc, right);
if (leftIsBoolean) {
return rightIsNumber || rightIsString;
}
if (leftIsNumber) {
return rightIsBoolean || rightIsString;
}
if (leftIsString) {
return rightIsBoolean || rightIsNumber;
}
return false;
}
bool NewObjRangeTypeInfoAccessor::FindHClass()
{
auto sampleType = acc_.TryGetPGOType(gate_).GetPGOSampleType();

View File

@ -50,6 +50,16 @@ public:
static bool IsTrustedStringType(
const CompilationEnv *env, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate);
static inline bool IsTrustedBooleanOrNumberOrStringType(const CompilationEnv *env, Circuit *circuit,
Chunk *chunk, GateAccessor acc, GateRef gate)
{
return IsTrustedBooleanType(acc, gate) || IsTrustedNumberType(acc, gate) ||
IsTrustedStringType(env, circuit, chunk, acc, gate);
}
static bool IsTrustedNotSameType(const CompilationEnv *env, Circuit *circuit, Chunk *chunk,
GateAccessor acc, GateRef left, GateRef right);
protected:
ParamType PGOSampleTypeToParamType() const;
static ParamType PGOBuiltinTypeToParamType(ProfileType pgoType);

View File

@ -1485,6 +1485,14 @@ bool TypedBytecodeLowering::TryLowerNewBuiltinConstructor(GateRef gate)
builder_.ObjectConstructorCheck(ctor);
}
constructGate = builder_.BuiltinConstructor(BuiltinTypeId::OBJECT, gate);
} else if (tacc.IsBuiltinConstructor(BuiltinTypeId::BOOLEAN)) {
if (acc_.GetNumValueIn(gate) <= 2) { // 2: ctor and first arg
AddProfiling(gate);
if (!Uncheck()) {
builder_.BooleanConstructorCheck(ctor);
}
constructGate = builder_.BuiltinConstructor(BuiltinTypeId::BOOLEAN, gate);
}
}
if (constructGate == Circuit::NullGate()) {
return false;

View File

@ -175,6 +175,12 @@ GateRef TypedHCRLowering::VisitGate(GateRef gate)
case OpCode::OBJECT_CONSTRUCTOR:
LowerObjectConstructor(gate, glue);
break;
case OpCode::BOOLEAN_CONSTRUCTOR_CHECK:
LowerBooleanConstructorCheck(gate, glue);
break;
case OpCode::BOOLEAN_CONSTRUCTOR:
LowerBooleanConstructor(gate, glue);
break;
case OpCode::ORDINARY_HAS_INSTANCE:
LowerOrdinaryHasInstance(gate, glue);
break;
@ -2290,7 +2296,7 @@ void TypedHCRLowering::LowerArrayConstructorCheck(GateRef gate, GateRef glue)
}
}
builder_.Bind(&exit);
builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORFAIL1);
builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORARRAY);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
@ -2435,7 +2441,7 @@ void TypedHCRLowering::LowerObjectConstructorCheck(GateRef gate, GateRef glue)
}
}
builder_.Bind(&exit);
builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORFAIL2);
builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTOROBJECT);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
@ -2521,6 +2527,77 @@ void TypedHCRLowering::LowerObjectConstructor(GateRef gate, GateRef glue)
ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *res);
}
void TypedHCRLowering::LowerBooleanConstructorCheck(GateRef gate, GateRef glue)
{
Environment env(gate, circuit_, &builder_);
GateRef frameState = GetFrameState(gate);
GateRef newTarget = acc_.GetValueIn(gate, 0);
Label isHeapObject(&builder_);
Label exit(&builder_);
DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
check = builder_.TaggedIsHeapObject(newTarget);
BRANCH_CIR(*check, &isHeapObject, &exit);
builder_.Bind(&isHeapObject);
{
Label isJSFunction(&builder_);
check = builder_.IsJSFunction(newTarget);
BRANCH_CIR(*check, &isJSFunction, &exit);
builder_.Bind(&isJSFunction);
{
Label getHclass(&builder_);
GateRef glueGlobalEnvOffset = builder_.IntPtr(
JSThread::GlueData::GetGlueGlobalEnvOffset(builder_.GetCurrentEnvironment()->Is32Bit()));
GateRef glueGlobalEnv = builder_.Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
GateRef booleanFunc =
builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
check = builder_.Equal(booleanFunc, newTarget);
BRANCH_CIR(*check, &getHclass, &exit);
builder_.Bind(&getHclass);
{
GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), newTarget,
builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
check = builder_.IsJSHClass(intialHClass);
builder_.Jump(&exit);
}
}
}
builder_.Bind(&exit);
builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORBOOLEAN);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypedHCRLowering::LowerBooleanConstructor(GateRef gate, GateRef glue)
{
Environment env(gate, circuit_, &builder_);
GateRef value = builder_.Undefined();
ASSERT(acc_.GetNumValueIn(gate) <= 2); // 2: new target and arg0
if (acc_.GetNumValueIn(gate) > 1) {
value = acc_.GetValueIn(gate, 1);
}
DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
Label isBoolean(&builder_);
Label slowPath(&builder_);
Label exit(&builder_);
BRANCH_CIR(builder_.TaggedIsBoolean(value), &isBoolean, &slowPath);
builder_.Bind(&isBoolean);
{
res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BOOLEAN, glue, value);
builder_.Jump(&exit);
}
builder_.Bind(&slowPath);
{
size_t range = acc_.GetNumValueIn(gate);
std::vector<GateRef> args(range);
for (size_t i = 0; i < range; ++i) {
args[i] = acc_.GetValueIn(gate, i);
}
res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *res);
}
GateRef TypedHCRLowering::NewJSPrimitiveRef(PrimitiveType type, GateRef glue, GateRef value)
{
GateRef glueGlobalEnvOffset = builder_.IntPtr(
@ -2659,7 +2736,22 @@ void TypedHCRLowering::LowerOrdinaryHasInstance(GateRef gate, GateRef glue)
{ target, prototypeString }, gate);
builder_.Jump(&gotCtorPrototype);
}
// 6. If Type(P) is not Object, throw a TypeError exception.
Label prototypeIsEcmaObj(&builder_);
Label prototypeNotEcmaObj(&builder_);
builder_.Bind(&gotCtorPrototype);
{
BRANCH_CIR(builder_.IsEcmaObject(*constructorPrototype), &prototypeIsEcmaObj, &prototypeNotEcmaObj);
builder_.Bind(&prototypeNotEcmaObj);
{
GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
{ builder_.Int32ToTaggedInt(taggedId) }, gate);
result = builder_.ExceptionConstant();
builder_.Jump(&exit);
}
}
builder_.Bind(&prototypeIsEcmaObj);
// 7. Repeat
// a.Let O be O.[[GetPrototypeOf]]().
// b.ReturnIfAbrupt(O).

View File

@ -211,6 +211,8 @@ private:
void LowerArrayConstructor(GateRef gate, GateRef glue);
void LowerObjectConstructorCheck(GateRef gate, GateRef glue);
void LowerObjectConstructor(GateRef gate, GateRef glue);
void LowerBooleanConstructorCheck(GateRef gate, GateRef glue);
void LowerBooleanConstructor(GateRef gate, GateRef glue);
GateRef NewJSPrimitiveRef(PrimitiveType type, GateRef glue, GateRef value);
void ReplaceGateWithPendingException(GateRef glue, GateRef gate, GateRef state, GateRef depend, GateRef value);
void LowerOrdinaryHasInstance(GateRef gate, GateRef glue);

View File

@ -18,6 +18,7 @@
#include "ecmascript/byte_array.h"
#include "ecmascript/compiler/assembler/assembler.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/builtins/builtins_object_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
@ -28,6 +29,7 @@
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/share_opcodes.h"
#include "ecmascript/compiler/type_info_accessors.h"
#include "ecmascript/compiler/variable_type.h"
#include "ecmascript/global_env.h"
#include "ecmascript/jit/jit.h"
@ -288,6 +290,45 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate)
case OpCode::STRING_SLICE:
LowerStringSlice(gate);
break;
case OpCode::OBJECT_IS:
LowerObjectIs(gate);
break;
case OpCode::OBJECT_GET_PROTOTYPE_OF:
LowerObjectGetPrototypeOf(gate);
break;
case OpCode::OBJECT_CREATE:
LowerObjectCreate(gate);
break;
case OpCode::OBJECT_IS_PROTOTYPE_OF:
LowerObjectIsPrototypeOf(gate);
break;
case OpCode::OBJECT_HAS_OWN_PROPERTY:
LowerObjectHasOwnProperty(gate);
break;
case OpCode::REFLECT_GET_PROTOTYPE_OF:
LowerReflectGetPrototypeOf(gate);
break;
case OpCode::REFLECT_GET:
LowerReflectGet(gate);
break;
case OpCode::REFLECT_HAS:
LowerReflectHas(gate);
break;
case OpCode::REFLECT_CONSTRUCT:
LowerReflectConstruct(gate);
break;
case OpCode::REFLECT_APPLY:
LowerReflectApply(gate);
break;
case OpCode::FUNCTION_PROTOTYPE_APPLY:
LowerFunctionPrototypeApply(gate);
break;
case OpCode::FUNCTION_PROTOTYPE_BIND:
LowerFunctionPrototypeBind(gate);
break;
case OpCode::FUNCTION_PROTOTYPE_CALL:
LowerFunctionPrototypeCall(gate);
break;
default:
break;
}
@ -2220,4 +2261,316 @@ GateRef TypedNativeInlineLowering::NumberToInt32(GateRef gate)
}
return Circuit::NullGate();
}
void TypedNativeInlineLowering::LowerObjectIs(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
GateRef result = Circuit::NullGate();
if (left == right) {
result = builder_.TaggedTrue();
} else if (TypeInfoAccessor::IsTrustedNotSameType(compilationEnv_, circuit_, chunk_, acc_, left, right)) {
result = builder_.TaggedFalse();
} else {
GateRef glue = acc_.GetGlueFromArgList();
GateRef boolRet = builder_.CallStub(glue, gate, CommonStubCSigns::SameValue, { glue, left, right});
result = builder_.BooleanToTaggedBooleanPtr(boolRet);
}
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
void TypedNativeInlineLowering::LowerObjectGetPrototypeOf(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef value = acc_.GetValueIn(gate, 0);
GateRef result = Circuit::NullGate();
// fast handle some primitive types
if (TypeInfoAccessor::IsTrustedBooleanOrNumberOrStringType(compilationEnv_, circuit_, chunk_, acc_, value)) {
GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env.Is32Bit()));
GateRef glueGlobalEnv = builder_.Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
size_t index = -1;
if (TypeInfoAccessor::IsTrustedBooleanType(acc_, value)) {
index = GlobalEnv::BOOLEAN_PROTOTYPE_INDEX;
} else if (TypeInfoAccessor::IsTrustedNumberType(acc_, value)) {
index = GlobalEnv::NUMBER_PROTOTYPE_INDEX;
} else {
ASSERT(TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, value));
index = GlobalEnv::STRING_PROTOTYPE_INDEX;
}
result = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
} else {
GateRef object = builder_.ToObject(glue, value);
result = builder_.GetPrototype(glue, object);
}
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
void TypedNativeInlineLowering::LowerObjectCreate(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef proto = acc_.GetValueIn(gate, 0);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
GateRef protoIsNull = builder_.TaggedIsNull(proto);
GateRef protoIsEcmaObj = builder_.IsEcmaObject(proto);
GateRef protoIsJSShared = builder_.TaggedIsSharedObj(proto);
Label exception(&builder_);
Label create(&builder_);
Label exit(&builder_);
BRANCH_CIR(builder_.BoolOr(builder_.BoolAnd(builder_.BoolNot(protoIsEcmaObj), builder_.BoolNot(protoIsNull)),
protoIsJSShared), &exception, &create);
builder_.Bind(&exception);
{
GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotValidObject));
builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
{ builder_.Int32ToTaggedInt(taggedId) }, gate);
result = builder_.ExceptionConstant();
builder_.Jump(&exit);
}
builder_.Bind(&create);
{
result = builder_.OrdinaryNewJSObjectCreate(glue, proto);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
}
void TypedNativeInlineLowering::LowerObjectIsPrototypeOf(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef thisValue = acc_.GetValueIn(gate, 0);
GateRef value = acc_.GetValueIn(gate, 1);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
// 1. If Type(V) is not Object, return false.
Label ecmaObject(&builder_);
Label returnFalse(&builder_);
Label returnException(&builder_);
Label exit(&builder_);
BRANCH_CIR(builder_.IsEcmaObject(value), &ecmaObject, &returnFalse);
builder_.Bind(&ecmaObject);
{
// 2. Let O be ? ToObject(this value).
GateRef obj = builder_.ToObject(glue, thisValue);
Label noPendingException(&builder_);
BRANCH_CIR(builder_.HasPendingException(glue), &returnException, &noPendingException);
builder_.Bind(&noPendingException);
{
// 3. Repeat,
// a. Set V to ? V.[[GetPrototypeOf]]().
// b. If V is null, return false.
// c. If SameValue(O, V) is true, return true.
DEFVALUE(proto, (&builder_), VariableType::JS_ANY(), value);
Label loopHead(&builder_);
Label loopEnd(&builder_);
Label loopExit(&builder_);
Label compare(&builder_);
builder_.Jump(&loopHead);
builder_.LoopBegin(&loopHead);
{
BRANCH_CIR(builder_.TaggedIsNotNull(*proto), &compare, &loopExit);
builder_.Bind(&compare);
{
proto = builder_.GetPrototype(glue, *proto);
Label noPendingException1(&builder_);
BRANCH_CIR(builder_.HasPendingException(glue), &returnException, &noPendingException1);
builder_.Bind(&noPendingException1);
{
Label sameValue(&builder_);
GateRef same = builder_.CallStub(glue, gate, CommonStubCSigns::SameValue,
{ glue, obj, *proto });
BRANCH_CIR(same, &sameValue, &loopEnd);
builder_.Bind(&sameValue);
{
result = builder_.TaggedTrue();
builder_.Jump(&exit);
}
}
}
}
builder_.Bind(&loopEnd);
builder_.LoopEnd(&loopHead);
builder_.Bind(&loopExit);
{
builder_.Jump(&exit);
}
}
}
builder_.Bind(&returnFalse);
{
result = builder_.TaggedFalse();
builder_.Jump(&exit);
}
builder_.Bind(&returnException);
{
result = builder_.ExceptionConstant();
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
}
void TypedNativeInlineLowering::LowerObjectHasOwnProperty(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef thisValue = acc_.GetValueIn(gate, 0);
GateRef key = acc_.GetValueIn(gate, 1);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
Label callRuntime(&builder_);
Label exit(&builder_);
BuiltinsObjectStubBuilder objectStubBuilder(&env, glue);
objectStubBuilder.HasOwnProperty(&result, &exit, &callRuntime, thisValue, key, gate);
builder_.Bind(&callRuntime);
{
result = builder_.CallRuntime(glue, RTSTUB_ID(ObjectPrototypeHasOwnProperty), Gate::InvalidGateRef,
{ thisValue, key }, gate);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
}
void TypedNativeInlineLowering::LowerReflectGetPrototypeOf(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef value = acc_.GetValueIn(gate, 0);
GateRef result = builder_.GetPrototype(glue, value); // Do not ToObject
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
void TypedNativeInlineLowering::LowerReflectGet(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef target = acc_.GetValueIn(gate, 0);
GateRef key = acc_.GetValueIn(gate, 1); // key is trusted string
Label isEcmaObject(&builder_);
Label notEcmaObject(&builder_);
Label exit(&builder_);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
// 1. If Type(target) is not Object, throw a TypeError exception.
BRANCH_CIR(builder_.IsEcmaObject(target), &isEcmaObject, &notEcmaObject);
builder_.Bind(&isEcmaObject);
{
result = builder_.CallStub(glue, gate, CommonStubCSigns::DeprecatedGetPropertyByName, // no ic
{ glue, target, key });
builder_.Jump(&exit);
}
builder_.Bind(&notEcmaObject);
{
GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
{ builder_.Int32ToTaggedInt(taggedId) }, gate);
result = builder_.ExceptionConstant();
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
}
void TypedNativeInlineLowering::LowerReflectHas(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef target = acc_.GetValueIn(gate, 0);
GateRef key = acc_.GetValueIn(gate, 1);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
Label afterHasOwn(&builder_);
Label callRuntime(&builder_);
Label exit(&builder_);
BuiltinsObjectStubBuilder objectStubBuilder(&env, glue);
objectStubBuilder.HasOwnProperty(&result, &afterHasOwn, &callRuntime, target, key, gate);
builder_.Bind(&afterHasOwn);
{
BRANCH_CIR(builder_.TaggedIsTrue(*result), &exit, &callRuntime);
}
builder_.Bind(&callRuntime);
{
result = builder_.CallRuntime(glue, RTSTUB_ID(ReflectHas), Gate::InvalidGateRef, { target, key }, gate);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
}
void TypedNativeInlineLowering::LowerReflectConstruct(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef target = acc_.GetValueIn(gate, 0);
GateRef thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewThisObjectChecked, { glue, target });
Label callCtor(&builder_);
Label callRuntime(&builder_);
Label exit(&builder_);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
BRANCH_CIR(builder_.TaggedIsHole(thisObj), &callRuntime, &callCtor);
builder_.Bind(&callCtor);
{
std::vector<GateRef> args { glue, builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS), target, target, thisObj };
result = builder_.Construct(gate, args);
builder_.Jump(&exit);
}
builder_.Bind(&callRuntime);
{
result = builder_.CallRuntime(glue, RTSTUB_ID(ReflectConstruct), Gate::InvalidGateRef, { target }, gate);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
}
void TypedNativeInlineLowering::LowerReflectApply(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef target = acc_.GetValueIn(gate, 0);
GateRef thisValue = acc_.GetValueIn(gate, 1);
GateRef argumentsList = acc_.GetValueIn(gate, 2);
GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(ReflectApply), Gate::InvalidGateRef,
{ target, thisValue, argumentsList }, gate);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
void TypedNativeInlineLowering::LowerFunctionPrototypeApply(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef thisFunc = acc_.GetValueIn(gate, 0);
GateRef thisArg = acc_.GetValueIn(gate, 1);
GateRef argArray = acc_.GetValueIn(gate, 2);
GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(FunctionPrototypeApply), Gate::InvalidGateRef,
{ thisFunc, thisArg, argArray }, gate);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
void TypedNativeInlineLowering::LowerFunctionPrototypeBind(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
GateRef target = acc_.GetValueIn(gate, 0);
GateRef thisArg = acc_.GetValueIn(gate, 1);
GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(FunctionPrototypeBind), Gate::InvalidGateRef,
{ target, thisArg }, gate);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
void TypedNativeInlineLowering::LowerFunctionPrototypeCall(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef glue = acc_.GetGlueFromArgList();
std::vector<GateRef> args = acc_.GetValueIns(gate);
GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(FunctionPrototypeCall), Gate::InvalidGateRef, args, gate);
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
}
}

View File

@ -126,6 +126,20 @@ private:
GateRef LowerGlobalTNumberIsFinite(GateRef value);
GateRef LowerGlobalTNumberIsNan(GateRef value);
void LowerObjectIs(GateRef gate);
void LowerObjectGetPrototypeOf(GateRef gate);
void LowerObjectCreate(GateRef gate);
void LowerObjectIsPrototypeOf(GateRef gate);
void LowerObjectHasOwnProperty(GateRef gate);
void LowerReflectGetPrototypeOf(GateRef gate);
void LowerReflectGet(GateRef gate);
void LowerReflectHas(GateRef gate);
void LowerReflectConstruct(GateRef gate);
void LowerReflectApply(GateRef gate);
void LowerFunctionPrototypeApply(GateRef gate);
void LowerFunctionPrototypeBind(GateRef gate);
void LowerFunctionPrototypeCall(GateRef gate);
void LowerToCommonStub(GateRef gate, CommonStubCSigns::ID id);
void LowerToBuiltinStub(GateRef gate, BuiltinsStubCSigns::ID id);

View File

@ -244,7 +244,22 @@ class ObjectFactory;
V(JSTaggedValue, NumberIsFinite, NUMBER_IS_FINITE_INDEX, ecma_roots_builtins) \
V(JSTaggedValue, NumberIsInteger, NUMBER_IS_INTEGER_INDEX, ecma_roots_builtins) \
V(JSTaggedValue, NumberIsSafeInteger, NUMBER_IS_SAFEINTEGER_INDEX, ecma_roots_builtins) \
V(JSTaggedValue, NumberParseFloat, NUMBER_PARSE_FLOAT_INDEX, ecma_roots_builtins)
V(JSTaggedValue, NumberParseFloat, NUMBER_PARSE_FLOAT_INDEX, ecma_roots_builtins) \
V(JSTaggedValue, ObjectIs, OBJECT_IS_INDEX, ecma_roots_special) \
V(JSTaggedValue, ObjectGetPrototypeOf, OBJECT_GET_PROTOTYPE_OF_INDEX, ecma_roots_special) \
V(JSTaggedValue, ObjectGetPrototo, OBJECT_GET_PROTO_INDEX, ecma_roots_special) \
V(JSTaggedValue, ObjectCreate, OBJECT_CREATE_INDEX, ecma_roots_special) \
V(JSTaggedValue, ObjectIsPrototypeOf, OBJECT_IS_PROTOTYPE_OF_INDEX, ecma_roots_special) \
V(JSTaggedValue, ObjectHasOwnProperty, OBJECT_HAS_OWN_PROPERTY_INDEX, ecma_roots_special) \
V(JSTaggedValue, ReflectGetPrototypeOf, REFLECT_GET_PROTOTYPE_OF_INDEX, ecma_roots_special) \
V(JSTaggedValue, ReflectGet, REFLECT_GET_INDEX, ecma_roots_special) \
V(JSTaggedValue, ReflectHas, REFLECT_HAS_INDEX, ecma_roots_special) \
V(JSTaggedValue, ReflectConstruct, REFLECT_CONSTRUCT_INDEX, ecma_roots_special) \
V(JSTaggedValue, ReflectApply, REFLECT_APPLY_INDEX, ecma_roots_special) \
V(JSTaggedValue, FunctionApply, FUNCTION_PROTOTYPE_APPLY_INDEX, ecma_roots_special) \
V(JSTaggedValue, FunctionBind, FUNCTION_PROTOTYPE_BIND_INDEX, ecma_roots_special) \
V(JSTaggedValue, FunctionCall, FUNCTION_PROTOTYPE_CALL_INDEX, ecma_roots_special) \
V(JSTaggedValue, FunctionHasInstance, FUNCTION_PROTOTYPE_HAS_INSTANCE_INDEX, ecma_roots_special)
// All of type JSTaggedValue
#define SHARED_GLOBAL_ENV_CONSTANT_STRING(V) \

View File

@ -34,6 +34,7 @@
V(JSTaggedValue, DateFunction, DATE_FUNCTION_INDEX) \
V(JSTaggedValue, DatePrototype, DATE_PROTOTYPE_INDEX) \
V(JSTaggedValue, BooleanFunction, BOOLEAN_FUNCTION_INDEX) \
V(JSTaggedValue, BooleanPrototype, BOOLEAN_PROTOTYPE_INDEX) \
V(JSTaggedValue, ErrorFunction, ERROR_FUNCTION_INDEX) \
V(JSTaggedValue, ArrayFunction, ARRAY_FUNCTION_INDEX) \
V(JSTaggedValue, ArrayPrototype, ARRAY_PROTOTYPE_INDEX) \

View File

@ -938,6 +938,11 @@ public:
return GetPGOSampleType()->IsString();
}
bool IsHeapObject() const
{
return GetPGOSampleType()->IsHeapObject();
}
const PGORWOpType* GetPGORWOpType()
{
if (type_ == nullptr) {

View File

@ -33,7 +33,9 @@
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/base/typed_array_helper.h"
#include "ecmascript/builtins/builtins_bigint.h"
#include "ecmascript/builtins/builtins_function.h"
#include "ecmascript/builtins/builtins_iterator.h"
#include "ecmascript/builtins/builtins_reflect.h"
#include "ecmascript/builtins/builtins_string_iterator.h"
#include "ecmascript/compiler/builtins/containers_stub_builder.h"
#include "ecmascript/builtins/builtins_array.h"
@ -53,6 +55,7 @@
#include "ecmascript/ic/ic_runtime.h"
#include "ecmascript/ic/profile_type_info.h"
#include "ecmascript/ic/properties_cache.h"
#include "ecmascript/interpreter/interpreter.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/interpreter/interpreter_assembly.h"
#include "ecmascript/js_api/js_api_arraylist.h"
@ -3843,6 +3846,86 @@ DEF_RUNTIME_STUBS(HasProperty)
return JSTaggedValue(res).GetRawData();
}
DEF_RUNTIME_STUBS(ObjectPrototypeHasOwnProperty)
{
RUNTIME_STUBS_HEADER(ObjectPrototypeHasOwnProperty);
JSHandle<JSTaggedValue> thisValue = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> key = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
JSTaggedValue result = builtins::BuiltinsObject::HasOwnPropertyInternal(thread, thisValue, key);
return result.GetRawData();
}
DEF_RUNTIME_STUBS(ReflectHas)
{
RUNTIME_STUBS_HEADER(ReflectHas);
JSHandle<JSTaggedValue> target = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> key = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
JSTaggedValue result = builtins::BuiltinsReflect::ReflectHasInternal(thread, target, key);
return result.GetRawData();
}
DEF_RUNTIME_STUBS(ReflectConstruct)
{
// newTarget = target, args = []
RUNTIME_STUBS_HEADER(ReflectConstruct);
JSHandle<JSTaggedValue> target = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->EmptyArray();
JSTaggedValue result = builtins::BuiltinsReflect::ReflectConstructInternal(thread, target, args, target);
return result.GetRawData();
}
DEF_RUNTIME_STUBS(ReflectApply)
{
RUNTIME_STUBS_HEADER(ReflectApply);
JSHandle<JSTaggedValue> target = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> thisValue = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
JSHandle<JSTaggedValue> argumentsList = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
JSTaggedValue result = builtins::BuiltinsReflect::ReflectApplyInternal(thread, target, thisValue, argumentsList);
return result.GetRawData();
}
DEF_RUNTIME_STUBS(FunctionPrototypeApply)
{
RUNTIME_STUBS_HEADER(FunctionPrototypeApply);
JSHandle<JSTaggedValue> thisFunc = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> thisArg = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
JSHandle<JSTaggedValue> argArray = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
JSTaggedValue result = builtins::BuiltinsFunction::FunctionPrototypeApplyInternal(thread, thisFunc,
thisArg, argArray);
return result.GetRawData();
}
DEF_RUNTIME_STUBS(FunctionPrototypeBind)
{
RUNTIME_STUBS_HEADER(FunctionPrototypeBind);
JSHandle<JSTaggedValue> target = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> thisArg = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
JSHandle<TaggedArray> argsArray = thread->GetEcmaVM()->GetFactory()->EmptyArray();
JSTaggedValue result = builtins::BuiltinsFunction::FunctionPrototypeBindInternal(thread, target,
thisArg, argsArray);
return result.GetRawData();
}
DEF_RUNTIME_STUBS(FunctionPrototypeCall)
{
RUNTIME_STUBS_HEADER(FunctionPrototypeCall);
JSHandle<JSTaggedValue> thisFunc = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> thisArg = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
if (!thisFunc->IsCallable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "call target is not callable", JSTaggedValue::VALUE_EXCEPTION);
}
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
uint32_t argsLength = argc - 2; // 2: thisFunc and thisArg
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, thisFunc, thisArg, undefined, argsLength);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::VALUE_EXCEPTION);
uint32_t index = 0;
for (uint32_t i = 2; i < argc; ++i) { // 2: thisFunc and thisArg
JSTaggedValue arg = GetArg(argv, argc, i);
info->SetCallArg(index++, arg);
}
return JSFunction::Call(info).GetRawData();
}
void RuntimeStubs::Initialize(JSThread *thread)
{
#define DEF_RUNTIME_STUB(name) kungfu::RuntimeStubCSigns::ID_##name

View File

@ -475,7 +475,14 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
V(DumpObject) \
V(TryGetInternString) \
V(TryToElementsIndexOrFindInStringTable) \
V(BigIntConstructor)
V(BigIntConstructor) \
V(ObjectPrototypeHasOwnProperty) \
V(ReflectHas) \
V(ReflectConstruct) \
V(ReflectApply) \
V(FunctionPrototypeApply) \
V(FunctionPrototypeBind) \
V(FunctionPrototypeCall)
#define RUNTIME_STUB_LIST(V) \
RUNTIME_ASM_STUB_LIST(V) \

View File

@ -18,10 +18,13 @@ group("ark_aot_builtin_inlining_test") {
"DataView:ark_aot_builtin_inlining_DataView_test",
"bigint:ark_aot_builtin_inlining_bigint_test",
"date:ark_aot_builtin_inlining_date_test",
"function:ark_aot_builtin_inlining_function_test",
"global:ark_aot_builtin_inlining_global_test",
"map:ark_aot_builtin_inlining_map_test",
"math:ark_aot_builtin_inlining_math_test",
"number:ark_aot_builtin_inlining_number_test",
"object:ark_aot_builtin_inlining_object_test",
"reflect:ark_aot_builtin_inlining_reflect_test",
"set:ark_aot_builtin_inlining_set_test",
"typedarray:ark_aot_builtin_inlining_typedarray_test",
]

View File

@ -84,8 +84,11 @@ print(time.getTime()); //: NaN
time = new Date(50000000000)
let true_func = time.getTime
//aot: [trace] aot inline builtin: Function.prototype.call, caller function name:func_main_0@builtinDateGetTime
print(true_func.call(time)) //: 50000000000
//aot: [trace] aot inline builtin: Function.prototype.call, caller function name:func_main_0@builtinDateGetTime
print(true_func.call(time, 1)) //: 50000000000
//aot: [trace] aot inline builtin: Function.prototype.call, caller function name:func_main_0@builtinDateGetTime
print(true_func.call(time, 1, 2)) //: 50000000000
if (ArkTools.isAOTCompiled(printDateGetTimeOneParam)) {

View File

@ -0,0 +1,25 @@
# Copyright (c) 2024 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.
group("ark_aot_builtin_inlining_function_test") {
testonly = true
test_list = [ "Function" ]
deps = []
foreach(test, test_list) {
deps += [ "${test}:builtinFunction${test}AotAction" ]
if (!is_debug) {
deps += [ "${test}:builtinFunction${test}AotContextAction" ]
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2024 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_builtin_inlining_test_action("builtinFunctionFunction") {
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2024 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.
*/
declare function print(arg:any):string;
function foo(a: any, b: any) {
return this + a + b;
}
//aot: [trace] aot inline builtin: Function.prototype.apply, caller function name:func_main_0@builtinFunctionFunction
print(foo.apply(1, [2, 3])); //: 6
//aot: [trace] aot inline builtin: Function.prototype.apply, caller function name:func_main_0@builtinFunctionFunction
print(foo.apply(1)); //: NaN
//aot: [trace] aot inline builtin: Function.prototype.bind, caller function name:func_main_0@builtinFunctionFunction
let bfoo = foo.bind(2);
print(bfoo(3, 4)); //: 9
let bfoo1 = foo.bind(5, 6);
print(bfoo1(7)); //: 18
//aot: [trace] aot inline builtin: Function.prototype.call, caller function name:func_main_0@builtinFunctionFunction
print(foo.call(10, 20)); //: NaN
//aot: [trace] aot inline builtin: Function.prototype.call, caller function name:func_main_0@builtinFunctionFunction
print(foo.call(10, 20, 30)); //: 60
class C {}
//aot: [trace] aot inline builtin: Function.prototype.hasInstance, caller function name:func_main_0@builtinFunctionFunction
print(C[Symbol.hasInstance](new C())); //: true
//aot: [trace] aot inline builtin: Function.prototype.hasInstance, caller function name:func_main_0@builtinFunctionFunction
print(C[Symbol.hasInstance]({})); //: false

View File

@ -247,6 +247,7 @@ if (ArkTools.isAOTCompiled(printGet2)) {
}
}
//aot: [trace] aot inline builtin: Object.getPrototypeOf, caller function name:func_main_0@builtinMapGet
print(Object.getPrototypeOf(m3) === Map.prototype) //: true
//aot: [trace] aot inline builtin: Map.get, caller function name:printGet2@builtinMapGet

View File

@ -75,6 +75,7 @@ print(Math.exp(10e-10)); //: 1.000000001
// Check with special float params
//aot: [trace] aot inline builtin: Math.exp, caller function name:func_main_0@builtinMathExp
//aot: [trace] aot inline function name: printZero@builtinMathExp caller function name: func_main_0@builtinMathExp
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathExp
printZero(Math.exp(-Infinity)); //: 0
//aot: [trace] aot inline builtin: Math.exp, caller function name:func_main_0@builtinMathExp
print(Math.exp(Infinity)); //: Infinity

View File

@ -61,9 +61,11 @@ print(Math.expm1()); //: NaN
// Check with single param
//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
//aot: [trace] aot inline function name: printZero@builtinMathExpm1 caller function name: func_main_0@builtinMathExpm1
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathExpm1
printZero(Math.expm1(0)); //: 0
//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
//aot: [trace] aot inline function name: printZero@builtinMathExpm1 caller function name: func_main_0@builtinMathExpm1
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathExpm1
printZero("1/x: " + 1 / Math.expm1(-0)); //: 1/x: -Infinity
//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
print(Math.expm1(1)); //: 1.718281828459045

View File

@ -68,23 +68,30 @@ print(Math.fround(-1073741804)) //: -1073741824
print(Math.fround(1.9e80)); //: Infinity
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline function name: printZero@builtinMathFround caller function name: func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(2.5)); //: 2.5
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline function name: printZero@builtinMathFround caller function name: func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(1.5)); //: 1.5
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline function name: printZero@builtinMathFround caller function name: func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(0.5)); //: 0.5
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline function name: printZero@builtinMathFround caller function name: func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(0.2)); //: 0.20000000298023224
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline function name: printZero@builtinMathFround caller function name: func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(-0)); //: -0
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline function name: printZero@builtinMathFround caller function name: func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(-1.9e-80)); //: -0
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathFround
printZero(Math.fround(-0.1)); //: -0.10000000149011612
//aot: [trace] aot inline builtin: Math.fround, caller function name:func_main_0@builtinMathFround
print(Math.fround(-0.5)); //: -0.5

View File

@ -130,21 +130,27 @@ print(Math.max(Infinity, NaN)); //: NaN
// Check 0 and -0
//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
//aot: [trace] aot inline function name: printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMax
printZero(Math.max(0, -0)); //: 0
//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
//aot: [trace] aot inline function name: printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMax
printZero(Math.max(-0, 0)); //: 0
//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
//aot: [trace] aot inline function name: printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMax
printZero(Math.max(0, 0)); //: 0
//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
//aot: [trace] aot inline function name: printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMax
printZero(Math.max(-0, -0)); //: -0
//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
//aot: [trace] aot inline function name: printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMax
printZero(Math.max(-5, -0)); //: -0
//aot: [trace] aot inline builtin: Math.max, caller function name:func_main_0@builtinMathMax
//aot: [trace] aot inline function name: printZero@builtinMathMax caller function name: func_main_0@builtinMathMax
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMax
printZero(Math.max(-5, 0)); //: 0
// Check with int and float param

View File

@ -125,21 +125,27 @@ print(Math.min(Infinity, NaN)); //: NaN
// Check 0 and -0
//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
//aot: [trace] aot inline function name: printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMin
printZero(Math.min(0, -0)); //: -0
//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
//aot: [trace] aot inline function name: printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMin
printZero(Math.min(-0, 0)); //: -0
//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
//aot: [trace] aot inline function name: printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMin
printZero(Math.min(0, 0)); //: 0
//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
//aot: [trace] aot inline function name: printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMin
printZero(Math.min(-0, -0)); //: -0
//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
//aot: [trace] aot inline function name: printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMin
printZero(Math.min(5, -0)); //: -0
//aot: [trace] aot inline builtin: Math.min, caller function name:func_main_0@builtinMathMin
//aot: [trace] aot inline function name: printZero@builtinMathMin caller function name: func_main_0@builtinMathMin
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathMin
printZero(Math.min(5, 0)); //: 0
// Check with int and float param

View File

@ -68,25 +68,33 @@ print(Math.round(-1073741804)) //: -1073741804
print(Math.round(1.9e80)); //: 1.9e+80
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline function name: printZero@builtinMathRound caller function name: func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(2.5)); //: 3
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline function name: printZero@builtinMathRound caller function name: func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(1.5)); //: 2
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline function name: printZero@builtinMathRound caller function name: func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(0.5)); //: 1
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline function name: printZero@builtinMathRound caller function name: func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(0.2)); //: 0
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline function name: printZero@builtinMathRound caller function name: func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(-0)); //: -0
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline function name: printZero@builtinMathRound caller function name: func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(-1.9e-80)); //: -0
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(-0.1)); //: -0
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
//aot: [trace] aot inline builtin: Object.is, caller function name:printZero@builtinMathRound
printZero(Math.round(-0.5)); //: -0
//aot: [trace] aot inline builtin: Math.round, caller function name:func_main_0@builtinMathRound
print(Math.round(-0.7)); //: -1

View File

@ -0,0 +1,25 @@
# Copyright (c) 2024 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.
group("ark_aot_builtin_inlining_object_test") {
testonly = true
test_list = [ "Object" ]
deps = []
foreach(test, test_list) {
deps += [ "${test}:builtinObject${test}AotAction" ]
if (!is_debug) {
deps += [ "${test}:builtinObject${test}AotContextAction" ]
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2024 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_builtin_inlining_test_action("builtinObjectObject") {
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2024 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.
*/
declare function print(arg:any):string;
//aot: [trace] aot inline builtin: Object.is, caller function name:func_main_0@builtinObjectObject
print(Object.is(1, 1)); //: true
//aot: [trace] aot inline builtin: Object.is, caller function name:func_main_0@builtinObjectObject
print(Object.is(1, 2)); //: false
//aot: [trace] aot inline builtin: Object.is, caller function name:func_main_0@builtinObjectObject
print(Object.is(1, "abc")); //: false
//aot: [trace] aot inline builtin: Object.is, caller function name:func_main_0@builtinObjectObject
print(Object.is(1, {})); //: false
//aot: [trace] aot inline builtin: Object.getPrototypeOf, caller function name:func_main_0@builtinObjectObject
print(Object.getPrototypeOf({})) //: [object Object]
//aot: [trace] aot inline builtin: Object.getPrototypeOf, caller function name:func_main_0@builtinObjectObject
print(Object.getPrototypeOf(1)) //: 0
//aot: [trace] aot inline builtin: Object.getPrototypeOf, caller function name:func_main_0@builtinObjectObject
print(Object.getPrototypeOf(true)) //: false
let proto = {name: "create"};
//aot: [trace] aot inline builtin: Object.create, caller function name:func_main_0@builtinObjectObject
print(Object.create(proto).name); //: create
print(Object.create(proto, {
name: {
value: "new create",
enumerable: false,
writable: true,
configurable: true,
},
}).name); //: new create
try {
//aot: [trace] aot inline builtin: Object.create, caller function name:func_main_0@builtinObjectObject
Object.create(undefined);
} catch(e) {
print(e instanceof TypeError); //: true
}
let isProto = {};
//aot: [trace] aot inline builtin: Object.prototype.isPrototypeOf, caller function name:func_main_0@builtinObjectObject
print(isProto.isPrototypeOf(isProto)); //: false
//aot: [trace] aot inline builtin: Object.prototype.isPrototypeOf, caller function name:func_main_0@builtinObjectObject
print(Object.prototype.isPrototypeOf(isProto)); //: true
let hasOwnProp = {a: 123};
//aot: [trace] aot inline builtin: Object.prototype.hasOwnProperty, caller function name:func_main_0@builtinObjectObject
print(hasOwnProp.hasOwnProperty("a")); //: true
//aot: [trace] aot inline builtin: Object.prototype.hasOwnProperty, caller function name:func_main_0@builtinObjectObject
print(hasOwnProp.hasOwnProperty("b")); //: false

View File

@ -0,0 +1,25 @@
# Copyright (c) 2024 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.
group("ark_aot_builtin_inlining_reflect_test") {
testonly = true
test_list = [ "Reflect" ]
deps = []
foreach(test, test_list) {
deps += [ "${test}:builtinReflect${test}AotAction" ]
if (!is_debug) {
deps += [ "${test}:builtinReflect${test}AotContextAction" ]
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2024 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_builtin_inlining_test_action("builtinReflectReflect") {
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 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.
*/
declare function print(arg:any):string;
//aot: [trace] aot inline builtin: Reflect.getPrototypeOf, caller function name:func_main_0@builtinReflectReflect
print(Reflect.getPrototypeOf({})) //: [object Object]
try {
//aot: [trace] aot inline builtin: Reflect.getPrototypeOf, caller function name:func_main_0@builtinReflectReflect
Reflect.getPrototypeOf(1);
} catch(e) {
print(e instanceof TypeError); //: true
}
let o = {a:123, b: "abc"};
//aot: [trace] aot inline builtin: Reflect.get, caller function name:func_main_0@builtinReflectReflect
print(Reflect.get(o, "a")); //: 123
//aot: [trace] aot inline builtin: Reflect.get, caller function name:func_main_0@builtinReflectReflect
print(Reflect.get(o, "b")); //: abc
//aot: [trace] aot inline builtin: Reflect.get, caller function name:func_main_0@builtinReflectReflect
print(Reflect.get(o, "c")); //: undefined
//aot: [trace] aot inline builtin: Reflect.has, caller function name:func_main_0@builtinReflectReflect
print(Reflect.has(o, "a")); //: true
//aot: [trace] aot inline builtin: Reflect.has, caller function name:func_main_0@builtinReflectReflect
print(Reflect.has(o, "c")); //: false
//aot: [trace] aot inline builtin: Reflect.has, caller function name:func_main_0@builtinReflectReflect
print(Reflect.has(o, "toString")); //: true
function foo(a: any, b: any) {
return this + a + b;
}
//aot: [trace] aot inline builtin: Reflect.apply, caller function name:func_main_0@builtinReflectReflect
print(Reflect.apply(foo, 1, [2, 3])); //: 6
class C {
x:number;
constructor(x: number = 123) {
this.x = x;
}
}
//aot: [trace] aot inline builtin: Reflect.construct, caller function name:func_main_0@builtinReflectReflect
print(Reflect.construct(C, []).x); //: 123
print(Reflect.construct(C, [456]).x); //: 456