Support getter/setter in literalBuffer

1.Support getter/setter in literalBuffer
2.Adapt IC slot for definesendableclass
3.Change normalFunction in class to sharedFunction

Signed-off-by: lukai <lukai25@huawei.com>
Change-Id: I57803612e8ab2a8b82a1ad1582e24bc4de35fa23
This commit is contained in:
lukai 2023-12-20 22:32:47 +08:00 committed by hzzhouzebin
parent 9edec0bf07
commit 138619bfc8
20 changed files with 258 additions and 58 deletions

View File

@ -214,6 +214,11 @@ void Builtins::InitializeForSharing(const JSHandle<GlobalEnv> &env)
InitializeSharedObject(env, sobjIHClass, sobjFuncPrototype);
env->SetSharedObjectFunctionPrototype(thread_, sobjFuncPrototype);
sobjFuncPrototype->GetJSHClass()->SetExtensible(false);
JSHandle<JSHClass> functionClass =
factory_->CreateFunctionClass(FunctionKind::NORMAL_FUNCTION, JSSharedFunction::SIZE,JSType::JS_SHARED_FUNCTION,
env->GetSharedFunctionPrototype());
functionClass->SetExtensible(false);
env->SetSharedFunctionClassWithoutProto(thread_, functionClass);
}
void Builtins::InitializeSharedObject(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &sobjIHClass,
@ -241,9 +246,9 @@ void Builtins::InitializeSharedObject(const JSHandle<GlobalEnv> &env, const JSHa
// B.2.2.1 sObject.prototype.__proto__
JSHandle<JSTaggedValue> protoKey(factory_->NewFromASCII("__proto__"));
JSHandle<JSTaggedValue> protoGetter =
CreateSharedGetter(env, Object::ProtoGetter, "__proto__", FunctionLength::ZERO);
CreateSharedGetterSetter(env, Object::ProtoGetter, "__proto__", FunctionLength::ZERO);
JSHandle<JSTaggedValue> protoSetter =
CreateSharedSetter(env, Object::ProtoSetter, "__proto__", FunctionLength::ONE);
CreateSharedGetterSetter(env, Object::ProtoSetter, "__proto__", FunctionLength::ONE);
SetSharedAccessor(sobjFuncPrototypeObj, protoKey, protoGetter, protoSetter);
}
@ -280,7 +285,7 @@ void Builtins::InitializeSharedFunciton(const JSHandle<GlobalEnv> &env,
env->SetSharedConstructorClass(thread_, sharedConstructorClass);
JSHandle<JSObject> sfuncPrototypeObj(sfuncPrototype);
StrictModeForbiddenAccessCallerArguments(env, sfuncPrototypeObj);
SharedStrictModeForbiddenAccessCallerArguments(env, sfuncPrototypeObj);
// Function.prototype method
// 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
SetSharedFunction(env, sfuncPrototypeObj, "apply", Function::FunctionPrototypeApply, FunctionLength::TWO,
@ -3727,19 +3732,25 @@ void Builtins::SetSharedAccessor(const JSHandle<JSObject> &obj, const JSHandle<J
JSObject::AddAccessor(thread_, JSHandle<JSTaggedValue>::Cast(obj), key, accessor, attr);
}
JSHandle<JSTaggedValue> Builtins::CreateSharedGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const
JSHandle<JSTaggedValue> Builtins::CreateSharedGetterSetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const
{
JSHandle<JSTaggedValue> funcName(factory_->NewFromUtf8(name));
auto getter = NewSharedFunction(env, funcName, func, length);
return JSHandle<JSTaggedValue>(getter);
}
JSHandle<JSTaggedValue> Builtins::CreateSharedSetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const
void Builtins::SharedStrictModeForbiddenAccessCallerArguments(const JSHandle<GlobalEnv> &env,
const JSHandle<JSObject> &prototype) const
{
JSHandle<JSTaggedValue> funcName(factory_->NewFromUtf8(name));
auto setter = NewSharedFunction(env, funcName, func, length);
return JSHandle<JSTaggedValue>(setter);
JSHandle<JSFunction> func =
factory_->NewJSSharedFunction(env, reinterpret_cast<void *>(JSFunction::AccessCallerArgumentsThrowTypeError),
FunctionKind::NORMAL_FUNCTION, kungfu::BuiltinsStubCSigns::INVALID, MemSpaceType::NON_MOVABLE);
JSHandle<JSTaggedValue> caller(factory_->NewFromASCII("caller"));
SetSharedAccessor(prototype, caller, JSHandle<JSTaggedValue>(func), JSHandle<JSTaggedValue>(func));
JSHandle<JSTaggedValue> arguments(factory_->NewFromASCII("arguments"));
SetSharedAccessor(prototype, arguments, JSHandle<JSTaggedValue>(func), JSHandle<JSTaggedValue>(func));
}
} // namespace panda::ecmascript

View File

@ -363,12 +363,10 @@ private:
void SetSharedAccessor(const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
const JSHandle<JSTaggedValue> &getter, const JSHandle<JSTaggedValue> &setter) const;
JSHandle<JSTaggedValue> CreateSharedGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const;
JSHandle<JSTaggedValue> CreateSharedSetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const;
JSHandle<JSTaggedValue> CreateSharedGetterSetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const;
void SharedStrictModeForbiddenAccessCallerArguments(const JSHandle<GlobalEnv> &env,
const JSHandle<JSObject> &prototype) const;
friend class builtins::BuiltinsLazyCallback;
};
} // namespace panda::ecmascript

