Optimization of building Class Constructor

Collect class-literal's message in ConstPool through GenerateProgram(), and create Class's Constructor during js-runtime.
issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5MKDB

Signed-off-by: wuwanqi <wuwanqi2@huawei.com>
This commit is contained in:
wuwanqi 2022-08-25 19:32:26 +08:00
parent 19fb4a2d9c
commit 0a0dc5bffb
16 changed files with 149 additions and 104 deletions

View File

@ -2895,11 +2895,11 @@ DECLARE_ASM_HANDLER(HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8)
GateRef v0 = ReadInst8_7(pc);
GateRef v1 = ReadInst8_8(pc);
GateRef classTemplate = GetObjectFromConstPool(constpool, ZExtInt16ToInt32(methodId));
GateRef lexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0));
GateRef proto = GetVregValue(sp, ZExtInt8ToPtr(v1));
GateRef res = CallRuntime(glue, RTSTUB_ID(CloneClassFromTemplate), { classTemplate, proto, lexicalEnv, constpool });
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateClassWithBuffer),
{ proto, lexicalEnv, constpool, Int16ToTaggedTypeNGC(methodId) });
Label isException(env);
Label isNotException(env);

View File

@ -2903,18 +2903,17 @@ void SlowPathLowering::LowerDefineClassWithBuffer(GateRef gate, GateRef glue, Ga
DebugPrintBC(gate, glue, builder_.Int32(GET_MESSAGE_STRING_ID(HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8)));
// 5: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 5);
GateRef methodId = builder_.ZExtInt16ToInt32(acc_.GetValueIn(gate, 0));
GateRef methodId = acc_.GetValueIn(gate, 0);
GateRef length = acc_.GetValueIn(gate, 2);
GateRef classTemplate = GetObjectFromConstPool(jsFunc, methodId);
GateRef lexicalEnv = acc_.GetValueIn(gate, 3);
GateRef proto = acc_.GetValueIn(gate, 4);
GateRef constpool = GetConstPool(jsFunc);
Label isException(&builder_);
Label isNotException(&builder_);
auto args = { classTemplate, proto, lexicalEnv, constpool };
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(CloneClassFromTemplate), args, true);
auto args = { proto, lexicalEnv, constpool, builder_.TaggedNGC(methodId) };
GateRef result = LowerCallRuntime(glue, RTSTUB_ID(CreateClassWithBuffer), args, true);
builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
&isException, &isNotException);
std::vector<GateRef> successControl;

View File

@ -3485,15 +3485,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
uint16_t v1 = READ_INST_8_8();
LOG_INST() << "intrinsics::defineclasswithbuffer"
<< " method id:" << methodId << " lexenv: v" << v0 << " parent: v" << v1;
JSFunction *classTemplate = JSFunction::Cast(GET_OBJ_FROM_CACHE(methodId).GetTaggedObject());
ASSERT(classTemplate != nullptr);
JSTaggedValue lexenv = GET_VREG_VALUE(v0);
JSTaggedValue proto = GET_VREG_VALUE(v1);
JSTaggedValue res;
SAVE_PC();
res = SlowRuntimeStub::CloneClassFromTemplate(thread, JSTaggedValue(classTemplate), proto, lexenv);
res = SlowRuntimeStub::CreateClassWithBuffer(thread, proto, lexenv, GetConstantPool(sp), methodId);
INTERPRETER_RETURN_IF_ABRUPT(res);
ASSERT(res.IsClassConstructor());

View File

