mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-30 13:40:51 +00:00
!7206 Inline some builtins of Object Function Reflect
Merge pull request !7206 from dingding/aot_inline
This commit is contained in:
commit
2d317fa7c1
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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), ¬Hole, exit);
|
||||
Bind(¬Hole);
|
||||
{
|
||||
@ -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, ¬DicMode);
|
||||
Bind(¬DicMode);
|
||||
{
|
||||
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)), ¬NegtiveOne, exit);
|
||||
@ -944,7 +879,7 @@ GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array)
|
||||
}
|
||||
Bind(&afterLoop);
|
||||
Jump(&exit);
|
||||
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 { \
|
||||
|
@ -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, ¬IsECMAObject);
|
||||
Bind(&isECMAObject);
|
||||
{
|
||||
result = obj;
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬IsECMAObject);
|
||||
BRANCH_CIR2(TaggedIsNumber(obj), &isNumber, ¬Number);
|
||||
Bind(&isNumber);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Number);
|
||||
BRANCH_CIR2(TaggedIsBoolean(obj), &isBoolean, ¬Boolean);
|
||||
Bind(&isBoolean);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Boolean);
|
||||
BRANCH_CIR2(TaggedIsString(obj), &isString, ¬String);
|
||||
Bind(&isString);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬String);
|
||||
BRANCH_CIR2(TaggedIsSymbol(obj), &isSymbol, ¬Symbol);
|
||||
Bind(&isSymbol);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Symbol);
|
||||
BRANCH_CIR2(TaggedIsUndefined(obj), &isUndefined, ¬IsUndefined);
|
||||
Bind(&isUndefined);
|
||||
{
|
||||
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
|
||||
Jump(&throwError);
|
||||
}
|
||||
Bind(¬IsUndefined);
|
||||
BRANCH_CIR2(TaggedIsHole(obj), &isHole, ¬IsHole);
|
||||
Bind(&isHole);
|
||||
{
|
||||
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
|
||||
Jump(&throwError);
|
||||
}
|
||||
Bind(¬IsHole);
|
||||
BRANCH_CIR2(TaggedIsNull(obj), &isNull, ¬IsNull);
|
||||
Bind(&isNull);
|
||||
{
|
||||
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
|
||||
Jump(&throwError);
|
||||
}
|
||||
Bind(¬IsNull);
|
||||
BRANCH_CIR2(TaggedIsBigInt(obj), &isBigInt, ¬IsBigInt);
|
||||
Bind(&isBigInt);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬IsBigInt);
|
||||
{
|
||||
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));
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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)), ¬Find, &find);
|
||||
Bind(¬Find);
|
||||
{
|
||||
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, ¬String);
|
||||
Bind(&isString);
|
||||
{
|
||||
hash = GetHashcodeFromString(glue, key);
|
||||
hash = GetHashcodeFromString(glue, key, hir);
|
||||
Jump(&beforeDefineHash);
|
||||
}
|
||||
Bind(¬String);
|
||||
@ -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, ¬IsECMAObject);
|
||||
Bind(&isECMAObject);
|
||||
{
|
||||
result = obj;
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬IsECMAObject);
|
||||
BRANCH(TaggedIsNumber(obj), &isNumber, ¬Number);
|
||||
Bind(&isNumber);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Number);
|
||||
BRANCH(TaggedIsBoolean(obj), &isBoolean, ¬Boolean);
|
||||
Bind(&isBoolean);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Boolean);
|
||||
BRANCH(TaggedIsString(obj), &isString, ¬String);
|
||||
Bind(&isString);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬String);
|
||||
BRANCH(TaggedIsSymbol(obj), &isSymbol, ¬Symbol);
|
||||
Bind(&isSymbol);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬Symbol);
|
||||
BRANCH(TaggedIsUndefined(obj), &isUndefined, ¬IsUndefined);
|
||||
Bind(&isUndefined);
|
||||
{
|
||||
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
|
||||
Jump(&throwError);
|
||||
}
|
||||
Bind(¬IsUndefined);
|
||||
BRANCH(TaggedIsHole(obj), &isHole, ¬IsHole);
|
||||
Bind(&isHole);
|
||||
{
|
||||
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
|
||||
Jump(&throwError);
|
||||
}
|
||||
Bind(¬IsHole);
|
||||
BRANCH(TaggedIsNull(obj), &isNull, ¬IsNull);
|
||||
Bind(&isNull);
|
||||
{
|
||||
taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
|
||||
Jump(&throwError);
|
||||
}
|
||||
Bind(¬IsNull);
|
||||
BRANCH(TaggedIsBigInt(obj), &isBigInt, ¬IsBigInt);
|
||||
Bind(&isBigInt);
|
||||
{
|
||||
result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬IsBigInt);
|
||||
{
|
||||
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)
|
||||
|
@ -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)>;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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).
|
||||
|
@ -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);
|
||||
|
@ -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, ¬EcmaObject);
|
||||
builder_.Bind(&isEcmaObject);
|
||||
{
|
||||
result = builder_.CallStub(glue, gate, CommonStubCSigns::DeprecatedGetPropertyByName, // no ic
|
||||
{ glue, target, key });
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬EcmaObject);
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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) \
|
||||
|
@ -938,6 +938,11 @@ public:
|
||||
return GetPGOSampleType()->IsString();
|
||||
}
|
||||
|
||||
bool IsHeapObject() const
|
||||
{
|
||||
return GetPGOSampleType()->IsHeapObject();
|
||||
}
|
||||
|
||||
const PGORWOpType* GetPGORWOpType()
|
||||
{
|
||||
if (type_ == nullptr) {
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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",
|
||||
]
|
||||
|
@ -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)) {
|
||||
|
25
test/aottest/builtin_inlining/function/BUILD.gn
Normal file
25
test/aottest/builtin_inlining/function/BUILD.gn
Normal 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" ]
|
||||
}
|
||||
}
|
||||
}
|
17
test/aottest/builtin_inlining/function/Function/BUILD.gn
Normal file
17
test/aottest/builtin_inlining/function/Function/BUILD.gn
Normal 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") {
|
||||
}
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
25
test/aottest/builtin_inlining/object/BUILD.gn
Normal file
25
test/aottest/builtin_inlining/object/BUILD.gn
Normal 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" ]
|
||||
}
|
||||
}
|
||||
}
|
17
test/aottest/builtin_inlining/object/Object/BUILD.gn
Normal file
17
test/aottest/builtin_inlining/object/Object/BUILD.gn
Normal 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") {
|
||||
}
|
@ -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
|
25
test/aottest/builtin_inlining/reflect/BUILD.gn
Normal file
25
test/aottest/builtin_inlining/reflect/BUILD.gn
Normal 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" ]
|
||||
}
|
||||
}
|
||||
}
|
17
test/aottest/builtin_inlining/reflect/Reflect/BUILD.gn
Normal file
17
test/aottest/builtin_inlining/reflect/Reflect/BUILD.gn
Normal 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") {
|
||||
}
|
@ -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
|
Loading…
Reference in New Issue
Block a user