View File

@ -379,7 +379,7 @@ namespace panda::ecmascript::kungfu {
T(HandleCallRuntimeToPropertyKeyPrefNone) \
T(HandleCallRuntimeCreatePrivatePropertyPrefImm16Id16) \
T(HandleCallRuntimeDefinePrivatePropertyPrefImm16Imm16V8) \
T(HandleCallRuntimeDefineSendableClassPrefId16Id16Imm16V8) \
T(HandleCallRuntimeDefineSendableClassPrefImm16Id16Id16Imm16V8) \
T(HandleCallRuntimeNewSendableLexenvImm16)
#define ASM_INTERPRETER_BC_HELPER_STUB_LIST(V) \

View File

@ -351,7 +351,7 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::TESTIN_IMM8_IMM16_IMM16:
case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16:
case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8:
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8:
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8:
flags |= BytecodeFlags::READ_ENV;
break;
default:
@ -443,7 +443,7 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYINDEX_PREF_IMM32_V8:
case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16:
case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8:
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8:
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8:
flags |= BytecodeFlags::READ_FUNC;
break;
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
@ -1655,11 +1655,11 @@ void BytecodeInfo::InitBytecodeInfo(BytecodeCircuitBuilder *builder,
info.inputs.emplace_back(VirtualRegister(builder->GetEnvVregIdx()));
break;
}
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8: {
uint16_t methodId = READ_INST_16_1();
uint16_t literaId = READ_INST_16_3();
uint16_t length = READ_INST_16_5();
uint16_t v0 = READ_INST_8_7();
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8: {
uint16_t methodId = READ_INST_16_3();
uint16_t literaId = READ_INST_16_5();
uint16_t length = READ_INST_16_7();
uint16_t v0 = READ_INST_8_9();
info.inputs.emplace_back(ConstDataId(ConstDataIDType::MethodIDType, methodId));
info.inputs.emplace_back(ConstDataId(ConstDataIDType::ClassLiteralIDType, literaId));
info.inputs.emplace_back(Immediate(length));

View File

@ -323,7 +323,7 @@ namespace panda::ecmascript::kungfu {
V(CALLRUNTIME_TOPROPERTYKEY_PREF_NONE) \
V(CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16) \
V(CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8) \
V(CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8) \
V(CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8) \
V(CALLRUNTIME_NEWSENDABLELEXENV_PREF_IMM16) \
inline std::string GetEcmaOpcodeStr(EcmaOpcode opcode)

View File

@ -79,6 +79,11 @@ GateRef InterpreterStubBuilder::ReadInst8_8(GateRef pc)
return Load(VariableType::INT8(), pc, IntPtr(9)); // 9 : skip 1 byte of bytecode
}
GateRef InterpreterStubBuilder::ReadInst8_9(GateRef pc)
{
return Load(VariableType::INT8(), pc, IntPtr(10)); // 10 : skip 1 byte of bytecode
}
GateRef InterpreterStubBuilder::ReadInst4_0(GateRef pc)
{
return Int8And(Load(VariableType::INT8(), pc, IntPtr(1)), Int8(0xf));
@ -194,6 +199,15 @@ GateRef InterpreterStubBuilder::ReadInst16_6(GateRef pc)
return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_6(pc)));
}
GateRef InterpreterStubBuilder::ReadInst16_7(GateRef pc)
{
/* 7 : skip 8 bits of opcode, 8 bits of prefix, first 2 parameters of 16 bits and 8 bits of low bits */
GateRef currentInst1 = ZExtInt8ToInt16(ReadInst8_8(pc));
GateRef currentInst2 = Int16LSL(currentInst1, Int16(8)); // 8 : set as high 8 bits
/* 6 : skip 8 bits of opcode, 8 bits of prefix and first 2 parameters of 16 bits */
return Int16Add(currentInst2, ZExtInt8ToInt16(ReadInst8_9(pc)));
}
GateRef InterpreterStubBuilder::GetFrame(GateRef CurrentSp)
{
return PtrSub(CurrentSp, IntPtr(AsmInterpretedFrame::GetSize(GetEnvironment()->IsArch32Bit())));

View File

@ -5025,15 +5025,15 @@ DECLARE_ASM_HANDLER(HandleCallRuntimeDefinePrivatePropertyPrefImm16Imm16V8)
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8));
}
DECLARE_ASM_HANDLER(HandleCallRuntimeDefineSendableClassPrefId16Id16Imm16V8)
DECLARE_ASM_HANDLER(HandleCallRuntimeDefineSendableClassPrefImm16Id16Id16Imm16V8)
{
auto env = GetEnvironment();
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
GateRef methodId = ReadInst16_1(pc);
GateRef literalId = ReadInst16_3(pc);
GateRef length = ReadInst16_5(pc);
GateRef v0 = ReadInst8_7(pc);
GateRef methodId = ReadInst16_3(pc);
GateRef literalId = ReadInst16_5(pc);
GateRef length = ReadInst16_7(pc);
GateRef v0 = ReadInst8_9(pc);
GateRef proto = GetVregValue(sp, ZExtInt8ToPtr(v0));
GateRef lexicalEnv = GetEnvFromFrame(GetFrame(sp));
@ -5054,7 +5054,7 @@ DECLARE_ASM_HANDLER(HandleCallRuntimeDefineSendableClassPrefId16Id16Imm16V8)
}
Bind(&isNotException);
varAcc = res;
DISPATCH_WITH_ACC(CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8);
DISPATCH_WITH_ACC(CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8);
}
DECLARE_ASM_HANDLER(HandleCallRuntimeNewSendableLexenvImm16)