@ -3350,15 +3350,12 @@ void InterpreterAssembly::HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8(
uint16_t v1 = READ_INST_8_8();
LOG_INST() << "intrinsics::defineclasswithbuffer"
<< " method id:" << methodId << " lexenv: v" << v0 << " parent: v" << v1;
JSFunction *classTemplate = JSFunction::Cast(
ConstantPool::Cast(constpool.GetTaggedObject())->GetObjectFromCache(methodId).GetTaggedObject());
ASSERT(classTemplate != nullptr);
JSTaggedValue lexenv = GET_VREG_VALUE(v0);
JSTaggedValue proto = GET_VREG_VALUE(v1);
SAVE_PC();
JSTaggedValue res = SlowRuntimeStub::CloneClassFromTemplate(thread, JSTaggedValue(classTemplate), proto, lexenv);
JSTaggedValue res = SlowRuntimeStub::CreateClassWithBuffer(thread, proto, lexenv, constpool, methodId);
INTERPRETER_RETURN_IF_ABRUPT(res);
ASSERT(res.IsClassConstructor());

View File

@ -22,6 +22,7 @@
#include "ecmascript/interpreter/frame_handler.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/interpreter/slow_runtime_helper.h"
#include "ecmascript/jspandafile/class_info_extractor.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/jspandafile/scope_info_extractor.h"
#include "ecmascript/js_arguments.h"
@ -1128,6 +1129,19 @@ JSTaggedValue SlowRuntimeStub::CloneClassFromTemplate(JSThread *thread, JSTagged
return RuntimeStubs::RuntimeCloneClassFromTemplate(thread, cls, baseHandle, lexenvHandle);
}
// clone class may need re-set inheritance relationship due to extends may be a variable.
JSTaggedValue SlowRuntimeStub::CreateClassWithBuffer(JSThread *thread, JSTaggedValue base,
JSTaggedValue lexenv, JSTaggedValue constpool,
const uint16_t methodId)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> baseHandle(thread, base);
JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
JSHandle<JSTaggedValue> constpoolHandle(thread, constpool);
return RuntimeStubs::RuntimeCreateClassWithBuffer(thread, baseHandle, lexenvHandle, constpoolHandle, methodId);
}
JSTaggedValue SlowRuntimeStub::SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);

View File

@ -163,10 +163,14 @@ public:
JSTaggedValue lexenv);
static JSTaggedValue CloneClassFromTemplate(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base,
JSTaggedValue lexenv);
static JSTaggedValue CreateClassWithBuffer(JSThread *thread, JSTaggedValue base,
JSTaggedValue lexenv, JSTaggedValue constpool,
const uint16_t methodId);
static JSTaggedValue SetClassConstructorLength(JSThread *thread, JSTaggedValue ctor, JSTaggedValue length);
static JSTaggedValue GetModuleNamespace(JSThread *thread, JSTaggedValue localName);
static JSTaggedValue LdBigInt(JSThread *thread, JSTaggedValue numberBigInt);
static JSTaggedValue ThrowTypeError(JSThread *thread, const char *message);
static JSTaggedValue SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base);
static JSTaggedValue AsyncGeneratorResolve(JSThread *thread, JSTaggedValue asyncFuncObj,
const JSTaggedValue value, JSTaggedValue flag);
@ -175,7 +179,6 @@ public:
private:
static JSTaggedValue ThrowSyntaxError(JSThread *thread, const char *message);
static JSTaggedValue GetCallSpreadArgs(JSThread *thread, JSTaggedValue array);
static JSTaggedValue SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_INTERPRETER_SLOW_RUNTIME_STUB_H

View File

