mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-30 13:40:51 +00:00
!5021 Impl for-of and for-in HIR lowering
Merge pull request !5021 from zhangyukun8/master
This commit is contained in:
commit
95e94e807a
@ -93,6 +93,7 @@
|
||||
#include "ecmascript/require/js_cjs_require.h"
|
||||
#include "ecmascript/require/js_cjs_exports.h"
|
||||
#include "ecmascript/symbol_table.h"
|
||||
#include "ecmascript/marker_cell.h"
|
||||
#include "ecmascript/napi/include/jsnapi.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#ifdef ARK_SUPPORT_INTL
|
||||
@ -358,7 +359,7 @@ void Builtins::Initialize(const JSHandle<GlobalEnv> &env, JSThread *thread, bool
|
||||
InitializeCjsRequire(env);
|
||||
InitializeDefaultExportOfScript(env);
|
||||
InitializeFunctionHclassForOptimized(env);
|
||||
InitializePropertyDetector(env);
|
||||
InitializePropertyDetector(env, lazyInit);
|
||||
JSHandle<JSHClass> generatorFuncClass =
|
||||
factory_->CreateFunctionClass(FunctionKind::GENERATOR_FUNCTION, JSFunction::SIZE, JSType::JS_GENERATOR_FUNCTION,
|
||||
env->GetGeneratorFunctionPrototype());
|
||||
@ -399,10 +400,13 @@ void Builtins::InitializeFunctionHclassForOptimized(const JSHandle<GlobalEnv> &e
|
||||
#undef JSFUNCTION_JCLASS_LIST
|
||||
}
|
||||
|
||||
void Builtins::InitializePropertyDetector(const JSHandle<GlobalEnv> &env) const
|
||||
void Builtins::InitializePropertyDetector(const JSHandle<GlobalEnv> &env, bool lazyInit) const
|
||||
{
|
||||
#define INITIALIZE_PROPERTY_DETECTOR(type, name, index) \
|
||||
JSHandle<MarkerCell> name##detector = factory_->NewMarkerCell(); \
|
||||
if (lazyInit) { \
|
||||
name##detector->InvalidatePropertyDetector(); \
|
||||
} \
|
||||
env->Set##name(thread_, name##detector);
|
||||
GLOBAL_ENV_DETECTOR_FIELDS(INITIALIZE_PROPERTY_DETECTOR)
|
||||
#undef INITIALIZE_PROPERTY_DETECTOR
|
||||
@ -596,8 +600,6 @@ void Builtins::InitializeSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<J
|
||||
SetNoneAttributeProperty(symbolFunction, "isConcatSpreadable", isConcatSpreadableSymbol);
|
||||
JSHandle<JSTaggedValue> toStringTagSymbol(factory_->NewWellKnownSymbolWithChar("Symbol.toStringTag"));
|
||||
SetNoneAttributeProperty(symbolFunction, "toStringTag", toStringTagSymbol);
|
||||
JSHandle<JSTaggedValue> iteratorSymbol(factory_->NewPublicSymbolWithChar("Symbol.iterator"));
|
||||
SetNoneAttributeProperty(symbolFunction, "iterator", iteratorSymbol);
|
||||
JSHandle<JSTaggedValue> asyncIteratorSymbol(factory_->NewPublicSymbolWithChar("Symbol.asyncIterator"));
|
||||
SetNoneAttributeProperty(symbolFunction, "asyncIterator", asyncIteratorSymbol);
|
||||
JSHandle<JSTaggedValue> matchSymbol(factory_->NewPublicSymbolWithChar("Symbol.match"));
|
||||
@ -662,7 +664,6 @@ DETECTOR_SYMBOL_LIST(REGISTER_SYMBOL)
|
||||
env->SetHasInstanceSymbol(thread_, hasInstanceSymbol);
|
||||
env->SetIsConcatSpreadableSymbol(thread_, isConcatSpreadableSymbol);
|
||||
env->SetToStringTagSymbol(thread_, toStringTagSymbol);
|
||||
env->SetIteratorSymbol(thread_, iteratorSymbol);
|
||||
env->SetAsyncIteratorSymbol(thread_, asyncIteratorSymbol);
|
||||
env->SetMatchSymbol(thread_, matchSymbol);
|
||||
env->SetMatchAllSymbol(thread_, matchAllSymbol);
|
||||
@ -1261,6 +1262,7 @@ void Builtins::InitializeSet(const JSHandle<GlobalEnv> &env, JSHandle<JSTaggedVa
|
||||
|
||||
env->SetBuiltinsSetFunction(thread_, setFunction);
|
||||
env->SetSetPrototype(thread_, setFuncPrototype);
|
||||
env->SetSetProtoValuesFunction(thread_, valuesFunc);
|
||||
thread_->SetInitialBuiltinHClass(BuiltinTypeId::SET,
|
||||
setFunction->GetTaggedObject()->GetClass(),
|
||||
setFuncPrototype->GetJSHClass());
|
||||
@ -1329,6 +1331,7 @@ void Builtins::InitializeMap(const JSHandle<GlobalEnv> &env, JSHandle<JSTaggedVa
|
||||
|
||||
env->SetBuiltinsMapFunction(thread_, mapFunction);
|
||||
env->SetMapPrototype(thread_, mapFuncPrototype);
|
||||
env->SetMapProtoEntriesFunction(thread_, entriesFunc);
|
||||
thread_->SetInitialBuiltinHClass(BuiltinTypeId::MAP,
|
||||
mapFunction->GetTaggedObject()->GetClass(),
|
||||
mapFuncPrototype->GetJSHClass());
|
||||
@ -1607,8 +1610,8 @@ void Builtins::InitializeString(const JSHandle<GlobalEnv> &env, JSHandle<JSTagge
|
||||
SetFunction(env, stringFuncPrototype, entry.GetName(), entry.GetEntrypoint(),
|
||||
entry.GetLength(), entry.GetBuiltinStubId());
|
||||
}
|
||||
SetFunctionAtSymbol(env, stringFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
|
||||
BuiltinsString::GetStringIterator, FunctionLength::ZERO);
|
||||
JSHandle<JSTaggedValue> stringIter = SetAndReturnFunctionAtSymbol(env, stringFuncPrototype,
|
||||
env->GetIteratorSymbol(), "[Symbol.iterator]", BuiltinsString::GetStringIterator, FunctionLength::ZERO);
|
||||
|
||||
// String method
|
||||
for (const base::BuiltinFunctionEntry &entry: BuiltinsString::GetStringFunctions()) {
|
||||
@ -1623,6 +1626,7 @@ void Builtins::InitializeString(const JSHandle<GlobalEnv> &env, JSHandle<JSTagge
|
||||
|
||||
env->SetStringFunction(thread_, stringFunction);
|
||||
env->SetStringPrototype(thread_, stringFuncPrototype);
|
||||
env->SetStringProtoIterFunction(thread_, stringIter);
|
||||
thread_->SetInitialBuiltinHClass(BuiltinTypeId::STRING,
|
||||
stringFunction->GetJSHClass(),
|
||||
stringFuncPrototype->GetJSHClass());
|
||||
@ -1642,11 +1646,13 @@ void Builtins::InitializeStringIterator(const JSHandle<GlobalEnv> &env,
|
||||
factory_->NewJSFunction(env, static_cast<void *>(nullptr), FunctionKind::BASE_CONSTRUCTOR));
|
||||
strIterFunction->SetFunctionPrototype(thread_, strIterFuncInstanceHClass.GetTaggedValue());
|
||||
|
||||
SetFunction(env, strIterPrototype, "next", StringIterator::Next, FunctionLength::ZERO);
|
||||
JSHandle<JSFunction> nextFunc = SetAndReturnFunction(
|
||||
env, strIterPrototype, "next", StringIterator::Next, FunctionLength::ZERO);
|
||||
SetStringTagSymbol(env, strIterPrototype, "String Iterator");
|
||||
|
||||
env->SetStringIterator(thread_, strIterFunction);
|
||||
env->SetStringIteratorPrototype(thread_, strIterPrototype);
|
||||
env->SetStringIteratorProtoNext(thread_, nextFunc);
|
||||
}
|
||||
|
||||
void Builtins::InitializeAsyncFromSyncIterator(const JSHandle<GlobalEnv> &env,
|
||||
@ -1762,9 +1768,11 @@ void Builtins::InitializeSetIterator(const JSHandle<GlobalEnv> &env,
|
||||
// SetIterator.prototype
|
||||
JSHandle<JSObject> setIteratorPrototype(factory_->NewJSObjectWithInit(iteratorFuncClass));
|
||||
// Iterator.prototype.next()
|
||||
SetFunction(env, setIteratorPrototype, "next", JSSetIterator::Next, FunctionLength::ZERO);
|
||||
JSHandle<JSFunction> nextFunc = SetAndReturnFunction(
|
||||
env, setIteratorPrototype, "next", JSSetIterator::Next, FunctionLength::ZERO);
|
||||
SetStringTagSymbol(env, setIteratorPrototype, "Set Iterator");
|
||||
env->SetSetIteratorPrototype(thread_, setIteratorPrototype);
|
||||
env->SetSetIteratorProtoNext(thread_, nextFunc);
|
||||
JSHandle<JSTaggedValue> protoValue = env->GetSetIteratorPrototype();
|
||||
const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
|
||||
JSHandle<JSHClass> hclassHandle(globalConst->GetHandledJSSetIteratorClass());
|
||||
@ -1778,9 +1786,11 @@ void Builtins::InitializeMapIterator(const JSHandle<GlobalEnv> &env,
|
||||
// MapIterator.prototype
|
||||
JSHandle<JSObject> mapIteratorPrototype(factory_->NewJSObjectWithInit(iteratorFuncClass));
|
||||
// Iterator.prototype.next()
|
||||
SetFunction(env, mapIteratorPrototype, "next", JSMapIterator::Next, FunctionLength::ZERO);
|
||||
JSHandle<JSFunction> nextFunc = SetAndReturnFunction(
|
||||
env, mapIteratorPrototype, "next", JSMapIterator::Next, FunctionLength::ZERO);
|
||||
SetStringTagSymbol(env, mapIteratorPrototype, "Map Iterator");
|
||||
env->SetMapIteratorPrototype(thread_, mapIteratorPrototype);
|
||||
env->SetMapIteratorProtoNext(thread_, nextFunc);
|
||||
JSHandle<JSTaggedValue> protoValue = env->GetMapIteratorPrototype();
|
||||
const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
|
||||
JSHandle<JSHClass> hclassHandle(globalConst->GetHandledJSMapIteratorClass());
|
||||
@ -1794,9 +1804,11 @@ void Builtins::InitializeArrayIterator(const JSHandle<GlobalEnv> &env,
|
||||
// ArrayIterator.prototype
|
||||
JSHandle<JSObject> arrayIteratorPrototype(factory_->NewJSObjectWithInit(iteratorFuncClass));
|
||||
// Iterator.prototype.next()
|
||||
SetFunction(env, arrayIteratorPrototype, "next", JSArrayIterator::Next, FunctionLength::ZERO);
|
||||
JSHandle<JSFunction> nextFunc = SetAndReturnFunction(
|
||||
env, arrayIteratorPrototype, "next", JSArrayIterator::Next, FunctionLength::ZERO);
|
||||
SetStringTagSymbol(env, arrayIteratorPrototype, "Array Iterator");
|
||||
env->SetArrayIteratorPrototype(thread_, arrayIteratorPrototype);
|
||||
env->SetArrayIteratorProtoNext(thread_, nextFunc);
|
||||
}
|
||||
|
||||
void Builtins::InitializeRegexpIterator(const JSHandle<GlobalEnv> &env,
|
||||
@ -2063,6 +2075,7 @@ void Builtins::InitializeTypedArray(const JSHandle<GlobalEnv> &env, JSHandle<JST
|
||||
|
||||
env->SetTypedArrayFunction(thread_, typedArrayFunction.GetTaggedValue());
|
||||
env->SetTypedArrayPrototype(thread_, typedArrFuncPrototype);
|
||||
env->SetTypedArrayProtoValuesFunction(thread_, valuesFunc);
|
||||
thread_->SetInitialBuiltinHClass(BuiltinTypeId::TYPED_ARRAY,
|
||||
typedArrayFunction->GetJSHClass(),
|
||||
typedArrFuncPrototype->GetJSHClass());
|
||||
@ -2115,9 +2128,10 @@ void Builtins::Initialize##Type(const JSHandle<GlobalEnv> &env, const JSHandle<J
|
||||
SetConstant(arrFuncPrototype, "BYTES_PER_ELEMENT", JSTaggedValue(bytesPerElement)); \
|
||||
SetConstant(JSHandle<JSObject>(arrayFunction), "BYTES_PER_ELEMENT", JSTaggedValue(bytesPerElement)); \
|
||||
env->Set##Type##Function(thread_, arrayFunction); \
|
||||
env->Set##Type##FunctionPrototype(thread_, arrFuncPrototypeValue); \
|
||||
/* Initializes HClass record of %TypedArray% */ \
|
||||
thread_->SetInitialBuiltinHClass(BuiltinTypeId::TYPE, \
|
||||
arrayFunction->GetJSHClass(), \
|
||||
arrayFunction->GetJSHClass(), \
|
||||
arrFuncPrototype->GetJSHClass()); \
|
||||
}
|
||||
|
||||
@ -2552,6 +2566,38 @@ void Builtins::SetFunctionAtSymbol(const JSHandle<GlobalEnv> &env, const JSHandl
|
||||
JSObject::DefineOwnProperty(thread_, obj, symbol, descriptor);
|
||||
}
|
||||
|
||||
template<int flag>
|
||||
JSHandle<JSTaggedValue> Builtins::SetAndReturnFunctionAtSymbol(const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSObject> &obj,
|
||||
const JSHandle<JSTaggedValue> &symbol,
|
||||
std::string_view name,
|
||||
EcmaEntrypoint func,
|
||||
int length) const
|
||||
{
|
||||
JSHandle<JSFunction> function = factory_->NewJSFunction(env, reinterpret_cast<void *>(func));
|
||||
JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(length));
|
||||
JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8(name));
|
||||
JSHandle<JSFunctionBase> baseFunction(function);
|
||||
JSHandle<JSTaggedValue> handleUndefine(thread_, JSTaggedValue::Undefined());
|
||||
JSFunction::SetFunctionName(thread_, baseFunction, nameString, handleUndefine);
|
||||
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
|
||||
if constexpr (flag == JSSymbol::SYMBOL_TO_PRIMITIVE_TYPE) {
|
||||
PropertyDescriptor descriptor(thread_, JSHandle<JSTaggedValue>::Cast(function), false, false, true);
|
||||
JSObject::DefineOwnProperty(thread_, obj, symbol, descriptor);
|
||||
return JSHandle<JSTaggedValue>(function);
|
||||
} else if constexpr (flag == JSSymbol::SYMBOL_HAS_INSTANCE_TYPE) { // NOLINTE(readability-braces-around-statements)
|
||||
// ecma 19.2.3.6 Function.prototype[@@hasInstance] has the attributes
|
||||
// { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
|
||||
PropertyDescriptor descriptor(thread_, JSHandle<JSTaggedValue>::Cast(function), false, false, false);
|
||||
JSObject::DefineOwnProperty(thread_, obj, symbol, descriptor);
|
||||
env->SetHasInstanceFunction(thread_, function);
|
||||
return JSHandle<JSTaggedValue>(function);
|
||||
}
|
||||
PropertyDescriptor descriptor(thread_, JSHandle<JSTaggedValue>::Cast(function), true, false, true);
|
||||
JSObject::DefineOwnProperty(thread_, obj, symbol, descriptor);
|
||||
return JSHandle<JSTaggedValue>(function);
|
||||
}
|
||||
|
||||
void Builtins::SetStringTagSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj,
|
||||
std::string_view key) const
|
||||
{
|
||||
|
@ -65,7 +65,7 @@ private:
|
||||
kungfu::BuiltinsStubCSigns::ID builtinId =
|
||||
kungfu::BuiltinsStubCSigns::INVALID) const;
|
||||
|
||||
void InitializePropertyDetector(const JSHandle<GlobalEnv> &env) const;
|
||||
void InitializePropertyDetector(const JSHandle<GlobalEnv> &env, bool lazyInit) const;
|
||||
|
||||
void SetLazyAccessor(const JSHandle<JSObject> &object, const JSHandle<JSTaggedValue> &key,
|
||||
const JSHandle<AccessorData> &accessor) const;
|
||||
@ -289,6 +289,14 @@ private:
|
||||
const JSHandle<JSTaggedValue> &symbol, std::string_view name, EcmaEntrypoint func,
|
||||
int length) const;
|
||||
|
||||
template<int type = JSSymbol::SYMBOL_DEFAULT_TYPE>
|
||||
JSHandle<JSTaggedValue> SetAndReturnFunctionAtSymbol(const JSHandle<GlobalEnv> &env,
|
||||
const JSHandle<JSObject> &obj,
|
||||
const JSHandle<JSTaggedValue> &symbol,
|
||||
std::string_view name,
|
||||
EcmaEntrypoint func,
|
||||
int length) const;
|
||||
|
||||
void SetStringTagSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj,
|
||||
std::string_view key) const;
|
||||
JSHandle<JSTaggedValue> CreateGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
|
||||
|
@ -327,6 +327,41 @@ JSTaggedValue BuiltinsArkTools::IsRegExpReplaceDetectorValid(EcmaRuntimeCallInfo
|
||||
return JSTaggedValue(PropertyDetector::IsRegExpReplaceDetectorValid(env));
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::IsSymbolIteratorDetectorValid(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> kind = GetCallArg(info, 0);
|
||||
if (!kind->IsString()) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<EcmaString> mapString = factory->NewFromUtf8("Map");
|
||||
if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(mapString))) {
|
||||
return JSTaggedValue(PropertyDetector::IsMapIteratorDetectorValid(env));
|
||||
}
|
||||
JSHandle<EcmaString> setString = factory->NewFromUtf8("Set");
|
||||
if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(setString))) {
|
||||
return JSTaggedValue(PropertyDetector::IsSetIteratorDetectorValid(env));
|
||||
}
|
||||
JSHandle<EcmaString> stringString = factory->NewFromUtf8("String");
|
||||
if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(stringString))) {
|
||||
return JSTaggedValue(PropertyDetector::IsStringIteratorDetectorValid(env));
|
||||
}
|
||||
JSHandle<EcmaString> arrayString = factory->NewFromUtf8("Array");
|
||||
if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(arrayString))) {
|
||||
return JSTaggedValue(PropertyDetector::IsArrayIteratorDetectorValid(env));
|
||||
}
|
||||
JSHandle<EcmaString> typedarrayString = factory->NewFromUtf8("TypedArray");
|
||||
if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(typedarrayString))) {
|
||||
return JSTaggedValue(PropertyDetector::IsTypedArrayIteratorDetectorValid(env));
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::TimeInUs([[maybe_unused]] EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ClockScope scope;
|
||||
|
@ -23,22 +23,23 @@
|
||||
// V(name, func, length, stubIndex)
|
||||
// where BuiltinsArkTools::func refers to the native implementation of ArkTools[name].
|
||||
// kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
|
||||
#define BUILTIN_ARK_TOOLS_FUNCTIONS_COMMON(V) \
|
||||
V("compareHClass", CompareHClass, 2, INVALID) \
|
||||
V("dumpHClass", DumpHClass, 1, INVALID) \
|
||||
V("excutePendingJob", ExcutePendingJob, 0, INVALID) \
|
||||
V("forceFullGC", ForceFullGC, 0, INVALID) \
|
||||
V("getHClass", GetHClass, 1, INVALID) \
|
||||
V("getLexicalEnv", GetLexicalEnv, 1, INVALID) \
|
||||
V("hasTSSubtyping", HasTSSubtyping, 1, INVALID) \
|
||||
V("hiddenStackSourceFile", HiddenStackSourceFile, 0, INVALID) \
|
||||
V("isNotHoleProperty", IsNotHoleProperty, 2, INVALID) \
|
||||
V("isPrototype", IsPrototype, 1, INVALID) \
|
||||
V("isRegExpReplaceDetectorValid", IsRegExpReplaceDetectorValid, 0, INVALID) \
|
||||
V("isTSHClass", IsTSHClass, 1, INVALID) \
|
||||
V("print", ObjectDump, 0, INVALID) \
|
||||
V("removeAOTFlag", RemoveAOTFlag, 1, INVALID) \
|
||||
V("timeInUs", TimeInUs, 0, INVALID)
|
||||
#define BUILTIN_ARK_TOOLS_FUNCTIONS_COMMON(V) \
|
||||
V("compareHClass", CompareHClass, 2, INVALID) \
|
||||
V("dumpHClass", DumpHClass, 1, INVALID) \
|
||||
V("excutePendingJob", ExcutePendingJob, 0, INVALID) \
|
||||
V("forceFullGC", ForceFullGC, 0, INVALID) \
|
||||
V("getHClass", GetHClass, 1, INVALID) \
|
||||
V("getLexicalEnv", GetLexicalEnv, 1, INVALID) \
|
||||
V("hasTSSubtyping", HasTSSubtyping, 1, INVALID) \
|
||||
V("hiddenStackSourceFile", HiddenStackSourceFile, 0, INVALID) \
|
||||
V("isNotHoleProperty", IsNotHoleProperty, 2, INVALID) \
|
||||
V("isPrototype", IsPrototype, 1, INVALID) \
|
||||
V("isRegExpReplaceDetectorValid", IsRegExpReplaceDetectorValid, 0, INVALID) \
|
||||
V("isSymbolIteratorDetectorValid", IsSymbolIteratorDetectorValid, 1, INVALID) \
|
||||
V("isTSHClass", IsTSHClass, 1, INVALID) \
|
||||
V("print", ObjectDump, 0, INVALID) \
|
||||
V("removeAOTFlag", RemoveAOTFlag, 1, INVALID) \
|
||||
V("timeInUs", TimeInUs, 0, INVALID)
|
||||
|
||||
#ifdef ECMASCRIPT_SUPPORT_CPUPROFILER
|
||||
#define BUILTIN_ARK_TOOLS_FUNCTIONS_CPUPROFILER(V) \
|
||||
@ -96,6 +97,8 @@ public:
|
||||
|
||||
static JSTaggedValue IsRegExpReplaceDetectorValid(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue IsSymbolIteratorDetectorValid(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue TimeInUs(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static Span<const base::BuiltinFunctionEntry> GetArkToolsFunctions()
|
||||
|
@ -32,6 +32,11 @@ JSTaggedValue BuiltinsStringIterator::Next(EcmaRuntimeCallInfo *argv)
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
// 1. Let O be the this value.
|
||||
JSHandle<JSTaggedValue> thisValue = GetThis(argv);
|
||||
return NextInternal(thread, thisValue);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsStringIterator::NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue)
|
||||
{
|
||||
// 2. If Type(O) is not Object, throw a TypeError exception.
|
||||
// 3. If O does not have all of the internal slots of an String Iterator Instance (21.1.5.3),
|
||||
// throw a TypeError exception.
|
||||
|
@ -23,6 +23,7 @@ class BuiltinsStringIterator : public base::BuiltinsBase {
|
||||
public:
|
||||
// 21.1.5.2.1
|
||||
static JSTaggedValue Next(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue);
|
||||
};
|
||||
} // namespace panda::ecmascript::builtins
|
||||
#endif // ECMASCRIPT_BUILTINS_BUILTINS_STRING_ITERATOR_H
|
||||
|
@ -451,6 +451,8 @@ namespace panda::ecmascript::kungfu {
|
||||
APPEND_SUFFIX_IMM16(HandleNewobjrangeImm16Imm8V8, V) \
|
||||
APPEND_SUFFIX_IMM16(HandleWideNewobjrangePrefImm16V8, V) \
|
||||
APPEND_SUFFIX(HandleInstanceofImm8V8, V) \
|
||||
APPEND_SUFFIX(HandleGetiteratorImm8, V) \
|
||||
APPEND_SUFFIX_IMM16(HandleGetiteratorImm16, V) \
|
||||
APPEND_SUFFIX(HandleTryldglobalbynameImm8Id16, V) \
|
||||
APPEND_SUFFIX_IMM16(HandleTryldglobalbynameImm16Id16, V) \
|
||||
APPEND_SUFFIX(HandleTrystglobalbynameImm8Id16, V) \
|
||||
|
@ -1302,7 +1302,7 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId,
|
||||
ans = byteCodeToJSGates_.at(iterator.Index()).at(0);
|
||||
auto oldType = gateAcc_.GetGateType(ans);
|
||||
if (!type.IsAnyType() && oldType.IsAnyType()) {
|
||||
typeRecorder_.GetOrUpdatePGOType(gateAcc_.TryGetPcOffset(ans));
|
||||
typeRecorder_.GetPGOHclassLayoutInfo(gateAcc_.TryGetPcOffset(ans));
|
||||
gateAcc_.SetGateType(ans, type);
|
||||
}
|
||||
break;
|
||||
@ -1429,14 +1429,16 @@ void BytecodeCircuitBuilder::BuildCircuit()
|
||||
|
||||
auto type = typeRecorder_.GetType(bcIndex);
|
||||
gateAcc_.SetGateType(gate, type);
|
||||
auto pgoType = typeRecorder_.GetOrUpdatePGOType(gateAcc_.TryGetPcOffset(gate));
|
||||
gateAcc_.TrySetPGOType(gate, pgoType);
|
||||
uint32_t pcOffset = gateAcc_.TryGetPcOffset(gate);
|
||||
EcmaOpcode opcode = bytecodeInfo.GetOpcode();
|
||||
auto pgoTypeInfo = typeRecorder_.GetPGOTypeInfo(pcOffset, opcode);
|
||||
gateAcc_.TrySetPGOType(gate, pgoTypeInfo);
|
||||
|
||||
auto valueCount = gateAcc_.GetInValueCount(gate);
|
||||
[[maybe_unused]] size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
|
||||
[[maybe_unused]] size_t numValueOutputs = bytecodeInfo.ComputeOutCount();
|
||||
// RETURNUNDEFINED has value input, but not from acc
|
||||
ASSERT(numValueInputs == valueCount || bytecodeInfo.GetOpcode() == EcmaOpcode::RETURNUNDEFINED);
|
||||
ASSERT(numValueInputs == valueCount || opcode == EcmaOpcode::RETURNUNDEFINED);
|
||||
ASSERT(numValueOutputs <= 1 + (bytecodeInfo.EnvOut() ? 1 : 0));
|
||||
auto valueStarts = gateAcc_.GetInValueStarts(gate);
|
||||
for (size_t valueIdx = 0; valueIdx < valueCount; valueIdx++) {
|
||||
@ -1455,7 +1457,7 @@ void BytecodeCircuitBuilder::BuildCircuit()
|
||||
gateAcc_.NewIn(gate, inIdx, defVreg);
|
||||
} else {
|
||||
GateRef defAcc = ResolveDef(bb, bcIndex, 0, true);
|
||||
if (!Bytecodes::IsCallOp(bytecodeInfo.GetOpcode())) {
|
||||
if (!Bytecodes::IsCallOp(opcode)) {
|
||||
gateAcc_.NewIn(gate, inIdx, defAcc);
|
||||
continue;
|
||||
}
|
||||
|
@ -440,7 +440,7 @@ public:
|
||||
|
||||
ElementsKind GetArrayElementsKind(GateRef gate) const
|
||||
{
|
||||
auto pgoType = typeRecorder_.GetOrUpdatePGOType(gateAcc_.TryGetPcOffset(gate));
|
||||
auto pgoType = typeRecorder_.GetPGOHclassLayoutInfo(gateAcc_.TryGetPcOffset(gate));
|
||||
return typeRecorder_.GetElementsKind(pgoType);
|
||||
}
|
||||
|
||||
|
@ -2093,6 +2093,36 @@ DEF_CALL_SIGNATURE(Getnextpropname)
|
||||
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(CreateJSSetIterator)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature signature("CreateJSSetIterator", 0, 2,
|
||||
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = signature;
|
||||
// 2 : 2 input parameters
|
||||
std::array<VariableType, 2> params = {
|
||||
VariableType::NATIVE_POINTER(), // glue
|
||||
VariableType::JS_ANY(), // obj
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(CreateJSMapIterator)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature signature("CreateJSMapIterator", 0, 2,
|
||||
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = signature;
|
||||
// 2 : 2 input parameters
|
||||
std::array<VariableType, 2> params = {
|
||||
VariableType::NATIVE_POINTER(), // glue
|
||||
VariableType::JS_ANY(), // obj
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FastStringEqual)
|
||||
{
|
||||
// 3 : 3 input parameters
|
||||
|
@ -467,6 +467,8 @@ private:
|
||||
V(FastStringEqual) \
|
||||
V(Getpropiterator) \
|
||||
V(Getnextpropname) \
|
||||
V(CreateJSSetIterator) \
|
||||
V(CreateJSMapIterator) \
|
||||
V(JSHClassFindProtoTransitions)
|
||||
|
||||
#define DECL_CALL_SIGNATURE(name) \
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "ecmascript/compiler/rt_call_signature.h"
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/ic/proto_change_details.h"
|
||||
#include "ecmascript/js_for_in_iterator.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/mem/region.h"
|
||||
@ -512,6 +514,134 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, Ga
|
||||
return GetObjectFromConstPool(glue, hirGate, constPool, module, index, type);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetEmptyArray(GateRef glue)
|
||||
{
|
||||
GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
|
||||
IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
|
||||
GateRef offset = GetGlobalConstantOffset(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
|
||||
return Load(VariableType::JS_ANY(), gConstAddr, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetPrototypeFromHClass(GateRef hClass)
|
||||
{
|
||||
GateRef protoOffset = IntPtr(JSHClass::PROTOTYPE_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), hClass, protoOffset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetEnumCacheFromHClass(GateRef hClass)
|
||||
{
|
||||
GateRef offset = IntPtr(JSHClass::ENUM_CACHE_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), hClass, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetProtoChangeMarkerFromHClass(GateRef hClass)
|
||||
{
|
||||
GateRef offset = IntPtr(JSHClass::PROTO_CHANGE_MARKER_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), hClass, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetLengthFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
|
||||
return Load(VariableType::INT32(), iter, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetIndexFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
|
||||
return Load(VariableType::INT32(), iter, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetKeysFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), iter, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetObjectFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), iter, offset);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetCachedHclassFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), iter, offset);
|
||||
}
|
||||
|
||||
void CircuitBuilder::SetLengthOfForInIterator(GateRef glue, GateRef iter, GateRef length)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
|
||||
Store(VariableType::INT32(), glue, iter, offset, length);
|
||||
}
|
||||
|
||||
void CircuitBuilder::SetIndexOfForInIterator(GateRef glue, GateRef iter, GateRef index)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
|
||||
Store(VariableType::INT32(), glue, iter, offset, index);
|
||||
}
|
||||
|
||||
void CircuitBuilder::SetKeysOfForInIterator(GateRef glue, GateRef iter, GateRef keys)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
|
||||
Store(VariableType::JS_ANY(), glue, iter, offset, keys);
|
||||
}
|
||||
|
||||
void CircuitBuilder::SetObjectOfForInIterator(GateRef glue, GateRef iter, GateRef object)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
|
||||
Store(VariableType::JS_ANY(), glue, iter, offset, object);
|
||||
}
|
||||
|
||||
void CircuitBuilder::SetCachedHclassOfForInIterator(GateRef glue, GateRef iter, GateRef hclass)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
|
||||
Store(VariableType::JS_ANY(), glue, iter, offset, hclass);
|
||||
}
|
||||
|
||||
void CircuitBuilder::IncreaseInteratorIndex(GateRef glue, GateRef iter, GateRef index)
|
||||
{
|
||||
GateRef newIndex = Int32Add(index, Int32(1));
|
||||
GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
|
||||
Store(VariableType::INT32(), glue, iter, offset, newIndex);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetHasChanged(GateRef object)
|
||||
{
|
||||
GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
|
||||
GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
|
||||
GateRef mask = Int32(1LLU << (ProtoChangeMarker::HAS_CHANGED_BITS - 1));
|
||||
return Int32NotEqual(Int32And(bitfield, mask), Int32(0));
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::HasDeleteProperty(GateRef hClass)
|
||||
{
|
||||
GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
|
||||
return Int32NotEqual(
|
||||
Int32And(Int32LSR(bitfield, Int32(JSHClass::HasDeletePropertyBit::START_BIT)),
|
||||
Int32((1LLU << JSHClass::HasDeletePropertyBit::SIZE) - 1)),
|
||||
Int32(0));
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::IsEcmaObject(GateRef obj)
|
||||
{
|
||||
Label entryPass(env_);
|
||||
SubCfgEntry(&entryPass);
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), False());
|
||||
Label heapObj(env_);
|
||||
Label exit(env_);
|
||||
GateRef isHeapObject = TaggedIsHeapObject(obj);
|
||||
Branch(isHeapObject, &heapObj, &exit);
|
||||
Bind(&heapObj);
|
||||
result = LogicAnd(isHeapObject, TaggedObjectIsEcmaObject(obj));
|
||||
Jump(&exit);
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module,
|
||||
GateRef index, ConstPoolType type)
|
||||
{
|
||||
|
@ -232,6 +232,24 @@ public:
|
||||
GateRef GetHomeObjectFromFunction(GateRef function);
|
||||
inline GateRef GetExpectedNumOfArgs(GateRef method);
|
||||
inline GateRef GetGlobalConstantOffset(ConstantIndex index); // shareir
|
||||
GateRef GetEmptyArray(GateRef glue);
|
||||
GateRef GetPrototypeFromHClass(GateRef hClass);
|
||||
GateRef GetEnumCacheFromHClass(GateRef hClass);
|
||||
GateRef GetProtoChangeMarkerFromHClass(GateRef hClass);
|
||||
GateRef GetLengthFromForInIterator(GateRef iter);
|
||||
GateRef GetIndexFromForInIterator(GateRef iter);
|
||||
GateRef GetKeysFromForInIterator(GateRef iter);
|
||||
GateRef GetObjectFromForInIterator(GateRef iter);
|
||||
GateRef GetCachedHclassFromForInIterator(GateRef iter);
|
||||
void SetLengthOfForInIterator(GateRef glue, GateRef iter, GateRef length);
|
||||
void SetIndexOfForInIterator(GateRef glue, GateRef iter, GateRef index);
|
||||
void SetKeysOfForInIterator(GateRef glue, GateRef iter, GateRef keys);
|
||||
void SetObjectOfForInIterator(GateRef glue, GateRef iter, GateRef object);
|
||||
void SetCachedHclassOfForInIterator(GateRef glue, GateRef iter, GateRef hclass);
|
||||
void IncreaseInteratorIndex(GateRef glue, GateRef iter, GateRef index);
|
||||
GateRef GetHasChanged(GateRef object);
|
||||
GateRef HasDeleteProperty(GateRef hClass);
|
||||
GateRef IsEcmaObject(GateRef obj);
|
||||
|
||||
// Set
|
||||
void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value);
|
||||
@ -295,6 +313,7 @@ public:
|
||||
GateRef CreateArrayWithBuffer(ElementsKind kind, ArrayMetaDataAccessor::Mode mode,
|
||||
GateRef constPoolIndex, GateRef elementIndex);
|
||||
GateRef Construct(GateRef hirGate, std::vector<GateRef> args);
|
||||
GateRef TypedCallNative(GateRef hirGate, GateRef thisObj, GateRef funcId);
|
||||
GateRef IsBase(GateRef ctor);
|
||||
GateRef ToLength(GateRef receiver);
|
||||
|
||||
@ -408,6 +427,9 @@ public:
|
||||
inline GateRef JSNoGCCallThisTargetTypeCheck(GateType type, GateRef func, GateRef methodId, GateRef gate);
|
||||
GateRef TypeOfCheck(GateRef gate, GateType type);
|
||||
GateRef TypedTypeOf(GateType type);
|
||||
GateRef IteratorFunctionCheck(GateRef obj, GateRef kind);
|
||||
GateRef GetFixedIterator(GateRef obj, GateRef kind);
|
||||
GateRef NativeCallTargetCheck(GateRef func, GateRef funcId);
|
||||
GateRef TypedCallOperator(GateRef hirGate, MachineType type, const std::vector<GateRef>& inList);
|
||||
inline GateRef TypedCallBuiltin(GateRef hirGate, const std::vector<GateRef> &args, BuiltinsStubCSigns::ID id);
|
||||
GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
|
||||
@ -498,6 +520,13 @@ public:
|
||||
GateRef IsOptimizedWithBitField(GateRef bitfield);
|
||||
GateRef ComputeTaggedArraySize(GateRef length);
|
||||
GateRef HeapAlloc(GateRef size, GateType type, RegionSpaceFlag flag);
|
||||
GateRef IsRegExpReplaceDetectorValid(GateRef glue);
|
||||
GateRef IsRegExpSplitDetectorValid(GateRef glue);
|
||||
GateRef IsMapIteratorDetectorValid(GateRef glue);
|
||||
GateRef IsSetIteratorDetectorValid(GateRef glue);
|
||||
GateRef IsStringIteratorDetectorValid(GateRef glue);
|
||||
GateRef IsArrayIteratorDetectorValid(GateRef glue);
|
||||
GateRef IsTypedArrayIteratorDetectorValid(GateRef glue);
|
||||
|
||||
// bit operation
|
||||
inline GateRef TaggedIsInt(GateRef x);
|
||||
@ -515,7 +544,7 @@ public:
|
||||
inline GateRef TaggedIsAsyncGeneratorObject(GateRef x);
|
||||
inline GateRef TaggedIsJSGlobalObject(GateRef x);
|
||||
inline GateRef TaggedIsGeneratorObject(GateRef x);
|
||||
inline GateRef TaggedIsJSArray(GateRef x);
|
||||
inline GateRef TaggedIsJSArray(GateRef obj);
|
||||
inline GateRef TaggedIsPropertyBox(GateRef x);
|
||||
inline GateRef TaggedIsWeak(GateRef x);
|
||||
inline GateRef TaggedIsPrototypeHandler(GateRef x);
|
||||
@ -532,6 +561,9 @@ public:
|
||||
inline GateRef TaggedIsStringOrSymbol(GateRef obj);
|
||||
inline GateRef TaggedIsSymbol(GateRef obj);
|
||||
inline GateRef TaggedIsProtoChangeMarker(GateRef obj);
|
||||
inline GateRef TaggedIsJSMap(GateRef obj);
|
||||
inline GateRef TaggedIsJSSet(GateRef obj);
|
||||
inline GateRef TaggedIsTypedArray(GateRef obj);
|
||||
inline GateRef TaggedGetInt(GateRef x);
|
||||
inline GateRef TaggedObjectIsString(GateRef obj);
|
||||
inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y);
|
||||
@ -550,6 +582,11 @@ public:
|
||||
GateRef GetHashcodeFromString(GateRef glue, GateRef value);
|
||||
GateRef TryGetHashcodeFromString(GateRef string);
|
||||
|
||||
// for in
|
||||
GateRef GetEnumCacheKind(GateRef glue, GateRef enumCache);
|
||||
GateRef IsEnumCacheValid(GateRef receiver, GateRef cachedHclass, GateRef kind);
|
||||
GateRef NeedCheckProperty(GateRef receiver);
|
||||
|
||||
// ************************************************************* Low IR **********************************************************************************
|
||||
inline GateRef Equal(GateRef x, GateRef y, const char* comment = nullptr);
|
||||
inline GateRef NotEqual(GateRef x, GateRef y, const char* comment = nullptr);
|
||||
|
@ -25,6 +25,10 @@
|
||||
#include "ecmascript/compiler/stub_builder-inl.h"
|
||||
#include "ecmascript/compiler/variable_type.h"
|
||||
#include "ecmascript/js_array.h"
|
||||
#include "ecmascript/js_map.h"
|
||||
#include "ecmascript/js_map_iterator.h"
|
||||
#include "ecmascript/js_set.h"
|
||||
#include "ecmascript/js_set_iterator.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/tagged_hash_table.h"
|
||||
|
||||
@ -936,6 +940,40 @@ void GetnextpropnameStubBuilder::GenerateCircuit()
|
||||
Return(result);
|
||||
}
|
||||
|
||||
void CreateJSSetIteratorStubBuilder::GenerateCircuit()
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label exit(env);
|
||||
|
||||
GateRef glue = PtrArgument(0);
|
||||
GateRef obj = TaggedArgument(1);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
||||
|
||||
NewObjectStubBuilder newBuilder(this);
|
||||
newBuilder.SetGlue(glue);
|
||||
GateRef kind = Int32(static_cast<int32_t>(IterationKind::VALUE));
|
||||
newBuilder.CreateJSCollectionIterator<JSSetIterator, JSSet>(&result, &exit, obj, kind);
|
||||
Bind(&exit);
|
||||
Return(*result);
|
||||
}
|
||||
|
||||
void CreateJSMapIteratorStubBuilder::GenerateCircuit()
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label exit(env);
|
||||
|
||||
GateRef glue = PtrArgument(0);
|
||||
GateRef obj = TaggedArgument(1);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
||||
|
||||
NewObjectStubBuilder newBuilder(this);
|
||||
newBuilder.SetGlue(glue);
|
||||
GateRef kind = Int32(static_cast<int32_t>(IterationKind::KEY_AND_VALUE));
|
||||
newBuilder.CreateJSCollectionIterator<JSMapIterator, JSMap>(&result, &exit, obj, kind);
|
||||
Bind(&exit);
|
||||
Return(*result);
|
||||
}
|
||||
|
||||
CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
|
||||
|
||||
void CommonStubCSigns::Initialize()
|
||||
|
@ -80,6 +80,8 @@ namespace panda::ecmascript::kungfu {
|
||||
V(CreateStringBySingleCharCode) \
|
||||
V(Getpropiterator) \
|
||||
V(Getnextpropname) \
|
||||
V(CreateJSSetIterator) \
|
||||
V(CreateJSMapIterator) \
|
||||
V(GetSingleCharCodeByIndex) \
|
||||
V(FastStringEqual)
|
||||
|
||||
|
@ -86,6 +86,8 @@ GateRef EarlyElimination::VisitGate(GateRef gate)
|
||||
case OpCode::ECMA_STRING_CHECK:
|
||||
case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK:
|
||||
case OpCode::TYPE_OF_CHECK:
|
||||
case OpCode::ITERATOR_FUNCTION_CHECK:
|
||||
case OpCode::NATIVE_CALLTARGET_CHECK:
|
||||
return TryEliminateGate(gate);
|
||||
case OpCode::STATE_SPLIT:
|
||||
return TryEliminateFrameState(gate);
|
||||
|
@ -455,6 +455,7 @@ uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const
|
||||
return gatePtr->GetJSBytecodeMetaData()->GetPcOffset();
|
||||
case OpCode::TYPED_CALL_BUILTIN:
|
||||
case OpCode::CONSTRUCT:
|
||||
case OpCode::TYPED_CALL_NATIVE:
|
||||
case OpCode::CALL_GETTER:
|
||||
case OpCode::CALL_SETTER:
|
||||
return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
|
@ -386,6 +386,25 @@ GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
|
||||
return callGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TypedCallNative(GateRef hirGate, GateRef thisObj, GateRef funcId)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
std::vector<GateRef> args = { currentControl, currentDepend, thisObj, funcId };
|
||||
uint64_t bitfield = args.size() - 2; // 2: skip control and depend
|
||||
AppendFrameArgs(args, hirGate);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallNative(bitfield, pcOffset),
|
||||
MachineType::I64, args.size(), args.data(), GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CreateArray(ElementsKind kind, uint32_t arraySize)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
|
@ -33,7 +33,8 @@ namespace panda::ecmascript::kungfu {
|
||||
V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value)
|
||||
|
||||
#define HCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
|
||||
V(Construct, CONSTRUCT, GateFlags::HAS_FRAME_STATE, 1, 1, value)
|
||||
V(Construct, CONSTRUCT, GateFlags::HAS_FRAME_STATE, 1, 1, value) \
|
||||
V(TypedCallNative, TYPED_CALL_NATIVE, GateFlags::HAS_FRAME_STATE, 1, 1, value)
|
||||
|
||||
#define HCR_GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(V) \
|
||||
V(CallGetter, CALL_GETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 2) \
|
||||
|
@ -495,14 +495,14 @@ DECLARE_ASM_HANDLER(HandleCreateemptyarrayImm16)
|
||||
DECLARE_ASM_HANDLER(HandleGetiteratorImm8)
|
||||
{
|
||||
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
|
||||
GateRef res = CallRuntime(glue, RTSTUB_ID(GetIterator), { *varAcc });
|
||||
GateRef res = GetIterator(glue, *varAcc, callback);
|
||||
CHECK_PENDING_EXCEPTION(res, INT_PTR(GETITERATOR_IMM8));
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleGetiteratorImm16)
|
||||
{
|
||||
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
|
||||
GateRef res = CallRuntime(glue, RTSTUB_ID(GetIterator), { *varAcc });
|
||||
GateRef res = GetIterator(glue, *varAcc, callback);
|
||||
CHECK_PENDING_EXCEPTION(res, INT_PTR(GETITERATOR_IMM16));
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "ecmascript/compiler/mcr_circuit_builder.h"
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "ecmascript/global_env.h"
|
||||
#include "ecmascript/js_object.h"
|
||||
#include "ecmascript/marker_cell.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
GateRef CircuitBuilder::ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex)
|
||||
@ -239,6 +243,60 @@ GateRef CircuitBuilder::TypedTypeOf(GateType type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::IteratorFunctionCheck(GateRef obj, GateRef kind)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->IteratorFunctionCheck(),
|
||||
MachineType::I1, {currentControl, currentDepend, obj, kind, frameState}, GateType::NJSValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetFixedIterator(GateRef obj, GateRef kind)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->GetFixedIterator(),
|
||||
MachineType::I64, {currentControl, currentDepend, obj, kind}, GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::NativeCallTargetCheck(GateRef func, GateRef funcId)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->NativeCallTargetCheck(),
|
||||
MachineType::I1, {currentControl, currentDepend, func, funcId, frameState}, GateType::NJSValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SYMBOL_DETECTOR_VALID_DEFINE(type, name, index) \
|
||||
GateRef CircuitBuilder::Is##name##Valid(GateRef glue) \
|
||||
{ \
|
||||
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit())); \
|
||||
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); \
|
||||
GateRef cell = GetGlobalEnvValue( \
|
||||
VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::index); \
|
||||
GateRef bitfield = Load(VariableType::INT32(), cell, IntPtr(MarkerCell::BIT_FIELD_OFFSET)); \
|
||||
return Int32Equal( \
|
||||
Int32And(Int32LSR(bitfield, Int32(MarkerCell::IsDetectorInvalidBits::START_BIT)), \
|
||||
Int32((1LU << MarkerCell::IsDetectorInvalidBits::SIZE) - 1)), \
|
||||
Int32(0)); \
|
||||
}
|
||||
GLOBAL_ENV_DETECTOR_FIELDS(SYMBOL_DETECTOR_VALID_DEFINE)
|
||||
#undef SYMBOL_DETECTOR_VALID_DEFINE
|
||||
|
||||
GateRef CircuitBuilder::CheckAndConvert(GateRef gate, ValueType src, ValueType dst, ConvertSupport support)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
@ -963,4 +1021,119 @@ GateRef CircuitBuilder::ComputeTaggedArraySize(GateRef length)
|
||||
return PtrAdd(IntPtr(TaggedArray::DATA_OFFSET),
|
||||
PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), length));
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetEnumCacheKind(GateRef glue, GateRef enumCache)
|
||||
{
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
DEFVAlUE(result, env_, VariableType::INT32(), Int32(static_cast<int32_t>(EnumCacheKind::NONE)));
|
||||
|
||||
Label enumCacheIsArray(env_);
|
||||
Label isEmptyArray(env_);
|
||||
Label notEmptyArray(env_);
|
||||
|
||||
Branch(TaggedIsUndefinedOrNull(enumCache), &exit, &enumCacheIsArray);
|
||||
Bind(&enumCacheIsArray);
|
||||
GateRef emptyArray = GetEmptyArray(glue);
|
||||
Branch(Int64Equal(enumCache, emptyArray), &isEmptyArray, ¬EmptyArray);
|
||||
Bind(&isEmptyArray);
|
||||
{
|
||||
result = Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬EmptyArray);
|
||||
{
|
||||
GateRef taggedKind = GetValueFromTaggedArray(enumCache, Int32(EnumCache::ENUM_CACHE_KIND_OFFSET));
|
||||
result = TaggedGetInt(taggedKind);
|
||||
Jump(&exit);
|
||||
}
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::IsEnumCacheValid(GateRef receiver, GateRef cachedHclass, GateRef kind)
|
||||
{
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), False());
|
||||
|
||||
Label isSameHclass(env_);
|
||||
Label isSimpleEnumCache(env_);
|
||||
Label notSimpleEnumCache(env_);
|
||||
Label prototypeIsEcmaObj(env_);
|
||||
Label isProtoChangeMarker(env_);
|
||||
Label protoNotChanged(env_);
|
||||
|
||||
GateRef hclass = LoadHClass(receiver);
|
||||
Branch(Int64Equal(hclass, cachedHclass), &isSameHclass, &exit);
|
||||
Bind(&isSameHclass);
|
||||
Branch(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
|
||||
&isSimpleEnumCache, ¬SimpleEnumCache);
|
||||
Bind(&isSimpleEnumCache);
|
||||
{
|
||||
result = True();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SimpleEnumCache);
|
||||
GateRef prototype = GetPrototypeFromHClass(hclass);
|
||||
Branch(IsEcmaObject(prototype), &prototypeIsEcmaObj, &exit);
|
||||
Bind(&prototypeIsEcmaObj);
|
||||
GateRef protoChangeMarker = GetProtoChangeMarkerFromHClass(hclass);
|
||||
Branch(TaggedIsProtoChangeMarker(protoChangeMarker), &isProtoChangeMarker, &exit);
|
||||
Bind(&isProtoChangeMarker);
|
||||
Branch(GetHasChanged(protoChangeMarker), &exit, &protoNotChanged);
|
||||
Bind(&protoNotChanged);
|
||||
{
|
||||
result = True();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::NeedCheckProperty(GateRef receiver)
|
||||
{
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
|
||||
Label loopHead(env_);
|
||||
Label loopEnd(env_);
|
||||
Label afterLoop(env_);
|
||||
Label isJSObject(env_);
|
||||
Label hasNoDeleteProperty(env_);
|
||||
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), True());
|
||||
DEFVAlUE(current, env_, VariableType::JS_ANY(), receiver);
|
||||
|
||||
Branch(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
|
||||
LoopBegin(&loopHead);
|
||||
{
|
||||
Branch(IsJSObject(*current), &isJSObject, &exit);
|
||||
Bind(&isJSObject);
|
||||
GateRef hclass = LoadHClass(*current);
|
||||
Branch(HasDeleteProperty(hclass), &exit, &hasNoDeleteProperty);
|
||||
Bind(&hasNoDeleteProperty);
|
||||
current = GetPrototypeFromHClass(hclass);
|
||||
Branch(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
LoopEnd(&loopHead);
|
||||
Bind(&afterLoop);
|
||||
{
|
||||
result = False();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/circuit_builder_helper.h"
|
||||
#include "ecmascript/mem/region.h"
|
||||
#include "ecmascript/method.h"
|
||||
|
||||
@ -184,6 +185,67 @@ GateRef CircuitBuilder::TaggedIsProtoChangeMarker(GateRef obj)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TaggedIsJSMap(GateRef obj)
|
||||
{
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), False());
|
||||
Label isHeapObject(env_);
|
||||
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
|
||||
Bind(&isHeapObject);
|
||||
{
|
||||
GateRef objType = GetObjectType(LoadHClass(obj));
|
||||
result = Equal(objType, Int32(static_cast<int32_t>(JSType::JS_MAP)));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TaggedIsJSSet(GateRef obj)
|
||||
{
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), False());
|
||||
Label isHeapObject(env_);
|
||||
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
|
||||
Bind(&isHeapObject);
|
||||
{
|
||||
GateRef objType = GetObjectType(LoadHClass(obj));
|
||||
result = Equal(objType, Int32(static_cast<int32_t>(JSType::JS_SET)));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TaggedIsTypedArray(GateRef obj)
|
||||
{
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), False());
|
||||
Label isHeapObject(env_);
|
||||
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
|
||||
Bind(&isHeapObject);
|
||||
{
|
||||
GateRef jsType = GetObjectType(LoadHClass(obj));
|
||||
result = BoolAnd(Int32GreaterThan(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
|
||||
Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), jsType));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline GateRef CircuitBuilder::IsOptimizedAndNotFastCall(GateRef obj)
|
||||
{
|
||||
GateRef hClass = LoadHClass(obj);
|
||||
@ -297,11 +359,24 @@ GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x)
|
||||
return LogicAnd(isHeapObj, isAsyncGeneratorObj);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TaggedIsJSArray(GateRef x)
|
||||
GateRef CircuitBuilder::TaggedIsJSArray(GateRef obj)
|
||||
{
|
||||
GateRef objType = GetObjectType(LoadHClass(x));
|
||||
GateRef isJSArray = Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
|
||||
return isJSArray;
|
||||
Label entry(env_);
|
||||
SubCfgEntry(&entry);
|
||||
Label exit(env_);
|
||||
DEFVAlUE(result, env_, VariableType::BOOL(), False());
|
||||
Label isHeapObject(env_);
|
||||
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
|
||||
Bind(&isHeapObject);
|
||||
{
|
||||
GateRef objType = GetObjectType(LoadHClass(obj));
|
||||
result = Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef x)
|
||||
|
@ -26,6 +26,9 @@ namespace panda::ecmascript::kungfu {
|
||||
V(Int32UnsignedUpperBoundCheck, INT32_UNSIGNED_UPPER_BOUND_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(Int32DivWithCheck, INT32_DIV_WITH_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(IteratorFunctionCheck, ITERATOR_FUNCTION_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(GetFixedIterator, GET_FIXED_ITERATOR, GateFlags::NONE_FLAG, 1, 1, 2) \
|
||||
V(NativeCallTargetCheck, NATIVE_CALLTARGET_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(StringEqual, STRING_EQUAL, GateFlags::NO_WRITE, 1, 1, 2)
|
||||
|
||||
#define MCR_IMMUTABLE_META_DATA_CACHE_LIST(V) \
|
||||
|
@ -216,7 +216,7 @@ GateRef NewObjectStubBuilder::NewJSForinIterator(GateRef glue, GateRef receiver,
|
||||
GateRef iter = NewJSObject(glue, hclass);
|
||||
// init JSForinIterator
|
||||
SetObjectOfForInIterator(glue, iter, receiver);
|
||||
SetCachedHclassOFForInIterator(glue, iter, cachedHclass);
|
||||
SetCachedHclassOfForInIterator(glue, iter, cachedHclass);
|
||||
SetKeysOfForInIterator(glue, iter, keys);
|
||||
SetIndexOfForInIterator(glue, iter, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE));
|
||||
GateRef length = GetLengthOfTaggedArray(keys);
|
||||
|
@ -24,6 +24,7 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
enum class OperationType : uint8_t {
|
||||
CALL,
|
||||
NATIVE_CALL,
|
||||
OPERATION_TYPE,
|
||||
DEFINE_CLASS,
|
||||
CREATE_OBJECT,
|
||||
@ -31,6 +32,7 @@ enum class OperationType : uint8_t {
|
||||
FALSE_BRANCH,
|
||||
TRY_DUMP,
|
||||
TRY_PREDUMP,
|
||||
ITERATOR_FUNC_KIND
|
||||
};
|
||||
|
||||
using SlotIDFormat = BytecodeInstruction::Format;
|
||||
@ -57,6 +59,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileNativeCall(GateRef func) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_({ func }, OperationType::NATIVE_CALL);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileOpType(GateRef type) const
|
||||
{
|
||||
if (callback_) {
|
||||
@ -108,6 +117,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline void ProfileGetIterator(GateRef iterator) const
|
||||
{
|
||||
if (callback_) {
|
||||
callback_({ iterator }, OperationType::ITERATOR_FUNC_KIND);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Callback callback_;
|
||||
};
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "ecmascript/ic/profile_type_info.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using PGONativeFunctionId = panda::ecmascript::pgo::DumpUtils::PGONativeFunctionId;
|
||||
void ProfilerStubBuilder::PGOProfiler(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo,
|
||||
const std::vector<GateRef> &values, SlotIDFormat format, OperationType type)
|
||||
{
|
||||
@ -28,6 +29,9 @@ void ProfilerStubBuilder::PGOProfiler(GateRef glue, GateRef pc, GateRef func, Ga
|
||||
case OperationType::CALL:
|
||||
ProfileCall(glue, pc, func, values[0], profileTypeInfo, format);
|
||||
break;
|
||||
case OperationType::NATIVE_CALL:
|
||||
ProfileNativeCall(glue, pc, func, values[0], profileTypeInfo, format);
|
||||
break;
|
||||
case OperationType::OPERATION_TYPE:
|
||||
ProfileOpType(glue, pc, func, profileTypeInfo, values[0], format);
|
||||
break;
|
||||
@ -49,6 +53,9 @@ void ProfilerStubBuilder::PGOProfiler(GateRef glue, GateRef pc, GateRef func, Ga
|
||||
case OperationType::FALSE_BRANCH:
|
||||
ProfileBranch(glue, pc, func, profileTypeInfo, false);
|
||||
break;
|
||||
case OperationType::ITERATOR_FUNC_KIND:
|
||||
ProfileGetIterator(glue, pc, func, values[0], profileTypeInfo, format);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -282,6 +289,107 @@ void ProfilerStubBuilder::ProfileCall(
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
GateRef ProfilerStubBuilder::TryGetPGONativeFunctionID(GateRef glue, GateRef target)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label subEntry(env);
|
||||
env->SubCfgEntry(&subEntry);
|
||||
Label exit(env);
|
||||
|
||||
DEFVARIABLE(functionKind, VariableType::INT32(), Int32(static_cast<int32_t>(PGONativeFunctionId::INVALID)));
|
||||
DEFVARIABLE(maybeFunc, VariableType::JS_ANY(), Undefined());
|
||||
Label isArrayIterProtoNext(env);
|
||||
Label notArrayIterProtoNext(env);
|
||||
Label isMapIterProtoNext(env);
|
||||
Label notMapIterProtoNext(env);
|
||||
Label isSetIterProtoNext(env);
|
||||
Label notSetIterProtoNext(env);
|
||||
Label isStringIterProtoNext(env);
|
||||
|
||||
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
|
||||
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_ITERATOR_PROTO_NEXT_INDEX);
|
||||
Branch(Int64Equal(target, *maybeFunc), &isArrayIterProtoNext, ¬ArrayIterProtoNext);
|
||||
Bind(&isArrayIterProtoNext);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::ARRAY_ITERATOR_PROTO_NEXT));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬ArrayIterProtoNext);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::MAP_ITERATOR_PROTO_NEXT_INDEX);
|
||||
Branch(Int64Equal(target, *maybeFunc), &isMapIterProtoNext, ¬MapIterProtoNext);
|
||||
Bind(&isMapIterProtoNext);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::MAP_ITERATOR_PROTO_NEXT));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬MapIterProtoNext);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::SET_ITERATOR_PROTO_NEXT_INDEX);
|
||||
Branch(Int64Equal(target, *maybeFunc), &isSetIterProtoNext, ¬SetIterProtoNext);
|
||||
Bind(&isSetIterProtoNext);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::SET_ITERATOR_PROTO_NEXT));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SetIterProtoNext);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::STRING_ITERATOR_PROTO_NEXT_INDEX);
|
||||
Branch(Int64Equal(target, *maybeFunc), &isStringIterProtoNext, &exit);
|
||||
Bind(&isStringIterProtoNext);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::STRING_ITERATOR_PROTO_NEXT));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *functionKind;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ProfilerStubBuilder::ProfileNativeCall(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef target, GateRef profileTypeInfo, SlotIDFormat format)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label subEntry(env);
|
||||
env->SubCfgEntry(&subEntry);
|
||||
|
||||
Label exit(env);
|
||||
Label currentIsHot(env);
|
||||
|
||||
Branch(TaggedIsUndefined(profileTypeInfo), &exit, ¤tIsHot);
|
||||
Bind(¤tIsHot);
|
||||
{
|
||||
Label updateSlot(env);
|
||||
Label initSlot(env);
|
||||
Label sameValueCheck(env);
|
||||
Label invalidate(env);
|
||||
|
||||
GateRef slotId = GetSlotID(pc, format);
|
||||
GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
|
||||
GateRef newId = TryGetPGONativeFunctionID(glue, target);
|
||||
Branch(TaggedIsInt(slotValue), &updateSlot, &initSlot);
|
||||
Bind(&updateSlot);
|
||||
GateRef oldId = TaggedGetInt(slotValue);
|
||||
Branch(Int32Equal(oldId, Int32(static_cast<int32_t>(PGONativeFunctionId::INVALID))), &exit, &sameValueCheck);
|
||||
Bind(&sameValueCheck);
|
||||
Branch(Int32Equal(oldId, newId), &exit, &invalidate);
|
||||
Bind(&invalidate);
|
||||
{
|
||||
GateRef invalidId = Int32(static_cast<int32_t>(PGONativeFunctionId::INVALID));
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(invalidId));
|
||||
TryPreDumpInner(glue, func, profileTypeInfo);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&initSlot);
|
||||
{
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(newId));
|
||||
TryPreDumpInner(glue, func, profileTypeInfo);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(&exit);
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
GateRef ProfilerStubBuilder::IsProfileTypeInfoDumped(GateRef profileTypeInfo, ProfileOperation callback)
|
||||
{
|
||||
if (callback.IsEmpty()) {
|
||||
@ -521,6 +629,118 @@ void ProfilerStubBuilder::TryPreDumpInner(GateRef glue, GateRef func, GateRef pr
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
GateRef ProfilerStubBuilder::GetIterationFunctionKind(GateRef glue, GateRef iterator)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label subEntry(env);
|
||||
env->SubCfgEntry(&subEntry);
|
||||
Label exit(env);
|
||||
|
||||
DEFVARIABLE(functionKind, VariableType::INT32(), Int32(static_cast<int32_t>(PGONativeFunctionId::INVALID)));
|
||||
DEFVARIABLE(maybeFunc, VariableType::JS_ANY(), Undefined());
|
||||
Label isArrayProtoValues(env);
|
||||
Label notArrayProtoValues(env);
|
||||
Label isSetProtoValues(env);
|
||||
Label notSetProtoValues(env);
|
||||
Label isMapProtoEntries(env);
|
||||
Label notMapProtoEntries(env);
|
||||
Label isStringProtoIter(env);
|
||||
Label notStringProtoIter(env);
|
||||
Label isTypedArrayProtoValues(env);
|
||||
|
||||
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
|
||||
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
|
||||
Branch(Int64Equal(iterator, *maybeFunc), &isArrayProtoValues, ¬ArrayProtoValues);
|
||||
Bind(&isArrayProtoValues);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::ARRAY_PROTO_ITERATOR));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬ArrayProtoValues);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::SET_PROTO_VALUES_FUNCTION_INDEX);
|
||||
Branch(Int64Equal(iterator, *maybeFunc), &isSetProtoValues, ¬SetProtoValues);
|
||||
Bind(&isSetProtoValues);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::SET_PROTO_ITERATOR));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SetProtoValues);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::MAP_PROTO_ENTRIES_FUNCTION_INDEX);
|
||||
Branch(Int64Equal(iterator, *maybeFunc), &isMapProtoEntries, ¬MapProtoEntries);
|
||||
Bind(&isMapProtoEntries);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::MAP_PROTO_ITERATOR));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬MapProtoEntries);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::STRING_PROTO_ITER_FUNCTION_INDEX);
|
||||
Branch(Int64Equal(iterator, *maybeFunc), &isStringProtoIter, ¬StringProtoIter);
|
||||
Bind(&isStringProtoIter);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::STRING_PROTO_ITERATOR));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬StringProtoIter);
|
||||
maybeFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
|
||||
GlobalEnv::TYPED_ARRAY_PROTO_VALUES_FUNCTION_INDEX);
|
||||
Branch(Int64Equal(iterator, *maybeFunc), &isTypedArrayProtoValues, &exit);
|
||||
Bind(&isTypedArrayProtoValues);
|
||||
{
|
||||
functionKind = Int32(static_cast<int32_t>(PGONativeFunctionId::TYPED_ARRAY_PROTO_ITERATOR));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *functionKind;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ProfilerStubBuilder::ProfileGetIterator(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef iterator, GateRef profileTypeInfo, SlotIDFormat format)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label subEntry(env);
|
||||
env->SubCfgEntry(&subEntry);
|
||||
|
||||
Label exit(env);
|
||||
Label profiler(env);
|
||||
Branch(TaggedIsUndefined(profileTypeInfo), &exit, &profiler);
|
||||
Bind(&profiler);
|
||||
{
|
||||
Label updateSlot(env);
|
||||
Label initSlot(env);
|
||||
Label sameValueCheck(env);
|
||||
Label invalidate(env);
|
||||
|
||||
GateRef slotId = GetSlotID(pc, format);
|
||||
GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
|
||||
GateRef newIterKind = GetIterationFunctionKind(glue, iterator);
|
||||
Branch(TaggedIsInt(slotValue), &updateSlot, &initSlot);
|
||||
Bind(&updateSlot);
|
||||
GateRef oldIterKind = TaggedGetInt(slotValue);
|
||||
Branch(Int32Equal(oldIterKind, Int32(static_cast<int32_t>(PGONativeFunctionId::INVALID))),
|
||||
&exit, &sameValueCheck);
|
||||
Bind(&sameValueCheck);
|
||||
Branch(Int32Equal(oldIterKind, newIterKind), &exit, &invalidate);
|
||||
Bind(&invalidate);
|
||||
{
|
||||
GateRef invalidKind = Int32(static_cast<int32_t>(PGONativeFunctionId::INVALID));
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(invalidKind));
|
||||
TryPreDumpInner(glue, func, profileTypeInfo);
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&initSlot);
|
||||
{
|
||||
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, IntToTaggedInt(newIterKind));
|
||||
TryPreDumpInner(glue, func, profileTypeInfo);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(&exit);
|
||||
env->SubCfgExit();
|
||||
}
|
||||
|
||||
GateRef ProfilerStubBuilder::GetSlotID(GateRef pc, SlotIDFormat format)
|
||||
{
|
||||
if (format == SlotIDFormat::IMM16) {
|
||||
|
@ -37,6 +37,8 @@ public:
|
||||
|
||||
void ProfileCall(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef target, GateRef profileTypeInfo, SlotIDFormat format);
|
||||
void ProfileNativeCall(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef target, GateRef profileTypeInfo, SlotIDFormat format);
|
||||
void ProfileOpType(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo, GateRef type, SlotIDFormat format);
|
||||
void ProfileDefineClass(
|
||||
@ -44,6 +46,8 @@ public:
|
||||
void ProfileCreateObject(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef newObj, GateRef profileTypeInfo, SlotIDFormat format);
|
||||
void ProfileBranch(GateRef glue, GateRef pc, GateRef func, GateRef profileTypeInfo, bool isTrue);
|
||||
void ProfileGetIterator(
|
||||
GateRef glue, GateRef pc, GateRef func, GateRef iterator, GateRef profileTypeInfo, SlotIDFormat format);
|
||||
|
||||
GateRef UpdateTrackTypeInPropAttr(GateRef attr, GateRef value, ProfileOperation callback);
|
||||
void UpdatePropAttrIC(GateRef glue, GateRef receiver, GateRef value, GateRef handler, ProfileOperation callback);
|
||||
@ -68,6 +72,8 @@ private:
|
||||
void SetDumpPeriodIndex(GateRef glue, GateRef profileTypeInfo);
|
||||
void SetPreDumpPeriodIndex(GateRef glue, GateRef profileTypeInfo);
|
||||
GateRef TaggedToTrackType(GateRef value);
|
||||
GateRef GetIterationFunctionKind(GateRef glue, GateRef iterator);
|
||||
GateRef TryGetPGONativeFunctionID(GateRef glue, GateRef target);
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_PROFILER_STUB_BUILDER_H
|
||||
|
@ -66,7 +66,9 @@ enum class TypedCallTargetCheckOp : uint8_t;
|
||||
V(NotString, NOTSTRING) \
|
||||
V(InconsistentType, INCONSISTENTTYPE) \
|
||||
V(NotNull, NOTNULL) \
|
||||
V(BuiltinPrototypeHClassMismatch, BUILTINPROTOHCLASSMISMATCH)
|
||||
V(BuiltinPrototypeHClassMismatch, BUILTINPROTOHCLASSMISMATCH) \
|
||||
V(IteratorFunctionDisMactch, ITERATORFUNCTIONDISMATCH) \
|
||||
V(NativeCallTargetDisMatch, NATIVECALLTARGETDISMATCH)
|
||||
|
||||
enum class DeoptType : uint8_t {
|
||||
NOTCHECK = 0,
|
||||
|
@ -1807,8 +1807,40 @@ void SlowPathLowering::LowerGetNextPropName(GateRef gate)
|
||||
// 1: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 1);
|
||||
GateRef iter = acc_.GetValueIn(gate, 0);
|
||||
GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::Getnextpropname, {glue_, iter});
|
||||
ReplaceHirWithValue(gate, newGate);
|
||||
|
||||
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
|
||||
|
||||
Label notFinish(&builder_);
|
||||
Label notEnumCacheValid(&builder_);
|
||||
Label fastGetKey(&builder_);
|
||||
Label slowpath(&builder_);
|
||||
Label exit(&builder_);
|
||||
|
||||
GateRef index = builder_.GetIndexFromForInIterator(iter);
|
||||
GateRef length = builder_.GetLengthFromForInIterator(iter);
|
||||
builder_.Branch(builder_.Int32GreaterThanOrEqual(index, length), &exit, ¬Finish);
|
||||
builder_.Bind(¬Finish);
|
||||
GateRef keys = builder_.GetKeysFromForInIterator(iter);
|
||||
GateRef receiver = builder_.GetObjectFromForInIterator(iter);
|
||||
GateRef cachedHclass = builder_.GetCachedHclassFromForInIterator(iter);
|
||||
GateRef kind = builder_.GetEnumCacheKind(glue_, keys);
|
||||
builder_.Branch(builder_.IsEnumCacheValid(receiver, cachedHclass, kind), &fastGetKey, ¬EnumCacheValid);
|
||||
builder_.Bind(¬EnumCacheValid);
|
||||
builder_.Branch(builder_.NeedCheckProperty(receiver), &slowpath, &fastGetKey);
|
||||
builder_.Bind(&fastGetKey);
|
||||
{
|
||||
result = builder_.GetValueFromTaggedArray(keys, index);
|
||||
builder_.IncreaseInteratorIndex(glue_, iter, index);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(&slowpath);
|
||||
{
|
||||
result = LowerCallRuntime(gate, RTSTUB_ID(GetNextPropNameSlowpath), { iter }, true);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
|
||||
builder_.Bind(&exit);
|
||||
ReplaceHirWithValue(gate, *result);
|
||||
}
|
||||
|
||||
void SlowPathLowering::LowerCopyDataProperties(GateRef gate)
|
||||
|
@ -1095,21 +1095,7 @@ inline GateRef StubBuilder::TaggedObjectIsEcmaObject(GateRef obj)
|
||||
|
||||
inline GateRef StubBuilder::IsEcmaObject(GateRef obj)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entryPass(env);
|
||||
env->SubCfgEntry(&entryPass);
|
||||
DEFVARIABLE(result, VariableType::BOOL(), False());
|
||||
Label heapObj(env);
|
||||
Label exit(env);
|
||||
GateRef isHeapObject = TaggedIsHeapObject(obj);
|
||||
Branch(isHeapObject, &heapObj, &exit);
|
||||
Bind(&heapObj);
|
||||
result = env_->GetBuilder()->LogicAnd(isHeapObject, TaggedObjectIsEcmaObject(obj));
|
||||
Jump(&exit);
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
return env_->GetBuilder()->IsEcmaObject(obj);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsJSObject(GateRef obj)
|
||||
@ -1425,10 +1411,7 @@ inline GateRef StubBuilder::GetStoreTSHandlerHandlerInfo(GateRef object)
|
||||
|
||||
inline GateRef StubBuilder::GetHasChanged(GateRef object)
|
||||
{
|
||||
GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
|
||||
GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
|
||||
GateRef mask = Int32(1LLU << (ProtoChangeMarker::HAS_CHANGED_BITS - 1));
|
||||
return Int32NotEqual(Int32And(bitfield, mask), Int32(0));
|
||||
return env_->GetBuilder()->GetHasChanged(object);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::HclassIsPrototypeHandler(GateRef hClass)
|
||||
@ -1456,77 +1439,62 @@ inline GateRef StubBuilder::TaggedIsProtoChangeMarker(GateRef obj)
|
||||
|
||||
inline GateRef StubBuilder::GetEmptyArray(GateRef glue)
|
||||
{
|
||||
GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
|
||||
IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
|
||||
GateRef offset = GetGlobalConstantOffset(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
|
||||
return Load(VariableType::JS_ANY(), gConstAddr, offset);
|
||||
return env_->GetBuilder()->GetEmptyArray(glue);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetLengthFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
|
||||
return Load(VariableType::INT32(), iter, offset);
|
||||
return env_->GetBuilder()->GetLengthFromForInIterator(iter);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetIndexFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
|
||||
return Load(VariableType::INT32(), iter, offset);
|
||||
return env_->GetBuilder()->GetIndexFromForInIterator(iter);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetKeysFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), iter, offset);
|
||||
return env_->GetBuilder()->GetKeysFromForInIterator(iter);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetObjectFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), iter, offset);
|
||||
return env_->GetBuilder()->GetObjectFromForInIterator(iter);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetCachedHclassFromForInIterator(GateRef iter)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), iter, offset);
|
||||
return env_->GetBuilder()->GetCachedHclassFromForInIterator(iter);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetLengthOfForInIterator(GateRef glue, GateRef iter, GateRef length)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
|
||||
Store(VariableType::INT32(), glue, iter, offset, length);
|
||||
env_->GetBuilder()->SetLengthOfForInIterator(glue, iter, length);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetIndexOfForInIterator(GateRef glue, GateRef iter, GateRef index)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
|
||||
Store(VariableType::INT32(), glue, iter, offset, index);
|
||||
env_->GetBuilder()->SetIndexOfForInIterator(glue, iter, index);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetKeysOfForInIterator(GateRef glue, GateRef iter, GateRef keys)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
|
||||
Store(VariableType::JS_ANY(), glue, iter, offset, keys);
|
||||
env_->GetBuilder()->SetKeysOfForInIterator(glue, iter, keys);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetObjectOfForInIterator(GateRef glue, GateRef iter, GateRef object)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
|
||||
Store(VariableType::JS_ANY(), glue, iter, offset, object);
|
||||
env_->GetBuilder()->SetObjectOfForInIterator(glue, iter, object);
|
||||
}
|
||||
|
||||
inline void StubBuilder::SetCachedHclassOFForInIterator(GateRef glue, GateRef iter, GateRef hclass)
|
||||
inline void StubBuilder::SetCachedHclassOfForInIterator(GateRef glue, GateRef iter, GateRef hclass)
|
||||
{
|
||||
GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
|
||||
Store(VariableType::JS_ANY(), glue, iter, offset, hclass);
|
||||
env_->GetBuilder()->SetCachedHclassOfForInIterator(glue, iter, hclass);
|
||||
}
|
||||
|
||||
inline void StubBuilder::IncreaseInteratorIndex(GateRef glue, GateRef iter, GateRef index)
|
||||
{
|
||||
GateRef newIndex = Int32Add(index, Int32(1));
|
||||
GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
|
||||
Store(VariableType::INT32(), glue, iter, offset, newIndex);
|
||||
env_->GetBuilder()->IncreaseInteratorIndex(glue, iter, index);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsField(GateRef attr)
|
||||
@ -1710,20 +1678,17 @@ inline GateRef StubBuilder::SetDictionaryOrderFieldInPropAttr(GateRef attr, Gate
|
||||
|
||||
inline GateRef StubBuilder::GetPrototypeFromHClass(GateRef hClass)
|
||||
{
|
||||
GateRef protoOffset = IntPtr(JSHClass::PROTOTYPE_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), hClass, protoOffset);
|
||||
return env_->GetBuilder()->GetPrototypeFromHClass(hClass);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetEnumCacheFromHClass(GateRef hClass)
|
||||
{
|
||||
GateRef offset = IntPtr(JSHClass::ENUM_CACHE_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), hClass, offset);
|
||||
return env_->GetBuilder()->GetEnumCacheFromHClass(hClass);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetProtoChangeMarkerFromHClass(GateRef hClass)
|
||||
{
|
||||
GateRef offset = IntPtr(JSHClass::PROTO_CHANGE_MARKER_OFFSET);
|
||||
return Load(VariableType::JS_ANY(), hClass, offset);
|
||||
return env_->GetBuilder()->GetProtoChangeMarkerFromHClass(hClass);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::GetLayoutFromHClass(GateRef hClass)
|
||||
@ -1885,11 +1850,7 @@ inline GateRef StubBuilder::GetNumberOfPropsFromHClass(GateRef hClass)
|
||||
|
||||
inline GateRef StubBuilder::HasDeleteProperty(GateRef hClass)
|
||||
{
|
||||
GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
|
||||
return Int32NotEqual(
|
||||
Int32And(Int32LSR(bitfield, Int32(JSHClass::HasDeletePropertyBit::START_BIT)),
|
||||
Int32((1LLU << JSHClass::HasDeletePropertyBit::SIZE) - 1)),
|
||||
Int32(0));
|
||||
return env_->GetBuilder()->HasDeleteProperty(hClass);
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsTSHClass(GateRef hClass)
|
||||
|
@ -3936,8 +3936,7 @@ GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef ke
|
||||
}
|
||||
Bind(&slowpath);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
|
||||
{ Undefined(), obj, key, Int64ToTaggedPtr(Int32(0)) });
|
||||
result = CallRuntime(glue, RTSTUB_ID(LoadICByName), { Undefined(), obj, key, IntToTaggedInt(Int32(0)) });
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
@ -4013,7 +4012,7 @@ void StubBuilder::FastSetPropertyByName(GateRef glue, GateRef obj, GateRef key,
|
||||
}
|
||||
Bind(&slowPath);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(StoreICByValue), { obj, *keyVar, value, Int64ToTaggedPtr(Int32(0)) });
|
||||
result = CallRuntime(glue, RTSTUB_ID(StoreICByValue), { obj, *keyVar, value, IntToTaggedInt(Int32(0)) });
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
@ -5474,120 +5473,17 @@ GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef i
|
||||
|
||||
GateRef StubBuilder::GetEnumCacheKind(GateRef glue, GateRef enumCache)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->SubCfgEntry(&entry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(result, VariableType::INT32(), Int32(static_cast<int32_t>(EnumCacheKind::NONE)));
|
||||
|
||||
Label enumCacheIsArray(env);
|
||||
Label isEmptyArray(env);
|
||||
Label notEmptyArray(env);
|
||||
|
||||
Branch(TaggedIsUndefinedOrNull(enumCache), &exit, &enumCacheIsArray);
|
||||
Bind(&enumCacheIsArray);
|
||||
GateRef emptyArray = GetEmptyArray(glue);
|
||||
Branch(Int64Equal(enumCache, emptyArray), &isEmptyArray, ¬EmptyArray);
|
||||
Bind(&isEmptyArray);
|
||||
{
|
||||
result = Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE));
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬EmptyArray);
|
||||
{
|
||||
GateRef taggedKind = GetValueFromTaggedArray(enumCache, Int32(EnumCache::ENUM_CACHE_KIND_OFFSET));
|
||||
result = TaggedGetInt(taggedKind);
|
||||
Jump(&exit);
|
||||
}
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
return env_->GetBuilder()->GetEnumCacheKind(glue, enumCache);
|
||||
}
|
||||
|
||||
GateRef StubBuilder::IsEnumCacheValid(GateRef receiver, GateRef cachedHclass, GateRef kind)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->SubCfgEntry(&entry);
|
||||
Label exit(env);
|
||||
DEFVARIABLE(result, VariableType::BOOL(), False());
|
||||
|
||||
Label isSameHclass(env);
|
||||
Label isSimpleEnumCache(env);
|
||||
Label notSimpleEnumCache(env);
|
||||
Label prototypeIsEcmaObj(env);
|
||||
Label isProtoChangeMarker(env);
|
||||
Label protoNotChanged(env);
|
||||
|
||||
GateRef hclass = LoadHClass(receiver);
|
||||
Branch(Int64Equal(hclass, cachedHclass), &isSameHclass, &exit);
|
||||
Bind(&isSameHclass);
|
||||
Branch(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
|
||||
&isSimpleEnumCache, ¬SimpleEnumCache);
|
||||
Bind(&isSimpleEnumCache);
|
||||
{
|
||||
result = True();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬SimpleEnumCache);
|
||||
GateRef prototype = GetPrototypeFromHClass(hclass);
|
||||
Branch(IsEcmaObject(prototype), &prototypeIsEcmaObj, &exit);
|
||||
Bind(&prototypeIsEcmaObj);
|
||||
GateRef protoChangeMarker = GetProtoChangeMarkerFromHClass(hclass);
|
||||
Branch(TaggedIsProtoChangeMarker(protoChangeMarker), &isProtoChangeMarker, &exit);
|
||||
Bind(&isProtoChangeMarker);
|
||||
Branch(GetHasChanged(protoChangeMarker), &exit, &protoNotChanged);
|
||||
Bind(&protoNotChanged);
|
||||
{
|
||||
result = True();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
return env_->GetBuilder()->IsEnumCacheValid(receiver, cachedHclass, kind);
|
||||
}
|
||||
|
||||
GateRef StubBuilder::NeedCheckProperty(GateRef receiver)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->SubCfgEntry(&entry);
|
||||
Label exit(env);
|
||||
|
||||
Label loopHead(env);
|
||||
Label loopEnd(env);
|
||||
Label afterLoop(env);
|
||||
Label isJSObject(env);
|
||||
Label hasNoDeleteProperty(env);
|
||||
|
||||
DEFVARIABLE(result, VariableType::BOOL(), True());
|
||||
DEFVARIABLE(current, VariableType::JS_ANY(), receiver);
|
||||
|
||||
Branch(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
|
||||
LoopBegin(&loopHead);
|
||||
{
|
||||
Branch(IsJSObject(*current), &isJSObject, &exit);
|
||||
Bind(&isJSObject);
|
||||
GateRef hclass = LoadHClass(*current);
|
||||
Branch(HasDeleteProperty(hclass), &exit, &hasNoDeleteProperty);
|
||||
Bind(&hasNoDeleteProperty);
|
||||
current = GetPrototypeFromHClass(hclass);
|
||||
Branch(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
|
||||
}
|
||||
Bind(&loopEnd);
|
||||
LoopEnd(&loopHead);
|
||||
Bind(&afterLoop);
|
||||
{
|
||||
result = False();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
return env_->GetBuilder()->NeedCheckProperty(receiver);
|
||||
}
|
||||
|
||||
GateRef StubBuilder::NextInternal(GateRef glue, GateRef iter)
|
||||
@ -6079,6 +5975,83 @@ GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef StubBuilder::GetIterator(GateRef glue, GateRef obj, ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entryPass(env);
|
||||
Label exit(env);
|
||||
env->SubCfgEntry(&entryPass);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
|
||||
|
||||
Label isPendingException(env);
|
||||
Label noPendingException(env);
|
||||
Label isHeapObject(env);
|
||||
Label objIsCallable(env);
|
||||
|
||||
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
|
||||
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
|
||||
GateRef iteratorKey = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ITERATOR_SYMBOL_INDEX);
|
||||
result = FastGetPropertyByName(glue, obj, iteratorKey, ProfileOperation());
|
||||
Branch(HasPendingException(glue), &isPendingException, &noPendingException);
|
||||
Bind(&isPendingException);
|
||||
{
|
||||
result = Exception();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&noPendingException);
|
||||
callback.ProfileGetIterator(*result);
|
||||
Branch(TaggedIsHeapObject(*result), &isHeapObject, &exit);
|
||||
Bind(&isHeapObject);
|
||||
Branch(IsCallable(*result), &objIsCallable, &exit);
|
||||
Bind(&objIsCallable);
|
||||
{
|
||||
result = JSCallDispatch(glue, *result, Int32(0), 0, Circuit::NullGate(),
|
||||
JSCallMode::CALL_GETTER, { obj }, ProfileOperation());
|
||||
Jump(&exit);
|
||||
}
|
||||
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool StubBuilder::IsCallModeSupportPGO(JSCallMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case JSCallMode::CALL_ARG0:
|
||||
case JSCallMode::CALL_ARG1:
|
||||
case JSCallMode::CALL_ARG2:
|
||||
case JSCallMode::CALL_ARG3:
|
||||
case JSCallMode::CALL_WITH_ARGV:
|
||||
case JSCallMode::CALL_THIS_ARG0:
|
||||
case JSCallMode::CALL_THIS_ARG1:
|
||||
case JSCallMode::CALL_THIS_ARG2:
|
||||
case JSCallMode::CALL_THIS_ARG3:
|
||||
case JSCallMode::CALL_THIS_WITH_ARGV:
|
||||
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
|
||||
return true;
|
||||
case JSCallMode::DEPRECATED_CALL_ARG0:
|
||||
case JSCallMode::DEPRECATED_CALL_ARG1:
|
||||
case JSCallMode::DEPRECATED_CALL_ARG2:
|
||||
case JSCallMode::DEPRECATED_CALL_ARG3:
|
||||
case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
|
||||
case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
|
||||
case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
|
||||
case JSCallMode::CALL_ENTRY:
|
||||
case JSCallMode::CALL_FROM_AOT:
|
||||
case JSCallMode::CALL_GENERATOR:
|
||||
case JSCallMode::CALL_GETTER:
|
||||
case JSCallMode::CALL_SETTER:
|
||||
case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
|
||||
case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
|
||||
return false;
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize,
|
||||
GateRef hotnessCounter, JSCallMode mode, std::initializer_list<GateRef> args,
|
||||
ProfileOperation callback)
|
||||
@ -6126,6 +6099,9 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
|
||||
// 3. call native
|
||||
Bind(&methodIsNative);
|
||||
{
|
||||
if (IsCallModeSupportPGO(mode)) {
|
||||
callback.ProfileNativeCall(func);
|
||||
}
|
||||
GateRef nativeCode = Load(VariableType::NATIVE_POINTER(), method,
|
||||
IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
|
||||
GateRef newTarget = Undefined();
|
||||
@ -6231,7 +6207,7 @@ GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNu
|
||||
// 4. call nonNative
|
||||
Bind(&methodNotNative);
|
||||
|
||||
if (mode != JSCallMode::CALL_GETTER && mode != JSCallMode::CALL_SETTER) {
|
||||
if (IsCallModeSupportPGO(mode)) {
|
||||
callback.ProfileCall(func);
|
||||
}
|
||||
Label funcIsClassConstructor(env);
|
||||
|
@ -632,7 +632,7 @@ public:
|
||||
void SetIndexOfForInIterator(GateRef glue, GateRef iter, GateRef index);
|
||||
void SetKeysOfForInIterator(GateRef glue, GateRef iter, GateRef keys);
|
||||
void SetObjectOfForInIterator(GateRef glue, GateRef iter, GateRef object);
|
||||
void SetCachedHclassOFForInIterator(GateRef glue, GateRef iter, GateRef hclass);
|
||||
void SetCachedHclassOfForInIterator(GateRef glue, GateRef iter, GateRef hclass);
|
||||
void IncreaseInteratorIndex(GateRef glue, GateRef iter, GateRef index);
|
||||
GateRef GetEnumCacheKind(GateRef glue, GateRef enumCache);
|
||||
GateRef GetEmptyArray(GateRef glue);
|
||||
@ -677,6 +677,7 @@ public:
|
||||
GateRef CallGetterHelper(
|
||||
GateRef glue, GateRef receiver, GateRef holder, GateRef accessor, ProfileOperation callback);
|
||||
GateRef ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj);
|
||||
GateRef GetIterator(GateRef glue, GateRef obj, ProfileOperation callback);
|
||||
GateRef JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, GateRef jumpSize, GateRef hotnessCounter,
|
||||
JSCallMode mode, std::initializer_list<GateRef> args,
|
||||
ProfileOperation callback = ProfileOperation());
|
||||
@ -733,6 +734,7 @@ private:
|
||||
const BinaryOperation& intOp, const BinaryOperation& floatOp, ProfileOperation callback);
|
||||
void InitializeArguments();
|
||||
void CheckDetectorName(GateRef glue, GateRef key, Label *fallthrough, Label *slow);
|
||||
bool IsCallModeSupportPGO(JSCallMode mode);
|
||||
|
||||
CallSignature *callSignature_ {nullptr};
|
||||
Environment *env_;
|
||||
|
@ -17,11 +17,12 @@
|
||||
#include "ecmascript/compiler/bytecodes.h"
|
||||
#include "ecmascript/compiler/builtins_lowering.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/enum_conversion.h"
|
||||
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
|
||||
#include "ecmascript/enum_conversion.h"
|
||||
#include "ecmascript/stackmap/llvm_stackmap_parser.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using PGONativeFunctionId = pgo::DumpUtils::PGONativeFunctionId;
|
||||
bool TSHCRLowering::RunTSHCRLowering()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
@ -319,6 +320,10 @@ void TSHCRLowering::Lower(GateRef gate)
|
||||
case EcmaOpcode::TYPEOF_IMM16:
|
||||
LowerTypedTypeOf(gate);
|
||||
break;
|
||||
case EcmaOpcode::GETITERATOR_IMM8:
|
||||
case EcmaOpcode::GETITERATOR_IMM16:
|
||||
LowerGetIterator(gate);
|
||||
break;
|
||||
default:
|
||||
DeleteBytecodeCount(ecmaOpcode);
|
||||
allNonTypedOpCount_++;
|
||||
@ -1201,6 +1206,28 @@ void TSHCRLowering::SpeculateCallBuiltin(GateRef gate, GateRef func, const std::
|
||||
}
|
||||
}
|
||||
|
||||
bool TSHCRLowering::TrySpeculateCallThis0Native(GateRef gate, GateRef func, GateRef thisObj)
|
||||
{
|
||||
PGOSampleType sampleType = acc_.TryGetPGOType(gate);
|
||||
if (sampleType.IsNone()) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(sampleType.GetProfileType().IsNativeFunctionId());
|
||||
int funcIdValue = (-1) * sampleType.GetProfileType().GetId();
|
||||
PGONativeFunctionId funcId = static_cast<PGONativeFunctionId>(funcIdValue);
|
||||
if (funcId == PGONativeFunctionId::INVALID) {
|
||||
return false;
|
||||
}
|
||||
AddProfiling(gate);
|
||||
GateRef funcIdGate = builder_.Int32(funcIdValue);
|
||||
if (!Uncheck()) {
|
||||
builder_.NativeCallTargetCheck(func, funcIdGate);
|
||||
}
|
||||
GateRef result = builder_.TypedCallNative(gate, thisObj, funcIdGate);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
return true;
|
||||
}
|
||||
|
||||
BuiltinsStubCSigns::ID TSHCRLowering::GetBuiltinId(BuiltinTypeId id, GateRef func)
|
||||
{
|
||||
GateType funcType = acc_.GetGateType(func);
|
||||
@ -1449,14 +1476,17 @@ void TSHCRLowering::LowerTypedCallthis0(GateRef gate)
|
||||
{
|
||||
// 2: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 2);
|
||||
GateRef thisObj = acc_.GetValueIn(gate, 0);
|
||||
GateRef func = acc_.GetValueIn(gate, 1);
|
||||
BuiltinsStubCSigns::ID id = GetBuiltinId(BuiltinTypeId::ARRAY, func);
|
||||
if (id == BuiltinsStubCSigns::ID::SORT) {
|
||||
AddProfiling(gate);
|
||||
GateRef thisObj = acc_.GetValueIn(gate, 0);
|
||||
SpeculateCallBuiltin(gate, func, { thisObj }, id, true);
|
||||
return;
|
||||
}
|
||||
if (TrySpeculateCallThis0Native(gate, func, thisObj)) {
|
||||
return;
|
||||
}
|
||||
if (!CanOptimizeAsFastCall(func)) {
|
||||
return;
|
||||
}
|
||||
@ -1659,4 +1689,28 @@ void TSHCRLowering::LowerTypedTypeOf(GateRef gate)
|
||||
GateRef result = builder_.TypedTypeOf(valueType);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
|
||||
}
|
||||
|
||||
void TSHCRLowering::LowerGetIterator(GateRef gate)
|
||||
{
|
||||
PGOSampleType sampleType = acc_.TryGetPGOType(gate);
|
||||
if (sampleType.IsNone()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(sampleType.GetProfileType().IsNativeFunctionId());
|
||||
int iterKindValue = (-1) * sampleType.GetProfileType().GetId();
|
||||
PGONativeFunctionId iterKind = static_cast<PGONativeFunctionId>(iterKindValue);
|
||||
if (iterKind == PGONativeFunctionId::INVALID) {
|
||||
return;
|
||||
}
|
||||
// 1: number of value inputs
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 1);
|
||||
GateRef obj = acc_.GetValueIn(gate, 0);
|
||||
GateRef iterKindGate = builder_.Int32(iterKindValue);
|
||||
AddProfiling(gate);
|
||||
if (!Uncheck()) {
|
||||
builder_.IteratorFunctionCheck(obj, iterKindGate);
|
||||
}
|
||||
GateRef result = builder_.GetFixedIterator(obj, iterKindGate);
|
||||
acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -139,6 +139,7 @@ private:
|
||||
void LowerFastCall(GateRef gate, GateRef func, const std::vector<GateRef> &argsFastCall, bool isNoGC);
|
||||
void LowerCall(GateRef gate, GateRef func, const std::vector<GateRef> &args, bool isNoGC);
|
||||
void LowerTypedTypeOf(GateRef gate);
|
||||
void LowerGetIterator(GateRef gate);
|
||||
GateRef LoadStringByIndex(GateRef receiver, GateRef propKey);
|
||||
GateRef LoadJSArrayByIndex(GateRef receiver, GateRef propKey, ElementsKind kind);
|
||||
GateRef LoadTypedArrayByIndex(GateRef receiver, GateRef propKey);
|
||||
@ -168,6 +169,7 @@ private:
|
||||
void SpeculateCallBuiltin(GateRef gate, GateRef func, const std::vector<GateRef> &args,
|
||||
BuiltinsStubCSigns::ID id, bool isThrow);
|
||||
BuiltinsStubCSigns::ID GetBuiltinId(BuiltinTypeId id, GateRef func);
|
||||
bool TrySpeculateCallThis0Native(GateRef gate, GateRef func, GateRef thisObj);
|
||||
void DeleteConstDataIfNoUser(GateRef gate);
|
||||
|
||||
void AddProfiling(GateRef gate);
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "ecmascript/vtable.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
using PGONativeFunctionId = panda::ecmascript::pgo::DumpUtils::PGONativeFunctionId;
|
||||
GateRef TypeMCRLowering::VisitGate(GateRef gate)
|
||||
{
|
||||
GateRef glue = acc_.GetGlueFromArgList();
|
||||
@ -133,6 +133,18 @@ GateRef TypeMCRLowering::VisitGate(GateRef gate)
|
||||
case OpCode::TYPE_OF:
|
||||
LowerTypeOf(gate, glue);
|
||||
break;
|
||||
case OpCode::ITERATOR_FUNCTION_CHECK:
|
||||
LowerIteratorFunctionCheck(gate, glue);
|
||||
break;
|
||||
case OpCode::GET_FIXED_ITERATOR:
|
||||
LowerGetFixedIterator(gate, glue);
|
||||
break;
|
||||
case OpCode::NATIVE_CALLTARGET_CHECK:
|
||||
LowerNativeCallTargetCheck(gate);
|
||||
break;
|
||||
case OpCode::TYPED_CALL_NATIVE:
|
||||
LowerTypedCallNative(gate, glue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1680,4 +1692,140 @@ void TypeMCRLowering::LowerTypeOf(GateRef gate, GateRef glue)
|
||||
GateRef result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, builder_.GetGlobalConstantOffset(index));
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void TypeMCRLowering::LowerIteratorFunctionCheck(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
GateRef obj = acc_.GetValueIn(gate, 0);
|
||||
GateRef iterKind = acc_.GetValueIn(gate, 1);
|
||||
PGONativeFunctionId iterKindValue = static_cast<PGONativeFunctionId>(acc_.GetConstantValue(iterKind));
|
||||
GateRef check = Circuit::NullGate();
|
||||
switch (iterKindValue) {
|
||||
case PGONativeFunctionId::MAP_PROTO_ITERATOR: {
|
||||
check = builder_.BoolAnd(builder_.TaggedIsJSMap(obj), builder_.IsMapIteratorDetectorValid(glue));
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::SET_PROTO_ITERATOR: {
|
||||
check = builder_.BoolAnd(builder_.TaggedIsJSSet(obj), builder_.IsSetIteratorDetectorValid(glue));
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::STRING_PROTO_ITERATOR: {
|
||||
check = builder_.BoolAnd(builder_.TaggedIsString(obj), builder_.IsStringIteratorDetectorValid(glue));
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::ARRAY_PROTO_ITERATOR: {
|
||||
check = builder_.BoolAnd(builder_.TaggedIsJSArray(obj), builder_.IsArrayIteratorDetectorValid(glue));
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::TYPED_ARRAY_PROTO_ITERATOR: {
|
||||
check =
|
||||
builder_.BoolAnd(builder_.TaggedIsTypedArray(obj), builder_.IsTypedArrayIteratorDetectorValid(glue));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
builder_.DeoptCheck(check, frameState, DeoptType::ITERATORFUNCTIONDISMATCH);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeMCRLowering::LowerGetFixedIterator(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef obj = acc_.GetValueIn(gate, 0);
|
||||
GateRef iterKind = acc_.GetValueIn(gate, 1);
|
||||
PGONativeFunctionId iterKindValue = static_cast<PGONativeFunctionId>(acc_.GetConstantValue(iterKind));
|
||||
GateRef result = Circuit::NullGate();
|
||||
switch (iterKindValue) {
|
||||
case PGONativeFunctionId::MAP_PROTO_ITERATOR: {
|
||||
result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateJSMapIterator, { glue, obj });
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::SET_PROTO_ITERATOR: {
|
||||
result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateJSSetIterator, { glue, obj });
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::STRING_PROTO_ITERATOR: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(CreateStringIterator), { obj }, true);
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::ARRAY_PROTO_ITERATOR: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(NewJSArrayIterator), { obj }, true);
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::TYPED_ARRAY_PROTO_ITERATOR: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(NewJSTypedArrayIterator), { obj }, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void TypeMCRLowering::LowerNativeCallTargetCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
GateRef func = acc_.GetValueIn(gate, 0);
|
||||
GateRef funcId = acc_.GetValueIn(gate, 1);
|
||||
PGONativeFunctionId funcIdValue = static_cast<PGONativeFunctionId>(acc_.GetConstantValue(funcId));
|
||||
size_t index = 0;
|
||||
switch (funcIdValue) {
|
||||
case PGONativeFunctionId::MAP_ITERATOR_PROTO_NEXT: {
|
||||
index = GlobalEnv::MAP_ITERATOR_PROTO_NEXT_INDEX;
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::SET_ITERATOR_PROTO_NEXT: {
|
||||
index = GlobalEnv::SET_ITERATOR_PROTO_NEXT_INDEX;
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::STRING_ITERATOR_PROTO_NEXT: {
|
||||
index = GlobalEnv::STRING_ITERATOR_PROTO_NEXT_INDEX;
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::ARRAY_ITERATOR_PROTO_NEXT: {
|
||||
index = GlobalEnv::ARRAY_ITERATOR_PROTO_NEXT_INDEX;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
GateRef globalEnv = builder_.GetGlobalEnv();
|
||||
GateRef expectFunc = builder_.GetGlobalEnvObj(globalEnv, index);
|
||||
GateRef check = builder_.Equal(func, expectFunc, "check calltarget");
|
||||
builder_.DeoptCheck(check, frameState, DeoptType::NATIVECALLTARGETDISMATCH);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeMCRLowering::LowerTypedCallNative(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef thisObj = acc_.GetValueIn(gate, 0);
|
||||
GateRef funcId = acc_.GetValueIn(gate, 1);
|
||||
PGONativeFunctionId funcIdValue = static_cast<PGONativeFunctionId>(acc_.GetConstantValue(funcId));
|
||||
GateRef result = Circuit::NullGate();
|
||||
switch (funcIdValue) {
|
||||
case PGONativeFunctionId::MAP_ITERATOR_PROTO_NEXT: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(MapIteratorNext), { thisObj }, true);
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::SET_ITERATOR_PROTO_NEXT: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(SetIteratorNext), { thisObj }, true);
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::STRING_ITERATOR_PROTO_NEXT: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(StringIteratorNext), { thisObj }, true);
|
||||
break;
|
||||
}
|
||||
case PGONativeFunctionId::ARRAY_ITERATOR_PROTO_NEXT: {
|
||||
result = LowerCallRuntime(glue, gate, RTSTUB_ID(ArrayIteratorNext), { thisObj }, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -187,6 +187,10 @@ private:
|
||||
void LowerStringEqual(GateRef gate, GateRef glue);
|
||||
void LowerTypeOfCheck(GateRef gate);
|
||||
void LowerTypeOf(GateRef gate, GateRef glue);
|
||||
void LowerIteratorFunctionCheck(GateRef gate, GateRef glue);
|
||||
void LowerGetFixedIterator(GateRef gate, GateRef glue);
|
||||
void LowerNativeCallTargetCheck(GateRef gate);
|
||||
void LowerTypedCallNative(GateRef gate, GateRef glue);
|
||||
|
||||
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
|
||||
bool useLabel = false);
|
||||
|
@ -162,7 +162,11 @@ void TypeRecorder::CreateTypesForPGO(const JSPandaFile *jsPandaFile, const Metho
|
||||
|
||||
EcmaOpcode ecmaOpcode = bytecodes_->GetOpcode(pcOffsets_[bcIdx]);
|
||||
if (jsPandaFile->HasTSTypes(recordName) && Bytecodes::IsCallOp(ecmaOpcode)) {
|
||||
uint32_t callTargetMethodOffset = it->second.GetProfileType().GetId();
|
||||
auto profile = it->second.GetProfileType();
|
||||
if (!profile.IsMethodId()) {
|
||||
return;
|
||||
}
|
||||
uint32_t callTargetMethodOffset = profile.GetId();
|
||||
if (callTargetMethodOffset == 0) {
|
||||
return;
|
||||
}
|
||||
@ -312,7 +316,7 @@ ElementsKind TypeRecorder::GetElementsKind(PGOSampleType type) const
|
||||
return ElementsKind::GENERIC;
|
||||
}
|
||||
|
||||
PGOSampleType TypeRecorder::GetOrUpdatePGOType(int32_t offset) const
|
||||
PGOSampleType TypeRecorder::GetPGOHclassLayoutInfo(int32_t offset) const
|
||||
{
|
||||
if (bcOffsetPGOOpTypeMap_.find(offset) != bcOffsetPGOOpTypeMap_.end()) {
|
||||
const auto iter = bcOffsetPGOOpTypeMap_.at(offset);
|
||||
@ -328,6 +332,39 @@ PGOSampleType TypeRecorder::GetOrUpdatePGOType(int32_t offset) const
|
||||
return PGOSampleType::NoneType();
|
||||
}
|
||||
|
||||
PGOSampleType TypeRecorder::GetPGOTypeInfo(int32_t offset, EcmaOpcode opcode) const
|
||||
{
|
||||
if (bcOffsetPGOOpTypeMap_.find(offset) == bcOffsetPGOOpTypeMap_.end()) {
|
||||
return PGOSampleType::NoneType();
|
||||
}
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::GETITERATOR_IMM8:
|
||||
case EcmaOpcode::GETITERATOR_IMM16:
|
||||
case EcmaOpcode::CALLARG0_IMM8:
|
||||
case EcmaOpcode::CALLARG1_IMM8_V8:
|
||||
case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
|
||||
case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
|
||||
case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::CALLTHIS0_IMM8_V8:
|
||||
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
|
||||
case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
|
||||
case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
|
||||
case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: {
|
||||
const auto sampleType = bcOffsetPGOOpTypeMap_.at(offset);
|
||||
ASSERT(sampleType.IsProfileType());
|
||||
if (!sampleType.GetProfileType().IsNativeFunctionId()) {
|
||||
return PGOSampleType::NoneType();
|
||||
}
|
||||
return sampleType;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return GetPGOHclassLayoutInfo(offset);
|
||||
}
|
||||
|
||||
GateType TypeRecorder::GetCallTargetType(int32_t offset) const
|
||||
{
|
||||
if (bcOffsetCallTargetGtMap_.find(offset) != bcOffsetCallTargetGtMap_.end()) {
|
||||
|
@ -39,12 +39,13 @@ public:
|
||||
|
||||
GateType GetType(const int32_t offset) const;
|
||||
ElementsKind GetElementsKind(PGOSampleType type) const;
|
||||
PGOSampleType GetOrUpdatePGOType(int32_t offset) const;
|
||||
PGOSampleType GetPGOHclassLayoutInfo(int32_t offset) const;
|
||||
PGORWOpType GetRwOpType(int32_t offset) const;
|
||||
std::vector<ElementsKind> LoadElementsKinds(int32_t offset) const;
|
||||
GateType GetArgType(const uint32_t argIndex) const;
|
||||
GateType UpdateType(const int32_t offset, const GateType &type) const;
|
||||
GateType GetCallTargetType(int32_t offset) const;
|
||||
PGOSampleType GetPGOTypeInfo(int32_t offset, EcmaOpcode opcode) const;
|
||||
void BindPgoTypeToGateType(const JSPandaFile *jsPandaFile, TSManager *tsManager,
|
||||
const MethodLiteral *methodLiteral) const;
|
||||
|
||||
|
@ -98,6 +98,7 @@ bool EcmaContext::Initialize()
|
||||
globalEnv_ = globalEnv.GetTaggedValue();
|
||||
Builtins builtins;
|
||||
bool builtinsLazyEnabled = vm_->GetJSOptions().IsWorker() && vm_->GetJSOptions().GetEnableBuiltinsLazy();
|
||||
thread_->SetEnableLazyBuiltins(builtinsLazyEnabled);
|
||||
builtins.Initialize(globalEnv, thread_, builtinsLazyEnabled);
|
||||
|
||||
SetupRegExpResultCache();
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
|
||||
GLOBAL_ENV_FIELDS(GLOBAL_ENV_SLOT)
|
||||
static constexpr uint8_t FIRST_DETECTOR_SYMBOL_INDEX = static_cast<uint8_t>(Field::REPLACE_SYMBOL_INDEX);
|
||||
static constexpr uint8_t LAST_DETECTOR_SYMBOL_INDEX = static_cast<uint8_t>(Field::SPLIT_SYMBOL_INDEX);
|
||||
static constexpr uint8_t LAST_DETECTOR_SYMBOL_INDEX = static_cast<uint8_t>(Field::ITERATOR_SYMBOL_INDEX);
|
||||
static constexpr uint8_t FINAL_INDEX = static_cast<uint8_t>(GlobalEnvField::FINAL_INDEX);
|
||||
#undef GLOBAL_ENV_SLOT
|
||||
|
||||
|
@ -49,9 +49,24 @@
|
||||
V(JSTaggedValue, Float64ArrayFunction, FLOAT64_ARRAY_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, BigInt64ArrayFunction, BIGINT64_ARRAY_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, BigUint64ArrayFunction, BIGUINT64_ARRAY_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, Int8ArrayFunctionPrototype, INT8_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Uint8ArrayFunctionPrototype, UINT8_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Uint8ClampedArrayFunctionPrototype, UINT8_CLAMPED_ARRAY_FUNCTION_PROTO_INDEX) \
|
||||
V(JSTaggedValue, Int16ArrayFunctionPrototype, INT16_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Uint16ArrayFunctionPrototype, UINT16_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Int32ArrayFunctionPrototype, INT32_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Uint32ArrayFunctionPrototype, UINT32_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Float32ArrayFunctionPrototype, FLOAT32_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, Float64ArrayFunctionPrototype, FLOAT64_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, BigInt64ArrayFunctionPrototype, BIGINT64_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, BigUint64ArrayFunctionPrototype, BIGUINT64_ARRAY_FUNCTION_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, ArrayBufferFunction, ARRAY_BUFFER_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, SharedArrayBufferFunction, SHAREDARRAY_BUFFER_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, ArrayProtoValuesFunction, ARRAY_PROTO_VALUES_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, SetProtoValuesFunction, SET_PROTO_VALUES_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, MapProtoEntriesFunction, MAP_PROTO_ENTRIES_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, StringProtoIterFunction, STRING_PROTO_ITER_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, TypedArrayProtoValuesFunction, TYPED_ARRAY_PROTO_VALUES_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, DataViewFunction, DATA_VIEW_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, DataViewPrototype, DATA_VIEW_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, SymbolFunction, SYMBOL_FUNCTION_INDEX) \
|
||||
@ -107,7 +122,6 @@
|
||||
V(JSTaggedValue, HasInstanceFunction, HASINSTANCE_FUNCTION_INDEX) \
|
||||
V(JSTaggedValue, IsConcatSpreadableSymbol, ISCONCAT_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, ToStringTagSymbol, TOSTRINGTAG_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, IteratorSymbol, ITERATOR_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, AsyncIteratorSymbol, ASYNC_ITERATOR_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, MatchSymbol, MATCH_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, MatchAllSymbol, MATCH_All_SYMBOL_INDEX) \
|
||||
@ -129,6 +143,10 @@
|
||||
V(JSTaggedValue, ArrayIteratorPrototype, ARRAY_ITERATOR_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, StringIteratorPrototype, STRING_ITERATOR_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, AsyncFromSyncIteratorPrototype, ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_INDEX) \
|
||||
V(JSTaggedValue, MapIteratorProtoNext, MAP_ITERATOR_PROTO_NEXT_INDEX) \
|
||||
V(JSTaggedValue, SetIteratorProtoNext, SET_ITERATOR_PROTO_NEXT_INDEX) \
|
||||
V(JSTaggedValue, StringIteratorProtoNext, STRING_ITERATOR_PROTO_NEXT_INDEX) \
|
||||
V(JSTaggedValue, ArrayIteratorProtoNext, ARRAY_ITERATOR_PROTO_NEXT_INDEX) \
|
||||
/* SymbolTable *RegisterSymbols */ \
|
||||
V(JSTaggedValue, RegisterSymbols, SYMBOLS_INDEX) \
|
||||
V(JSTaggedValue, ThrowTypeError, THROW_TYPE_ERROR_INDEX) \
|
||||
@ -201,6 +219,7 @@
|
||||
#define GLOBAL_ENV_DETECTOR_SYMBOL_FIELDS(V) \
|
||||
V(JSTaggedValue, ReplaceSymbol, REPLACE_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, SplitSymbol, SPLIT_SYMBOL_INDEX) \
|
||||
V(JSTaggedValue, IteratorSymbol, ITERATOR_SYMBOL_INDEX)
|
||||
|
||||
#define GLOBAL_ENV_FIELDS(V) \
|
||||
GLOBAL_ENV_COMMON_FIELDS(V) \
|
||||
|
@ -30,15 +30,19 @@ JSTaggedValue JSArrayIterator::Next(EcmaRuntimeCallInfo *argv)
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
// 1.Let O be the this value.
|
||||
JSHandle<JSTaggedValue> input(BuiltinsBase::GetThis(argv));
|
||||
JSHandle<JSTaggedValue> thisObj(BuiltinsBase::GetThis(argv));
|
||||
return NextInternal(thread, thisObj);
|
||||
}
|
||||
|
||||
JSTaggedValue JSArrayIterator::NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisObj)
|
||||
{
|
||||
// 2.If Type(O) is not Object, throw a TypeError exception.
|
||||
// 3.If O does not have all of the internal slots of an TaggedArray Iterator Instance (22.1.5.3), throw a TypeError
|
||||
// exception.
|
||||
if (!input->IsJSArrayIterator()) {
|
||||
if (!thisObj->IsJSArrayIterator()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an array iterator", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSArrayIterator> iter(input);
|
||||
JSHandle<JSArrayIterator> iter(thisObj);
|
||||
// 4.Let a be O.[[IteratedArrayLike]].
|
||||
JSHandle<JSTaggedValue> array(thread, iter->GetIteratedArray());
|
||||
JSHandle<JSTaggedValue> undefinedHandle(thread, JSTaggedValue::Undefined());
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
CAST_CHECK(JSArrayIterator, IsJSArrayIterator);
|
||||
|
||||
static JSTaggedValue Next(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisObj);
|
||||
|
||||
static constexpr size_t ITERATED_ARRAY_OFFSET = JSObject::SIZE;
|
||||
ACCESSORS(IteratedArray, ITERATED_ARRAY_OFFSET, NEXT_INDEX_OFFSET)
|
||||
|
@ -29,14 +29,18 @@ JSTaggedValue JSMapIterator::Next(EcmaRuntimeCallInfo *argv)
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
// 1.Let O be the this value
|
||||
JSHandle<JSTaggedValue> input(BuiltinsBase::GetThis(argv));
|
||||
JSHandle<JSTaggedValue> thisObj(BuiltinsBase::GetThis(argv));
|
||||
return NextInternal(thread, thisObj);
|
||||
}
|
||||
|
||||
JSTaggedValue JSMapIterator::NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisObj)
|
||||
{
|
||||
// 3.If O does not have all of the internal slots of a Map Iterator Instance (23.1.5.3), throw a TypeError
|
||||
// exception.
|
||||
if (!input->IsJSMapIterator()) {
|
||||
if (!thisObj->IsJSMapIterator()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not a map iterator", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSMapIterator> iter(input);
|
||||
JSHandle<JSMapIterator> iter(thisObj);
|
||||
iter->Update(thread);
|
||||
JSHandle<JSTaggedValue> undefinedHandle(thread, JSTaggedValue::Undefined());
|
||||
// 4.Let m be O.[[IteratedMap]].
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
IterationKind kind);
|
||||
|
||||
static JSTaggedValue Next(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisObj);
|
||||
void Update(const JSThread *thread);
|
||||
static JSTaggedValue MapIteratorToList(JSThread *thread, JSHandle<JSTaggedValue> &items,
|
||||
JSHandle<JSTaggedValue> &method);
|
||||
|
@ -1250,6 +1250,7 @@ bool JSObject::SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, con
|
||||
JSHClass::NotifyHclassChanged(thread, hclass, newClass);
|
||||
obj->SynchronizedSetClass(*newClass);
|
||||
thread->NotifyStableArrayElementsGuardians(obj, StableArrayChangeKind::PROTO);
|
||||
ObjectOperator::UpdateDetectorOnSetPrototype(thread, obj.GetTaggedValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -30,14 +30,18 @@ JSTaggedValue JSSetIterator::Next(EcmaRuntimeCallInfo *argv)
|
||||
JSThread *thread = argv->GetThread();
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
// 1.If Type(O) is not Object, throw a TypeError exception.
|
||||
JSHandle<JSTaggedValue> input(BuiltinsBase::GetThis(argv));
|
||||
JSHandle<JSTaggedValue> thisObj(BuiltinsBase::GetThis(argv));
|
||||
return NextInternal(thread, thisObj);
|
||||
}
|
||||
|
||||
JSTaggedValue JSSetIterator::NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisObj)
|
||||
{
|
||||
// 3.If O does not have all of the internal slots of a Set Iterator Instance (23.2.5.3), throw a TypeError
|
||||
// exception.
|
||||
if (!input->IsJSSetIterator()) {
|
||||
if (!thisObj->IsJSSetIterator()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not a set iterator", JSTaggedValue::Exception());
|
||||
}
|
||||
JSHandle<JSSetIterator> iter(input);
|
||||
JSHandle<JSSetIterator> iter(thisObj);
|
||||
iter->Update(thread);
|
||||
JSHandle<JSTaggedValue> undefinedHandle(thread, JSTaggedValue::Undefined());
|
||||
// 4.Let s be O.[[IteratedSet]].
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
IterationKind kind);
|
||||
|
||||
static JSTaggedValue Next(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue NextInternal(JSThread *thread, JSHandle<JSTaggedValue> thisObj);
|
||||
|
||||
void Update(const JSThread *thread);
|
||||
|
||||
|
@ -704,6 +704,11 @@ bool JSThread::IsAllContextsInitialized() const
|
||||
return contexts_.back()->IsInitialized();
|
||||
}
|
||||
|
||||
bool JSThread::IsReadyToUpdateDetector() const
|
||||
{
|
||||
return !GetEnableLazyBuiltins() && IsAllContextsInitialized();
|
||||
}
|
||||
|
||||
Area *JSThread::GetOrCreateRegExpCache()
|
||||
{
|
||||
if (regExpCache_ == nullptr) {
|
||||
|
@ -427,6 +427,16 @@ public:
|
||||
return enableStackSourceFile_;
|
||||
}
|
||||
|
||||
void SetEnableLazyBuiltins(bool value)
|
||||
{
|
||||
enableLazyBuiltins_ = value;
|
||||
}
|
||||
|
||||
bool GetEnableLazyBuiltins() const
|
||||
{
|
||||
return enableLazyBuiltins_;
|
||||
}
|
||||
|
||||
static constexpr size_t GetGlueDataOffset()
|
||||
{
|
||||
return MEMBER_OFFSET(JSThread, glueData_);
|
||||
@ -885,6 +895,7 @@ public:
|
||||
|
||||
const GlobalEnvConstants *GetFirstGlobalConst() const;
|
||||
bool IsAllContextsInitialized() const;
|
||||
bool IsReadyToUpdateDetector() const;
|
||||
Area *GetOrCreateRegExpCache();
|
||||
|
||||
private:
|
||||
@ -941,6 +952,7 @@ private:
|
||||
bool isAsmInterpreter_ {false};
|
||||
VmThreadControl *vmThreadControl_ {nullptr};
|
||||
bool enableStackSourceFile_ {true};
|
||||
bool enableLazyBuiltins_ {false};
|
||||
|
||||
// CpuProfiler
|
||||
bool isProfiling_ {false};
|
||||
|
@ -214,6 +214,63 @@ void ObjectOperator::FastAdd(JSThread *thread, const JSTaggedValue &receiver, co
|
||||
op.AddPropertyInternal(value);
|
||||
}
|
||||
|
||||
// static
|
||||
void ObjectOperator::UpdateDetectorOnSetPrototype(const JSThread *thread, JSTaggedValue receiver)
|
||||
{
|
||||
// skip env prepare
|
||||
if (!thread->IsReadyToUpdateDetector()) {
|
||||
return;
|
||||
}
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
if (receiver.IsJSRegExp()) {
|
||||
if (PropertyDetector::IsRegExpReplaceDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateRegExpReplaceDetector(env);
|
||||
}
|
||||
if (PropertyDetector::IsRegExpSplitDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateRegExpSplitDetector(env);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (receiver.IsJSMap() && PropertyDetector::IsMapIteratorDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateMapIteratorDetector(env);
|
||||
return;
|
||||
}
|
||||
if (receiver.IsJSSet() && PropertyDetector::IsSetIteratorDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateSetIteratorDetector(env);
|
||||
return;
|
||||
}
|
||||
if (receiver.IsJSPrimitiveRef() &&
|
||||
JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString() &&
|
||||
PropertyDetector::IsStringIteratorDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateStringIteratorDetector(env);
|
||||
return;
|
||||
}
|
||||
if (receiver.IsJSArray() && PropertyDetector::IsArrayIteratorDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateArrayIteratorDetector(env);
|
||||
return;
|
||||
}
|
||||
if (receiver.IsTypedArray() && PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
|
||||
return;
|
||||
}
|
||||
if (receiver.GetTaggedObject()->GetClass()->IsPrototype() &&
|
||||
(receiver == env->GetTaggedInt8ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint8ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedInt16ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint16ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedInt32ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint32ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedFloat32ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedFloat64ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) &&
|
||||
PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
|
||||
PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectOperator::UpdateDetector()
|
||||
{
|
||||
if (IsElement()) {
|
||||
@ -226,7 +283,7 @@ void ObjectOperator::UpdateDetector()
|
||||
void ObjectOperator::UpdateDetector(const JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
|
||||
{
|
||||
// skip env prepare
|
||||
if (!thread->IsAllContextsInitialized()) {
|
||||
if (!thread->IsReadyToUpdateDetector()) {
|
||||
return;
|
||||
}
|
||||
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
||||
@ -250,6 +307,46 @@ void ObjectOperator::UpdateDetector(const JSThread *thread, JSTaggedValue receiv
|
||||
}
|
||||
PropertyDetector::InvalidateRegExpSplitDetector(env);
|
||||
}
|
||||
} else if (key == env->GetTaggedIteratorSymbol()) {
|
||||
if (receiver.IsJSMap() || receiver == env->GetTaggedMapPrototype()) {
|
||||
if (!PropertyDetector::IsMapIteratorDetectorValid(env)) {
|
||||
return;
|
||||
}
|
||||
PropertyDetector::InvalidateMapIteratorDetector(env);
|
||||
} else if (receiver.IsJSSet() || receiver == env->GetTaggedSetPrototype()) {
|
||||
if (!PropertyDetector::IsSetIteratorDetectorValid(env)) {
|
||||
return;
|
||||
}
|
||||
PropertyDetector::InvalidateSetIteratorDetector(env);
|
||||
} else if ((receiver.IsJSPrimitiveRef() && JSPrimitiveRef::Cast(receiver.GetTaggedObject())->IsString()) ||
|
||||
receiver == env->GetTaggedStringPrototype()) {
|
||||
if (!PropertyDetector::IsStringIteratorDetectorValid(env)) {
|
||||
return;
|
||||
}
|
||||
PropertyDetector::InvalidateStringIteratorDetector(env);
|
||||
} else if (receiver.IsJSArray() || receiver == env->GetTaggedArrayPrototype()) {
|
||||
if (!PropertyDetector::IsArrayIteratorDetectorValid(env)) {
|
||||
return;
|
||||
}
|
||||
PropertyDetector::InvalidateArrayIteratorDetector(env);
|
||||
} else if (receiver.IsTypedArray() ||
|
||||
receiver == env->GetTaggedArrayPrototype() ||
|
||||
receiver == env->GetTaggedInt8ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint8ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint8ClampedArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedInt16ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint16ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedInt32ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedUint32ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedFloat32ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedFloat64ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedBigInt64ArrayFunctionPrototype() ||
|
||||
receiver == env->GetTaggedBigUint64ArrayFunctionPrototype()) {
|
||||
if (!PropertyDetector::IsTypedArrayIteratorDetectorValid(env)) {
|
||||
return;
|
||||
}
|
||||
PropertyDetector::InvalidateTypedArrayIteratorDetector(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
|
||||
void UpdateDetector();
|
||||
static void UpdateDetector(const JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);
|
||||
static void UpdateDetectorOnSetPrototype(const JSThread *thread, JSTaggedValue receiver);
|
||||
static bool IsDetectorName(JSHandle<GlobalEnv> env, JSTaggedValue key);
|
||||
|
||||
NO_COPY_SEMANTIC(ObjectOperator);
|
||||
|
@ -490,6 +490,16 @@ void PGOProfiler::ProfileBytecode(ApEntityId abcId, const CString &recordName, J
|
||||
DumpCreateObject(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, traceId);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::GETITERATOR_IMM8: {
|
||||
uint8_t slotId = READ_INST_8_0();
|
||||
DumpGetIterator(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::GETITERATOR_IMM16: {
|
||||
uint16_t slotId = READ_INST_16_0();
|
||||
DumpGetIterator(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo);
|
||||
break;
|
||||
}
|
||||
case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8:
|
||||
default:
|
||||
break;
|
||||
@ -862,9 +872,27 @@ void PGOProfiler::DumpCall(ApEntityId abcId, const CString &recordName, EntityId
|
||||
if (!slotValue.IsInt()) {
|
||||
return;
|
||||
}
|
||||
auto calleeMethodId = slotValue.GetInt();
|
||||
int calleeMethodId = slotValue.GetInt();
|
||||
ProfileType::Kind kind = (calleeMethodId < 0) ? ProfileType::Kind::NativeFunctionId : ProfileType::Kind::MethodId;
|
||||
PGOSampleType type = PGOSampleType::CreateProfileType(abcId, std::abs(calleeMethodId), kind);
|
||||
ProfileType recordType = GetRecordProfileType(abcId, recordName);
|
||||
recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type);
|
||||
}
|
||||
|
||||
PGOSampleType type = PGOSampleType::CreateProfileType(abcId, calleeMethodId);
|
||||
void PGOProfiler::DumpGetIterator(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
|
||||
uint32_t slotId, ProfileTypeInfo *profileTypeInfo)
|
||||
{
|
||||
if (vm_->GetJSThread()->GetEnableLazyBuiltins()) {
|
||||
return;
|
||||
}
|
||||
JSTaggedValue value = profileTypeInfo->Get(slotId);
|
||||
if (!value.IsInt()) {
|
||||
return;
|
||||
}
|
||||
int iterKind = value.GetInt();
|
||||
ASSERT(iterKind <= 0);
|
||||
ProfileType::Kind pgoKind = ProfileType::Kind::NativeFunctionId;
|
||||
PGOSampleType type = PGOSampleType::CreateProfileType(abcId, std::abs(iterKind), pgoKind);
|
||||
ProfileType recordType = GetRecordProfileType(abcId, recordName);
|
||||
recordInfos_->AddCallTargetType(recordType, methodId, bcOffset, type);
|
||||
}
|
||||
|
@ -123,6 +123,9 @@ private:
|
||||
void DumpCall(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, uint32_t slotId,
|
||||
ProfileTypeInfo *profileTypeInfo);
|
||||
|
||||
void DumpGetIterator(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
|
||||
uint32_t slotId, ProfileTypeInfo *profileTypeInfo);
|
||||
|
||||
void AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
|
||||
JSHClass *hclass, PGOObjKind kind);
|
||||
bool AddObjectInfoByTraceId(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
|
||||
|
@ -40,6 +40,23 @@ public:
|
||||
static const std::string VERSION_HEADER;
|
||||
static const std::string PANDA_FILE_INFO_HEADER;
|
||||
static const uint32_t HEX_FORMAT_WIDTH_FOR_32BITS;
|
||||
|
||||
enum class PGONativeFunctionId : int8_t {
|
||||
// iterator function
|
||||
MAP_PROTO_ITERATOR = -9, // 9: number of registered functions
|
||||
SET_PROTO_ITERATOR,
|
||||
STRING_PROTO_ITERATOR,
|
||||
ARRAY_PROTO_ITERATOR,
|
||||
TYPED_ARRAY_PROTO_ITERATOR,
|
||||
// next function
|
||||
MAP_ITERATOR_PROTO_NEXT,
|
||||
SET_ITERATOR_PROTO_NEXT,
|
||||
STRING_ITERATOR_PROTO_NEXT,
|
||||
ARRAY_ITERATOR_PROTO_NEXT,
|
||||
LAST,
|
||||
INVALID = 0, // keep the same with method offset 0 to reuse calltarget offset field in pgo
|
||||
};
|
||||
static_assert(PGONativeFunctionId::LAST == PGONativeFunctionId::INVALID);
|
||||
};
|
||||
|
||||
class ApNameUtils {
|
||||
|
@ -41,6 +41,8 @@ public:
|
||||
ElementId,
|
||||
BuiltinsId,
|
||||
LegacyKind = BuiltinsId,
|
||||
MethodId, // method offset of js function
|
||||
NativeFunctionId, // function index of registered function
|
||||
LocalRecordId,
|
||||
ModuleRecordId,
|
||||
TotalKinds,
|
||||
@ -97,6 +99,16 @@ public:
|
||||
return GetKind() == Kind::ElementId;
|
||||
}
|
||||
|
||||
bool IsMethodId() const
|
||||
{
|
||||
return GetKind() == Kind::MethodId;
|
||||
}
|
||||
|
||||
bool IsNativeFunctionId() const
|
||||
{
|
||||
return GetKind() == Kind::NativeFunctionId;
|
||||
}
|
||||
|
||||
uint32_t GetId() const
|
||||
{
|
||||
return IdBits::Decode(type_);
|
||||
|
@ -194,10 +194,13 @@ public:
|
||||
PGOSampleTemplate CombineCallTargetType(PGOSampleTemplate type)
|
||||
{
|
||||
ASSERT(type_.index() == 1);
|
||||
ProfileType::Kind oldKind = GetProfileType().GetKind();
|
||||
ProfileType::Kind newKind = type.GetProfileType().GetKind();
|
||||
uint32_t oldMethodId = GetProfileType().GetId();
|
||||
uint32_t newMethodId = type.GetProfileType().GetId();
|
||||
// If we have recorded a valid method if before, invalidate it.
|
||||
if ((oldMethodId != newMethodId) && (oldMethodId != 0)) {
|
||||
if ((oldMethodId != 0) &&
|
||||
((oldKind != newKind) || (oldMethodId != newMethodId))) {
|
||||
type_ = ProfileType::PROFILE_TYPE_NONE;
|
||||
}
|
||||
return *this;
|
||||
|
@ -25,9 +25,14 @@ namespace ecmascript {
|
||||
class GlobalEnv;
|
||||
class PropertyDetector {
|
||||
public:
|
||||
#define GLOBAL_ENV_DETECTOR_FIELDS(V) \
|
||||
V(JSTaggedValue, RegExpReplaceDetector, REGEXP_REPLACE_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, RegExpSplitDetector, REGEXP_SPLIT_DETECTOR_INDEX)
|
||||
#define GLOBAL_ENV_DETECTOR_FIELDS(V) \
|
||||
V(JSTaggedValue, RegExpReplaceDetector, REGEXP_REPLACE_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, RegExpSplitDetector, REGEXP_SPLIT_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, MapIteratorDetector, MAP_ITERATOR_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, SetIteratorDetector, SET_ITERATOR_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, StringIteratorDetector, STRING_ITERATOR_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, ArrayIteratorDetector, ARRAY_ITERATOR_DETECTOR_INDEX) \
|
||||
V(JSTaggedValue, TypedArrayIteratorDetector, TYPED_ARRAY_ITERATOR_DETECTOR_INDEX)
|
||||
|
||||
#define DECLARE_DETECTOR(type, name, index) \
|
||||
static inline bool Is##name##Valid(JSHandle<GlobalEnv> env); \
|
||||
@ -35,9 +40,10 @@ public:
|
||||
GLOBAL_ENV_DETECTOR_FIELDS(DECLARE_DETECTOR)
|
||||
#undef DECLARE_DETECTOR
|
||||
|
||||
#define DETECTOR_SYMBOL_LIST(V) \
|
||||
V(ReplaceSymbol, "Symbol.replace", replace) \
|
||||
V(SplitSymbol, "Symbol.split", split )
|
||||
#define DETECTOR_SYMBOL_LIST(V) \
|
||||
V(ReplaceSymbol, "Symbol.replace", replace ) \
|
||||
V(SplitSymbol, "Symbol.split", split ) \
|
||||
V(IteratorSymbol, "Symbol.iterator", iterator)
|
||||
};
|
||||
|
||||
} // namespace ecmascript
|
||||
|
@ -116,6 +116,13 @@ namespace panda::ecmascript {
|
||||
V(Copyrestargs) \
|
||||
V(Trystobjprop) \
|
||||
V(GetTemplateObject) \
|
||||
V(CreateStringIterator) \
|
||||
V(NewJSArrayIterator) \
|
||||
V(NewJSTypedArrayIterator) \
|
||||
V(MapIteratorNext) \
|
||||
V(SetIteratorNext) \
|
||||
V(StringIteratorNext) \
|
||||
V(ArrayIteratorNext) \
|
||||
V(GetIterator) \
|
||||
V(GetAsyncIterator) \
|
||||
V(ThrowIfNotObject) \
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "ecmascript/base/fast_json_stringifier.h"
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/base/string_helper.h"
|
||||
#include "ecmascript/base/typed_array_helper.h"
|
||||
#include "ecmascript/builtins/builtins_string_iterator.h"
|
||||
#include "ecmascript/compiler/builtins/containers_stub_builder.h"
|
||||
#include "ecmascript/compiler/call_signature.h"
|
||||
#include "ecmascript/compiler/ecma_opcode_des.h"
|
||||
@ -39,11 +41,15 @@
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "ecmascript/interpreter/interpreter_assembly.h"
|
||||
#include "ecmascript/js_api/js_api_arraylist.h"
|
||||
#include "ecmascript/js_array_iterator.h"
|
||||
#include "ecmascript/js_date.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_map_iterator.h"
|
||||
#include "ecmascript/js_object.h"
|
||||
#include "ecmascript/js_primitive_ref.h"
|
||||
#include "ecmascript/js_proxy.h"
|
||||
#include "ecmascript/js_set_iterator.h"
|
||||
#include "ecmascript/js_string_iterator.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/js_typed_array.h"
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
@ -635,6 +641,60 @@ DEF_RUNTIME_STUBS(GetTemplateObject)
|
||||
return RuntimeGetTemplateObject(thread, literal).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(CreateStringIterator)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(CreateStringIterator);
|
||||
JSHandle<JSTaggedValue> obj = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
return JSStringIterator::CreateStringIterator(thread, JSHandle<EcmaString>(obj)).GetTaggedValue().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(NewJSArrayIterator)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(NewJSArrayIterator);
|
||||
JSHandle<JSObject> obj = GetHArg<JSObject>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
return factory->NewJSArrayIterator(obj, IterationKind::VALUE).GetTaggedValue().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(NewJSTypedArrayIterator)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(NewJSArrayIterator);
|
||||
JSHandle<JSTaggedValue> obj = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
base::TypedArrayHelper::ValidateTypedArray(thread, obj);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData());
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSArrayIterator> iter(factory->NewJSArrayIterator(JSHandle<JSObject>(obj), IterationKind::VALUE));
|
||||
return iter.GetTaggedValue().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(MapIteratorNext)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(MapIteratorNext);
|
||||
JSHandle<JSTaggedValue> thisObj = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
return JSMapIterator::NextInternal(thread, thisObj).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(SetIteratorNext)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(SetIteratorNext);
|
||||
JSHandle<JSTaggedValue> thisObj = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
return JSSetIterator::NextInternal(thread, thisObj).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(StringIteratorNext)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(StringIteratorNext);
|
||||
JSHandle<JSTaggedValue> thisObj = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
return builtins::BuiltinsStringIterator::NextInternal(thread, thisObj).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(ArrayIteratorNext)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(ArrayIteratorNext);
|
||||
JSHandle<JSTaggedValue> thisObj = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
return JSArrayIterator::NextInternal(thread, thisObj).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(GetNextPropName)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(GetNextPropName);
|
||||
|
@ -176,6 +176,13 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(CreateGeneratorObj) \
|
||||
V(ThrowConstAssignment) \
|
||||
V(GetTemplateObject) \
|
||||
V(CreateStringIterator) \
|
||||
V(NewJSArrayIterator) \
|
||||
V(NewJSTypedArrayIterator) \
|
||||
V(MapIteratorNext) \
|
||||
V(SetIteratorNext) \
|
||||
V(StringIteratorNext) \
|
||||
V(ArrayIteratorNext) \
|
||||
V(GetNextPropName) \
|
||||
V(GetNextPropNameSlowpath) \
|
||||
V(ThrowIfNotObject) \
|
||||
|
@ -108,6 +108,12 @@ group("ark_aot_ts_test") {
|
||||
"exp",
|
||||
"fast_call_builtins",
|
||||
"frame_states",
|
||||
"forin_delete_property",
|
||||
"forin_dictionary_mode",
|
||||
"forin_empty_prototype",
|
||||
"forin_enum_cache",
|
||||
"forin_non_empty_prototype",
|
||||
"forin_special_object",
|
||||
"forloop",
|
||||
"framestatesasync",
|
||||
"framestatesphi",
|
||||
@ -166,6 +172,13 @@ group("ark_aot_ts_test") {
|
||||
"or",
|
||||
"pgo_call",
|
||||
"pgo_class_operation",
|
||||
"pgo_forof_array",
|
||||
"pgo_forof_map",
|
||||
"pgo_forof_modify_iterator",
|
||||
"pgo_forof_set",
|
||||
"pgo_forof_set_prototype",
|
||||
"pgo_forof_string",
|
||||
"pgo_forof_typed_array",
|
||||
"pgo_objectliteral_operation",
|
||||
"pgo_call_deopt",
|
||||
"poplexenv",
|
||||
|
18
test/aottest/forin_delete_property/BUILD.gn
Normal file
18
test/aottest/forin_delete_property/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 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_test_action("forin_delete_property") {
|
||||
deps = []
|
||||
}
|
23
test/aottest/forin_delete_property/expect_output.txt
Normal file
23
test/aottest/forin_delete_property/expect_output.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
a
|
||||
b
|
||||
===============
|
||||
a
|
||||
b
|
||||
1
|
||||
===============
|
||||
b
|
||||
1
|
||||
a
|
53
test/aottest/forin_delete_property/forin_delete_property.ts
Normal file
53
test/aottest/forin_delete_property/forin_delete_property.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:forin_delete_property
|
||||
* @tc.desc:test forin_delete_property
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI89SMQ
|
||||
*/
|
||||
|
||||
declare function print(str:any):string;
|
||||
// fast path
|
||||
let fast = {"a":1}
|
||||
fast.b = "a"
|
||||
for (let i in fast) {
|
||||
print(i)
|
||||
delete fast.a
|
||||
}
|
||||
print("===============")
|
||||
// slow path
|
||||
let parent = {
|
||||
"c": undefined,
|
||||
"a": 1,
|
||||
"b": undefined,
|
||||
1: 2
|
||||
}
|
||||
let own = {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
}
|
||||
own.__proto__ = parent
|
||||
|
||||
for (let i in own) {
|
||||
delete own.a
|
||||
print(i)
|
||||
delete parent.c
|
||||
}
|
||||
print("===============")
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
18
test/aottest/forin_dictionary_mode/BUILD.gn
Normal file
18
test/aottest/forin_dictionary_mode/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 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_test_action("forin_dictionary_mode") {
|
||||
deps = []
|
||||
}
|
21
test/aottest/forin_dictionary_mode/expect_output.txt
Normal file
21
test/aottest/forin_dictionary_mode/expect_output.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
1
|
||||
c
|
||||
b
|
||||
=============
|
||||
1
|
||||
a
|
||||
c
|
||||
b
|
47
test/aottest/forin_dictionary_mode/forin_dictionary_mode.ts
Normal file
47
test/aottest/forin_dictionary_mode/forin_dictionary_mode.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:forin_dictionary_mode
|
||||
* @tc.desc:test forin_dictionary_mode
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI89SMQ
|
||||
*/
|
||||
|
||||
declare function print(str:any):string;
|
||||
|
||||
let parent = {
|
||||
"c": undefined,
|
||||
"a": 1,
|
||||
"b": undefined,
|
||||
1: 2
|
||||
}
|
||||
delete parent.a
|
||||
|
||||
let own = {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
1: 2,
|
||||
}
|
||||
delete own.b
|
||||
own.__proto__ = parent
|
||||
|
||||
for (let i in parent) {
|
||||
print(i)
|
||||
}
|
||||
print("=============")
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
18
test/aottest/forin_empty_prototype/BUILD.gn
Normal file
18
test/aottest/forin_empty_prototype/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 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_test_action("forin_empty_prototype") {
|
||||
deps = []
|
||||
}
|
23
test/aottest/forin_empty_prototype/expect_output.txt
Normal file
23
test/aottest/forin_empty_prototype/expect_output.txt
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
a
|
||||
b
|
||||
a
|
||||
b
|
||||
a
|
||||
b
|
||||
c
|
||||
2
|
||||
4
|
||||
s
|
49
test/aottest/forin_empty_prototype/forin_empty_prototype.ts
Normal file
49
test/aottest/forin_empty_prototype/forin_empty_prototype.ts
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:forin_empty_prototype
|
||||
* @tc.desc:test forin_empty_prototype
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI89SMQ
|
||||
*/
|
||||
|
||||
declare function print(str:any):string;
|
||||
|
||||
// no elements
|
||||
let fast = {"a":1}
|
||||
fast.b = "a"
|
||||
for (let i in fast) {
|
||||
print(i)
|
||||
}
|
||||
|
||||
// use enum cache
|
||||
for (let i in fast) {
|
||||
print(i)
|
||||
}
|
||||
|
||||
fast.c = 1
|
||||
// invalidate enum cache
|
||||
for (let i in fast) {
|
||||
print(i)
|
||||
}
|
||||
|
||||
// has elements
|
||||
let slow = {"s":222}
|
||||
slow[2] = "aa"
|
||||
slow[4] = 1
|
||||
for (let i in slow) {
|
||||
print(i)
|
||||
}
|
18
test/aottest/forin_enum_cache/BUILD.gn
Normal file
18
test/aottest/forin_enum_cache/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 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_test_action("forin_enum_cache") {
|
||||
deps = []
|
||||
}
|
34
test/aottest/forin_enum_cache/expect_output.txt
Normal file
34
test/aottest/forin_enum_cache/expect_output.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
===generate enum cache===
|
||||
a
|
||||
b
|
||||
c
|
||||
===use enum cache===
|
||||
a
|
||||
b
|
||||
c
|
||||
===re-generate enum cache===
|
||||
a
|
||||
b
|
||||
c
|
||||
e
|
||||
===change attribute===
|
||||
a
|
||||
b
|
||||
c
|
||||
===delete property===
|
||||
a
|
||||
b
|
||||
c
|
71
test/aottest/forin_enum_cache/forin_enum_cache.ts
Normal file
71
test/aottest/forin_enum_cache/forin_enum_cache.ts
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:forin_enum_cache
|
||||
* @tc.desc:test forin_enum_cache
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI89SMQ
|
||||
*/
|
||||
|
||||
declare function print(str:any):string;
|
||||
|
||||
let grandparent = {}
|
||||
let parent = {
|
||||
"c": undefined,
|
||||
"a": 1,
|
||||
"b": undefined,
|
||||
}
|
||||
let own = {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
}
|
||||
own.__proto__ = parent
|
||||
parent.__proto__ = grandparent
|
||||
|
||||
// generate enum cache
|
||||
print("===generate enum cache===")
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
||||
// use enum cache
|
||||
print("===use enum cache===")
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
||||
// invalid enum cache and re-generate enum cache
|
||||
print("===re-generate enum cache===")
|
||||
grandparent['e'] = 1
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
||||
// change attribute
|
||||
print("===change attribute===")
|
||||
Object.defineProperty(grandparent, "e", {
|
||||
configurable:true,
|
||||
enumerable:false,
|
||||
value:"ggg",
|
||||
writable:true
|
||||
})
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
||||
// delete property
|
||||
print("===delete property===")
|
||||
grandparent['f'] = 1
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
delete grandparent['f']
|
||||
}
|
18
test/aottest/forin_non_empty_prototype/BUILD.gn
Normal file
18
test/aottest/forin_non_empty_prototype/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 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_test_action("forin_non_empty_prototype") {
|
||||
deps = []
|
||||
}
|
19
test/aottest/forin_non_empty_prototype/expect_output.txt
Normal file
19
test/aottest/forin_non_empty_prototype/expect_output.txt
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
1
|
||||
a
|
||||
b
|
||||
c
|
||||
2
|
||||
d
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:forin_non_empty_prototype
|
||||
* @tc.desc:test forin_non_empty_prototype
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI89SMQ
|
||||
*/
|
||||
|
||||
declare function print(str:any):string;
|
||||
|
||||
let grandparent = {
|
||||
"a": 1,
|
||||
"d": undefined,
|
||||
1: 2,
|
||||
2: 3
|
||||
}
|
||||
|
||||
let parent = {
|
||||
"c": undefined,
|
||||
"a": 1,
|
||||
"b": undefined,
|
||||
1: 2
|
||||
}
|
||||
|
||||
let own = {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
1: 2,
|
||||
}
|
||||
own.__proto__ = parent
|
||||
parent.__proto__ = grandparent
|
||||
|
||||
for (let i in own) {
|
||||
print(i)
|
||||
}
|
18
test/aottest/forin_special_object/BUILD.gn
Normal file
18
test/aottest/forin_special_object/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 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_test_action("forin_special_object") {
|
||||
deps = []
|
||||
}
|
39
test/aottest/forin_special_object/expect_output.txt
Normal file
39
test/aottest/forin_special_object/expect_output.txt
Normal file
@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
2
|
||||
8
|
||||
a
|
||||
0
|
||||
1
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
9
|
||||
===============
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
===============
|
||||
_secret
|
||||
test
|
||||
eyeCount
|
58
test/aottest/forin_special_object/forin_special_object.ts
Normal file
58
test/aottest/forin_special_object/forin_special_object.ts
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:forin_specail_object
|
||||
* @tc.desc:test forin_specail_object
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI89SMQ
|
||||
*/
|
||||
|
||||
declare function print(str:any):string;
|
||||
|
||||
var arr = new Array(10)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
arr[i] = i;
|
||||
}
|
||||
let parent = new Int8Array(arr);
|
||||
let self = {
|
||||
2: "b",
|
||||
"a": {},
|
||||
8: []
|
||||
}
|
||||
self.__proto__ = parent
|
||||
for (let i in self) {
|
||||
print(i)
|
||||
}
|
||||
print("===============")
|
||||
for (let i in parent) {
|
||||
print(i)
|
||||
}
|
||||
print("===============")
|
||||
const targetObj = {
|
||||
_secret: 'easily scared',
|
||||
test: "ss",
|
||||
eyeCount: 4
|
||||
};
|
||||
|
||||
const proxy_has = new Proxy(targetObj, {
|
||||
has: (target, key) => {
|
||||
return key in target;
|
||||
}
|
||||
})
|
||||
|
||||
for (const key in proxy_has) {
|
||||
print(key);
|
||||
}
|
22
test/aottest/pgo_forof_array/BUILD.gn
Normal file
22
test/aottest/pgo_forof_array/BUILD.gn
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2023 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_test_action("pgo_forof_array") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
is_enable_trace_deopt = true
|
||||
log_option = " --log-info=trace"
|
||||
}
|
14
test/aottest/pgo_forof_array/expect_output.txt
Normal file
14
test/aottest/pgo_forof_array/expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
600
|
14
test/aottest/pgo_forof_array/pgo_expect_output.txt
Normal file
14
test/aottest/pgo_forof_array/pgo_expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
600
|
32
test/aottest/pgo_forof_array/pgo_forof_array.ts
Normal file
32
test/aottest/pgo_forof_array/pgo_forof_array.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
declare function print(arg:any):string;
|
||||
|
||||
let r = 0;
|
||||
function foo(obj) {
|
||||
for (let value of obj) {
|
||||
r += value
|
||||
}
|
||||
for (let value of obj) {
|
||||
r += value
|
||||
}
|
||||
}
|
||||
let obj1 = new Array(1, 2, 3)
|
||||
for (let i = 0; i < 50; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print(r)
|
22
test/aottest/pgo_forof_map/BUILD.gn
Normal file
22
test/aottest/pgo_forof_map/BUILD.gn
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2023 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_test_action("pgo_forof_map") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
is_enable_trace_deopt = true
|
||||
log_option = " --log-info=trace"
|
||||
}
|
24
test/aottest/pgo_forof_map/expect_output.txt
Normal file
24
test/aottest/pgo_forof_map/expect_output.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
600
|
24
test/aottest/pgo_forof_map/pgo_expect_output.txt
Normal file
24
test/aottest/pgo_forof_map/pgo_expect_output.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
600
|
46
test/aottest/pgo_forof_map/pgo_forof_map.ts
Normal file
46
test/aottest/pgo_forof_map/pgo_forof_map.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
declare function print(arg:any):string;
|
||||
|
||||
let r = 0
|
||||
function foo(obj) {
|
||||
for (let value of obj) {
|
||||
if (typeof value[0] == "string"){
|
||||
r += value[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
let p1 = new Array("apples", 1)
|
||||
let p2 = new Array("bananas", 2)
|
||||
let p3 = new Array("oranges", 3)
|
||||
let a = new Array(p1, p2, p3)
|
||||
let obj1 = new Map(a)
|
||||
for (let i = 0; i < 100; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
Object.prototype[Symbol.iterator] = { "next": function () { return {"value":1, "done":true} } }
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
print(r)
|
22
test/aottest/pgo_forof_modify_iterator/BUILD.gn
Normal file
22
test/aottest/pgo_forof_modify_iterator/BUILD.gn
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2023 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_test_action("pgo_forof_modify_iterator") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
is_enable_trace_deopt = true
|
||||
log_option = " --log-info=trace"
|
||||
}
|
24
test/aottest/pgo_forof_modify_iterator/expect_output.txt
Normal file
24
test/aottest/pgo_forof_modify_iterator/expect_output.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
true
|
||||
600
|
24
test/aottest/pgo_forof_modify_iterator/pgo_expect_output.txt
Normal file
24
test/aottest/pgo_forof_modify_iterator/pgo_expect_output.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
true
|
||||
600
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
declare function print(arg:any):string;
|
||||
|
||||
let r = 0;
|
||||
function foo(obj) {
|
||||
for (let value of obj) {
|
||||
r += value
|
||||
}
|
||||
}
|
||||
// let obj1 = [1,2,3]
|
||||
let obj1 = new Array(1, 2, 3)
|
||||
for (let i = 0; i < 100; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
Array.prototype[Symbol.iterator] = { "next": function () { return {"value":1, "done":true} } }
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
foo(obj1)
|
||||
print(r)
|
22
test/aottest/pgo_forof_set/BUILD.gn
Normal file
22
test/aottest/pgo_forof_set/BUILD.gn
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2023 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_test_action("pgo_forof_set") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
is_enable_trace_deopt = true
|
||||
log_option = " --log-info=trace"
|
||||
}
|
14
test/aottest/pgo_forof_set/expect_output.txt
Normal file
14
test/aottest/pgo_forof_set/expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
600
|
14
test/aottest/pgo_forof_set/pgo_expect_output.txt
Normal file
14
test/aottest/pgo_forof_set/pgo_expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
600
|
30
test/aottest/pgo_forof_set/pgo_forof_set.ts
Normal file
30
test/aottest/pgo_forof_set/pgo_forof_set.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
declare function print(arg:any):string;
|
||||
|
||||
let r = 0;
|
||||
function foo(obj) {
|
||||
for (let value of obj) {
|
||||
r += value
|
||||
}
|
||||
}
|
||||
let a = new Array(1, 2, 3)
|
||||
let obj1 = new Set(a)
|
||||
for (let i = 0; i < 100; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print(r)
|
22
test/aottest/pgo_forof_set_prototype/BUILD.gn
Normal file
22
test/aottest/pgo_forof_set_prototype/BUILD.gn
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2023 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_test_action("pgo_forof_set_prototype") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_pgo = true
|
||||
is_enable_trace_deopt = true
|
||||
log_option = " --log-info=trace"
|
||||
}
|
62
test/aottest/pgo_forof_set_prototype/expect_output.txt
Normal file
62
test/aottest/pgo_forof_set_prototype/expect_output.txt
Normal file
@ -0,0 +1,62 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
before change
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
after change raw string.__proto__
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
after change string.__proto__
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
after change array.__proto__
|
||||
true
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
after change map.__proto__
|
||||
false
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
after change set.__proto__
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
true
|
||||
after change Uint8Array.prototype.__proto__
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
after change obj(typed array).__proto__
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
601
|
62
test/aottest/pgo_forof_set_prototype/pgo_expect_output.txt
Normal file
62
test/aottest/pgo_forof_set_prototype/pgo_expect_output.txt
Normal file
@ -0,0 +1,62 @@
|
||||
# Copyright (c) 2023 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.
|
||||
|
||||
before change
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
after change raw string.__proto__
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
after change string.__proto__
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
after change array.__proto__
|
||||
true
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
after change map.__proto__
|
||||
false
|
||||
true
|
||||
false
|
||||
false
|
||||
true
|
||||
after change set.__proto__
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
true
|
||||
after change Uint8Array.prototype.__proto__
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
after change obj(typed array).__proto__
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
601
|
112
test/aottest/pgo_forof_set_prototype/pgo_forof_set_prototype.ts
Normal file
112
test/aottest/pgo_forof_set_prototype/pgo_forof_set_prototype.ts
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
declare function print(arg:any):string;
|
||||
|
||||
let r = 0;
|
||||
function foo(obj) {
|
||||
for (let value of obj) {
|
||||
r += value
|
||||
}
|
||||
}
|
||||
let a = new Array(1, 2, 3)
|
||||
let obj1 = new Uint8Array(a);
|
||||
for (let i = 0; i < 100; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print("before change")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
let obj2 = "123";
|
||||
obj2.__proto__ = {}
|
||||
print("after change raw string.__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
let obj3 = new String("123")
|
||||
obj3.__proto__ = {}
|
||||
print("after change string.__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
let obj4 = new Array(1, 2, 3)
|
||||
obj4.__proto__ = {}
|
||||
print("after change array.__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
let temp = new Array()
|
||||
let obj5 = new Map(temp)
|
||||
obj5.__proto__ = {}
|
||||
print("after change map.__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
let obj6 = new Set(temp)
|
||||
obj6.__proto__ = {}
|
||||
print("after change set.__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
let index = 0
|
||||
Uint8Array.prototype.__proto__ = {[Symbol.iterator] : { "next": function () {
|
||||
if (index == 1) {
|
||||
return {"value":1, "done":true}
|
||||
} else {
|
||||
index++
|
||||
return {"value":1, "done":false}
|
||||
}
|
||||
}}}
|
||||
for (let i = 0; i < 100; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print("after change Uint8Array.prototype.__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
|
||||
obj1.__proto__ = {[Symbol.iterator] : { "next": function () { return {"value":1, "done":true} } }}
|
||||
for (let i = 0; i < 100; i++) {
|
||||
foo(obj1)
|
||||
}
|
||||
print("after change obj(typed array).__proto__")
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Map"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Set"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("Array"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("String"))
|
||||
print(ArkTools.isSymbolIteratorDetectorValid("TypedArray"))
|
||||
print(r)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user