mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
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:
parent
19fb4a2d9c
commit
0a0dc5bffb
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user