View File

@ -71,6 +71,7 @@ public:
inline GateRef ReadInst8_6(GateRef pc);
inline GateRef ReadInst8_7(GateRef pc);
inline GateRef ReadInst8_8(GateRef pc);
inline GateRef ReadInst8_9(GateRef pc);
inline GateRef ReadInst16_0(GateRef pc);
inline GateRef ReadInst16_1(GateRef pc);
inline GateRef ReadInst16_2(GateRef pc);
@ -78,6 +79,7 @@ public:
inline GateRef ReadInst16_4(GateRef pc);
inline GateRef ReadInst16_5(GateRef pc);
inline GateRef ReadInst16_6(GateRef pc);
inline GateRef ReadInst16_7(GateRef pc);
inline GateRef ReadInstSigned8_0(GateRef pc);
inline GateRef ReadInstSigned16_0(GateRef pc);
inline GateRef ReadInstSigned32_0(GateRef pc);

View File

@ -733,7 +733,7 @@ void SlowPathLowering::Lower(GateRef gate)
case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8:
LowerDefinePrivateProperty(gate);
break;
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8:
case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8:
LowerDefineSendableClass(gate);
break;
case EcmaOpcode::CALLRUNTIME_NEWSENDABLELEXENV_PREF_IMM16:

View File

@ -160,6 +160,7 @@
V(JSTaggedValue, FunctionClassWithProto, FUNCTION_CLASS_WITH_PROTO) \
V(JSTaggedValue, FunctionClassWithoutProto, FUNCTION_CLASS_WITHOUT_PROTO) \
V(JSTaggedValue, FunctionClassWithoutName, FUNCTION_CLASS_WITHOUT_NAME) \
V(JSTaggedValue, SharedFunctionClassWithoutProto, SHARED_FUNCTION_CLASS_WITHOUT_PROTO) \
V(JSTaggedValue, ArgumentsClass, ARGUMENTS_CLASS) \
V(JSTaggedValue, ArgumentsCallerAccessor, ARGUMENTS_CALLER_ACCESSOR) \
V(JSTaggedValue, ArgumentsCalleeAccessor, ARGUMENTS_CALLEE_ACCESSOR) \