@ -14,16 +14,15 @@
*/
#include "ecmascript/jspandafile/class_info_extractor.h"
#include "ecmascript/global_env.h"
#include "ecmascript/js_function.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/tagged_dictionary.h"
namespace panda::ecmascript {
void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<TaggedArray> &literal,
const JSPandaFile *jsPandaFile)
const JSHandle<TaggedArray> &literal)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
@ -46,7 +45,7 @@ void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JS
ExtractContentsDetail nonStaticDetail {0, nonStaticNum * 2, NON_STATIC_RESERVED_LENGTH, nullptr};
if (UNLIKELY(ExtractAndReturnWhetherWithElements(thread, literal, nonStaticDetail, nonStaticKeys,
nonStaticProperties, nonStaticElements, jsPandaFile))) {
nonStaticProperties, nonStaticElements))) {
extractor->SetNonStaticWithElements(true);
extractor->SetNonStaticElements(thread, nonStaticElements);
}
@ -55,9 +54,6 @@ void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JS
extractor->SetNonStaticKeys(thread, nonStaticKeys);
extractor->SetNonStaticProperties(thread, nonStaticProperties);
JSHandle<JSHClass> prototypeHClass = CreatePrototypeHClass(thread, nonStaticKeys, nonStaticProperties);
extractor->SetPrototypeHClass(thread, prototypeHClass);
uint32_t staticNum = (literalBufferLength - 1) / 2 - nonStaticNum;
// Reserve sufficient length to prevent frequent creation.
@ -75,18 +71,17 @@ void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JS
nonStaticNum * 2,
literalBufferLength - 1,
STATIC_RESERVED_LENGTH,
extractor->GetConstructorMethod()
Method::Cast(extractor->GetConstructorMethod().GetTaggedObject())
};
if (UNLIKELY(ExtractAndReturnWhetherWithElements(thread, literal, staticDetail, staticKeys,
staticProperties, staticElements, jsPandaFile))) {
staticProperties, staticElements))) {
extractor->SetStaticWithElements(true);
extractor->SetStaticElements(thread, staticElements);
}
} else {
// without static properties, set class name
MethodLiteral *methodLiteral = extractor->GetConstructorMethod();
std::string clsName = MethodLiteral::ParseFunctionName(jsPandaFile, methodLiteral->GetMethodId());
std::string clsName = Method::Cast(extractor->GetConstructorMethod().GetTaggedObject())->ParseFunctionName();
JSHandle<EcmaString> clsNameHandle = factory->NewFromStdString(clsName);
staticProperties->Set(thread, NAME_INDEX, clsNameHandle);
}
@ -97,17 +92,13 @@ void ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JS
extractor->SetStaticKeys(thread, staticKeys);
extractor->SetStaticProperties(thread, staticProperties);
JSHandle<JSHClass> ctorHClass = CreateConstructorHClass(thread, staticKeys, staticProperties);
extractor->SetConstructorHClass(thread, ctorHClass);
}
bool ClassInfoExtractor::ExtractAndReturnWhetherWithElements(JSThread *thread, const JSHandle<TaggedArray> &literal,
const ExtractContentsDetail &detail,
JSHandle<TaggedArray> &keys,
JSHandle<TaggedArray> &properties,
JSHandle<TaggedArray> &elements,
const JSPandaFile *jsPandaFile)
JSHandle<TaggedArray> &elements)
{
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
@ -115,7 +106,7 @@ bool ClassInfoExtractor::ExtractAndReturnWhetherWithElements(JSThread *thread, c
uint32_t pos = detail.fillStartLoc;
bool withElementsFlag = false;
bool isStaticFlag = detail.ctorMethod ? true : false;
bool isStaticFlag = detail.method ? true : false;
bool keysHasNameFlag = false;
JSHandle<JSTaggedValue> nameString = globalConst->GetHandledNameString();
@ -156,7 +147,7 @@ bool ClassInfoExtractor::ExtractAndReturnWhetherWithElements(JSThread *thread, c
if (LIKELY(!keysHasNameFlag)) {
[[maybe_unused]] EcmaHandleScope handleScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
std::string clsName = MethodLiteral::ParseFunctionName(jsPandaFile, detail.ctorMethod->GetMethodId());
std::string clsName = detail.method->ParseFunctionName();
JSHandle<EcmaString> clsNameHandle = factory->NewFromStdString(clsName);
properties->Set(thread, NAME_INDEX, clsNameHandle);
} else {
@ -278,21 +269,30 @@ JSHandle<JSHClass> ClassInfoExtractor::CreateConstructorHClass(JSThread *thread,
return hclass;
}
JSHandle<JSFunction> ClassHelper::DefineClassTemplate(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<ConstantPool> &constantpool)
JSHandle<JSFunction> ClassHelper::DefineClassFromExtractor(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<JSTaggedValue> &constpool,
const JSHandle<JSTaggedValue> &lexenv)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<ConstantPool> constantPool = JSHandle<ConstantPool>::Cast(constpool);
JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys());
JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties());
JSHandle<JSHClass> constructorHClass = ClassInfoExtractor::CreateConstructorHClass(thread, staticKeys,
staticProperties);
JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys());
JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties());
JSHandle<JSHClass> prototypeHClass = ClassInfoExtractor::CreatePrototypeHClass(thread, nonStaticKeys,
nonStaticProperties);
JSHandle<JSHClass> prototypeHClass(thread, extractor->GetPrototypeHClass());
JSHandle<JSObject> prototype = factory->NewOldSpaceJSObject(prototypeHClass);
JSHandle<JSHClass> constructorHClass(thread, extractor->GetConstructorHClass());
JSHandle<Method> method = factory->NewJSMethod(extractor->GetConstructorMethod());
JSHandle<Method> method(thread, Method::Cast(extractor->GetConstructorMethod().GetTaggedObject()));
JSHandle<JSFunction> constructor = factory->NewJSFunctionByDynClass(method,
constructorHClass, FunctionKind::CLASS_CONSTRUCTOR, MemSpaceType::OLD_SPACE);
// non-static
JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties());
nonStaticProperties->Set(thread, 0, constructor);
uint32_t nonStaticLength = nonStaticProperties->GetLength();
@ -305,25 +305,31 @@ JSHandle<JSFunction> ClassHelper::DefineClassTemplate(JSThread *thread, JSHandle
JSHandle<JSFunction> propFunc = JSHandle<JSFunction>::Cast(propValue);
propFunc->SetHomeObject(thread, prototype);
JSHandle<Method> propMethod(thread, propFunc->GetMethod());
propMethod->SetConstantPool(thread, constantpool.GetTaggedValue());
propMethod->SetConstantPool(thread, constantPool.GetTaggedValue());
propFunc->SetLexicalEnv(thread, lexenv);
}
prototype->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue());
}
} else {
JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys());
JSHandle<NameDictionary> dict = BuildDictionaryProperties(thread, prototype, nonStaticKeys, nonStaticProperties,
ClassPropertyType::NON_STATIC, constantpool);
ClassPropertyType::NON_STATIC, constantPool);
for (uint32_t index = 0; index < nonStaticLength; ++index) {
propValue.Update(nonStaticProperties->Get(index));
if (propValue->IsJSFunction()) {
JSHandle<JSFunction> propFunc = JSHandle<JSFunction>::Cast(propValue);
propFunc->SetLexicalEnv(thread, lexenv);
}
}
prototype->SetProperties(thread, dict);
}
// non-static elements
if (UNLIKELY(extractor->GetNonStaticWithElements())) {
JSHandle<TaggedArray> nonStaticElements(thread, extractor->GetNonStaticElements());
ClassHelper::HandleElementsProperties(thread, prototype, nonStaticElements, constantpool);
ClassHelper::HandleElementsProperties(thread, prototype, nonStaticElements, constantPool);
}
// static
JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties());
uint32_t staticLength = staticProperties->GetLength();
if (LIKELY(!constructorHClass->IsDictionaryMode())) {
@ -333,24 +339,37 @@ JSHandle<JSFunction> ClassHelper::DefineClassTemplate(JSThread *thread, JSHandle
JSHandle<JSFunction> propFunc = JSHandle<JSFunction>::Cast(propValue);
propFunc->SetHomeObject(thread, constructor);
JSHandle<Method> propMethod(thread, propFunc->GetMethod());
propMethod->SetConstantPool(thread, constantpool.GetTaggedValue());
propMethod->SetConstantPool(thread, constantPool.GetTaggedValue());
propFunc->SetLexicalEnv(thread, lexenv);
}
JSHandle<JSObject>::Cast(constructor)->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue());
}
} else {
JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys());
JSHandle<NameDictionary> dict = BuildDictionaryProperties(thread, JSHandle<JSObject>(constructor), staticKeys,
staticProperties, ClassPropertyType::STATIC,
constantpool);
constantPool);
for (uint32_t index = 0; index < staticLength; ++index) {
propValue.Update(staticProperties->Get(index));
if (propValue->IsJSFunction()) {
JSHandle<JSFunction> propFunc = JSHandle<JSFunction>::Cast(propValue);
propFunc->SetLexicalEnv(thread, lexenv);
}
}
constructor->SetProperties(thread, dict);
}
// static elements
if (UNLIKELY(extractor->GetStaticWithElements())) {
JSHandle<TaggedArray> staticElements(thread, extractor->GetStaticElements());
ClassHelper::HandleElementsProperties(thread, JSHandle<JSObject>(constructor), staticElements, constantpool);
ClassHelper::HandleElementsProperties(thread, JSHandle<JSObject>(constructor), staticElements, constantPool);
}
PropertyDescriptor ctorDesc(thread, JSHandle<JSTaggedValue>(constructor), true, false, true);
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(prototype),
globalConst->GetHandledConstructorString(), ctorDesc);
constructor->SetHomeObject(thread, prototype);
constructor->SetProtoOrDynClass(thread, prototype);
return constructor;

