From 235941a4bfe69823fe40304b6c3c954947be709a Mon Sep 17 00:00:00 2001 From: luochuhao Date: Thu, 30 Sep 2021 17:21:46 +0800 Subject: [PATCH] Add set property by name stub and its related testcase. Signed-off-by: luochuhao Change-Id: I300714665de79f63997330dcc42d78cf283f85b1 --- ecmascript/compiler/fast_stub.cpp | 204 +++++++++++++++ ecmascript/compiler/fast_stub.h | 13 + ecmascript/compiler/fast_stub_define.h | 6 +- ecmascript/compiler/llvm_codegen.cpp | 10 +- ecmascript/compiler/llvm_ir_builder.cpp | 9 +- ecmascript/compiler/llvm_ir_builder.h | 4 +- ecmascript/compiler/stub.cpp | 291 ++++++++++++++++++++- ecmascript/compiler/stub.h | 293 ++++++++++++++-------- ecmascript/compiler/stub_aot_compiler.cpp | 3 +- ecmascript/compiler/stub_descriptor.cpp | 70 +++++- ecmascript/compiler/tests/stub_tests.cpp | 200 ++++++++------- ecmascript/interpreter/interpreter-inl.h | 23 +- ecmascript/mem/ecma_heap_manager-inl.h | 15 +- ecmascript/mem/heap-inl.h | 1 + ecmascript/mem/heap.cpp | 14 ++ ecmascript/mem/heap.h | 10 + ecmascript/mem/mem.h | 3 +- ecmascript/mem/old_space_collector.cpp | 8 + ecmascript/mem/old_space_collector.h | 2 +- ecmascript/mem/space.cpp | 58 ++++- ecmascript/mem/space.h | 4 + ecmascript/runtime_trampolines.cpp | 72 +++++- ecmascript/runtime_trampolines.h | 9 +- ecmascript/stub_module.cpp | 3 - 24 files changed, 1105 insertions(+), 220 deletions(-) diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 46ff2415f1..3bfe9ff3de 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -1009,6 +1009,210 @@ void GetPropertyByNameStub::GenerateCircuit() } } +void SetPropertyByNameStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift receiver = Int64Argument(1); + AddrShift key = Int64Argument(2); // 2 : 3rd para + AddrShift value = Int64Argument(3); // 3 : 4th para + AddrShift isOwnProperty = Int1Argument(4); // 4 : 5th para + DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver); + Label loopHead(env); + Label loopEnd(env); + Label loopExit(env); + Label afterLoop(env); + // a do-while loop + Jump(&loopHead); + LoopBegin(&loopHead); + { + // auto *hclass = holder.GetTaggedObject()->GetClass() + // JSType jsType = hclass->GetObjectType() + AddrShift hClass = LoadHClass(*holder); + AddrShift jsType = GetObjectType(hClass); + Label isSIndexObj(env); + Label notSIndexObj(env); + // if branch condition : IsSpecialIndexedObj(jsType) + Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj); + Bind(&isSIndexObj); + Return(GetHoleConstant()); + Bind(¬SIndexObj); + { + Label isDicMode(env); + Label notDicMode(env); + // if branch condition : LIKELY(!hclass->IsDictionaryMode()) + Branch(IsDictionaryModeByHClass(hClass), &isDicMode, ¬DicMode); + Bind(¬DicMode); + { + // LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject()) + AddrShift layOutInfo = GetAttributesFromHclass(hClass); + // int propsNumber = hclass->GetPropertiesNumber() + AddrShift propsNum = ChangeInt64ToInt32(GetPropertiesNumberFromHClass(hClass)); + // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber) + AddrShift entry = CallRuntime(GET_STUBDESCRIPTOR(FindElementWithCache), thread, + GetWord64Constant(FAST_STUB_ID(FindElementWithCache)), + {thread, hClass, key, propsNum}); + Label hasEntry(env); + Label noEntry(env); + // if branch condition : entry != -1 + Branch(Word32NotEqual(entry, GetInt32Constant(-1)), &hasEntry, &noEntry); + Bind(&hasEntry); + { + // PropertyAttributes attr(layoutInfo->GetAttr(entry)) + AddrShift propAttr = GetPropAttrFromLayoutInfo(layOutInfo, entry); + AddrShift attr = TaggedCastToInt32(propAttr); + Label isAccessor(env); + Label notAccessor(env); + Label afterIsAccessor(env); + Branch(IsAccessor(attr), &isAccessor, ¬Accessor); + Bind(&isAccessor); + { + // auto accessor = JSObject::Cast(holder)->GetProperty(hclass, attr) + AddrShift accessor = JSObjectGetProperty(*holder, hClass, attr); + Label shouldCall(env); + Label shouldNotCall(env); + // ShouldCallSetter(receiver, *holder, accessor, attr) + Branch(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, &shouldNotCall); + { + Bind(&shouldCall); + Return(CallSetterUtil(thread, receiver, accessor, value)); + Bind(&shouldNotCall); + Jump(&afterIsAccessor); + } + } + Bind(¬Accessor); + Jump(&afterIsAccessor); + Bind(&afterIsAccessor); + { + Label writable(env); + Label notWritable(env); + Label afterIsWritable(env); + Branch(IsWritable(attr), &writable, ¬Writable); + { + Bind(&writable); + Jump(&afterIsWritable); + Bind(¬Writable); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), + GetExceptionConstant()); + } + Bind(&afterIsWritable); + { + Label holdEqualsRecv(env); + Label holdNotEqualsRecv(env); + Label afterComp(env); + Branch(Word64Equal(*holder, receiver), &holdEqualsRecv, &holdNotEqualsRecv); + { + Bind(&holdEqualsRecv); + Jump(&afterComp); + Bind(&holdNotEqualsRecv); + Jump(&afterLoop); + } + Bind(&afterComp); + // JSObject::Cast(holder)->SetProperty(thread, hclass, attr, value) + // return JSTaggedValue::Undefined() + JSObjectSetProperty(thread, *holder, hClass, attr, value); + Return(GetUndefinedConstant()); + } + } + } + Bind(&noEntry); + { + Jump(&loopExit); + } + } + Bind(&isDicMode); + { + // TaggedArray *array = TaggedArray::Cast(JSObject::Cast(holder)->GetProperties().GetTaggedObject()) + AddrShift array = GetProperties(*holder); + // int entry = dict->FindEntry(key) + AddrShift entry1 = FindEntryFromNameDictionary(thread, array, key); + Label notNegtiveOne(env); + Label negtiveOne(env); + // if branch condition : entry != -1 + Branch(Word32NotEqual(entry1, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Bind(¬NegtiveOne); + { + // auto attr = dict->GetAttributes(entry) + AddrShift attr1 = GetAttributesFromDictionary(array, entry1); + Label isAccessor1(env); + Label notAccessor1(env); + Label afterIsAccessor1(env); + // if branch condition : UNLIKELY(attr.IsAccessor()) + Branch(IsAccessor(attr1), &isAccessor1, ¬Accessor1); + Bind(&isAccessor1); + { + Label isInternal1(env); + Label notInternal1(env); + // auto accessor = dict->GetValue(entry) + AddrShift accessor1 = GetValueFromDictionary(array, entry1); + Label shouldCall1(env); + Label shouldNotCall1(env); + Branch(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, &shouldNotCall1); + Bind(&shouldCall1); + Return(CallSetterUtil(thread, receiver, accessor1, value)); + Bind(&shouldNotCall1); + Jump(&afterIsAccessor1); + } + Bind(¬Accessor1); + Jump(&afterIsAccessor1); + Bind(&afterIsAccessor1); + { + Label writable1(env); + Label notWritable1(env); + Label afterIsWritable1(env); + Branch(IsWritable(attr1), &writable1, ¬Writable1); + { + Bind(&writable1); + Jump(&afterIsWritable1); + Bind(¬Writable1); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), + GetExceptionConstant()); + } + Bind(&afterIsWritable1); + { + Label holdEqualsRecv1(env); + Label holdNotEqualsRecv1(env); + Label afterComp1(env); + Branch(Word64Equal(*holder, receiver), &holdEqualsRecv1, &holdNotEqualsRecv1); + { + Bind(&holdEqualsRecv1); + Jump(&afterComp1); + Bind(&holdNotEqualsRecv1); + Jump(&afterLoop); + } + Bind(&afterComp1); + // dict->UpdateValue(thread, entry, value) + // return JSTaggedValue::Undefined() + UpdateValueInDict(thread, array, entry1, value); + Return(GetUndefinedConstant()); + } + } + } + Bind(&negtiveOne); + Jump(&loopExit); + } + Bind(&loopExit); + { + Label isOwnProp(env); + Label notOwnProp(env); + // isOwnProp equals true or not, constant with value 1: true + Branch(isOwnProperty, &isOwnProp, ¬OwnProp); + Bind(&isOwnProp); + Jump(&afterLoop); + Bind(¬OwnProp); + // holder = hclass->GetPrototype() + holder = GetPrototypeFromHClass(LoadHClass(*holder)); + // loop condition for a do-while loop + Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop); + } + } + Bind(&loopEnd); + LoopEnd(&loopHead); + Bind(&afterLoop); + Return(AddPropertyByName(thread, receiver, key, value)); + } +} + void FastModStub::GenerateCircuit() { auto env = GetEnvironment(); diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 0b37583f12..e971024374 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -162,6 +162,19 @@ public: void GenerateCircuit() override; }; +class SetPropertyByNameStub : public Stub { +public: + // 5 : 5 means argument counts + explicit SetPropertyByNameStub(Circuit *circuit) : Stub("SetPropertyByName", 5, circuit) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~SetPropertyByNameStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByNameStub); + NO_COPY_SEMANTIC(SetPropertyByNameStub); + void GenerateCircuit() override; +}; + class FastModStub : public Stub { public: // 3 means argument counts diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index c94c34dfe3..b2cd1b0b4d 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -32,7 +32,11 @@ namespace kungfu { V(FloatMod, 2) \ V(SetValueWithBarrier, 4) \ V(GetTaggedArrayPtrTest, 1) \ - V(NewInternalString, 2) + V(NewInternalString, 2) \ + V(JSHClassAddProperty, 4) \ + V(NewTaggedArray, 2) \ + V(CopyArray, 3) \ + V(NameDictPutIfAbsent, 7) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define FAST_RUNTIME_STUB_LIST(V) \ diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index 973343fe51..860674e151 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -168,10 +168,18 @@ LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_( LLVMAssembler::~LLVMAssembler() { - module_ = nullptr; if (engine_ != nullptr) { + if (module_ != nullptr) { + char *error = nullptr; + LLVMRemoveModule(engine_, module_, &module_, &error); + if (error != nullptr) { + LLVMDisposeMessage(error); + } + } LLVMDisposeExecutionEngine(engine_); + engine_ = nullptr; } + module_ = nullptr; hostTriple_ = ""; error_ = nullptr; } diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index d8756c0483..6934c5dc8b 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -184,7 +184,6 @@ void LLVMIRBuilder::Build() AddrShift gate = (*schedule_)[bbIdx][instIdx - 1]; std::vector ins = circuit_->GetInVector(gate); std::vector outs = circuit_->GetOutVector(gate); - circuit_->Print(gate); auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate)); if (found != opCodeHandleMap_.end()) { (this->*(found->second))(gate); @@ -1341,6 +1340,14 @@ LLVMStubModule::LLVMStubModule(const char *name, const char *triple) LLVMSetTarget(module_, triple); } +LLVMStubModule::~LLVMStubModule() +{ + if (module_ != nullptr) { + LLVMDisposeModule(module_); + module_ = nullptr; + } +} + void LLVMStubModule::Initialize() { uint32_t i; diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 9191be54b7..1c4b0c30b1 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -105,8 +105,8 @@ struct LLVMTFBuilderBasicBlockImpl { class LLVMStubModule { public: - explicit LLVMStubModule(const char *name, const char *triple); - ~LLVMStubModule() = default; + LLVMStubModule(const char *name, const char *triple); + ~LLVMStubModule(); void Initialize(); diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 0e9264dafc..6a1dc976aa 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -624,7 +624,7 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); Label inlinedProp(env); Label notInlinedProp(env); - AddrShift attrOffset = PropAttrGetOffset(attr); + AddrShift attrOffset = GetOffsetFieldInPropAttr(attr); Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp); { Bind(&inlinedProp); @@ -655,6 +655,295 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a return ret; } +void Stub::JSObjectSetProperty(AddrShift thread, AddrShift obj, AddrShift hClass, AddrShift attr, AddrShift value) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->PushCurrentLabel(&subEntry); + Label exit(env); + Label inlinedProp(env); + Label notInlinedProp(env); + AddrShift attrOffset = GetOffsetFieldInPropAttr(attr); + Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp); + { + Bind(&inlinedProp); + { + SetPropertyInlinedProps(thread, obj, hClass, value, attrOffset); + Jump(&exit); + } + Bind(¬InlinedProp); + { + // compute outOfLineProp offset, get it and return + AddrShift array = Load(MachineType::UINT64_TYPE, obj, + GetPtrConstant(panda::ecmascript::JSObject::PROPERTIES_OFFSET)); + SetValueToTaggedArray(thread, array, Int32Sub(attrOffset, + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS)), value); + Jump(&exit); + } + } + Bind(&exit); + env->PopCurrentLabel(); + return; +} + +AddrShift Stub::ComputePropertyCapacityInJSObj(AddrShift oldLength) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->PushCurrentLabel(&subEntry); + Label exit(env); + DEFVARIABLE(result, MachineType::UINT32_TYPE, GetInt32Constant(0)); + AddrShift newL = Int32Add(oldLength, GetInt32Constant(panda::ecmascript::JSObject::PROPERTIES_GROW_SIZE)); + Label reachMax(env); + Label notReachMax(env); + Branch(Int32GreaterThan(newL, GetInt32Constant(panda::ecmascript::PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)), + &reachMax, ¬ReachMax); + { + Bind(&reachMax); + result = GetInt32Constant(panda::ecmascript::PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES); + Jump(&exit); + Bind(¬ReachMax); + result = newL; + Jump(&exit); + } + Bind(&exit); + auto ret = *result; + env->PopCurrentLabel(); + return ret; +} + +AddrShift Stub::CallSetterUtil(AddrShift thread, AddrShift holder, AddrShift accessor, AddrShift value) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->PushCurrentLabel(&subEntry); + Label exit(env); + DEFVARIABLE(result, MachineType::UINT64_TYPE, GetUndefinedConstant()); + AddrShift callRes = CallRuntime(GET_STUBDESCRIPTOR(CallSetter), thread, GetWord64Constant(FAST_STUB_ID(CallSetter)), + {thread, accessor, holder, value, TrueConstant()}); + Label callSuccess(env); + Label callFail(env); + Branch(Word32Equal(ZExtInt1ToInt32(callRes), GetInt32Constant(1)), &callSuccess, &callFail); + { + Bind(&callSuccess); + result = GetUndefinedConstant(); + Jump(&exit); + Bind(&callFail); + result = GetExceptionConstant(); + Jump(&exit); + } + Bind(&exit); + auto ret = *result; + env->PopCurrentLabel(); + return ret; +} + +AddrShift Stub::ShouldCallSetter(AddrShift receiver, AddrShift holder, AddrShift accessor, AddrShift attr) +{ + auto env = GetEnvironment(); + Label subEntry(env); + env->PushCurrentLabel(&subEntry); + Label exit(env); + DEFVARIABLE(result, MachineType::BOOL_TYPE, TrueConstant()); + Label isInternal(env); + Label notInternal(env); + Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal); + Bind(&isInternal); + { + Label receiverEqualsHolder(env); + Label receiverNotEqualsHolder(env); + Branch(Word64Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder); + Bind(&receiverEqualsHolder); + { + result = IsWritable(attr); + Jump(&exit); + } + Bind(&receiverNotEqualsHolder); + { + result = FalseConstant(); + Jump(&exit); + } + } + Bind(¬Internal); + { + result = TrueConstant(); + Jump(&exit); + } + Bind(&exit); + auto ret = *result; + env->PopCurrentLabel(); + return ret; +} + +// if condition:objHandle->IsJSArray() && +// keyHandle.GetTaggedValue() == thread->GlobalConstants()->GetConstructorString() +AddrShift Stub::SetHasConstructorCondition(AddrShift thread, AddrShift receiver, AddrShift key) +{ + AddrShift gConstOffset = PtrAdd(thread, + GetPtrConstant(static_cast(panda::ecmascript::JSThread::GetGlobalConstantOffset()))); + AddrShift gCtorStr = Load(MachineType::TAGGED_TYPE, + gConstOffset, + Int64Mul(GetWord64Constant(sizeof(JSTaggedValue)), + GetWord64Constant(static_cast(panda::ecmascript::ConstantIndex::CONSTRUCTOR_STRING_INDEX)))); + AddrShift isCtorStr = Word64Equal(key, gCtorStr); + return Word32NotEqual( + Word32And(SExtInt1ToInt32(IsJsArray(receiver)), SExtInt1ToInt32(isCtorStr)), GetInt32Constant(0)); +} + +// Note: set return exit node +AddrShift Stub::AddPropertyByName(AddrShift thread, AddrShift receiver, AddrShift key, AddrShift value) +{ + auto env = GetEnvironment(); + Label subentry(env); + env->PushCurrentLabel(&subentry); + Label exit(env); + DEFVARIABLE(result, MachineType::TAGGED_TYPE, GetUndefinedConstant()); + DEFVARIABLE(obj, MachineType::TAGGED_POINTER_TYPE, receiver); + Label extensible(env); + Label inextensible(env); + Label afterExtenCon(env); + Branch(IsExtensible(*obj), &extensible, &inextensible); + { + Bind(&extensible); + Jump(&afterExtenCon); + Bind(&inextensible); + AddrShift taggedId = GetInt32Constant(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible)); + CallRuntime(GET_STUBDESCRIPTOR(ThrowTypeError), thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), + {thread, taggedId}); + result = GetExceptionConstant(); + Jump(&exit); + } + Bind(&afterExtenCon); + Label setHasCtor(env); + Label notSetHasCtor(env); + Label afterCtorCon(env); + Branch(SetHasConstructorCondition(thread, *obj, key), &setHasCtor, ¬SetHasCtor); + { + Bind(&setHasCtor); + SetHasConstructorToHClass(LoadHClass(*obj), GetWord64Constant(1)); + Jump(&afterCtorCon); + Bind(¬SetHasCtor); + Jump(&afterCtorCon); + } + Bind(&afterCtorCon); + // 0x111 : default attribute for property: writable, enumerable, configurable + DEFVARIABLE(attr, MachineType::UINT32_TYPE, + GetInt32Constant(panda::ecmascript::PropertyAttributes::GetDefaultAttributes())); + AddrShift hClass = LoadHClass(*obj); + AddrShift unusedInProps = GetUnusedInlinedPropsNum(hClass); + Label hasUnusedInProps(env); + Label noUnusedInProps(env); + Label afterInPropsCon(env); + Branch(Word32Equal(unusedInProps, GetInt32Constant(0)), &noUnusedInProps, &hasUnusedInProps); + { + Bind(&noUnusedInProps); + Jump(&afterInPropsCon); + Bind(&hasUnusedInProps); + { + AddrShift order = Int32Sub( + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), unusedInProps); + SetPropertyInlinedProps(thread, *obj, hClass, value, order); + attr = SetOffsetFieldInPropAttr(*attr, order); + attr = SetIsInlinePropsFieldInPropAttr(*attr, GetInt32Constant(1)); // 1: set inInlineProps true + CallRuntime(GET_STUBDESCRIPTOR(JSHClassAddProperty), thread, + GetWord64Constant(FAST_STUB_ID(JSHClassAddProperty)), {thread, *obj, key, *attr}); + result = GetUndefinedConstant(); + Jump(&exit); + } + } + Bind(&afterInPropsCon); + DEFVARIABLE(array, MachineType::POINTER_TYPE, GetProperties(*obj)); + DEFVARIABLE(length, MachineType::UINT32_TYPE, GetLengthofElements(*array)); + Label lenIsZero(env); + Label lenNotZero(env); + Label afterLenCon(env); + Branch(Word32Equal(*length, GetInt32Constant(0)), &lenIsZero, &lenNotZero); + { + Bind(&lenIsZero); + { + length = GetInt32Constant(panda::ecmascript::JSObject::MIN_PROPERTIES_LENGTH); + array = CallRuntime(GET_STUBDESCRIPTOR(NewTaggedArray), thread, + GetWord64Constant(FAST_STUB_ID(NewTaggedArray)), {thread, *length}); + setProperties(thread, *obj, *array); + Jump(&afterLenCon); + } + Bind(&lenNotZero); + Jump(&afterLenCon); + } + Bind(&afterLenCon); + Label isDictMode(env); + Label notDictMode(env); + Branch(IsDictionaryMode(*array), &isDictMode, ¬DictMode); + { + Bind(&isDictMode); + { + AddrShift res = CallRuntime(GET_STUBDESCRIPTOR(NameDictPutIfAbsent), thread, + GetWord64Constant(FAST_STUB_ID(NameDictPutIfAbsent)), + {thread, *obj, *array, key, value, *attr, FalseConstant()}); + setProperties(thread, *obj, res); + Jump(&exit); + } + Bind(¬DictMode); + { + attr = SetIsInlinePropsFieldInPropAttr(*attr, GetInt32Constant(0)); + AddrShift outProps = Int32Sub( + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_OUT_OBJECTS), + GetUnusedNonInlinedPropsNum(hClass)); + Label isArrayFull(env); + Label arrayNotFull(env); + Label afterArrLenCon(env); + Branch(Word32Equal(*length, outProps), &isArrayFull, &arrayNotFull); + { + Bind(&isArrayFull); + { + Label ChangeToDict(env); + Label notChangeToDict(env); + Label afterDictChangeCon(env); + Branch(Int32GreaterThanOrEqual(*length, + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_OUT_OBJECTS)), + &ChangeToDict, ¬ChangeToDict); + { + Bind(&ChangeToDict); + { + attr = SetDictionaryOrderFieldInPropAttr(*attr, + GetInt32Constant(panda::ecmascript::PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)); + AddrShift res = CallRuntime(GET_STUBDESCRIPTOR(NameDictPutIfAbsent), thread, + GetWord64Constant(FAST_STUB_ID(NameDictPutIfAbsent)), + {thread, *obj, *array, key, value, *attr, TrueConstant()}); + setProperties(thread, *obj, res); + result = GetUndefinedConstant(); + Jump(&exit); + } + Bind(¬ChangeToDict); + Jump(&afterDictChangeCon); + } + Bind(&afterDictChangeCon); + AddrShift capacity = ComputePropertyCapacityInJSObj(*length); + array = CallRuntime(GET_STUBDESCRIPTOR(CopyArray), thread, + GetWord64Constant(FAST_STUB_ID(CopyArray)), {thread, *array, *length, capacity}); + setProperties(thread, *obj, *array); + Jump(&afterArrLenCon); + } + Bind(&arrayNotFull); + Jump(&afterArrLenCon); + } + Bind(&afterArrLenCon); + { + attr = SetOffsetFieldInPropAttr(*attr, Int32Add(outProps, + GetInt32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS))); + CallRuntime(GET_STUBDESCRIPTOR(JSHClassAddProperty), thread, + GetWord64Constant(FAST_STUB_ID(JSHClassAddProperty)), {thread, *obj, key, *attr}); + SetValueToTaggedArray(thread, *array, outProps, value); + Jump(&exit); + } + } + } + Bind(&exit); + auto ret = *result; + env->PopCurrentLabel(); + return ret; +} + void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); diff --git a/ecmascript/compiler/stub.h b/ecmascript/compiler/stub.h index 3116a7edfa..70f87211c2 100644 --- a/ecmascript/compiler/stub.h +++ b/ecmascript/compiler/stub.h @@ -285,7 +285,7 @@ public: } } - void SetFrameType(panda::ecmascript::FrameType type) + void SetFrameType(FrameType type) { circuit_->SetFrameType(type); } @@ -770,8 +770,8 @@ public: AddrShift Word64Sar(AddrShift x, AddrShift y); AddrShift TaggedIsInt(AddrShift x) { - return Word64Equal(Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_MASK)), - GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_INT)); + return Word64Equal(Word64And(x, GetWord64Constant(JSTaggedValue::TAG_MASK)), + GetWord64Constant(JSTaggedValue::TAG_INT)); } AddrShift TaggedIsDouble(AddrShift x) @@ -782,8 +782,8 @@ public: AddrShift TaggedIsObject(AddrShift x) { - return Word64Equal(Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_MASK)), - GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_OBJECT)); + return Word64Equal(Word64And(x, GetWord64Constant(JSTaggedValue::TAG_MASK)), + GetWord64Constant(JSTaggedValue::TAG_OBJECT)); } AddrShift TaggedIsNumber(AddrShift x) @@ -793,27 +793,26 @@ public: AddrShift TaggedIsHole(AddrShift x) { - return Word64Equal(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_HOLE)); + return Word64Equal(x, GetWord64Constant(JSTaggedValue::VALUE_HOLE)); } AddrShift TaggedIsNotHole(AddrShift x) { - return Word64NotEqual(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_HOLE)); + return Word64NotEqual(x, GetWord64Constant(JSTaggedValue::VALUE_HOLE)); } AddrShift TaggedIsUndefined(AddrShift x) { - return Word64Equal(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::VALUE_UNDEFINED)); + return Word64Equal(x, GetWord64Constant(JSTaggedValue::VALUE_UNDEFINED)); } AddrShift TaggedIsSpecial(AddrShift x) { return TruncInt32ToInt1(Word32And( SExtInt1ToInt32( - Word64Equal(Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)), + Word64Equal(Word64And(x, GetWord64Constant(~JSTaggedValue::TAG_SPECIAL_MASK)), GetWord64Constant(0))), - Word32Or(SExtInt1ToInt32(Word64NotEqual( - Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_VALUE)), + Word32Or(SExtInt1ToInt32(Word64NotEqual(Word64And(x, GetWord64Constant(JSTaggedValue::TAG_SPECIAL_VALUE)), GetWord64Constant(0))), SExtInt1ToInt32(TaggedIsHole(x))))); } @@ -830,8 +829,7 @@ public: AddrShift GetNextPositionForHash(AddrShift last, AddrShift count, AddrShift size) { - auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInt32Constant(1))), - GetInt32Constant(1)); + auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInt32Constant(1))), GetInt32Constant(1)); return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInt32Constant(1))); } @@ -854,18 +852,18 @@ public: AddrShift IntBuildTagged(AddrShift x) { AddrShift val = ZExtInt32ToInt64(x); - return Word64Or(val, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_INT)); + return Word64Or(val, GetWord64Constant(JSTaggedValue::TAG_INT)); } AddrShift Int64BuildTagged(AddrShift x) { - return Word64Or(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_INT)); + return Word64Or(x, GetWord64Constant(JSTaggedValue::TAG_INT)); } AddrShift DoubleBuildTagged(AddrShift x) { AddrShift val = CastDoubleToInt64(x); - return Int64Add(val, GetWord64Constant(panda::ecmascript::JSTaggedValue::DOUBLE_ENCODE_OFFSET)); + return Int64Add(val, GetWord64Constant(JSTaggedValue::DOUBLE_ENCODE_OFFSET)); } AddrShift CastDoubleToInt64(AddrShift x) @@ -1006,13 +1004,13 @@ public: AddrShift GetSetterFromAccessor(AddrShift accessor) { - AddrShift setterOffset = GetPtrConstant(panda::ecmascript::AccessorData::SETTER_OFFSET); + AddrShift setterOffset = GetPtrConstant(AccessorData::SETTER_OFFSET); return Load(MachineType::UINT64_TYPE, accessor, setterOffset); } AddrShift GetElements(AddrShift object) { - AddrShift elementsOffset = GetInt32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); + AddrShift elementsOffset = GetInt32Constant(JSObject::ELEMENTS_OFFSET); if (PtrValueCode() == ValueCode::INT64) { elementsOffset = SExtInt32ToInt64(elementsOffset); } @@ -1022,7 +1020,7 @@ public: AddrShift GetProperties(AddrShift object) { - AddrShift propertiesOffset = GetInt32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); + AddrShift propertiesOffset = GetInt32Constant(JSObject::PROPERTIES_OFFSET); if (PtrValueCode() == ValueCode::INT64) { propertiesOffset = SExtInt32ToInt64(propertiesOffset); } @@ -1033,16 +1031,16 @@ public: // setProperties in js_object.h void setProperties(AddrShift thread, AddrShift object, AddrShift value) { - AddrShift propertiesOffset = GetInt32Constant(panda::ecmascript::JSObject::PROPERTIES_OFFSET); + AddrShift propertiesOffset = GetInt32Constant(JSObject::PROPERTIES_OFFSET); if (PtrValueCode() == ValueCode::INT64) { propertiesOffset = SExtInt32ToInt64(propertiesOffset); } - Store(MachineType::UINT64_TYPE, thread, object, propertiesOffset, value); + Store(MachineType::TAGGED_TYPE, thread, object, propertiesOffset, value); } AddrShift GetLengthofElements(AddrShift elements) { - return Load(MachineType::UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + return Load(MachineType::UINT32_TYPE, elements, GetPtrConstant(TaggedArray::GetLengthOffset())); } // object operation @@ -1051,116 +1049,112 @@ public: return ChangeInt32ToPointer(Load(MachineType::UINT32_TYPE, object)); } + AddrShift ComputePropertyCapacityInJSObj(AddrShift oldLength); + AddrShift GetObjectType(AddrShift hClass) { - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::UINT64_TYPE, hClass, bitfieldOffset); - return ChangeInt64ToInt32( - Word64And(bitfield, GetWord64Constant((1LLU << panda::ecmascript::JSHClass::ObjectTypeBits::SIZE) - 1))); + return ChangeInt64ToInt32(Word64And(bitfield, GetWord64Constant((1LLU << JSHClass::ObjectTypeBits::SIZE) - 1))); } AddrShift IsDictionaryMode(AddrShift object) { AddrShift objectType = GetObjectType(LoadHClass(object)); - return Word32Equal(objectType, - GetInt32Constant(static_cast(panda::ecmascript::JSType::TAGGED_DICTIONARY))); + return Word32Equal(objectType, GetInt32Constant(static_cast(JSType::TAGGED_DICTIONARY))); } AddrShift IsDictionaryModeByHClass(AddrShift hClass) { - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); return Word64NotEqual( Word64And( - Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::IsDictionaryBit::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::IsDictionaryBit::SIZE) - 1)), + Word64LSR(bitfield, GetWord64Constant(JSHClass::IsDictionaryBit::START_BIT)), + GetWord64Constant((1LLU << JSHClass::IsDictionaryBit::SIZE) - 1)), GetWord64Constant(0)); } AddrShift IsDictionaryElement(AddrShift hClass) { - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); - // decode return Word64NotEqual( Word64And( - Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::DictionaryElementBits::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::DictionaryElementBits::SIZE) - 1)), + Word64LSR(bitfield, GetWord64Constant(JSHClass::DictionaryElementBits::START_BIT)), + GetWord64Constant((1LLU << JSHClass::DictionaryElementBits::SIZE) - 1)), GetWord64Constant(0)); } AddrShift NotBuiltinsConstructor(AddrShift object) { AddrShift hclass = LoadHClass(object); - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::INT64_TYPE, hclass, bitfieldOffset); // decode return Word64Equal( Word64And( - Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::BuiltinsCtorBit::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::BuiltinsCtorBit::SIZE) - 1)), + Word64LSR(bitfield, GetWord64Constant(JSHClass::BuiltinsCtorBit::START_BIT)), + GetWord64Constant((1LLU << JSHClass::BuiltinsCtorBit::SIZE) - 1)), GetWord64Constant(0)); } AddrShift IsClassConstructor(AddrShift object) { - AddrShift functionInfoFlagOffset = GetPtrConstant(panda::ecmascript::JSFunction::FUNCTION_INFO_FLAG_OFFSET); + AddrShift functionInfoFlagOffset = GetPtrConstant(JSFunction::FUNCTION_INFO_FLAG_OFFSET); AddrShift functionInfoTaggedValue = Load(MachineType::UINT64_TYPE, object, functionInfoFlagOffset); AddrShift functionInfoInt32 = TaggedCastToInt32(functionInfoTaggedValue); AddrShift functionInfoFlag = ZExtInt32ToInt64(functionInfoInt32); // decode return Word64NotEqual( - Word64And( - Word64LSR(functionInfoFlag, - GetWord64Constant(panda::ecmascript::JSFunction::ClassConstructorBit::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSFunction::ClassConstructorBit::SIZE) - 1)), + Word64And(Word64LSR(functionInfoFlag, GetWord64Constant(JSFunction::ClassConstructorBit::START_BIT)), + GetWord64Constant((1LLU << JSFunction::ClassConstructorBit::SIZE) - 1)), GetWord64Constant(0)); } AddrShift IsExtensible(AddrShift object) { AddrShift hClass = LoadHClass(object); - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); // decode return Word64NotEqual( - Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ExtensibleBit::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::ExtensibleBit::SIZE) - 1)), + Word64And(Word64LSR(bitfield, GetWord64Constant(JSHClass::ExtensibleBit::START_BIT)), + GetWord64Constant((1LLU << JSHClass::ExtensibleBit::SIZE) - 1)), GetWord64Constant(0)); } AddrShift IsSymbol(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::SYMBOL))); + return Word32Equal(objectType, GetInt32Constant(static_cast(JSType::SYMBOL))); } AddrShift IsString(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::STRING))); + return Word32Equal(objectType, GetInt32Constant(static_cast(JSType::STRING))); } AddrShift IsJsProxy(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_PROXY))); + return Word32Equal(objectType, GetInt32Constant(static_cast(JSType::JS_PROXY))); } AddrShift IsJsArray(AddrShift obj) { AddrShift objectType = GetObjectType(LoadHClass(obj)); - return Word32Equal(objectType, GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); + return Word32Equal(objectType, GetInt32Constant(static_cast(JSType::JS_ARRAY))); } AddrShift IsWritable(AddrShift attr) { return Word32NotEqual( Word32And( - Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::WritableField::START_BIT)), - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::WritableField::SIZE) - 1)), + Word32LSR(attr, GetInt32Constant(PropertyAttributes::WritableField::START_BIT)), + GetInt32Constant((1LLU << PropertyAttributes::WritableField::SIZE) - 1)), GetInt32Constant(0)); } @@ -1168,8 +1162,8 @@ public: { return Word32NotEqual( Word32And(Word32LSR(attr, - GetInt32Constant(panda::ecmascript::PropertyAttributes::IsAccessorField::START_BIT)), - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsAccessorField::SIZE) - 1)), + GetInt32Constant(PropertyAttributes::IsAccessorField::START_BIT)), + GetInt32Constant((1LLU << PropertyAttributes::IsAccessorField::SIZE) - 1)), GetInt32Constant(0)); } @@ -1177,74 +1171,139 @@ public: { return Word32NotEqual( Word32And(Word32LSR(attr, - GetInt32Constant(panda::ecmascript::PropertyAttributes::IsInlinedPropsField::START_BIT)), - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::IsInlinedPropsField::SIZE) - 1)), + GetInt32Constant(PropertyAttributes::IsInlinedPropsField::START_BIT)), + GetInt32Constant((1LLU << PropertyAttributes::IsInlinedPropsField::SIZE) - 1)), GetInt32Constant(0)); } - AddrShift PropAttrGetOffset(AddrShift attr) + // GetOffset func in property_attribute.h + AddrShift GetOffsetFieldInPropAttr(AddrShift attr) { return Word32And( - Word32LSR(attr, GetInt32Constant(panda::ecmascript::PropertyAttributes::OffsetField::START_BIT)), - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::OffsetField::SIZE) - 1)); + Word32LSR(attr, GetInt32Constant(PropertyAttributes::OffsetField::START_BIT)), + GetInt32Constant((1LLU << PropertyAttributes::OffsetField::SIZE) - 1)); + } + + // SetOffset func in property_attribute.h + AddrShift SetOffsetFieldInPropAttr(AddrShift attr, AddrShift value) + { + AddrShift mask = Word32LSL( + GetInt32Constant((1LLU << PropertyAttributes::OffsetField::SIZE) - 1), + GetInt32Constant(PropertyAttributes::OffsetField::START_BIT)); + AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), + Word32LSL(value, GetInt32Constant(PropertyAttributes::OffsetField::START_BIT))); + return newVal; + } + + // SetIsInlinedProps func in property_attribute.h + AddrShift SetIsInlinePropsFieldInPropAttr(AddrShift attr, AddrShift value) + { + AddrShift mask = Word32LSL( + GetInt32Constant((1LLU << PropertyAttributes::IsInlinedPropsField::SIZE) - 1), + GetInt32Constant(PropertyAttributes::IsInlinedPropsField::START_BIT)); + AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), + Word32LSL(value, GetInt32Constant(PropertyAttributes::IsInlinedPropsField::START_BIT))); + return newVal; } // SetDictionaryOrder func in property_attribute.h AddrShift SetDictionaryOrderFieldInPropAttr(AddrShift attr, AddrShift value) { AddrShift mask = Word32LSL( - GetInt32Constant((1LLU << panda::ecmascript::PropertyAttributes::DictionaryOrderField::SIZE) - 1), - GetInt32Constant(panda::ecmascript::PropertyAttributes::DictionaryOrderField::START_BIT)); + GetInt32Constant((1LLU << PropertyAttributes::DictionaryOrderField::SIZE) - 1), + GetInt32Constant(PropertyAttributes::DictionaryOrderField::START_BIT)); AddrShift newVal = Word32Or(Word32And(attr, Word32Not(mask)), - Word32LSL(value, GetInt32Constant(panda::ecmascript::PropertyAttributes::DictionaryOrderField::START_BIT))); + Word32LSL(value, GetInt32Constant(PropertyAttributes::DictionaryOrderField::START_BIT))); return newVal; } AddrShift GetPrototypeFromHClass(AddrShift hClass) { - AddrShift protoOffset = GetPtrConstant(panda::ecmascript::JSHClass::PROTOTYPE_OFFSET); + AddrShift protoOffset = GetPtrConstant(JSHClass::PROTOTYPE_OFFSET); return Load(MachineType::TAGGED_TYPE, hClass, protoOffset); } AddrShift GetAttributesFromHclass(AddrShift hClass) { - AddrShift attrOffset = GetPtrConstant(panda::ecmascript::JSHClass::ATTRIBUTES_OFFSET); + AddrShift attrOffset = GetPtrConstant(JSHClass::ATTRIBUTES_OFFSET); return Load(MachineType::TAGGED_TYPE, hClass, attrOffset); } - AddrShift GetPropertiesNumberFromHClass(AddrShift hClass) + // GetUnusedInlinedProps in js_hclass.h + AddrShift GetUnusedInlinedPropsNum(AddrShift hClass) + { + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, + GetPtrConstant(JSHClass::BIT_FIELD_OFFSET)); + return ChangeInt64ToInt32(Word64And(Word64LSR(bitfield, + GetWord64Constant(JSHClass::NumberOfUnusedInlinedPropsBits::START_BIT)), + GetWord64Constant((1LLU << JSHClass::NumberOfUnusedInlinedPropsBits::SIZE) - 1))); + } + + // GetUnusedNonInlinedProps in js_hclass.h + AddrShift GetUnusedNonInlinedPropsNum(AddrShift hClass) { AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, - GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET)); + GetPtrConstant(JSHClass::BIT_FIELD_OFFSET)); + return ChangeInt64ToInt32(Word64And(Word64LSR(bitfield, + GetWord64Constant(JSHClass::NumberOfUnusedNonInlinedPropsBits::START_BIT)), + GetWord64Constant((1LLU << JSHClass::NumberOfUnusedNonInlinedPropsBits::SIZE) - 1))); + } + + // SetPropertyInlinedProps in js_object-inl.h + void SetPropertyInlinedProps(AddrShift thread, AddrShift obj, AddrShift hClass, + AddrShift value, AddrShift attrOffset) + { + AddrShift hClassObjectSize = GetObjectSizeFromHClass(hClass); + AddrShift propOffset = Int32Sub( + ChangeInt64ToInt32(hClassObjectSize), + Int32Mul(Int32Sub( + GetInt32Constant(JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset), + GetInt32Constant(JSTaggedValue::TaggedTypeSize()))); + // NOTE: need to translate MarkingBarrier + Store(MachineType::TAGGED_TYPE, thread, obj, ZExtInt32ToInt64(propOffset), value); + } + + AddrShift GetPropertiesNumberFromHClass(AddrShift hClass) + { + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, GetPtrConstant(JSHClass::BIT_FIELD_OFFSET)); AddrShift unusedNonInlinedProps = Word64And(Word64LSR(bitfield, - GetWord64Constant(panda::ecmascript::JSHClass::NumberOfUnusedNonInlinedPropsBits::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::NumberOfUnusedNonInlinedPropsBits::SIZE) - 1)); + GetWord64Constant(JSHClass::NumberOfUnusedNonInlinedPropsBits::START_BIT)), + GetWord64Constant((1LLU << JSHClass::NumberOfUnusedNonInlinedPropsBits::SIZE) - 1)); AddrShift unusedInlinedProps = Word64And(Word64LSR(bitfield, - GetWord64Constant(panda::ecmascript::JSHClass::NumberOfUnusedInlinedPropsBits::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::NumberOfUnusedInlinedPropsBits::SIZE) - 1)); + GetWord64Constant(JSHClass::NumberOfUnusedInlinedPropsBits::START_BIT)), + GetWord64Constant((1LLU << JSHClass::NumberOfUnusedInlinedPropsBits::SIZE) - 1)); return Int64Sub(Int64Sub(GetWord64Constant( - panda::ecmascript::PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES), + PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES), unusedNonInlinedProps), unusedInlinedProps); } AddrShift GetObjectSizeFromHClass(AddrShift hClass) // NOTE: need to add special case for string and TAGGED_ARRAY { - return Load(MachineType::UINT64_TYPE, hClass, GetPtrConstant(panda::ecmascript::JSHClass::OBJECT_SIZE_OFFSET)); + return Load(MachineType::UINT64_TYPE, hClass, GetPtrConstant(JSHClass::OBJECT_SIZE_OFFSET)); + } + + void SetHasConstructorToHClass(AddrShift hClass, AddrShift value) + { + AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, GetPtrConstant(JSHClass::BIT_FIELD_OFFSET)); + AddrShift mask = Word64LSL( + GetWord64Constant((1LLU << JSHClass::HasConstructorBits::SIZE) - 1), + GetWord64Constant(JSHClass::HasConstructorBits::START_BIT)); + AddrShift newVal = Word64Or(Word64And(bitfield, Word64Not(mask)), + Word64LSL(value, GetWord64Constant(JSHClass::HasConstructorBits::START_BIT))); + Store(MachineType::UINT64_TYPE, hClass, GetPtrConstant(JSHClass::BIT_FIELD_OFFSET), newVal); } void StoreElement(AddrShift thread, AddrShift elements, AddrShift index, AddrShift value) { - AddrShift offset = - PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); + AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); Store(MachineType::TAGGED_TYPE, thread, elements, dataOffset, value); } void StoreElement(AddrShift elements, AddrShift index, AddrShift value) { - AddrShift offset = - PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); + AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); Store(MachineType::TAGGED_TYPE, elements, dataOffset, value); } @@ -1254,57 +1313,74 @@ public: AddrShift GetValueFromTaggedArray(AddrShift elements, AddrShift index) { AddrShift offset = - PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())); + PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); return Load(MachineType::TAGGED_TYPE, elements, dataOffset); } + AddrShift SetValueToTaggedArray(AddrShift thread, AddrShift elements, AddrShift index, AddrShift val) + { + // NOTE: need to translate MarkingBarrier + AddrShift offset = + PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); + AddrShift dataOffset = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); + return Store(MachineType::TAGGED_TYPE, thread, elements, dataOffset, val); + } + AddrShift TaggedToRepresentation(AddrShift value); AddrShift GetElementRepresentation(AddrShift hClass) { - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); return Word64And( - Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)), - GetWord64Constant(((1LLU << panda::ecmascript::JSHClass::ElementRepresentationBits::SIZE) - 1))); + Word64LSR(bitfield, GetWord64Constant(JSHClass::ElementRepresentationBits::START_BIT)), + GetWord64Constant(((1LLU << JSHClass::ElementRepresentationBits::SIZE) - 1))); } void SetElementRepresentation(AddrShift hClass, AddrShift value) { - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift oldValue = Load(MachineType::INT64_TYPE, hClass, bitfieldOffset); AddrShift oldWithMask = Word64And(oldValue, - GetWord64Constant(~panda::ecmascript::JSHClass::ElementRepresentationBits::Mask())); + GetWord64Constant(~JSHClass::ElementRepresentationBits::Mask())); AddrShift newValue = Word64LSR(value, GetWord64Constant( - panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)); + JSHClass::ElementRepresentationBits::START_BIT)); Store(MachineType::INT64_TYPE, hClass, bitfieldOffset, Word64Or(oldWithMask, newValue)); } + void UpdateValueInDict(AddrShift thread, AddrShift elements, AddrShift index, AddrShift value) + { + AddrShift arrayIndex = Int32Add(GetInt32Constant(NameDictionary::TABLE_HEADER_SIZE), + Int32Mul(index, GetInt32Constant(NameDictionary::ENTRY_SIZE))); + AddrShift valueIndex = Int32Add(arrayIndex, GetInt32Constant(NameDictionary::ENTRY_VALUE_INDEX)); + StoreElement(thread, elements, valueIndex, value); + } + void UpdateValueAndAttributes(AddrShift thread, AddrShift elements, AddrShift index, AddrShift value, AddrShift attr) { AddrShift arrayIndex = - Int32Add(GetInt32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), - Int32Mul(index, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(NameDictionary::TABLE_HEADER_SIZE), + Int32Mul(index, GetInt32Constant(NameDictionary::ENTRY_SIZE))); AddrShift valueIndex = - Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(NameDictionary::ENTRY_VALUE_INDEX)); AddrShift attributesIndex = - Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); - StoreElement(elements, valueIndex, value); - StoreElement(elements, attributesIndex, IntBuildTagged(attr)); + Int32Add(arrayIndex, GetInt32Constant(NameDictionary::ENTRY_DETAILS_INDEX)); + StoreElement(thread, elements, valueIndex, value); + StoreElement(thread, elements, attributesIndex, IntBuildTagged(attr)); } AddrShift IsSpecialIndexedObj(AddrShift jsType) { return Int32GreaterThan(jsType, - GetInt32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); + GetInt32Constant(static_cast(JSType::JS_ARRAY))); } AddrShift IsAccessorInternal(AddrShift value) { return Word32Equal(GetObjectType(LoadHClass(value)), - GetInt32Constant(static_cast(panda::ecmascript::JSType::INTERNAL_ACCESSOR))); + GetInt32Constant(static_cast(JSType::INTERNAL_ACCESSOR))); } void UpdateAndStoreRepresention(AddrShift hClass, AddrShift value); @@ -1314,20 +1390,20 @@ public: AddrShift GetAttributesFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = - Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(NumberDictionary::ENTRY_SIZE))); AddrShift attributesIndex = - Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_DETAILS_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(NameDictionary::ENTRY_DETAILS_INDEX)); return TaggedCastToInt32(GetValueFromTaggedArray(elements, attributesIndex)); } AddrShift GetValueFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = - Int32Add(GetInt32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInt32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); + Int32Add(GetInt32Constant(NumberDictionary::TABLE_HEADER_SIZE), + Int32Mul(entry, GetInt32Constant(NumberDictionary::ENTRY_SIZE))); AddrShift valueIndex = - Int32Add(arrayIndex, GetInt32Constant(panda::ecmascript::NameDictionary::ENTRY_VALUE_INDEX)); + Int32Add(arrayIndex, GetInt32Constant(NameDictionary::ENTRY_VALUE_INDEX)); return GetValueFromTaggedArray(elements, valueIndex); } @@ -1336,7 +1412,7 @@ public: AddrShift GetPropAttrFromLayoutInfo(AddrShift layout, AddrShift entry) { AddrShift index = Int32Add( - Int32Add(GetInt32Constant(panda::ecmascript::LayoutInfo::ELEMENTS_START_INDEX), + Int32Add(GetInt32Constant(LayoutInfo::ELEMENTS_START_INDEX), Word32LSL(entry, GetInt32Constant(1))), GetInt32Constant(1)); return GetValueFromTaggedArray(layout, index); @@ -1350,6 +1426,16 @@ public: AddrShift JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift propAttr); + void JSObjectSetProperty(AddrShift thread, AddrShift obj, AddrShift hClass, AddrShift attr, AddrShift value); + + AddrShift ShouldCallSetter(AddrShift receiver, AddrShift holder, AddrShift accessor, AddrShift attr); + + AddrShift CallSetterUtil(AddrShift thread, AddrShift holder, AddrShift accessor, AddrShift value); + + AddrShift SetHasConstructorCondition(AddrShift thread, AddrShift receiver, AddrShift key); + + AddrShift AddPropertyByName(AddrShift thread, AddrShift receiver, AddrShift key, AddrShift value); + AddrShift IsUtf16String(AddrShift string); AddrShift IsUtf8String(AddrShift string); @@ -1364,7 +1450,7 @@ public: AddrShift TaggedCastToInt64(AddrShift x) { - return Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_MASK)); + return Word64And(x, GetWord64Constant(~JSTaggedValue::TAG_MASK)); } AddrShift TaggedCastToInt32(AddrShift x) @@ -1374,7 +1460,7 @@ public: AddrShift TaggedCastToDouble(AddrShift x) { - AddrShift val = Int64Sub(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::DOUBLE_ENCODE_OFFSET)); + AddrShift val = Int64Sub(x, GetWord64Constant(JSTaggedValue::DOUBLE_ENCODE_OFFSET)); return CastInt64ToFloat64(val); } @@ -1471,13 +1557,12 @@ public: AddrShift IsCallable(AddrShift obj) { AddrShift hclass = LoadHClass(obj); - AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); - + AddrShift bitfieldOffset = GetPtrConstant(JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(MachineType::INT64_TYPE, hclass, bitfieldOffset); // decode return Word64NotEqual( - Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::CallableBit::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::CallableBit::SIZE) - 1)), + Word64And(Word64LSR(bitfield, GetWord64Constant(JSHClass::CallableBit::START_BIT)), + GetWord64Constant((1LLU << JSHClass::CallableBit::SIZE) - 1)), GetWord64Constant(0)); } diff --git a/ecmascript/compiler/stub_aot_compiler.cpp b/ecmascript/compiler/stub_aot_compiler.cpp index d6b30c872e..0f580358b7 100644 --- a/ecmascript/compiler/stub_aot_compiler.cpp +++ b/ecmascript/compiler/stub_aot_compiler.cpp @@ -160,7 +160,8 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri SET_STUB_TO_MODULE(module, SetPropertyByIndex) \ SET_STUB_TO_MODULE(module, FunctionCallInternal) \ SET_STUB_TO_MODULE(module, GetPropertyByName) \ - SET_STUB_TO_MODULE(module, GetPropertyByValue) + SET_STUB_TO_MODULE(module, GetPropertyByValue) \ + SET_STUB_TO_MODULE(module, SetPropertyByName) #ifndef NDEBUG #define SET_TEST_STUB_TO_MODEULE(module) \ diff --git a/ecmascript/compiler/stub_descriptor.cpp b/ecmascript/compiler/stub_descriptor.cpp index 90b0a399da..250fa19bc6 100644 --- a/ecmascript/compiler/stub_descriptor.cpp +++ b/ecmascript/compiler/stub_descriptor.cpp @@ -172,7 +172,19 @@ CALL_STUB_INIT_DESCRIPTOR(SetElement) descriptor->SetParameters(params.data()); } -CALL_STUB_INIT_DESCRIPTOR(SetPropertyByName) {} +CALL_STUB_INIT_DESCRIPTOR(SetPropertyByName) +{ + // 5 : 5 input parameters + StubDescriptor setPropertyByName("SetPropertyByName", 0, 5, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); + *descriptor = setPropertyByName; + + std::array params = { // 5 : 5 input parameters + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, + MachineType::BOOL_TYPE, + }; + descriptor->SetParameters(params.data()); +} CALL_STUB_INIT_DESCRIPTOR(GetPropertyByName) { @@ -433,7 +445,7 @@ CALL_STUB_INIT_DESCRIPTOR(FunctionCallInternal) { // 5 : 5 input parameters StubDescriptor functionCallInternal("FunctionCallInternal", 0, 5, - ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); *descriptor = functionCallInternal; std::array params = { // 5 : 5 input parameters MachineType::UINT64_TYPE, @@ -461,7 +473,7 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode) CALL_STUB_INIT_DESCRIPTOR(SetValueWithBarrier) { // 4 : 4 input parameters - static StubDescriptor SetValueWithBarrier("SetValueWithBarrier", 0, 4, + StubDescriptor SetValueWithBarrier("SetValueWithBarrier", 0, 4, ArgumentsOrder::DEFAULT_ORDER, MachineType::NONE_TYPE); *descriptor = SetValueWithBarrier; // 4 : 4 input parameters @@ -490,6 +502,58 @@ CALL_STUB_INIT_DESCRIPTOR(NewInternalString) descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); } +CALL_STUB_INIT_DESCRIPTOR(JSHClassAddProperty) +{ + // 4 : 4 input parameters + StubDescriptor jsHClassAddProperty("JSHClassAddProperty", 0, 4, ArgumentsOrder::DEFAULT_ORDER, + MachineType::NONE_TYPE); + *descriptor = jsHClassAddProperty; + std::array params = { // 4 : 4 input parameters + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(NewTaggedArray) +{ + // 2 : 2 input parameters + StubDescriptor newTaggedArray("NewTaggedArray", 0, 2, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); + *descriptor = newTaggedArray; + std::array params = { // 2 : 2 input parameters + MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(CopyArray) +{ + // 4 : 4 input parameters + StubDescriptor copyArray("CopyArray", 0, 4, ArgumentsOrder::DEFAULT_ORDER, MachineType::UINT64_TYPE); + *descriptor = copyArray; + std::array params = { // 4 : 4 input parameters + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(NameDictPutIfAbsent) +{ + // 7 : 7 input parameters + StubDescriptor nameDictPutIfAbsent("NameDictPutIfAbsent", 0, 7, ArgumentsOrder::DEFAULT_ORDER, + MachineType::UINT64_TYPE); + *descriptor = nameDictPutIfAbsent; + std::array params = { // 7 : 7 input parameters + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, MachineType::BOOL_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB); +} + CALL_STUB_INIT_DESCRIPTOR(FastLoadElement) { // 2 : 2 input parameters diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 8e656928f1..6309bdd30f 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -151,8 +151,8 @@ HWTEST_F_L0(StubTest, PhiGateTest) auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); auto valA = fn(3); // 3 : size of array auto valB = fn(0); - EXPECT_EQ(valA, 103); // 103 : eXpert res for fn(3) - EXPECT_EQ(valB, 100); // 100 : eXpert res for fn(0) + EXPECT_EQ(valA, 103); // 103 : expected res for fn(3) + EXPECT_EQ(valB, 100); // 100 : expected res for fn(0) } class LoopStub : public Stub { @@ -211,8 +211,8 @@ HWTEST_F_L0(StubTest, LoopTest) auto valA = fn(1); auto valB = fn(9); // 9 : size of array auto valC = fn(11); // 11 : size of array - EXPECT_EQ(valA, 109); // 109 : eXpert res for fn(1) - EXPECT_EQ(valB, 19); // 10 : eXpert res for fn(9) + EXPECT_EQ(valA, 109); // 109 : expected res for fn(1) + EXPECT_EQ(valB, 19); // 10 : expected res for fn(9) EXPECT_EQ(valC, 0); } @@ -254,10 +254,7 @@ public: HWTEST_F_L0(StubTest, LoopTest1) { auto module = stubModule.GetModule(); - LLVMTypeRef paramTys[] = { - LLVMInt32Type(), - }; - LLVMValueRef function = LLVMAddFunction(module, "LoopTest1", LLVMFunctionType(LLVMInt32Type(), paramTys, 1, 0)); + auto function = stubModule.GetTestFunction(FAST_STUB_ID(LoopTest1)); Circuit netOfGates; LoopStub1 optimizer(&netOfGates); optimizer.GenerateCircuit(); @@ -268,15 +265,14 @@ HWTEST_F_L0(StubTest, LoopTest1) llvmBuilder.Build(); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - auto engine = assembler.GetEngine(); // Testcase build and run - auto fn = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); + auto fn = reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); auto valA = fn(1); auto valB = fn(9); // 9 : size of array auto valC = fn(11); // 11 : size of array - EXPECT_EQ(valA, 10); // 10 : eXpert res for fn(1) - EXPECT_EQ(valB, 10); // 10 : eXpert res for fn(9) - EXPECT_EQ(valC, 11); // 10 : eXpert res for fn(11) + EXPECT_EQ(valA, 10); // 10 : expected res for fn(1) + EXPECT_EQ(valB, 10); // 10 : expected res for fn(9) + EXPECT_EQ(valC, 11); // 10 : expected res for fn(11) } HWTEST_F_L0(StubTest, FastAddTest) @@ -490,6 +486,92 @@ HWTEST_F_L0(StubTest, FastModTest) EXPECT_EQ(result5, expectRes5); } +HWTEST_F_L0(StubTest, FastTypeOfTest) +{ + auto module = stubModule.GetModule(); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastTypeOf)); + Circuit netOfGates; + FastTypeOfStub optimizer(&netOfGates); + optimizer.GenerateCircuit(); + netOfGates.PrintAllGates(); + bool verRes = Verifier::Run(&netOfGates); + ASSERT_TRUE(verRes); + auto cfg = Scheduler::Run(&netOfGates); + PrintCircuitByBasicBlock(cfg, netOfGates); + LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); + llvmBuilder.Build(); + char *error = nullptr; + LLVMVerifyModule(module, LLVMAbortProcessAction, &error); + LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); + assembler.Run(); + LLVMDumpModule(module); + auto *typeOfPtr = + reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + + // obj is JSTaggedValue::VALUE_TRUE + JSTaggedValue resultVal = typeOfPtr(thread, JSTaggedValue::True().GetRawData()); + JSTaggedValue expectResult = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::True()); + EXPECT_EQ(resultVal, globalConst->GetBooleanString()); + EXPECT_EQ(resultVal, expectResult); + + // obj is JSTaggedValue::VALUE_FALSE + JSTaggedValue resultVal2 = typeOfPtr(thread, JSTaggedValue::False().GetRawData()); + JSTaggedValue expectResult2 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::False()); + EXPECT_EQ(resultVal2, globalConst->GetBooleanString()); + EXPECT_EQ(resultVal2, expectResult2); + + // obj is JSTaggedValue::VALUE_NULL + JSTaggedValue resultVal3 = typeOfPtr(thread, JSTaggedValue::Null().GetRawData()); + JSTaggedValue expectResult3 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Null()); + EXPECT_EQ(resultVal3, globalConst->GetObjectString()); + EXPECT_EQ(resultVal3, expectResult3); + + // obj is JSTaggedValue::VALUE_UNDEFINED + JSTaggedValue resultVal4 = typeOfPtr(thread, JSTaggedValue::Undefined().GetRawData()); + JSTaggedValue expectResult4 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Undefined()); + EXPECT_EQ(resultVal4, globalConst->GetUndefinedString()); + EXPECT_EQ(resultVal4, expectResult4); + + // obj is IsNumber + JSTaggedValue resultVal5 = typeOfPtr(thread, JSTaggedValue(5).GetRawData()); + JSTaggedValue expectResult5 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue(5)); + EXPECT_EQ(resultVal5, globalConst->GetNumberString()); + EXPECT_EQ(resultVal5, expectResult5); + + // obj is String + auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); + JSHandle str1 = factory->NewFromStdString("a"); + JSHandle str2 = factory->NewFromStdString("a"); + JSTaggedValue expectResult6 = FastRuntimeStub::FastTypeOf(thread, str1.GetTaggedValue()); + JSTaggedValue resultVal6 = typeOfPtr(thread, str2.GetTaggedValue().GetRawData()); + EXPECT_EQ(resultVal6, globalConst->GetStringString()); + EXPECT_EQ(resultVal6, expectResult6); + + // obj is Symbol + JSHandle globalEnv = JSThread::Cast(thread)->GetEcmaVM()->GetGlobalEnv(); + JSTaggedValue symbol = globalEnv->GetIteratorSymbol().GetTaggedValue(); + JSTaggedValue expectResult7= FastRuntimeStub::FastTypeOf(thread, symbol); + JSTaggedValue resultVal7 = typeOfPtr(thread, symbol.GetRawData()); + EXPECT_EQ(resultVal7, globalConst->GetSymbolString()); + EXPECT_EQ(resultVal7, expectResult7); + + // obj is callable + JSHandle resolveCallable = + factory->CreateJSPromiseReactionsFunction(reinterpret_cast(BuiltinsPromiseHandler::Resolve)); + JSTaggedValue expectResult8= FastRuntimeStub::FastTypeOf(thread, resolveCallable.GetTaggedValue()); + JSTaggedValue resultVal8 = typeOfPtr(thread, resolveCallable.GetTaggedValue().GetRawData()); + EXPECT_EQ(resultVal8, globalConst->GetFunctionString()); + EXPECT_EQ(resultVal8, expectResult8); + + // obj is heapObject + JSHandle object = factory->NewEmptyJSObject(); + JSTaggedValue expectResult9= FastRuntimeStub::FastTypeOf(thread, object.GetTaggedValue()); + JSTaggedValue resultVal9 = typeOfPtr(thread, object.GetTaggedValue().GetRawData()); + EXPECT_EQ(resultVal9, globalConst->GetObjectString()); + EXPECT_EQ(resultVal9, expectResult9); +} + HWTEST_F_L0(StubTest, FastFindOwnElementStub) { auto module = stubModule.GetModule(); @@ -1167,7 +1249,7 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub) reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); JSHandle obj = factory->NewEmptyJSObject(); - int x = 213; + int x = 256; int y = 10; JSHandle strA(factory->NewFromCanBeCompressString("a")); JSHandle strBig(factory->NewFromCanBeCompressString("biggest")); @@ -1269,89 +1351,35 @@ HWTEST_F_L0(StubTest, GetPropertyByValueStub) EXPECT_EQ(resVal.GetRawData(), 0); } -HWTEST_F_L0(StubTest, FastTypeOfTest) +HWTEST_F_L0(StubTest, SetPropertyByNameStub) { auto module = stubModule.GetModule(); - auto function = stubModule.GetStubFunction(FAST_STUB_ID(FastTypeOf)); + auto function = stubModule.GetStubFunction(FAST_STUB_ID(SetPropertyByName)); Circuit netOfGates; - FastTypeOfStub optimizer(&netOfGates); + SetPropertyByNameStub optimizer(&netOfGates); optimizer.GenerateCircuit(); netOfGates.PrintAllGates(); - bool verRes = Verifier::Run(&netOfGates); - ASSERT_TRUE(verRes); auto cfg = Scheduler::Run(&netOfGates); PrintCircuitByBasicBlock(cfg, netOfGates); LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function); llvmBuilder.Build(); - char *error = nullptr; - LLVMVerifyModule(module, LLVMAbortProcessAction, &error); LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu"); assembler.Run(); - LLVMDumpModule(module); - auto *typeOfPtr = - reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function)); - const GlobalEnvConstants *globalConst = thread->GlobalConstants(); - - // obj is JSTaggedValue::VALUE_TRUE - JSTaggedValue resultVal = typeOfPtr(thread, JSTaggedValue::True().GetRawData()); - JSTaggedValue expectResult = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::True()); - EXPECT_EQ(resultVal, globalConst->GetBooleanString()); - EXPECT_EQ(resultVal, expectResult); - - // obj is JSTaggedValue::VALUE_FALSE - JSTaggedValue resultVal2 = typeOfPtr(thread, JSTaggedValue::False().GetRawData()); - JSTaggedValue expectResult2 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::False()); - EXPECT_EQ(resultVal2, globalConst->GetBooleanString()); - EXPECT_EQ(resultVal2, expectResult2); - - // obj is JSTaggedValue::VALUE_NULL - JSTaggedValue resultVal3 = typeOfPtr(thread, JSTaggedValue::Null().GetRawData()); - JSTaggedValue expectResult3 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Null()); - EXPECT_EQ(resultVal3, globalConst->GetObjectString()); - EXPECT_EQ(resultVal3, expectResult3); - - // obj is JSTaggedValue::VALUE_UNDEFINED - JSTaggedValue resultVal4 = typeOfPtr(thread, JSTaggedValue::Undefined().GetRawData()); - JSTaggedValue expectResult4 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue::Undefined()); - EXPECT_EQ(resultVal4, globalConst->GetUndefinedString()); - EXPECT_EQ(resultVal4, expectResult4); - - // obj is IsNumber - JSTaggedValue resultVal5 = typeOfPtr(thread, JSTaggedValue(5).GetRawData()); - JSTaggedValue expectResult5 = FastRuntimeStub::FastTypeOf(thread, JSTaggedValue(5)); - EXPECT_EQ(resultVal5, globalConst->GetNumberString()); - EXPECT_EQ(resultVal5, expectResult5); - - // obj is String + assembler.Disassemble(); + auto *setPropertyByName = reinterpret_cast + (reinterpret_cast(assembler.GetFuncPtrFromCompiledModule(function))); auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory(); - JSHandle str1 = factory->NewFromStdString("a"); - JSHandle str2 = factory->NewFromStdString("a"); - JSTaggedValue expectResult6 = FastRuntimeStub::FastTypeOf(thread, str1.GetTaggedValue()); - JSTaggedValue resultVal6 = typeOfPtr(thread, str2.GetTaggedValue().GetRawData()); - EXPECT_EQ(resultVal6, globalConst->GetStringString()); - EXPECT_EQ(resultVal6, expectResult6); - - // obj is Symbol - JSHandle globalEnv = JSThread::Cast(thread)->GetEcmaVM()->GetGlobalEnv(); - JSTaggedValue symbol = globalEnv->GetIteratorSymbol().GetTaggedValue(); - JSTaggedValue expectResult7= FastRuntimeStub::FastTypeOf(thread, symbol); - JSTaggedValue resultVal7 = typeOfPtr(thread, symbol.GetRawData()); - EXPECT_EQ(resultVal7, globalConst->GetSymbolString()); - EXPECT_EQ(resultVal7, expectResult7); - - // obj is callable - JSHandle resolveCallable = - factory->CreateJSPromiseReactionsFunction(reinterpret_cast(BuiltinsPromiseHandler::Resolve)); - JSTaggedValue expectResult8= FastRuntimeStub::FastTypeOf(thread, resolveCallable.GetTaggedValue()); - JSTaggedValue resultVal8 = typeOfPtr(thread, resolveCallable.GetTaggedValue().GetRawData()); - EXPECT_EQ(resultVal8, globalConst->GetFunctionString()); - EXPECT_EQ(resultVal8, expectResult8); - - // obj is heapObject - JSHandle object = factory->NewEmptyJSObject(); - JSTaggedValue expectResult9= FastRuntimeStub::FastTypeOf(thread, object.GetTaggedValue()); - JSTaggedValue resultVal9 = typeOfPtr(thread, object.GetTaggedValue().GetRawData()); - EXPECT_EQ(resultVal9, globalConst->GetObjectString()); - EXPECT_EQ(resultVal9, expectResult9); + JSHandle obj = factory->NewEmptyJSObject(); + int x = 256; + int y = 10; + JSHandle strA(factory->NewFromCanBeCompressString("hello")); + JSHandle strBig(factory->NewFromCanBeCompressString("biggest")); + setPropertyByName(thread, obj.GetTaggedValue(), strA.GetTaggedValue(), JSTaggedValue(x), false); + setPropertyByName(thread, obj.GetTaggedValue(), strBig.GetTaggedValue(), JSTaggedValue(y), false); + auto resA = FastRuntimeStub::GetPropertyByName(thread, obj.GetTaggedValue(), strA.GetTaggedValue()); + EXPECT_EQ(resA.GetNumber(), x); + auto resB = FastRuntimeStub::GetPropertyByName(thread, obj.GetTaggedValue(), strBig.GetTaggedValue()); + EXPECT_EQ(resB.GetNumber(), y); } } // namespace panda::test diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index 41555801d7..c41396d6f9 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -222,7 +222,7 @@ JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& { INTERPRETER_TRACE(thread, ExecuteNative); JSTaggedType *sp = GetCurrentInterpretedFrameSp(thread); - + JSMethod *methodToCall = params.callTarget->GetCallTarget(); ASSERT(methodToCall->GetNumVregs() == 0); uint32_t numActualArgs = params.argc + RESERVED_CALL_ARGCOUNT; @@ -2127,7 +2127,14 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue value = GET_ACC(); // fast path SAVE_ACC(); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByName)); + typedef JSTaggedValue (*PFSetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue, JSTaggedValue, bool); + auto setPropertyByNamePtr = reinterpret_cast(stubAddr); + JSTaggedValue res = setPropertyByNamePtr(thread, receiver, propKey, value, true); +#else JSTaggedValue res = FastRuntimeStub::SetPropertyByName(thread, receiver, propKey, value); +#endif if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); RESTORE_ACC(); @@ -2844,7 +2851,14 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool JSTaggedValue value = GET_ACC(); // fast path SAVE_ACC(); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByName)); + typedef JSTaggedValue (*PFSetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue, JSTaggedValue, bool); + auto setPropertyByNamePtr = reinterpret_cast(stubAddr); + JSTaggedValue res = setPropertyByNamePtr(thread, receiver, propKey, value, true); +#else JSTaggedValue res = FastRuntimeStub::SetPropertyByName(thread, receiver, propKey, value); +#endif if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); JSFunction::SetFunctionNameNoPrefix(thread, JSFunction::Cast(value.GetTaggedObject()), propKey); @@ -2996,7 +3010,14 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool value = GET_ACC(); // fast path SAVE_ACC(); +#ifdef ECMASCRIPT_ENABLE_STUB_AOT + auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByName)); + typedef JSTaggedValue (*PFSetPropertyByName)(JSThread *, JSTaggedValue, JSTaggedValue, JSTaggedValue, bool); + auto setPropertyByNamePtr = reinterpret_cast(stubAddr); + JSTaggedValue res = setPropertyByNamePtr(thread, receiver, propKey, value, false); +#else JSTaggedValue res = FastRuntimeStub::SetPropertyByName(thread, receiver, propKey, value); +#endif if (!res.IsHole()) { INTERPRETER_RETURN_IF_ABRUPT(res); RESTORE_ACC(); diff --git a/ecmascript/mem/ecma_heap_manager-inl.h b/ecmascript/mem/ecma_heap_manager-inl.h index 8b9f0e146b..6eaf86536f 100644 --- a/ecmascript/mem/ecma_heap_manager-inl.h +++ b/ecmascript/mem/ecma_heap_manager-inl.h @@ -188,13 +188,18 @@ TaggedObject *EcmaHeapManager::AllocateMachineCodeSpaceObject(JSHClass *hclass, { auto object = reinterpret_cast(GetMachineCodeSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { - if (!heap_->FillMachineCodeSpaceAndTryGC(&GetMachineCodeSpaceAllocator())) { - return nullptr; + if (heap_->CheckAndTriggerMachineCodeGC()) { + object = reinterpret_cast(GetMachineCodeSpaceAllocator().Allocate(size)); } - object = reinterpret_cast(GetMachineCodeSpaceAllocator().Allocate(size)); if (UNLIKELY(object == nullptr)) { - heap_->ThrowOutOfMemoryError(size); - return nullptr; + if (!heap_->FillMachineCodeSpaceAndTryGC(&GetMachineCodeSpaceAllocator())) { + return nullptr; + } + object = reinterpret_cast(GetMachineCodeSpaceAllocator().Allocate(size)); + if (UNLIKELY(object == nullptr)) { + heap_->ThrowOutOfMemoryError(size); + return nullptr; + } } } SetClass(object, hclass); diff --git a/ecmascript/mem/heap-inl.h b/ecmascript/mem/heap-inl.h index a459e3e372..ad8709e10a 100644 --- a/ecmascript/mem/heap-inl.h +++ b/ecmascript/mem/heap-inl.h @@ -62,6 +62,7 @@ void Heap::IteratorOverObjects(const Callback &cb) const oldSpace_->IterateOverObjects(cb); nonMovableSpace_->IterateOverObjects(cb); hugeObjectSpace_->IterateOverObjects(cb); + machineCodeSpace_->IterateOverObjects(cb); } bool Heap::FillNewSpaceAndTryGC(BumpPointerAllocator *spaceAllocator, bool allowGc) diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 76bfc94b4c..7115b2a909 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -215,6 +215,11 @@ size_t Heap::VerifyHeapObjects() const hugeObjectSpace_->IterateOverObjects(verifier); } + { + VerifyObjectVisitor verifier(this, &failCount); + machineCodeSpace_->IterateOverObjects(verifier); + } + return failCount; } @@ -255,4 +260,13 @@ bool Heap::CheckAndTriggerNonMovableGC() CollectGarbage(TriggerGCType::NON_MOVE_GC); return true; } + +bool Heap::CheckAndTriggerMachineCodeGC() +{ + if (machineCodeSpace_->GetCommittedSize() <= DEFAULT_MACHINE_CODE_SPACE_LIMIT) { + return false; + } + CollectGarbage(TriggerGCType::MACHINE_CODE_GC); + return true; +} } // namespace panda::ecmascript diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index 55ce680c72..b246db549c 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -182,6 +182,8 @@ public: bool CheckAndTriggerNonMovableGC(); + bool CheckAndTriggerMachineCodeGC(); + const RegionFactory *GetRegionFactory() const { return regionFactory_; @@ -214,6 +216,10 @@ public: if (hugeObjectSpace_->IsLive(object)) { return true; } + // machine code space + if (machineCodeSpace_->IsLive(object)) { + return true; + } return false; } @@ -236,6 +242,10 @@ public: return true; } + // machine code space + if (machineCodeSpace_->ContainObject(object)) { + return true; + } return false; } diff --git a/ecmascript/mem/mem.h b/ecmascript/mem/mem.h index 83742742ad..480b6a4e5b 100644 --- a/ecmascript/mem/mem.h +++ b/ecmascript/mem/mem.h @@ -56,7 +56,8 @@ static constexpr size_t REGION_SIZE_LOG2 = 18U; static constexpr size_t DEFAULT_SNAPSHOT_SPACE_SIZE = 1U << REGION_SIZE_LOG2; static constexpr size_t MAX_SNAPSHOT_SPACE_SIZE = 8 * 1024 * 1024; -static constexpr size_t DEFAULT_MACHINE_CODE_SPACE_SIZE = 1024 * 1024; +static constexpr size_t DEFAULT_MACHINE_CODE_SPACE_SIZE = 256 * 1024; +static constexpr size_t DEFAULT_MACHINE_CODE_SPACE_LIMIT = 1024 * 1024; static constexpr size_t MAX_MACHINE_CODE_SPACE_SIZE = 8 * 1024 * 1024; static constexpr size_t MAX_HEAP_SIZE = 256 * 1024 * 1024; diff --git a/ecmascript/mem/old_space_collector.cpp b/ecmascript/mem/old_space_collector.cpp index 343f7c7e03..863f4745d7 100644 --- a/ecmascript/mem/old_space_collector.cpp +++ b/ecmascript/mem/old_space_collector.cpp @@ -33,6 +33,14 @@ OldSpaceCollector::OldSpaceCollector(Heap *heap, bool parallelGc) workList_ = new OldGCWorker(heap_, heap_->GetThreadPool()->GetThreadNum()); } +OldSpaceCollector::~OldSpaceCollector() +{ + if (workList_ != nullptr) { + delete workList_; + workList_ = nullptr; + } +} + void OldSpaceCollector::RunPhases() { [[maybe_unused]] ecmascript::JSThread *thread = heap_->GetEcmaVM()->GetJSThread(); diff --git a/ecmascript/mem/old_space_collector.h b/ecmascript/mem/old_space_collector.h index 5da8b52071..5473a50d48 100644 --- a/ecmascript/mem/old_space_collector.h +++ b/ecmascript/mem/old_space_collector.h @@ -35,7 +35,7 @@ class JSHClass; class OldSpaceCollector : public GarbageCollector { public: explicit OldSpaceCollector(Heap *heap, bool parallelGc); - ~OldSpaceCollector() override = default; + ~OldSpaceCollector() override; NO_COPY_SEMANTIC(OldSpaceCollector); NO_MOVE_SEMANTIC(OldSpaceCollector); void RunPhases(); diff --git a/ecmascript/mem/space.cpp b/ecmascript/mem/space.cpp index c1156bc0ee..1d93c6dac4 100644 --- a/ecmascript/mem/space.cpp +++ b/ecmascript/mem/space.cpp @@ -41,7 +41,7 @@ void Space::Initialize() region->SetFlag(RegionFlags::IS_IN_OLD_GENERATION); } else if (spaceType_ == MemSpaceType::MACHINE_CODE_SPACE) { region->InitializeKind(); - region->SetFlag(RegionFlags::IS_IN_OLD_GENERATION); + region->SetFlag(RegionFlags::IS_IN_NON_MOVABLE_GENERATION); int res = region->SetCodeExecutableAndReadable(); LOG_ECMA_MEM(DEBUG) << "Initialize SetCodeExecutableAndReadable" << res; } else if (spaceType_ == MemSpaceType::NON_MOVABLE) { @@ -433,10 +433,66 @@ bool MachineCodeSpace::Expand() } Region *region = const_cast(GetHeap()->GetRegionFactory())->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE); + region->SetFlag(IS_IN_NON_MOVABLE_GENERATION); region->InitializeKind(); AddRegion(region); int res = region->SetCodeExecutableAndReadable(); LOG_ECMA_MEM(DEBUG) << "MachineCodeSpace::Expand() SetCodeExecutableAndReadable" << res; return true; } + +size_t MachineCodeSpace::GetHeapObjectSize() const +{ + size_t result; + size_t availableSize = GetHeap()->GetHeapManager()->GetMachineCodeSpaceAllocator().GetAvailableSize(); + size_t regionSize = GetRegionList().GetLength() * DEFAULT_REGION_SIZE; + result = regionSize - availableSize; + return result; +} + +void MachineCodeSpace::IterateOverObjects(const std::function &visitor) const +{ + EnumerateRegions([&](Region *region) { + uintptr_t curPtr = region->GetBegin(); + uintptr_t endPtr = region->GetEnd(); + while (curPtr < endPtr) { + auto freeObject = FreeObject::Cast(curPtr); + size_t objSize; + if (!freeObject->IsFreeObject()) { + auto obj = reinterpret_cast(curPtr); + visitor(obj); + objSize = obj->GetObjectSize(); + } else { + objSize = freeObject->Available(); + } + LOG_IF(objSize == 0, FATAL, RUNTIME) << "MachineCodeSpace IterateOverObjects objSize==0 invalid: " << curPtr; + curPtr += AlignUp(objSize, sizeof(JSTaggedType)); + } + }); +} + +bool MachineCodeSpace::ContainObject(TaggedObject *object) const +{ + auto region = GetRegionList().GetFirst(); + while (region != nullptr) { + if (region->InRange(ToUintPtr(object))) { + return true; + } + region = region->GetNext(); + } + return false; +} + +bool MachineCodeSpace::IsLive(TaggedObject *object) const +{ + auto region = GetRegionList().GetFirst(); + while (region != nullptr) { + if (region->InRange(ToUintPtr(object))) { + auto freeObject = FreeObject::Cast(ToUintPtr(object)); + return !freeObject->IsFreeObject(); + } + region = region->GetNext(); + } + return false; +} } // namespace panda::ecmascript diff --git a/ecmascript/mem/space.h b/ecmascript/mem/space.h index 25f353e253..9d06af3f32 100644 --- a/ecmascript/mem/space.h +++ b/ecmascript/mem/space.h @@ -256,6 +256,10 @@ public: NO_COPY_SEMANTIC(MachineCodeSpace); NO_MOVE_SEMANTIC(MachineCodeSpace); bool Expand(); + bool ContainObject(TaggedObject *object) const; + bool IsLive(TaggedObject *object) const; + void IterateOverObjects(const std::function &objectVisitor) const; + size_t GetHeapObjectSize() const; }; } // namespace panda::ecmascript diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index ad76986c5c..50a84166bf 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -178,6 +178,7 @@ TaggedArray* RuntimeTrampolines::GetTaggedArrayPtrTest(uint64_t argThread) i++; return *arr; } + uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv) { @@ -194,15 +195,15 @@ uint64_t RuntimeTrampolines::Execute(uint64_t argThread, uint64_t argFunc, return EcmaInterpreter::Execute(thread, params).GetRawData(); } -void RuntimeTrampolines::SetValueWithBarrier(uint64_t argThread, uint64_t argAddr, uint64_t argOffset, +void RuntimeTrampolines::SetValueWithBarrier([[maybe_unused]] uint64_t argThread, uint64_t argAddr, uint64_t argOffset, uint64_t argValue) { - auto thread = reinterpret_cast(argThread); auto addr = reinterpret_cast(argAddr); auto offset = static_cast(argOffset); auto value = static_cast(argValue); - - SET_VALUE_WITH_BARRIER(thread, addr, offset, value); + if (value.IsHeapObject()) { + MarkingBarrier(addr, offset, value.GetRawData()); + } } double RuntimeTrampolines::FloatMod(double left, double right) @@ -220,4 +221,67 @@ uint64_t RuntimeTrampolines::NewInternalString(uint64_t argThread, uint64_t argK JSHandle keyHandle(thread, JSTaggedValue(reinterpret_cast(argKey))); return JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(keyHandle)).GetRawData(); } + +void RuntimeTrampolines::JSHClassAddProperty(uint64_t argThread, uint64_t receiver, uint64_t key, uint32_t attr) +{ + uintptr_t *curFp = nullptr; + auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(receiver))); + JSHandle keyHandle(thread, JSTaggedValue(reinterpret_cast(key))); + PropertyAttributes propAttr(attr); + JSHClass::AddProperty(thread, objHandle, keyHandle, propAttr); +} + +uint64_t RuntimeTrampolines::NewTaggedArray(uint64_t argThread, uint32_t length) +{ + uintptr_t *curFp = nullptr; + auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + return factory->NewTaggedArray(length).GetTaggedValue().GetRawData(); +} + +uint64_t RuntimeTrampolines::CopyArray(uint64_t argThread, uint64_t argArray, uint32_t length, uint32_t capacity) +{ + uintptr_t *curFp = nullptr; + auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle array(thread, JSTaggedValue(reinterpret_cast(argArray))); + return factory->CopyArray(array, length, capacity).GetTaggedValue().GetRawData(); +} + +uint64_t RuntimeTrampolines::NameDictPutIfAbsent(uint64_t argThread, uint64_t receiver, uint64_t array, uint64_t key, + uint64_t value, uint32_t attr, bool needTransToDict) +{ + uintptr_t *curFp = nullptr; + auto thread = reinterpret_cast(argThread); + GET_CURRETN_FP(curFp); + uintptr_t *prevFp = GET_PREV_FP(curFp); + CallRuntimeTrampolinesScope scope(thread, prevFp, curFp); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle keyHandle(thread, JSTaggedValue(reinterpret_cast(key))); + JSHandle valueHandle(thread, JSTaggedValue(reinterpret_cast(value))); + PropertyAttributes propAttr(attr); + if (needTransToDict) { + JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(receiver))); + JSHandle dictHandle(JSObject::TransitionToDictionary(thread, objHandle)); + return JSTaggedValue(NameDictionary:: + PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, propAttr)).GetRawData(); + } else { + JSHandle dictHandle(thread, JSTaggedValue(reinterpret_cast(array))); + return JSTaggedValue(NameDictionary:: + PutIfAbsent(thread, dictHandle, keyHandle, valueHandle, propAttr)).GetRawData(); + } +} } // namespace panda::ecmascript diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index c6396b2294..43e71a2105 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -56,6 +56,11 @@ public: static double FloatMod(double left, double right); static uint64_t NewInternalString(uint64_t argThread, uint64_t argKey); static void PrintHeapReginInfo(uint64_t argThread); + static void JSHClassAddProperty(uint64_t argThread, uint64_t receiver, uint64_t key, uint32_t attr); + static uint64_t NewTaggedArray(uint64_t argThread, uint32_t length); + static uint64_t CopyArray(uint64_t argThread, uint64_t array, uint32_t length, uint32_t capacity); + static uint64_t NameDictPutIfAbsent(uint64_t argThread, uint64_t receiver, uint64_t array, uint64_t key, + uint64_t value, uint32_t attr, bool needTransToDict); }; class CallRuntimeTrampolinesScope { @@ -71,15 +76,11 @@ public: thread->SetLastIFrameSp(cursp); JSTaggedType *newSp = static_cast(static_cast(newFp)); thread_->SetCurrentSPFrame(newSp); - LOG_ECMA(INFO) << "Sp: " << newSp << " type:" << - static_cast(FrameHandler(newSp).GetFrameType()); } ~CallRuntimeTrampolinesScope() { JSTaggedType *oldSp = static_cast(static_cast(lastFp_)); thread_->SetCurrentSPFrame(oldSp); - LOG_ECMA(INFO) << "Sp: " << oldSp << " type:" << - static_cast(FrameHandler(oldSp).GetFrameType()); thread_->SetLastOptCallRuntimePc(lastOptCallRuntimePc_); } private: diff --git a/ecmascript/stub_module.cpp b/ecmascript/stub_module.cpp index 9449ac3c0a..8eba7cc8f2 100644 --- a/ecmascript/stub_module.cpp +++ b/ecmascript/stub_module.cpp @@ -53,9 +53,6 @@ void StubModule::Save(const std::string &filename) void StubModule::Load(JSThread *thread, const std::string &filename) { -#ifndef NDEBUG - Logger::SetLevel(Logger::Level::INFO); -#endif // now MachineCode is non movable, code and stackmap sperately is saved to MachineCode // by calling NewMachineCodeObject. // then MachineCode will support movable, code is saved to MachineCode and stackmap is saved -- Gitee