View File

@ -569,6 +569,7 @@ using CommonStubCSigns = kungfu::CommonStubCSigns;
#define READ_INST_8_6() READ_INST_8(7) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8_7() READ_INST_8(8) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8_8() READ_INST_8(9) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8_9() READ_INST_8(10) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8(offset) (*(pc + (offset)))
#define MOVE_AND_READ_INST_8(currentInst, offset) \
currentInst <<= 8; \
@ -581,6 +582,7 @@ using CommonStubCSigns = kungfu::CommonStubCSigns;
#define READ_INST_16_4() READ_INST_16(6)
#define READ_INST_16_5() READ_INST_16(7)
#define READ_INST_16_6() READ_INST_16(8)
#define READ_INST_16_7() READ_INST_16(9)
#define READ_INST_16(offset) \
({ \
uint16_t currentInst = READ_INST_8(offset); \
@ -7425,11 +7427,11 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
INTERPRETER_RETURN_IF_ABRUPT(res);
DISPATCH(CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8);
}
HANDLE_OPCODE(CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8) {
uint16_t methodId = READ_INST_16_1();
uint16_t literaId = READ_INST_16_3();
uint16_t length = READ_INST_16_5();
uint16_t v0 = READ_INST_8_7();
HANDLE_OPCODE(CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8) {
uint16_t methodId = READ_INST_16_3();
uint16_t literaId = READ_INST_16_5();
uint16_t length = READ_INST_16_7();
uint16_t v0 = READ_INST_8_9();
LOG_INST() << "intrinsics::definesendableclass"
<< " method id:" << methodId << " base: v" << v0;
@ -7445,7 +7447,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
ASSERT(res.IsClassConstructor());
ASSERT(res.IsJSSharedFunction());
SET_ACC(res);
DISPATCH(CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8);
DISPATCH(CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8);
}
HANDLE_OPCODE(CALLRUNTIME_NEWSENDABLELEXENV_PREF_IMM16) {
uint16_t numVars = READ_INST_16_1();

View File

@ -148,6 +148,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns;
#define READ_INST_8_6() READ_INST_8(7) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8_7() READ_INST_8(8) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8_8() READ_INST_8(9) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8_9() READ_INST_8(10) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
#define READ_INST_8(offset) (*(pc + (offset)))
#define MOVE_AND_READ_INST_8(currentInst, offset) \
(currentInst) <<= 8; \
@ -158,6 +159,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns;
#define READ_INST_16_2() READ_INST_16(4)
#define READ_INST_16_3() READ_INST_16(5)
#define READ_INST_16_5() READ_INST_16(7)
#define READ_INST_16_7() READ_INST_16(9)
#define READ_INST_16(offset) \
({ \
uint16_t currentInst = READ_INST_8(offset); \
@ -6048,14 +6050,14 @@ void InterpreterAssembly::HandleCallRuntimeDefinePrivatePropertyPrefImm16Imm16V8
DISPATCH(CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8);
}
void InterpreterAssembly::HandleCallRuntimeDefineSendableClassPrefId16Id16Imm16V8(
void InterpreterAssembly::HandleCallRuntimeDefineSendableClassPrefImm16Id16Id16Imm16V8(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
uint16_t methodId = READ_INST_16_1();
uint16_t literaId = READ_INST_16_3();
uint16_t length = READ_INST_16_5();
uint16_t v0 = READ_INST_8_7();
uint16_t methodId = READ_INST_16_3();
uint16_t literaId = READ_INST_16_5();
uint16_t length = READ_INST_16_7();
uint16_t v0 = READ_INST_8_9();
LOG_INST() << "intrinsics::definesendableclass"
<< " method id:" << methodId << " base: v" << v0;
@ -6071,7 +6073,7 @@ void InterpreterAssembly::HandleCallRuntimeDefineSendableClassPrefId16Id16Imm16V
ASSERT(res.IsClassConstructor());
ASSERT(res.IsJSSharedFunction());
SET_ACC(res);
DISPATCH(CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8);
DISPATCH(CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8);
}
void InterpreterAssembly::HandleCallRuntimeNewSendableLexenvImm16(

View File

@ -20,5 +20,5 @@
&&HANDLE_CALLRUNTIME_TOPROPERTYKEY_PREF_NONE,
&&HANDLE_CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16,
&&HANDLE_CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM16_IMM16_V8,
&&HANDLE_CALLRUNTIME_DEFINESENDABLECLASS_PREF_ID16_ID16_IMM16_V8,
&&HANDLE_CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8,
&&HANDLE_CALLRUNTIME_NEWSENDABLELEXENV_PREF_IMM16,

View File

@ -165,6 +165,24 @@ public:
SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, length);
}
inline bool IsGetterOrSetterFunction() const
{
FunctionKind kind = GetFunctionKind();
return kind == FunctionKind::GETTER_FUNCTION || kind == FunctionKind::SETTER_FUNCTION;
}
inline bool IsGetterFunction() const
{
FunctionKind kind = GetFunctionKind();
return kind == FunctionKind::GETTER_FUNCTION;
}
inline bool IsSetterFunction() const
{
FunctionKind kind = GetFunctionKind();
return kind == FunctionKind::SETTER_FUNCTION;
}
inline bool IsBase() const
{
FunctionKind kind = GetFunctionKind();

View File

@ -406,6 +406,31 @@ JSHandle<JSFunction> ClassHelper::DefineClassFromExtractor(JSThread *thread, con
return constructor;
}
void ClassHelper::UpdateAccessorFunction(JSThread *thread, const JSMutableHandle<JSTaggedValue> &value,
JSHandle<JSTaggedValue> homeObject, JSHandle<JSTaggedValue> lexenv)
{
ASSERT(value->IsAccessorData());
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<AccessorData> accessor(value);
auto getter = accessor->GetGetter();
if (getter.IsJSFunction()) {
JSHandle<JSFunction> func(thread, getter);
JSHandle<JSFunction> propFunc = factory->CloneJSFuction(func);
propFunc->SetHomeObject(thread, homeObject);
propFunc->SetLexicalEnv(thread, lexenv);
accessor->SetGetter(thread, propFunc);
}
auto setter = accessor->GetSetter();
if (setter.IsJSFunction()) {
JSHandle<JSFunction> func(thread, setter);
JSHandle<JSFunction> propFunc = factory->CloneJSFuction(func);
propFunc->SetHomeObject(thread, homeObject);
propFunc->SetLexicalEnv(thread, lexenv);
accessor->SetSetter(thread, propFunc);
}
}
JSHandle<JSFunction> ClassHelper::DefineSendableClassFromExtractor(JSThread *thread,
JSHandle<ClassInfoExtractor> &extractor,
const JSHandle<JSTaggedValue> &lexenv,
@ -414,9 +439,12 @@ JSHandle<JSFunction> ClassHelper::DefineSendableClassFromExtractor(JSThread *thr
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys());
JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties());
ClassHelper::FilterDuplicatedKeys(thread, staticKeys, staticProperties);
JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys());
JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties());
ClassHelper::FilterDuplicatedKeys(thread, nonStaticKeys, nonStaticProperties);
JSHandle<JSHClass> prototypeHClass = ClassInfoExtractor::CreateSendableHClass(thread, nonStaticKeys,
nonStaticProperties, true);
JSHandle<JSObject> prototype = factory->NewOldSpaceJSObject(prototypeHClass);
@ -447,6 +475,8 @@ JSHandle<JSFunction> ClassHelper::DefineSendableClassFromExtractor(JSThread *thr
propFunc->SetHomeObject(thread, prototype);
propFunc->SetLexicalEnv(thread, lexenv);
propValue.Update(propFunc);
} else if (propValue->IsAccessorData()) {
UpdateAccessorFunction(thread, propValue, JSHandle<JSTaggedValue>(prototype), lexenv);
}
prototype->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue());
}
@ -472,6 +502,8 @@ JSHandle<JSFunction> ClassHelper::DefineSendableClassFromExtractor(JSThread *thr
propFunc->SetHomeObject(thread, constructor);
propFunc->SetLexicalEnv(thread, lexenv);
propValue.Update(propFunc);
} else if (propValue->IsAccessorData()) {
UpdateAccessorFunction(thread, propValue, JSHandle<JSTaggedValue>(constructor), lexenv);
}
JSHandle<JSObject>::Cast(constructor)->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue());
}
@ -501,6 +533,89 @@ JSHandle<JSFunction> ClassHelper::DefineSendableClassFromExtractor(JSThread *thr
return constructor;
}
// Process duplicated key due to getter/setter.
void ClassHelper::FilterDuplicatedKeys(JSThread *thread, const JSHandle<TaggedArray> &keys,
const JSHandle<TaggedArray> &properties)
{
auto attr = PropertyAttributes::Default();
uint32_t length = keys->GetLength();
uint32_t left = 0;
uint32_t right = 0;
JSMutableHandle<NameDictionary> dict(
thread, NameDictionary::Create(thread, NameDictionary::ComputeHashTableSize(length)));
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> existValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> index(thread, JSTaggedValue::Undefined());
for (; right < length; right++) {
key.Update(keys->Get(right));
value.Update(properties->Get(right));
int entry = dict->FindEntry(key.GetTaggedValue());
if (entry == -1) {
TryUpdateValue(thread, value);
index.Update(JSTaggedValue(left));
JSHandle<NameDictionary> newDict =
NameDictionary::PutIfAbsent(thread, dict, key, index, attr);
dict.Update(newDict);
if (left < right) {
keys->Set(thread, left, key);
}
properties->Set(thread, left, value);
left++;
continue;
}
auto existIndex = static_cast<uint32_t>(dict->GetValue(entry).GetNumber());
existValue.Update(properties->Get(existIndex));
bool needUpdateValue = TryUpdateExistValue(thread, existValue, value);
if (needUpdateValue) {
properties->Set(thread, existIndex, value);
}
}
if (left < right) {
keys->Trim(thread, left);
properties->Trim(thread, left);
}
}
bool ClassHelper::TryUpdateExistValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &existValue,
JSMutableHandle<JSTaggedValue> &value)
{
bool needUpdateValue = true;
if (existValue->IsAccessorData()) {
if (value->IsJSFunction() && JSHandle<JSFunction>(value)->IsGetterOrSetterFunction()) {
JSHandle<AccessorData> accessor(existValue);
UpdateValueToAccessor(thread, value, accessor);
needUpdateValue = false;
}
} else {
if (value->IsJSFunction() && JSHandle<JSFunction>(value)->IsGetterOrSetterFunction()) {
JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewAccessorData();
UpdateValueToAccessor(thread, value, accessor);
}
}
return needUpdateValue;
}
void ClassHelper::TryUpdateValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &value)
{
if (value->IsJSFunction() && JSHandle<JSFunction>(value)->IsGetterOrSetterFunction()) {
JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewAccessorData();
UpdateValueToAccessor(thread, value, accessor);
}
}
void ClassHelper::UpdateValueToAccessor(JSThread *thread, JSMutableHandle<JSTaggedValue> &value,
JSHandle<AccessorData> &accessor)
{
ASSERT(value->IsJSFunction() && JSHandle<JSFunction>(value)->IsGetterOrSetterFunction());
if (JSHandle<JSFunction>(value)->IsGetterFunction()) {
accessor->SetGetter(thread, value);
} else {
accessor->SetSetter(thread, value);
}
value.Update(accessor);
}
JSHandle<JSHClass> ClassInfoExtractor::CreateSendableHClass(JSThread *thread, JSHandle<TaggedArray> &keys,
JSHandle<TaggedArray> &properties, bool isProtoClass,
uint32_t extraLength)
@ -578,6 +693,8 @@ JSHandle<NameDictionary> ClassHelper::BuildSendableDictionaryProperties(JSThread
propFunc->SetHomeObject(thread, object);
propFunc->SetLexicalEnv(thread, lexenv);
propValue.Update(propFunc);
} else if (propValue->IsAccessorData()) {
UpdateAccessorFunction(thread, propValue, JSHandle<JSTaggedValue>(object), lexenv);
}
JSHandle<NameDictionary> newDict = NameDictionary::PutIfAbsent(thread, dict, propKey, propValue, attributes);
dict.Update(newDict);