View File

@ -37,14 +37,19 @@ public:
uint32_t extractBegin;
uint32_t extractEnd;
uint8_t fillStartLoc;
MethodLiteral *ctorMethod;
Method *method;
};
CAST_CHECK(ClassInfoExtractor, IsClassInfoExtractor);
static void BuildClassInfoExtractorFromLiteral(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<TaggedArray> &literal,
const JSPandaFile *jsPandaFile);
const JSHandle<TaggedArray> &literal);
static JSHandle<JSHClass> CreatePrototypeHClass(JSThread *thread, JSHandle<TaggedArray> &keys,
JSHandle<TaggedArray> &properties);
static JSHandle<JSHClass> CreateConstructorHClass(JSThread *thread, JSHandle<TaggedArray> &keys,
JSHandle<TaggedArray> &properties);
static constexpr size_t PROTOTYPE_HCLASS_OFFSET = TaggedObjectSize();
ACCESSORS(PrototypeHClass, PROTOTYPE_HCLASS_OFFSET, NON_STATIC_KEYS_OFFSET)
@ -55,7 +60,7 @@ public:
ACCESSORS(StaticKeys, STATIC_KEYS_OFFSET, STATIC_PROPERTIES_OFFSET)
ACCESSORS(StaticProperties, STATIC_PROPERTIES_OFFSET, STATIC_ELEMENTS_OFFSET)
ACCESSORS(StaticElements, STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_METHOD_OFFSET)
ACCESSORS_NATIVE_FIELD(ConstructorMethod, MethodLiteral, CONSTRUCTOR_METHOD_OFFSET, BIT_FIELD_OFFSET)
ACCESSORS(ConstructorMethod, CONSTRUCTOR_METHOD_OFFSET, BIT_FIELD_OFFSET)
ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
DEFINE_ALIGN_SIZE(LAST_OFFSET);
@ -65,8 +70,7 @@ public:
FIRST_BIT_FIELD(BitField, NonStaticWithElements, bool, NON_STATIC_BITS)
NEXT_BIT_FIELD(BitField, StaticWithElements, bool, STATIC_BITS, NonStaticWithElements)
DECL_VISIT_OBJECT(PROTOTYPE_HCLASS_OFFSET, CONSTRUCTOR_METHOD_OFFSET)
DECL_VISIT_NATIVE_FIELD(CONSTRUCTOR_METHOD_OFFSET, BIT_FIELD_OFFSET)
DECL_VISIT_OBJECT(PROTOTYPE_HCLASS_OFFSET, BIT_FIELD_OFFSET)
DECL_DUMP()
@ -74,22 +78,16 @@ private:
static bool ExtractAndReturnWhetherWithElements(JSThread *thread, const JSHandle<TaggedArray> &literal,
const ExtractContentsDetail &detail,
JSHandle<TaggedArray> &keys, JSHandle<TaggedArray> &properties,
JSHandle<TaggedArray> &elements,
const JSPandaFile *jsPandaFile);
static JSHandle<JSHClass> CreatePrototypeHClass(JSThread *thread, JSHandle<TaggedArray> &keys,
JSHandle<TaggedArray> &properties);
static JSHandle<JSHClass> CreateConstructorHClass(JSThread *thread, JSHandle<TaggedArray> &keys,
JSHandle<TaggedArray> &properties);
JSHandle<TaggedArray> &elements);
};
enum class ClassPropertyType : uint8_t { NON_STATIC = 0, STATIC };
class ClassHelper {
public:
static JSHandle<JSFunction> DefineClassTemplate(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<ConstantPool> &constantpool);
static JSHandle<JSFunction> DefineClassFromExtractor(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<JSTaggedValue> &constpool,
const JSHandle<JSTaggedValue> &lexenv);
private:
static JSHandle<NameDictionary> BuildDictionaryProperties(JSThread *thread, const JSHandle<JSObject> &object,

View File

@ -227,8 +227,9 @@ JSTaggedValue PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSPandaFile
MethodLiteral *methodLiteral = jsPandaFile->FindMethods(it.first);
ASSERT(methodLiteral != nullptr);
JSHandle<ClassInfoExtractor> classInfoExtractor = factory->NewClassInfoExtractor(methodLiteral);
constpool->Set(thread, value.GetConstpoolIndex(), classInfoExtractor.GetTaggedValue());
JSHandle<Method> method = factory->NewJSMethod(methodLiteral);
method->SetConstantPool(thread, constpool.GetTaggedValue());
constpool->Set(thread, value.GetConstpoolIndex(), method.GetTaggedValue());
} else if (value.GetConstpoolType() == ConstPoolType::METHOD) {
panda_file::File::EntityId id(it.first);
MethodLiteral *methodLiteral = jsPandaFile->FindMethods(it.first);
@ -287,8 +288,6 @@ JSTaggedValue PandaFileTranslator::ParseConstPool(EcmaVM *vm, const JSPandaFile
}
}
DefineClassesInConstPool(thread, constpool, jsPandaFile);
return constpool.GetTaggedValue();
}
@ -569,35 +568,4 @@ void PandaFileTranslator::TranslateBytecode(JSPandaFile *jsPandaFile, uint32_t i
UpdateICOffset(const_cast<MethodLiteral *>(method), pc);
}
}
void PandaFileTranslator::DefineClassesInConstPool(JSThread *thread, JSHandle<ConstantPool> constpool,
const JSPandaFile *jsPandaFile)
{
uint32_t length = constpool->GetLength();
uint32_t index = 1;
const bool isLoadedAOT = jsPandaFile->IsLoadedAOT();
auto fileLoader = thread->GetEcmaVM()->GetFileLoader();
while (index < length) {
JSTaggedValue value = constpool->Get(index);
if (!value.IsClassInfoExtractor()) {
index++;
continue;
}
// Here, using a law: when inserting ctor in index of constantpool, the index + 1 location will be inserted by
// corresponding class literal. Because translator fixes ECMA_DEFINECLASSWITHBUFFER two consecutive times.
JSTaggedValue nextValue = constpool->Get(index + 1);
ASSERT(nextValue.IsTaggedArray());
JSHandle<ClassInfoExtractor> extractor(thread, value);
JSHandle<TaggedArray> literal(thread, nextValue);
ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread, extractor, literal, jsPandaFile);
JSHandle<JSFunction> cls = ClassHelper::DefineClassTemplate(thread, extractor, constpool);
if (isLoadedAOT) {
fileLoader->SetAOTFuncEntry(jsPandaFile, cls);
}
constpool->Set(thread, index, cls);
index += 2; // 2: pair of extractor and literal
}
}
} // namespace panda::ecmascript

