mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
!8328 Fix deopt of hclass
Merge pull request !8328 from xing-yunhao/fix_deopt_hclass
This commit is contained in:
commit
a65dfdea3a
@ -22,10 +22,10 @@
|
||||
#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
|
||||
#include "ecmascript/compiler/aot_file/an_file_info.h"
|
||||
#include "ecmascript/compiler/aot_file/aot_file_info.h"
|
||||
#include "ecmascript/compiler/aot_snapshot/snapshot_constantpool_data.h"
|
||||
#include "ecmascript/compiler/aot_file/binary_buffer_parser.h"
|
||||
#include "ecmascript/compiler/aot_file/module_section_des.h"
|
||||
#include "ecmascript/compiler/aot_file/stub_file_info.h"
|
||||
#include "ecmascript/compiler/aot_snapshot/snapshot_constantpool_data.h"
|
||||
#include "ecmascript/compiler/binary_section.h"
|
||||
#include "ecmascript/deoptimizer/calleeReg.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
@ -42,18 +42,20 @@ namespace kungfu {
|
||||
class ArkStackMapParser;
|
||||
} // namespace kungfu
|
||||
|
||||
/* AOTLiteralInfo (TaggedArray)
|
||||
* +--------------------------------------------------+------
|
||||
* | AOT Function CodeEntry of 1st Method | ^
|
||||
* | (NO_FUNC_ENTRY_VALUE if NoMethodEntry) | |
|
||||
* | ... | MethodsCache
|
||||
* | ... | |
|
||||
* | AOT Function CodeEntry of nth Method | v
|
||||
* +--------------------------------------------------+------
|
||||
* | AOT Instance Hclass (IHC) (JSTaggedValue) |
|
||||
* | AOT Constructor Hclass (CHC) (JSTaggedValue) |
|
||||
* +--------------------------------------------------+
|
||||
*
|
||||
/* AOTLiteralInfo
|
||||
* +-----------------------------------+----
|
||||
* | ... | ^
|
||||
* | ... | |
|
||||
* | cache(store function entry index) | AOT Function Entry Index, if its value is -1,
|
||||
* | ... | means the function has not been compiled with AOT.
|
||||
* | ... | v
|
||||
* +-----------------------------------+----
|
||||
* | Literal Type | JSTaggedValue(int32_t)
|
||||
* +-----------------------------------+----
|
||||
* | AOT Instance Hclass (IHC) | JSTaggedValue(HClass)
|
||||
* +-----------------------------------+----
|
||||
* | AOT Constructor Hclass (CHC) | JSTaggedValue(HClass)
|
||||
* +-----------------------------------+----
|
||||
*/
|
||||
class AOTLiteralInfo : public TaggedArray {
|
||||
public:
|
||||
@ -66,10 +68,10 @@ public:
|
||||
static constexpr int32_t METHOD_LITERAL_TYPE = 1;
|
||||
static constexpr int32_t INVALID_LITERAL_TYPE = 0;
|
||||
|
||||
static AOTLiteralInfo *Cast(TaggedObject *object)
|
||||
static AOTLiteralInfo* Cast(TaggedObject* object)
|
||||
{
|
||||
ASSERT(JSTaggedValue(object).IsTaggedArray());
|
||||
return static_cast<AOTLiteralInfo *>(object);
|
||||
return static_cast<AOTLiteralInfo*>(object);
|
||||
}
|
||||
|
||||
static size_t ComputeSize(uint32_t cacheSize)
|
||||
@ -121,8 +123,8 @@ public:
|
||||
{
|
||||
return Get(index);
|
||||
}
|
||||
private:
|
||||
|
||||
private:
|
||||
inline size_t GetIhcOffset() const
|
||||
{
|
||||
return JSTaggedValue::TaggedTypeSize() * (GetLength() - AOT_IHC_INDEX);
|
||||
@ -141,7 +143,7 @@ private:
|
||||
|
||||
class AOTFileManager {
|
||||
public:
|
||||
explicit AOTFileManager(EcmaVM *vm);
|
||||
explicit AOTFileManager(EcmaVM* vm);
|
||||
virtual ~AOTFileManager();
|
||||
|
||||
static constexpr char FILE_EXTENSION_AN[] = ".an";
|
||||
@ -152,36 +154,40 @@ public:
|
||||
static void SetJsAotReader(JsAotReaderCallback cb);
|
||||
static JsAotReaderCallback GetJsAotReader();
|
||||
#endif
|
||||
void LoadStubFile(const std::string &fileName);
|
||||
static bool LoadAnFile(const std::string &fileName);
|
||||
void LoadStubFile(const std::string& fileName);
|
||||
static bool LoadAnFile(const std::string& fileName);
|
||||
static AOTFileInfo::CallSiteInfo CalCallSiteInfo(uintptr_t retAddr);
|
||||
static bool TryReadLock();
|
||||
static bool InsideStub(uintptr_t pc);
|
||||
static bool InsideAOT(uintptr_t pc);
|
||||
bool IsEnableAOT() const;
|
||||
void Iterate(const RootVisitor &v);
|
||||
void Iterate(const RootVisitor& v);
|
||||
|
||||
const std::shared_ptr<AnFileInfo> GetAnFileInfo(const JSPandaFile *jsPandaFile) const;
|
||||
bool IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry) const;
|
||||
const std::shared_ptr<AnFileInfo> GetAnFileInfo(const JSPandaFile* jsPandaFile) const;
|
||||
bool IsLoadMain(const JSPandaFile* jsPandaFile, const CString& entry) const;
|
||||
uint32_t GetFileIndex(uint32_t anFileInfoIndex, CString abcNormalizedName) const;
|
||||
std::list<CString> GetPandaFiles(uint32_t aotFileInfoIndex);
|
||||
uint32_t GetAnFileIndex(const JSPandaFile *jsPandaFile) const;
|
||||
void BindPreloadedPandaFilesInAotFile(const std::string &moduleName);
|
||||
bool HasPandaFile(uint32_t aotFileInfoIndex, const CString &abcNormalizedName) const;
|
||||
void BindPandaFileInAotFile(const std::string &aotFileBaseName, JSPandaFile *jsPandaFile) const;
|
||||
void SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc, const JSPandaFile *jsPandaFile,
|
||||
uint32_t GetAnFileIndex(const JSPandaFile* jsPandaFile) const;
|
||||
void BindPreloadedPandaFilesInAotFile(const std::string& moduleName);
|
||||
bool HasPandaFile(uint32_t aotFileInfoIndex, const CString& abcNormalizedName) const;
|
||||
void BindPandaFileInAotFile(const std::string& aotFileBaseName, JSPandaFile* jsPandaFile) const;
|
||||
void SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc,
|
||||
const JSPandaFile* jsPandaFile,
|
||||
std::string_view entryPoint);
|
||||
void SetAOTFuncEntry(const JSPandaFile *jsPandaFile, JSFunction *function,
|
||||
Method *method, uint32_t entryIndex = 0, bool *canFastCall = nullptr);
|
||||
bool LoadAiFile([[maybe_unused]] const std::string &filename);
|
||||
bool LoadAiFile(const JSPandaFile *jsPandaFile);
|
||||
void SetAOTFuncEntry(const JSPandaFile* jsPandaFile,
|
||||
JSFunction* function,
|
||||
Method* method,
|
||||
uint32_t entryIndex = 0,
|
||||
bool* canFastCall = nullptr);
|
||||
bool LoadAiFile([[maybe_unused]] const std::string& filename);
|
||||
bool LoadAiFile(const JSPandaFile* jsPandaFile);
|
||||
kungfu::ArkStackMapParser* GetStackMapParser() const;
|
||||
static JSTaggedValue GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal);
|
||||
static bool GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr);
|
||||
static JSTaggedValue GetAbsolutePath(JSThread* thread, JSTaggedValue relativePathVal);
|
||||
static bool GetAbsolutePath(const CString& relativePathCstr, CString& absPathCstr);
|
||||
static bool RewriteDataSection(uintptr_t dataSec, size_t size, uintptr_t newData, size_t newSize);
|
||||
void ParseDeserializedData(const CString &snapshotFileName, JSTaggedValue deserializedData);
|
||||
JSHandle<JSTaggedValue> GetDeserializedConstantPool(const JSPandaFile *jsPandaFile, int32_t cpID);
|
||||
const Heap *GetHeap();
|
||||
void ParseDeserializedData(const CString& snapshotFileName, JSTaggedValue deserializedData);
|
||||
JSHandle<JSTaggedValue> GetDeserializedConstantPool(const JSPandaFile* jsPandaFile, int32_t cpID);
|
||||
const Heap* GetHeap();
|
||||
|
||||
static void DumpAOTInfo() DUMP_API_ATTR;
|
||||
|
||||
@ -211,5 +217,5 @@ private:
|
||||
friend class AnFileInfo;
|
||||
friend class StubFileInfo;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_MANAGER_H
|
||||
|
@ -1298,12 +1298,50 @@ void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef ke
|
||||
Label exit(env);
|
||||
GateRef hclass = LoadHClass(receiver);
|
||||
GateRef metaData = GetPropertyMetaDataFromAttr(attr);
|
||||
GateRef newClass = FindTransitions(glue, receiver, hclass, key, metaData, value);
|
||||
GateRef newClass = FindTransitions(glue, hclass, key, metaData, value);
|
||||
Label findHClass(env);
|
||||
Label notFindHClass(env);
|
||||
BRANCH(Equal(newClass, Undefined()), ¬FindHClass, &findHClass);
|
||||
Bind(&findHClass);
|
||||
{
|
||||
GateRef isTSHClass = IsTSHClass(newClass);
|
||||
Label setPrototype(env);
|
||||
Label endSetPrototypeCheck(env);
|
||||
Branch(isTSHClass, &setPrototype, &endSetPrototypeCheck);
|
||||
Bind(&setPrototype);
|
||||
{
|
||||
GateRef prototype = GetPrototypeFromHClass(hclass);
|
||||
StorePrototype(glue, newClass, prototype);
|
||||
Jump(&endSetPrototypeCheck);
|
||||
}
|
||||
Bind(&endSetPrototypeCheck);
|
||||
StoreHClass(glue, receiver, newClass);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
Label needUpdateAOTHClass(env);
|
||||
Label normalNotify(env);
|
||||
Label endUpdate(env);
|
||||
GateRef updateCondition = BoolAnd(isTSHClass, IsProtoTypeHClass(newClass));
|
||||
Branch(updateCondition, &needUpdateAOTHClass, &normalNotify);
|
||||
Bind(&needUpdateAOTHClass);
|
||||
{
|
||||
// Use single CallRuntime here to perform both function: UpadteAOTHClass and
|
||||
// TryRestoreElementsKind, reducing the overhead of one CallRuntime
|
||||
CallRuntime(glue, RTSTUB_ID(UpdateAOTHcAndTryResotreEleKind),
|
||||
{ receiver, hclass, newClass, key });
|
||||
Jump(&endUpdate);
|
||||
}
|
||||
Bind(&normalNotify);
|
||||
{
|
||||
// Because we currently only supports Fast ElementsKind
|
||||
CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, newClass });
|
||||
NotifyHClassChanged(glue, hclass, newClass);
|
||||
Jump(&endUpdate);
|
||||
}
|
||||
Bind(&endUpdate);
|
||||
#else
|
||||
// Because we currently only supports Fast ElementsKind
|
||||
CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, newClass });
|
||||
#endif
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(¬FindHClass);
|
||||
@ -3996,9 +4034,7 @@ GateRef StubBuilder::CheckHClassForRep(GateRef hclass, GateRef value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef StubBuilder::FindTransitions(GateRef glue, GateRef receiver,
|
||||
GateRef hclass, GateRef key,
|
||||
GateRef metaData, GateRef value)
|
||||
GateRef StubBuilder::FindTransitions(GateRef glue, GateRef hclass, GateRef key, GateRef metaData, GateRef value)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
@ -4006,7 +4042,7 @@ GateRef StubBuilder::FindTransitions(GateRef glue, GateRef receiver,
|
||||
Label exit(env);
|
||||
GateRef transitionOffset = IntPtr(JSHClass::TRANSTIONS_OFFSET);
|
||||
GateRef transition = Load(VariableType::JS_POINTER(), hclass, transitionOffset);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), transition);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
||||
|
||||
Label notUndefined(env);
|
||||
BRANCH(Equal(transition, Undefined()), &exit, ¬Undefined);
|
||||
@ -4026,71 +4062,37 @@ GateRef StubBuilder::FindTransitions(GateRef glue, GateRef receiver,
|
||||
GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
|
||||
Label keyMatch(env);
|
||||
Label isMatch(env);
|
||||
Label notMatch(env);
|
||||
Label repMatch(env);
|
||||
BRANCH(Equal(cachedKey, key), &keyMatch, ¬Match);
|
||||
BRANCH(Equal(cachedKey, key), &keyMatch, &exit);
|
||||
Bind(&keyMatch);
|
||||
{
|
||||
BRANCH(Int32Equal(metaData, cachedMetaData), &isMatch, ¬Match);
|
||||
BRANCH(Int32Equal(metaData, cachedMetaData), &isMatch, &exit);
|
||||
Bind(&isMatch);
|
||||
{
|
||||
BRANCH(CheckHClassForRep(transitionHClass, value), &repMatch, ¬Match);
|
||||
BRANCH(CheckHClassForRep(transitionHClass, value), &repMatch, &exit);
|
||||
Bind(&repMatch);
|
||||
GateRef oldHClass = LoadHClass(receiver);
|
||||
GateRef prototype = GetPrototypeFromHClass(oldHClass);
|
||||
StorePrototype(glue, transitionHClass, prototype);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
NotifyHClassChanged(glue, hclass, transitionHClass);
|
||||
#endif
|
||||
StoreHClass(glue, receiver, transitionHClass);
|
||||
// Because we currently only supports Fast ElementsKind
|
||||
CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, transitionHClass });
|
||||
result = transitionHClass;
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬Match);
|
||||
{
|
||||
result = Undefined();
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬Weak);
|
||||
{
|
||||
// need to find from dictionary
|
||||
GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
|
||||
Label isFound(env);
|
||||
Label notFound(env);
|
||||
BRANCH(Int32NotEqual(entryA, Int32(-1)), &isFound, ¬Found);
|
||||
BRANCH(Int32NotEqual(entryA, Int32(-1)), &isFound, &exit);
|
||||
Bind(&isFound);
|
||||
auto cachedValue = GetValueFromDictionary<TransitionsDictionary>(transition, entryA);
|
||||
Label valueUndefined(env);
|
||||
Label valueNotUndefined(env);
|
||||
Label repMatch(env);
|
||||
BRANCH(Int64NotEqual(cachedValue, Undefined()), &valueNotUndefined,
|
||||
&valueUndefined);
|
||||
BRANCH(Int64NotEqual(cachedValue, Undefined()), &valueNotUndefined, &exit);
|
||||
Bind(&valueNotUndefined);
|
||||
{
|
||||
GateRef newHClass = LoadObjectFromWeakRef(cachedValue);
|
||||
BRANCH(CheckHClassForRep(newHClass, value), &repMatch, &valueUndefined);
|
||||
BRANCH(CheckHClassForRep(newHClass, value), &repMatch, &exit);
|
||||
Bind(&repMatch);
|
||||
result = newHClass;
|
||||
GateRef oldHClass = LoadHClass(receiver);
|
||||
GateRef prototype = GetPrototypeFromHClass(oldHClass);
|
||||
StorePrototype(glue, newHClass, prototype);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
NotifyHClassChanged(glue, hclass, newHClass);
|
||||
#endif
|
||||
StoreHClass(glue, receiver, newHClass);
|
||||
// Because we currently only supports Fast ElementsKind
|
||||
CallRuntime(glue, RTSTUB_ID(TryRestoreElementsKind), { receiver, newHClass });
|
||||
Jump(&exit);
|
||||
Bind(¬Found);
|
||||
result = Undefined();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&valueUndefined);
|
||||
{
|
||||
result = Undefined();
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
|
@ -625,7 +625,7 @@ ShortcutBoolOr([&]{ return first; }, [&]{ return second; })
|
||||
GateRef ComputeElementCapacity(GateRef oldLength);
|
||||
GateRef ComputeNonInlinedFastPropsCapacity(GateRef glue, GateRef oldLength,
|
||||
GateRef maxNonInlinedFastPropsCapacity);
|
||||
GateRef FindTransitions(GateRef glue, GateRef receiver, GateRef hClass, GateRef key, GateRef attr, GateRef value);
|
||||
GateRef FindTransitions(GateRef glue, GateRef hClass, GateRef key, GateRef attr, GateRef value);
|
||||
GateRef CheckHClassForRep(GateRef hClass, GateRef rep);
|
||||
void TransitionForRepChange(GateRef glue, GateRef receiver, GateRef key, GateRef attr);
|
||||
void TransitToElementsKind(GateRef glue, GateRef receiver, GateRef value, GateRef kind);
|
||||
|
@ -304,13 +304,19 @@ void JSHClass::AddProperty(const JSThread *thread, const JSHandle<JSObject> &obj
|
||||
JSHandle<JSHClass> newHClass(thread, newClass);
|
||||
TryRestoreElementsKind(thread, newHClass, obj);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, JSHandle<JSHClass>(thread, newClass), key.GetTaggedValue());
|
||||
#endif
|
||||
// The transition hclass from AOT, which does not have protochangemarker, needs to be reset here
|
||||
if (newClass->IsTS() && newClass->IsPrototype()) {
|
||||
JSHClass::RefreshUsers(thread, jshclass, JSHandle<JSHClass>(thread, newClass));
|
||||
JSHClass::EnableProtoChangeMarker(thread, JSHandle<JSHClass>(thread, newClass));
|
||||
if (JSHClass::IsNeedNotifyHclassChangedForAotTransition(thread, jshclass, key.GetTaggedValue())) {
|
||||
JSHClass::EnableProtoChangeMarker(thread, JSHandle<JSHClass>(thread, newClass));
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, newHClass, key.GetTaggedValue());
|
||||
} else {
|
||||
JSHClass::RefreshUsers(thread, jshclass, newHClass);
|
||||
}
|
||||
JSHClass::EnablePHCProtoChangeMarker(thread, newHClass);
|
||||
} else {
|
||||
JSHClass::NotifyHclassChanged(thread, jshclass, newHClass, key.GetTaggedValue());
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
JSHandle<JSHClass> newJsHClass = JSHClass::Clone(thread, jshclass);
|
||||
@ -1655,5 +1661,17 @@ void JSHClass::CreateSDictLayout(JSThread *thread,
|
||||
hclass->SetNumberOfProps(0);
|
||||
hclass->SetIsDictionaryMode(true);
|
||||
}
|
||||
|
||||
bool JSHClass::IsNeedNotifyHclassChangedForAotTransition(const JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
JSTaggedValue key)
|
||||
{
|
||||
JSMutableHandle<JSObject> protoHandle(thread, hclass->GetPrototype());
|
||||
while (protoHandle.GetTaggedValue().IsHeapObject()) {
|
||||
JSHClass *protoHclass = protoHandle->GetJSHClass();
|
||||
if (JSHClass::FindPropertyEntry(thread, protoHclass, key) != -1) {
|
||||
return true;
|
||||
}
|
||||
protoHandle.Update(protoHclass->GetPrototype());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -517,6 +517,9 @@ public:
|
||||
static void RefreshUsers(const JSThread *thread, const JSHandle<JSHClass> &oldHclass,
|
||||
const JSHandle<JSHClass> &newHclass);
|
||||
|
||||
static bool IsNeedNotifyHclassChangedForAotTransition(const JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
JSTaggedValue key);
|
||||
|
||||
static JSHandle<JSTaggedValue> ParseKeyFromPGOCString(ObjectFactory* factory,
|
||||
const CString& key,
|
||||
const PGOHandler& handler);
|
||||
|
@ -480,25 +480,41 @@ JSHandle<JSFunction> ClassHelper::DefineClassFromExtractor(JSThread *thread, con
|
||||
return constructor;
|
||||
}
|
||||
|
||||
JSHandle<JSFunction> ClassHelper::DefineClassWithIHClass(JSThread *thread,
|
||||
JSHandle<JSFunction> ClassHelper::DefineClassWithIHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base,
|
||||
JSHandle<ClassInfoExtractor> &extractor,
|
||||
const JSHandle<JSTaggedValue> &lexenv,
|
||||
const JSHandle<JSTaggedValue> &prototypeOrHClass,
|
||||
const JSHandle<JSHClass> &constructorHClass)
|
||||
const JSHandle<JSTaggedValue> &prototypeOrHClassVal,
|
||||
const JSHandle<JSTaggedValue> &constructorHClassVal)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys());
|
||||
JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties());
|
||||
ClassInfoExtractor::CorrectConstructorHClass(thread,
|
||||
staticProperties, *constructorHClass);
|
||||
JSHandle<JSHClass> constructorHClass;
|
||||
// When constructorHClassVal is undefined, it means that AOT has not generated the corresponding hclass (chc),
|
||||
// then chc will be created through the interpreter.
|
||||
if (constructorHClassVal->IsUndefined()) {
|
||||
constructorHClass = ClassInfoExtractor::CreateConstructorHClass(thread, base, staticKeys, staticProperties);
|
||||
} else {
|
||||
constructorHClass = JSHandle<JSHClass>(constructorHClassVal);
|
||||
ClassInfoExtractor::CorrectConstructorHClass(thread, staticProperties, *constructorHClass);
|
||||
}
|
||||
|
||||
JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys());
|
||||
JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties());
|
||||
JSHandle<JSObject> prototype;
|
||||
if (prototypeOrHClass->IsJSHClass()) {
|
||||
JSHandle<JSHClass> ihclass(prototypeOrHClass);
|
||||
JSHandle<JSTaggedValue> prototypeOrHClass = prototypeOrHClassVal;
|
||||
// When prototypeOrHClassVal is undefined, it means that AOT has not generated the corresponding hclass or
|
||||
// prototype, then prototype will be created through the interpreter.
|
||||
if (prototypeOrHClassVal->IsUndefined()) {
|
||||
JSHandle<JSHClass> prototypeHClass = ClassInfoExtractor::CreatePrototypeHClass(thread, nonStaticKeys,
|
||||
nonStaticProperties);
|
||||
prototype = factory->NewOldSpaceJSObject(prototypeHClass);
|
||||
prototypeOrHClass = JSHandle<JSTaggedValue>(prototype);
|
||||
} else if (prototypeOrHClassVal->IsJSHClass()) {
|
||||
JSHandle<JSHClass> ihclass(prototypeOrHClassVal);
|
||||
prototype = JSHandle<JSObject>(thread, ihclass->GetProto());
|
||||
} else {
|
||||
prototype = JSHandle<JSObject>(prototypeOrHClass);
|
||||
prototype = JSHandle<JSObject>(prototypeOrHClassVal);
|
||||
}
|
||||
|
||||
JSHandle<Method> method(thread, Method::Cast(extractor->GetConstructorMethod().GetTaggedObject()));
|
||||
|
@ -114,11 +114,11 @@ public:
|
||||
JSHandle<ClassInfoExtractor> &extractor,
|
||||
const JSHandle<JSTaggedValue> &lexenv);
|
||||
|
||||
static JSHandle<JSFunction> DefineClassWithIHClass(JSThread *thread,
|
||||
static JSHandle<JSFunction> DefineClassWithIHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base,
|
||||
JSHandle<ClassInfoExtractor> &extractor,
|
||||
const JSHandle<JSTaggedValue> &lexenv,
|
||||
const JSHandle<JSTaggedValue> &ihclass,
|
||||
const JSHandle<JSHClass> &constructorHClass);
|
||||
const JSHandle<JSTaggedValue> &prototypeOrHClassVal,
|
||||
const JSHandle<JSTaggedValue> &constructorHClassVal);
|
||||
|
||||
static bool PUBLIC_API MatchFieldType(SharedFieldType fieldType, JSTaggedValue value);
|
||||
private:
|
||||
|
@ -473,6 +473,7 @@ namespace panda::ecmascript {
|
||||
V(FunctionPrototypeBind) \
|
||||
V(FunctionPrototypeCall) \
|
||||
V(SetPrototypeTransition) \
|
||||
V(UpdateAOTHcAndTryResotreEleKind) \
|
||||
V(GetSharedModule)
|
||||
|
||||
#define RUNTIME_STUB_LIST(V) \
|
||||
|
@ -895,7 +895,9 @@ bool RuntimeStubs::ShouldUseAOTHClass(const JSHandle<JSTaggedValue> &ihc,
|
||||
const JSHandle<JSTaggedValue> &chc,
|
||||
const JSHandle<ClassLiteral> &classLiteral)
|
||||
{
|
||||
return !(ihc->IsUndefined() || chc->IsUndefined() || classLiteral->GetIsAOTUsed());
|
||||
// In the case of incomplete data collection in PGO, AOT may not create ihc and chc at the same time.
|
||||
// Therefore, there is no need to check for the existence of both at this point.
|
||||
return (!ihc->IsUndefined() || !chc->IsUndefined()) && !classLiteral->GetIsAOTUsed();
|
||||
}
|
||||
// clone class may need re-set inheritance relationship due to extends may be a variable.
|
||||
JSTaggedValue RuntimeStubs::RuntimeCreateClassWithBuffer(JSThread *thread,
|
||||
@ -945,9 +947,7 @@ JSTaggedValue RuntimeStubs::RuntimeCreateClassWithBuffer(JSThread *thread,
|
||||
|
||||
if (ShouldUseAOTHClass(ihc, chc, classLiteral)) {
|
||||
classLiteral->SetIsAOTUsed(true);
|
||||
JSHandle<JSHClass> chclass(chc);
|
||||
cls = ClassHelper::DefineClassWithIHClass(thread, extractor,
|
||||
lexenv, ihc, chclass);
|
||||
cls = ClassHelper::DefineClassWithIHClass(thread, base, extractor, lexenv, ihc, chc);
|
||||
} else {
|
||||
cls = ClassHelper::DefineClassFromExtractor(thread, base, extractor, lexenv);
|
||||
}
|
||||
@ -3115,31 +3115,15 @@ JSTaggedValue RuntimeStubs::RuntimeNotifyConcurrentResult(JSThread *thread, JSTa
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
bool RuntimeStubs::IsNeedNotifyHclassChangedForAotTransition(JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
JSTaggedValue key)
|
||||
{
|
||||
JSMutableHandle<JSObject> protoHandle(thread, hclass->GetPrototype());
|
||||
while (true) {
|
||||
if (!protoHandle.GetTaggedValue().IsHeapObject()) {
|
||||
break;
|
||||
}
|
||||
JSHClass *protoHclass = protoHandle->GetJSHClass();
|
||||
if (JSHClass::FindPropertyEntry(thread, protoHclass, key) != -1) {
|
||||
return true;
|
||||
}
|
||||
protoHandle.Update(protoHclass->GetPrototype());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeUpdateAOTHClass(JSThread *thread,
|
||||
const JSHandle<JSHClass> &oldhclass, const JSHandle<JSHClass> &newhclass, JSTaggedValue key)
|
||||
{
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
if (IsNeedNotifyHclassChangedForAotTransition(thread, oldhclass, key)) {
|
||||
if (JSHClass::IsNeedNotifyHclassChangedForAotTransition(thread, oldhclass, key)) {
|
||||
JSHClass::NotifyHclassChanged(thread, oldhclass, newhclass, key);
|
||||
} else {
|
||||
JSHClass::RefreshUsers(thread, oldhclass, newhclass);
|
||||
}
|
||||
JSHClass::RefreshUsers(thread, oldhclass, newhclass);
|
||||
JSHClass::EnablePHCProtoChangeMarker(thread, newhclass);
|
||||
#endif
|
||||
return JSTaggedValue::Undefined();
|
||||
|
@ -2974,11 +2974,22 @@ DEF_RUNTIME_STUBS(NotifyConcurrentResult)
|
||||
DEF_RUNTIME_STUBS(UpdateAOTHClass)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(UpdateAOTHClass);
|
||||
JSTaggedValue oldhc = GetArg(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSTaggedValue newhc = GetArg(argv, argc, 1); // 1: means the first parameter
|
||||
JSHandle<JSHClass> oldhclass = GetHArg<JSHClass>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSHandle<JSHClass> newhclass = GetHArg<JSHClass>(argv, argc, 1); // 1: means the first parameter
|
||||
JSTaggedValue key = GetArg(argv, argc, 2); // 2: means the second parameter
|
||||
JSHandle<JSHClass> oldhclass(thread, oldhc);
|
||||
JSHandle<JSHClass> newhclass(thread, newhc);
|
||||
return RuntimeUpdateAOTHClass(thread, oldhclass, newhclass, key).GetRawData();
|
||||
}
|
||||
|
||||
|
||||
DEF_RUNTIME_STUBS(UpdateAOTHcAndTryResotreEleKind)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(UpdateAOTHClass);
|
||||
JSHandle<JSObject> receiver = GetHArg<JSObject>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSHandle<JSHClass> oldhclass = GetHArg<JSHClass>(argv, argc, 1); // 1: means the first parameter
|
||||
JSHandle<JSHClass> newhclass = GetHArg<JSHClass>(argv, argc, 2); // 2: means the second parameter
|
||||
JSTaggedValue key = GetArg(argv, argc, 3); // 3: means the third parameter
|
||||
|
||||
JSHClass::TryRestoreElementsKind(thread, newhclass, receiver);
|
||||
return RuntimeUpdateAOTHClass(thread, oldhclass, newhclass, key).GetRawData();
|
||||
}
|
||||
|
||||
|
@ -495,8 +495,6 @@ private:
|
||||
uint32_t levelIndex, uint32_t slotIndex, JSTaggedValue obj, JSTaggedValue value);
|
||||
static inline JSTaggedValue RuntimeTestIn(JSThread *thread, JSTaggedValue lexicalEnv,
|
||||
uint32_t levelIndex, uint32_t slotIndex, JSTaggedValue obj);
|
||||
static inline bool IsNeedNotifyHclassChangedForAotTransition(JSThread *thread, const JSHandle<JSHClass> &hclass,
|
||||
JSTaggedValue key);
|
||||
static inline JSTaggedValue RuntimeUpdateAOTHClass(JSThread *thread, const JSHandle<JSHClass> &oldhclass,
|
||||
const JSHandle<JSHClass> &newhclass, JSTaggedValue key);
|
||||
static inline JSTaggedValue RuntimeNotifyDebuggerStatement(JSThread *thread);
|
||||
|
@ -202,7 +202,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -188,7 +188,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -130,7 +130,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -136,7 +136,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -171,7 +171,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -136,7 +136,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -136,7 +136,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -191,7 +191,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
@ -136,7 +136,6 @@ Throwing.prototype.valueOf = function() {
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
//aot: [trace] Check Type: ProtoTypeChanged2
|
||||
let throwingObj = new Throwing();
|
||||
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user