View File

@ -122,9 +122,15 @@ public:
static void DefineSendableInstanceHClass(JSThread *thread, const JSHandle<JSTaggedValue> &lexenv,
const JSHandle<TaggedArray> &fieldTypeArray,
const JSHandle<JSFunction> &ctor, const JSHandle<JSTaggedValue> &base);
static JSHandle<TaggedArray> ExtractStaticFieldTypeArray(JSThread *thread,
const JSHandle<TaggedArray> &fieldTypeArray);
static TrackType FromFieldType(FieldType type) {
static void FilterDuplicatedKeys(JSThread *thread, const JSHandle<TaggedArray> &keys,
const JSHandle<TaggedArray> &properties);
static TrackType FromFieldType(FieldType type)
{
switch (type) {
case FieldType::NONE:
return TrackType::NONE;
@ -159,6 +165,9 @@ private:
static void HandleElementsProperties(JSThread *thread, const JSHandle<JSObject> &object,
JSHandle<TaggedArray> &elements);
static void UpdateAccessorFunction(JSThread *thread, const JSMutableHandle<JSTaggedValue> &value,
JSHandle<JSTaggedValue> homeObject, JSHandle<JSTaggedValue> lexenv);
static void AddFieldTypeToHClass(JSThread *thread, const JSHandle<JSTaggedValue> &lexenv,
const JSHandle<TaggedArray> &fieldTypeArray,
const JSHandle<LayoutInfo> &layout, const JSHandle<JSHClass> &hclass);
@ -170,6 +179,14 @@ private:
static void AddFieldTypeToDict(JSThread *thread, const JSHandle<JSTaggedValue> &lexenv,
const JSHandle<TaggedArray> &fieldTypeArray, JSMutableHandle<NameDictionary> &dict,
PropertyAttributes attributes = PropertyAttributes::Default(true, true, true));
static bool TryUpdateExistValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &existValue,
JSMutableHandle<JSTaggedValue> &value);
static void TryUpdateValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &value);
static void UpdateValueToAccessor(JSThread *thread, JSMutableHandle<JSTaggedValue> &value,
JSHandle<AccessorData> &accessor);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H

View File

@ -236,7 +236,8 @@ JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *threa
uint32_t offset, JSHandle<ConstantPool> constpool,
FunctionKind kind, uint16_t length,
const CString &entryPoint,
bool isLoadedAOT, uint32_t entryIndex)
bool isLoadedAOT, uint32_t entryIndex,
bool sendableClass)
{
EcmaVM *vm = thread->GetEcmaVM();
ObjectFactory *factory = vm->GetFactory();
@ -268,10 +269,20 @@ JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *threa
module, entryIndex, isLoadedAOT, &canFastCall);
JSHandle<JSHClass> functionClass;
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
if (kind == FunctionKind::NORMAL_FUNCTION) {
functionClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
if (sendableClass) {
if (kind == FunctionKind::NORMAL_FUNCTION ||
kind == FunctionKind::GETTER_FUNCTION ||
kind == FunctionKind::SETTER_FUNCTION) {
functionClass = JSHandle<JSHClass>::Cast(env->GetSharedFunctionClassWithoutProto());
} else {
functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
}
} else {
functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
if (kind == FunctionKind::NORMAL_FUNCTION) {
functionClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
} else {
functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
}
}
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByHClass(method, functionClass, MemSpaceType::OLD_SPACE);
jsFunc->SetLength(length);
@ -429,7 +440,8 @@ void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFil
JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
EntityId id, JSHandle<ConstantPool> constpool,
const CString &entryPoint,
bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes)
bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes,
bool sendableClass)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
@ -441,7 +453,7 @@ JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread,
int index = 0;
lda.EnumerateLiteralVals(
id, [literals, &pos, factory, thread, jsPandaFile,
&methodId, &kind, &constpool, &entryPoint, &entryIndexes, &index, isLoadedAOT]
&methodId, &kind, &constpool, &entryPoint, &entryIndexes, &index, isLoadedAOT, sendableClass]
(const LiteralValue &value, const LiteralTag &tag) {
JSTaggedValue jt = JSTaggedValue::Null();
switch (tag) {
@ -495,7 +507,7 @@ JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread,
}
JSHandle<JSFunction> jsFunc =
DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool,
kind, length, entryPoint, needSetAotFlag, entryIndex);
kind, length, entryPoint, needSetAotFlag, entryIndex, sendableClass);
jt = jsFunc.GetTaggedValue();
break;
}