View File

@ -48,8 +48,6 @@ private:
static void FixOpcode(uint8_t *pc);
static void UpdateICOffset(MethodLiteral *method, uint8_t *pc);
static JSTaggedValue ParseConstPool(EcmaVM *vm, const JSPandaFile *jsPandaFile);
static void DefineClassesInConstPool(JSThread *thread, JSHandle<ConstantPool> constpool,
const JSPandaFile *jsPandaFile);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_JSPANDAFILE_PANDA_FILE_TRANSLATOR_H

View File

@ -2905,14 +2905,14 @@ JSHandle<MachineCode> ObjectFactory::NewMachineCodeObject(size_t length, const u
return codeObj;
}
JSHandle<ClassInfoExtractor> ObjectFactory::NewClassInfoExtractor(MethodLiteral *ctorMethod)
JSHandle<ClassInfoExtractor> ObjectFactory::NewClassInfoExtractor(JSHandle<JSTaggedValue> method)
{
NewObjectHook();
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
JSHClass::Cast(thread_->GlobalConstants()->GetClassInfoExtractorHClass().GetTaggedObject()));
JSHandle<ClassInfoExtractor> obj(thread_, header);
obj->ClearBitField();
obj->SetConstructorMethod(ctorMethod);
obj->SetConstructorMethod(thread_, method.GetTaggedValue());
JSHandle<TaggedArray> emptyArray = EmptyArray();
obj->SetPrototypeHClass(thread_, JSTaggedValue::Undefined());
obj->SetNonStaticKeys(thread_, emptyArray, SKIP_BARRIER);

View File

@ -438,7 +438,7 @@ public:
JSHandle<JSObject> NewJSObjectWithInit(const JSHandle<JSHClass> &jshclass);
uintptr_t NewSpaceBySnapshotAllocator(size_t size);
JSHandle<MachineCode> NewMachineCodeObject(size_t length, const uint8_t *data);
JSHandle<ClassInfoExtractor> NewClassInfoExtractor(MethodLiteral *ctorMethod);
JSHandle<ClassInfoExtractor> NewClassInfoExtractor(JSHandle<JSTaggedValue> method);
// ----------------------------------- new TSType ----------------------------------------
JSHandle<TSObjLayoutInfo> CreateTSObjLayoutInfo(int propNum, JSTaggedValue initVal = JSTaggedValue::Hole());

View File

@ -37,6 +37,7 @@
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/template_string.h"
#include "ecmascript/ts_types/ts_manager.h"
#include "ecmascript/jspandafile/class_info_extractor.h"
#include "ecmascript/jspandafile/literal_data_extractor.h"
#include "ecmascript/jspandafile/scope_info_extractor.h"
@ -703,6 +704,38 @@ JSTaggedValue RuntimeStubs::RuntimeCloneClassFromTemplate(JSThread *thread, cons
return cloneClass.GetTaggedValue();
}
// clone class may need re-set inheritance relationship due to extends may be a variable.
JSTaggedValue RuntimeStubs::RuntimeCreateClassWithBuffer(JSThread *thread,
const JSHandle<JSTaggedValue> &base,
const JSHandle<JSTaggedValue> &lexenv,
const JSHandle<JSTaggedValue> &constpool,
const uint16_t methodId)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<ConstantPool> constantPool = JSHandle<ConstantPool>::Cast(constpool);
JSHandle<JSTaggedValue> method(thread, constantPool->Get(methodId));
JSHandle<TaggedArray> literal(thread, constantPool->Get(methodId + 1));
JSHandle<ClassInfoExtractor> extractor = factory->NewClassInfoExtractor(method);
ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread, extractor, literal);
JSHandle<JSFunction> cls = ClassHelper::DefineClassFromExtractor(thread, extractor, constpool, lexenv);
// JSPandaFile is in the first index of constpool.
JSPandaFile *jsPandaFile = reinterpret_cast<JSPandaFile *>(
JSNativePointer::Cast(constantPool->Get(0).GetTaggedObject())->GetExternalPointer());
FileLoader *fileLoader = thread->GetEcmaVM()->GetFileLoader();
if (jsPandaFile->IsLoadedAOT()) {
fileLoader->SetAOTFuncEntry(jsPandaFile, cls);
}
SlowRuntimeStub::SetClassInheritanceRelationship(thread, cls.GetTaggedValue(), base.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return cls.GetTaggedValue();
}
JSTaggedValue RuntimeStubs::RuntimeSetClassInheritanceRelationship(JSThread *thread,
const JSHandle<JSTaggedValue> &ctor,
const JSHandle<JSTaggedValue> &base)