View File

@ -45,7 +45,8 @@ public:
JSHandle<ConstantPool> constpool, const CString &entryPoint = "");
static JSHandle<TaggedArray> GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id,
JSHandle<ConstantPool> constpool, const CString &entryPoint = "",
bool isLoadedAOT = false, JSHandle<AOTLiteralInfo> entryIndexes = JSHandle<AOTLiteralInfo>());
bool isLoadedAOT = false, JSHandle<AOTLiteralInfo> entryIndexes = JSHandle<AOTLiteralInfo>(),
bool sendableClass = false);
static JSHandle<TaggedArray> GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile,
size_t index, JSHandle<ConstantPool> constpool,
const CString &entryPoint = "");
@ -54,7 +55,8 @@ public:
uint32_t offset, JSHandle<ConstantPool> constpool,
FunctionKind kind, uint16_t length,
const CString &entryPoint = "",
bool isLoadedAOT = false, uint32_t entryIndex = 0);
bool isLoadedAOT = false, uint32_t entryIndex = 0,
bool sendableClass = false);
static void PUBLIC_API GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index,
std::vector<uint32_t> &methodOffsets);

View File

@ -256,7 +256,7 @@ public:
}
static JSTaggedValue GetClassLiteralFromCache(JSThread *thread, JSHandle<ConstantPool> constpool,
uint32_t literal, CString entry)
uint32_t literal, CString entry, bool sendableClass = false)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
auto val = constpool->GetObjectFromCache(literal);
@ -277,7 +277,7 @@ public:
panda_file::File::EntityId literalId = constpool->GetEntityId(literal);
bool needSetAotFlag = isLoadedAOT && !entryIndexes.GetTaggedValue().IsUndefined();
JSHandle<TaggedArray> literalArray = LiteralDataExtractor::GetDatasIgnoreType(
thread, jsPandaFile, literalId, constpool, entry, needSetAotFlag, entryIndexes);
thread, jsPandaFile, literalId, constpool, entry, needSetAotFlag, entryIndexes, sendableClass);
JSHandle<ClassLiteral> classLiteral = factory->NewClassLiteral();
classLiteral->SetArray(thread, literalArray);
val = classLiteral.GetTaggedValue();

View File

@ -899,6 +899,10 @@ JSTaggedValue RuntimeStubs::RuntimeCreateSendableClass(JSThread *thread,
THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(ClassNotDerivedFromSharedFamily), JSTaggedValue::Exception());
}
[[maybe_unused]] EcmaHandleScope handleScope(thread);
if (!base->IsHole() && !base->IsNull() && !base->IsJSSharedFunction()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "sendable class shouldn't extend non-sendable class",
JSTaggedValue::Exception());
}
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
CString entry = ModuleManager::GetRecordName(module.GetTaggedValue());
@ -907,7 +911,7 @@ JSTaggedValue RuntimeStubs::RuntimeCreateSendableClass(JSThread *thread,
JSHandle<JSTaggedValue> method(thread, methodObj);
JSHandle<ConstantPool> constpoolHandle = JSHandle<ConstantPool>::Cast(constpool);
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread, constpoolHandle, literalId, entry);
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread, constpoolHandle, literalId, entry, true);
JSHandle<ClassLiteral> classLiteral(thread, literalObj);
JSHandle<TaggedArray> arrayHandle(thread, classLiteral->GetArray());
auto literalLength = arrayHandle->GetLength();