View File

@ -812,6 +812,17 @@ DEF_RUNTIME_STUBS(CloneClassFromTemplate)
return RuntimeCloneClassFromTemplate(thread, ctor, base, lexenv).GetRawData();
}
DEF_RUNTIME_STUBS(CreateClassWithBuffer)
{
RUNTIME_STUBS_HEADER(CreateClassWithBuffer);
JSHandle<JSTaggedValue> base = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> lexenv = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
JSHandle<JSTaggedValue> constpool = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
JSTaggedValue methodId = GetArg(argv, argc, 3); // 3: means the third parameter
return RuntimeCreateClassWithBuffer(thread, base, lexenv, constpool,
static_cast<uint16_t>(methodId.GetInt())).GetRawData();
}
DEF_RUNTIME_STUBS(SetClassConstructorLength)
{
RUNTIME_STUBS_HEADER(SetClassConstructorLength);

View File

@ -157,6 +157,7 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uintptr_t prevFp,
V(StOwnByIndex) \
V(ResolveClass) \
V(CloneClassFromTemplate) \
V(CreateClassWithBuffer) \
V(SetClassConstructorLength) \
V(LoadICByName) \
V(StoreICByName) \
@ -384,6 +385,11 @@ private:
static inline JSTaggedValue RuntimeCloneClassFromTemplate(JSThread *thread, const JSHandle<JSFunction> &ctor,
const JSHandle<JSTaggedValue> &base,
const JSHandle<JSTaggedValue> &lexenv);
static inline JSTaggedValue RuntimeCreateClassWithBuffer(JSThread *thread,
const JSHandle<JSTaggedValue> &base,
const JSHandle<JSTaggedValue> &lexenv,
const JSHandle<JSTaggedValue> &constpool,
const uint16_t methodId);
static inline JSTaggedValue RuntimeSetClassInheritanceRelationship(JSThread *thread,
const JSHandle<JSTaggedValue> &ctor,
const JSHandle<JSTaggedValue> &base);

View File

@ -932,7 +932,8 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
#else
CHECK_DUMP_FIELDS(TaggedObject::TaggedObjectSize(), ClassInfoExtractor::SIZE, 9U);
#endif
JSHandle<ClassInfoExtractor> classInfoExtractor = factory->NewClassInfoExtractor(nullptr);
JSHandle<ClassInfoExtractor> classInfoExtractor = factory->NewClassInfoExtractor(
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
DUMP_FOR_HANDLE(classInfoExtractor)
break;
}