diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index bb62715e91..481d89a664 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -131,7 +131,8 @@ int Main(const int argc, const char **argv) cOptions.isEnableCollectLiteralInfo_, cOptions.isEnableOptConstantFolding_, cOptions.isEnableLexenvSpecialization_, - cOptions.isEnableNativeInline_); + cOptions.isEnableNativeInline_, + cOptions.isEnableFastModule_); PassManager passManager(vm, cOptions.triple_, diff --git a/ecmascript/compiler/aot_compiler_preprocessor.cpp b/ecmascript/compiler/aot_compiler_preprocessor.cpp index e437e1cc8f..70e52a1ec2 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.cpp +++ b/ecmascript/compiler/aot_compiler_preprocessor.cpp @@ -59,6 +59,7 @@ CompilationOptions::CompilationOptions(EcmaVM *vm, JSRuntimeOptions &runtimeOpti isEnableCollectLiteralInfo_ = false; isEnableLexenvSpecialization_ = runtimeOptions.IsEnableLexenvSpecialization(); isEnableNativeInline_ = runtimeOptions.IsEnableNativeInline(); + isEnableFastModule_ = runtimeOptions.IsEnableFastModule(); } bool AotCompilerPreprocessor::HandleTargetCompilerMode(CompilationOptions &cOptions) diff --git a/ecmascript/compiler/aot_compiler_preprocessor.h b/ecmascript/compiler/aot_compiler_preprocessor.h index 0362df2aa4..d232f3d1fe 100644 --- a/ecmascript/compiler/aot_compiler_preprocessor.h +++ b/ecmascript/compiler/aot_compiler_preprocessor.h @@ -64,6 +64,7 @@ struct CompilationOptions { bool isEnableLexenvSpecialization_; bool isEnableNativeInline_; bool isEnablePGOHCRLowering_; + bool isEnableFastModule_; }; class AotCompilerPreprocessor { diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 20d19b5567..2f7cbcfc2c 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -327,6 +327,9 @@ public: GateRef TypedCallNative(GateRef hirGate, GateRef thisObj, GateRef funcId); GateRef IsBase(GateRef ctor); GateRef ToLength(GateRef receiver); + GateRef StoreModuleVar(GateRef jsFunc, GateRef index, GateRef value); + GateRef LdLocalModuleVar(GateRef jsFunc, GateRef index); + GateRef BuiltinConstructor(BuiltinTypeId id, GateRef gate); inline GateRef GetMethodId(GateRef func); inline GateRef IsAOTLiteralInfo(GateRef x); @@ -397,6 +400,7 @@ public: inline void StoreHClass(GateRef glue, GateRef object, GateRef hClass); GateRef IsStabelArray(GateRef glue, GateRef obj); inline void StorePrototype(GateRef glue, GateRef hclass, GateRef prototype); + void SetExtensibleToBitfield(GateRef glue, GateRef obj, bool isExtensible); // WeakRef inline GateRef CreateWeakRef(GateRef x); @@ -456,6 +460,7 @@ public: GateRef InsertStableArrayCheck(GateRef array); GateRef InsertLoadArrayLength(GateRef array, bool isTypedArray); GateRef InsertTypedArrayCheck(GateType type, GateRef array); + GateRef ArrayConstructorCheck(GateRef gate); GateRef InsertTypedBinaryop(GateRef left, GateRef right, GateType leftType, GateType rightType, GateType gateType, PGOTypeRef pgoType, TypedBinOp op); GateRef InsertRangeCheckPredicate(GateRef left, TypedBinOp cond, GateRef right); diff --git a/ecmascript/compiler/early_elimination.cpp b/ecmascript/compiler/early_elimination.cpp index eee3b1064b..d98605c7ff 100644 --- a/ecmascript/compiler/early_elimination.cpp +++ b/ecmascript/compiler/early_elimination.cpp @@ -87,6 +87,7 @@ GateRef EarlyElimination::VisitGate(GateRef gate) case OpCode::ECMA_STRING_CHECK: case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK: case OpCode::TYPE_OF_CHECK: + case OpCode::ARRAY_CONSTRUCTOR_CHECK: return TryEliminateGate(gate); case OpCode::STATE_SPLIT: return TryEliminateFrameState(gate); @@ -364,6 +365,10 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs) } break; } + case OpCode::ARRAY_CONSTRUCTOR_CHECK: + if (acc_.GetValueIn(lhs) != acc_.GetValueIn(rhs)) { + return false; + } default: break; } diff --git a/ecmascript/compiler/hcr_circuit_builder.cpp b/ecmascript/compiler/hcr_circuit_builder.cpp index 0a391d2f51..d339e84332 100644 --- a/ecmascript/compiler/hcr_circuit_builder.cpp +++ b/ecmascript/compiler/hcr_circuit_builder.cpp @@ -457,4 +457,70 @@ GateRef CircuitBuilder::IsStabelArray(GateRef glue, GateRef obj) env_->SubCfgExit(); return res; } + +GateRef CircuitBuilder::StoreModuleVar(GateRef jsFunc, GateRef index, GateRef value) +{ + auto currentLabel = env_->GetCurrentLabel(); + auto currentControl = currentLabel->GetControl(); + auto currentDepend = currentLabel->GetDepend(); + GateRef newGate = GetCircuit()->NewGate(circuit_->StoreModuleVar(), MachineType::I64, + { currentControl, currentDepend, jsFunc, index, value }, GateType::TaggedValue()); + currentLabel->SetControl(newGate); + currentLabel->SetDepend(newGate); + return newGate; +} + +GateRef CircuitBuilder::LdLocalModuleVar(GateRef jsFunc, GateRef index) +{ + auto currentLabel = env_->GetCurrentLabel(); + auto currentControl = currentLabel->GetControl(); + auto currentDepend = currentLabel->GetDepend(); + GateRef newGate = GetCircuit()->NewGate(circuit_->LdLocalModuleVar(), MachineType::I64, + { currentControl, currentDepend, jsFunc, index}, GateType::TaggedValue()); + currentLabel->SetControl(newGate); + currentLabel->SetDepend(newGate); + return newGate; +} + +GateRef CircuitBuilder::BuiltinConstructor(BuiltinTypeId id, GateRef gate) +{ + auto currentLabel = env_->GetCurrentLabel(); + auto currentControl = currentLabel->GetControl(); + auto currentDepend = currentLabel->GetDepend(); + GateRef newGate = Circuit::NullGate(); + switch (id) { + case BuiltinTypeId::ARRAY: { + if (acc_.GetNumValueIn(gate) == 1) { + newGate = GetCircuit()->NewGate(circuit_->ArrayConstructor(1), MachineType::I64, + { currentControl, currentDepend, acc_.GetValueIn(gate, 0)}, + GateType::TaggedValue()); + } else { + ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: num value in + newGate = GetCircuit()->NewGate(circuit_->ArrayConstructor(2), MachineType::I64, + { currentControl, currentDepend, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)}, + GateType::TaggedValue()); + } + break; + } + default: + LOG_ECMA(FATAL) << "this branch is unreachable"; + UNREACHABLE(); + break; + } + currentLabel->SetControl(newGate); + currentLabel->SetDepend(newGate); + return newGate; +} + +void CircuitBuilder::SetExtensibleToBitfield(GateRef glue, GateRef obj, bool isExtensible) +{ + GateRef jsHclass = LoadHClass(obj); + GateRef bitfield = Load(VariableType::INT32(), jsHclass, IntPtr(JSHClass::BIT_FIELD_OFFSET)); + GateRef boolVal = Boolean(isExtensible); + GateRef boolToInt32 = ZExtInt1ToInt32(boolVal); + GateRef encodeValue = Int32LSL(boolToInt32, Int32(JSHClass::ExtensibleBit::START_BIT)); + GateRef mask = Int32(((1LU << JSHClass::ExtensibleBit::SIZE) - 1) << JSHClass::ExtensibleBit::START_BIT); + bitfield = Int32Or(Int32And(bitfield, Int32Not(mask)), encodeValue); + Store(VariableType::INT32(), glue, jsHclass, IntPtr(JSHClass::BIT_FIELD_OFFSET), bitfield); +} } \ No newline at end of file diff --git a/ecmascript/compiler/hcr_opcodes.h b/ecmascript/compiler/hcr_opcodes.h index 9dc9bbb1a7..bfd544eaf1 100644 --- a/ecmascript/compiler/hcr_opcodes.h +++ b/ecmascript/compiler/hcr_opcodes.h @@ -19,7 +19,10 @@ namespace panda::ecmascript::kungfu { #define HCR_IMMUTABLE_META_DATA_CACHE_LIST(V) \ - V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) + V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) \ + V(StoreModuleVar, STORE_MODULE_VAR, GateFlags::NONE_FLAG, 1, 1, 3) \ + V(LdLocalModuleVar, LD_LOCAL_MODULE_VAR, GateFlags::NONE_FLAG, 1, 1, 2) + #define HCR_GATE_META_DATA_LIST_WITH_VALUE_IN(V) \ V(Call, CALL, GateFlags::NONE_FLAG, 0, 1, value) \ @@ -30,7 +33,8 @@ namespace panda::ecmascript::kungfu { V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value) \ V(RuntimeCall, RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value) \ V(RuntimeCallWithArgv, RUNTIME_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \ - V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value) + V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value) \ + V(ArrayConstructor, ARRAY_CONSTRUCTOR, GateFlags::NONE_FLAG, 1, 1, value) #define HCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \ V(Construct, CONSTRUCT, GateFlags::HAS_FRAME_STATE, 1, 1, value) diff --git a/ecmascript/compiler/mcr_circuit_builder.cpp b/ecmascript/compiler/mcr_circuit_builder.cpp index d0dd27b966..d6b442f2d9 100644 --- a/ecmascript/compiler/mcr_circuit_builder.cpp +++ b/ecmascript/compiler/mcr_circuit_builder.cpp @@ -1198,4 +1198,17 @@ GateRef CircuitBuilder::NeedCheckProperty(GateRef receiver) SubCfgExit(); return ret; } + +GateRef CircuitBuilder::ArrayConstructorCheck(GateRef gate) +{ + auto currentLabel = env_->GetCurrentLabel(); + auto currentControl = currentLabel->GetControl(); + auto currentDepend = currentLabel->GetDepend(); + auto frameState = acc_.FindNearestFrameState(currentDepend); + GateRef ret = GetCircuit()->NewGate(circuit_->ArrayConstructorCheck(), + MachineType::I64, {currentControl, currentDepend, gate, frameState}, GateType::IntType()); + currentLabel->SetControl(ret); + currentLabel->SetDepend(ret); + return ret; +} } diff --git a/ecmascript/compiler/mcr_opcodes.h b/ecmascript/compiler/mcr_opcodes.h index 88d7d3eddd..3c704434c0 100644 --- a/ecmascript/compiler/mcr_opcodes.h +++ b/ecmascript/compiler/mcr_opcodes.h @@ -50,6 +50,7 @@ namespace panda::ecmascript::kungfu { V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \ V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \ V(InlineAccessorCheck, INLINE_ACCESSOR_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \ + V(ArrayConstructorCheck, ARRAY_CONSTRUCTOR_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ MCR_BINARY_GATE_META_DATA_CACHE_LIST(V) #define MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \ diff --git a/ecmascript/compiler/ntype_bytecode_lowering.cpp b/ecmascript/compiler/ntype_bytecode_lowering.cpp index 161087a52d..f7f747c9a1 100644 --- a/ecmascript/compiler/ntype_bytecode_lowering.cpp +++ b/ecmascript/compiler/ntype_bytecode_lowering.cpp @@ -75,6 +75,14 @@ void NTypeBytecodeLowering::Lower(GateRef gate) case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16: LowerStLexVar(gate); break; + case EcmaOpcode::LDLOCALMODULEVAR_IMM8: + case EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16: + LowerLdLocalMoudleVar(gate); + break; + case EcmaOpcode::STMODULEVAR_IMM8: + case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16: + LowerStModuleVar(gate); + break; default: break; } @@ -82,6 +90,7 @@ void NTypeBytecodeLowering::Lower(GateRef gate) void NTypeBytecodeLowering::LowerThrowUndefinedIfHoleWithName(GateRef gate) { + AddProfiling(gate); GateRef value = acc_.GetValueIn(gate, 1); // 1: the second parameter builder_.LexVarIsHoleCheck(value); acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate()); @@ -233,4 +242,29 @@ void NTypeBytecodeLowering::AddProfiling(GateRef gate) builder_.SetDepend(acc_.GetDep(gate)); // set gate depend: profiling or STATE_SPLIT } } + +void NTypeBytecodeLowering::LowerLdLocalMoudleVar(GateRef gate) +{ + if (!IsFastModule()) { + return; + } + AddProfiling(gate); + GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); + GateRef index = acc_.GetValueIn(gate, 0); + GateRef result = builder_.LdLocalModuleVar(jsFunc, index); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); +} + +void NTypeBytecodeLowering::LowerStModuleVar(GateRef gate) +{ + if (!IsFastModule()) { + return; + } + AddProfiling(gate); + GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); + GateRef index = acc_.GetValueIn(gate, 0); + GateRef value = acc_.GetValueIn(gate, 1); + builder_.StoreModuleVar(jsFunc, index, value); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); +} } diff --git a/ecmascript/compiler/ntype_bytecode_lowering.h b/ecmascript/compiler/ntype_bytecode_lowering.h index 4e90d960f6..b522fda91c 100644 --- a/ecmascript/compiler/ntype_bytecode_lowering.h +++ b/ecmascript/compiler/ntype_bytecode_lowering.h @@ -26,7 +26,7 @@ namespace panda::ecmascript::kungfu { class NTypeBytecodeLowering { public: NTypeBytecodeLowering(Circuit *circuit, PassContext *ctx, TSManager *tsManager, - bool enableLog, const std::string& name) + bool enableLog, const std::string& name, bool fastModule) : circuit_(circuit), acc_(circuit), builder_(circuit, ctx->GetCompilerConfig()), @@ -37,7 +37,9 @@ public: profiling_(ctx->GetCompilerConfig()->IsProfiling()), traceBc_(ctx->GetCompilerConfig()->IsTraceBC()), methodName_(name), - glue_(acc_.GetGlueFromArgList()) {} + glue_(acc_.GetGlueFromArgList()), + argAcc_(circuit), + fastModule_(fastModule) {} ~NTypeBytecodeLowering() = default; @@ -50,6 +52,8 @@ private: void LowerLdLexVar(GateRef gate); void LowerStLexVar(GateRef gate); void LowerThrowUndefinedIfHoleWithName(GateRef gate); + void LowerLdLocalMoudleVar(GateRef gate); + void LowerStModuleVar(GateRef gate); bool IsLogEnabled() const { @@ -66,6 +70,11 @@ private: return traceBc_; } + bool IsFastModule() const + { + return fastModule_; + } + const std::string& GetMethodName() const { return methodName_; @@ -83,6 +92,8 @@ private: bool traceBc_ {false}; std::string methodName_; GateRef glue_ {Circuit::NullGate()}; + ArgumentAccessor argAcc_; + bool fastModule_; }; } // panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_NTYPE_BYTECODE_LOWERING_H diff --git a/ecmascript/compiler/ntype_hcr_lowering.cpp b/ecmascript/compiler/ntype_hcr_lowering.cpp index eaab6542d9..0fcc8c35a5 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.cpp +++ b/ecmascript/compiler/ntype_hcr_lowering.cpp @@ -30,6 +30,12 @@ GateRef NTypeHCRLowering::VisitGate(GateRef gate) case OpCode::CREATE_ARRAY_WITH_BUFFER: LowerCreateArrayWithBuffer(gate, glue); break; + case OpCode::STORE_MODULE_VAR: + LowerStoreModuleVar(gate, glue); + break; + case OpCode::LD_LOCAL_MODULE_VAR: + LowerLdLocalModuleVar(gate); + break; default: break; } @@ -199,4 +205,126 @@ GateRef NTypeHCRLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int in return result; } } + +void NTypeHCRLowering::LowerStoreModuleVar(GateRef gate, GateRef glue) +{ + Environment env(gate, circuit_, &builder_); + GateRef jsFunc = acc_.GetValueIn(gate, 0); + GateRef index = acc_.GetValueIn(gate, 1); + GateRef value = acc_.GetValueIn(gate, 2); + GateRef method = builder_.GetMethodFromFunction(jsFunc); + GateRef moduleOffset = builder_.IntPtr(Method::ECMA_MODULE_OFFSET); + GateRef module = builder_.Load(VariableType::JS_ANY(), method, moduleOffset); + GateRef localExportEntriesOffset = builder_.IntPtr(SourceTextModule::LOCAL_EXPORT_ENTTRIES_OFFSET); + GateRef localExportEntries = builder_.Load(VariableType::JS_ANY(), module, localExportEntriesOffset); + GateRef nameDictionaryOffset = builder_.IntPtr(SourceTextModule::NAME_DICTIONARY_OFFSET); + GateRef data = builder_.Load(VariableType::JS_ANY(), module, nameDictionaryOffset); + DEFVALUE(array, (&builder_), VariableType::JS_ANY(), data); + + Label dataIsUndefined(&builder_); + Label exit(&builder_); + builder_.Branch(builder_.TaggedIsUndefined(data), &dataIsUndefined, &exit); + builder_.Bind(&dataIsUndefined); + { + GateRef size = builder_.GetLengthOfTaggedArray(localExportEntries); + Label fastpath(&builder_); + Label slowPath(&builder_); + Label finishNew(&builder_); + builder_.Branch(builder_.Int32LessThan(size, builder_.Int32(MAX_TAGGED_ARRAY_LENGTH)), &fastpath, &slowPath); + builder_.Bind(&fastpath); + { + array = NewTaggedArray(size); + builder_.Jump(&finishNew); + } + builder_.Bind(&slowPath); + { + array = LowerCallRuntime(glue, gate, RTSTUB_ID(NewTaggedArray), { builder_.Int32ToTaggedInt(size) }, true); + builder_.Jump(&finishNew); + } + builder_.Bind(&finishNew); + { + builder_.StoreConstOffset(VariableType::JS_ANY(), module, SourceTextModule::NAME_DICTIONARY_OFFSET, *array); + builder_.Jump(&exit); + } + } + builder_.Bind(&exit); + GateRef dataOffset = builder_.Int32(TaggedArray::DATA_OFFSET); + GateRef indexOffset = builder_.Int32Mul(index, builder_.Int32(JSTaggedValue::TaggedTypeSize())); + GateRef offset = builder_.Int32Add(indexOffset, dataOffset); + builder_.Store(VariableType::JS_ANY(), glue_, *array, offset, value); + ReplaceGateWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); +} + +GateRef NTypeHCRLowering::NewTaggedArray(GateRef length) +{ + Label subentry(&builder_); + builder_.SubCfgEntry(&subentry); + Label exit(&builder_); + DEFVALUE(array, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); + GateRef hclass = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_CLASS_INDEX); + GateRef size = builder_.ComputeTaggedArraySize(builder_.ZExtInt32ToPtr(length)); + builder_.StartAllocate(); + array = builder_.HeapAlloc(size, GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE); + builder_.StoreConstOffset(VariableType::JS_POINTER(), *array, 0, hclass); + builder_.StoreConstOffset(VariableType::JS_ANY(), *array, TaggedArray::LENGTH_OFFSET, + builder_.Int32ToTaggedInt(length)); + GateRef dataOffset = builder_.Int32(TaggedArray::DATA_OFFSET); + GateRef offset = builder_.Int32Mul(length, builder_.Int32(JSTaggedValue::TaggedTypeSize())); + GateRef endOffset = builder_.Int32Add(offset, builder_.Int32(TaggedArray::DATA_OFFSET)); + Label loopHead(&builder_); + Label loopEnd(&builder_); + DEFVALUE(startOffset, (&builder_), VariableType::INT32(), dataOffset); + builder_.Branch(builder_.Int32UnsignedLessThan(*startOffset, endOffset), &loopHead, &exit); + builder_.LoopBegin(&loopHead); + builder_.Store(VariableType::INT64(), glue_, *array, *startOffset, builder_.Hole()); + startOffset = builder_.Int32Add(*startOffset, builder_.Int32(JSTaggedValue::TaggedTypeSize())); + builder_.Branch(builder_.Int32UnsignedLessThan(*startOffset, endOffset), &loopEnd, &exit); + builder_.Bind(&loopEnd); + builder_.LoopEnd(&loopHead); + builder_.Bind(&exit); + builder_.FinishAllocate(); + auto ret = *array; + builder_.SubCfgExit(); + return ret; +} + +void NTypeHCRLowering::LowerLdLocalModuleVar(GateRef gate) +{ + Environment env(gate, circuit_, &builder_); + GateRef jsFunc = acc_.GetValueIn(gate, 0); + GateRef index = acc_.GetValueIn(gate, 1); + GateRef method = builder_.GetMethodFromFunction(jsFunc); + GateRef moduleOffset = builder_.IntPtr(Method::ECMA_MODULE_OFFSET); + GateRef module = builder_.Load(VariableType::JS_ANY(), method, moduleOffset); + GateRef nameDictionaryOffset = builder_.IntPtr(SourceTextModule::NAME_DICTIONARY_OFFSET); + GateRef dictionary = builder_.Load(VariableType::JS_ANY(), module, nameDictionaryOffset); + DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Hole()); + Label dataIsNotUndefined(&builder_); + Label exit(&builder_); + builder_.Branch(builder_.TaggedIsUndefined(dictionary), &exit, &dataIsNotUndefined); + builder_.Bind(&dataIsNotUndefined); + { + GateRef dataOffset = builder_.Int32(TaggedArray::DATA_OFFSET); + GateRef indexOffset = builder_.Int32Mul(index, builder_.Int32(JSTaggedValue::TaggedTypeSize())); + GateRef offset = builder_.Int32Add(indexOffset, dataOffset); + result = builder_.Load(VariableType::JS_ANY(), dictionary, offset); + builder_.Jump(&exit); + } + builder_.Bind(&exit); + ReplaceGateWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), *result); +} + +void NTypeHCRLowering::ReplaceGateWithPendingException(GateRef gate, GateRef state, GateRef depend, GateRef value) +{ + auto condition = builder_.HasPendingException(glue_); + GateRef ifBranch = builder_.Branch(state, condition); + GateRef ifTrue = builder_.IfTrue(ifBranch); + GateRef ifFalse = builder_.IfFalse(ifBranch); + GateRef eDepend = builder_.DependRelay(ifTrue, depend); + GateRef sDepend = builder_.DependRelay(ifFalse, depend); + + StateDepend success(ifFalse, sDepend); + StateDepend exception(ifTrue, eDepend); + acc_.ReplaceHirWithIfBranch(gate, success, exception, value); +} } diff --git a/ecmascript/compiler/ntype_hcr_lowering.h b/ecmascript/compiler/ntype_hcr_lowering.h index 3c1cad18c1..ece0f796ca 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.h +++ b/ecmascript/compiler/ntype_hcr_lowering.h @@ -46,15 +46,17 @@ private: void LowerCreateArrayWithBuffer(GateRef gate, GateRef glue); void LowerCreateEmptyArray(GateRef gate); void LowerCreateArrayWithOwn(GateRef gate, GateRef glue); - void LowerStLexVar(GateRef gate); - void LowerLdLexVar(GateRef gate); + void LowerStoreModuleVar(GateRef gate, GateRef glue); + void LowerLdLocalModuleVar(GateRef gate); GateRef LoadFromConstPool(GateRef jsFunc, size_t index, size_t valVecType); GateRef NewJSArrayLiteral(GateRef gate, GateRef elements, GateRef length); GateRef NewTaggedArray(size_t length); + GateRef NewTaggedArray(GateRef length); GateRef CreateElementsWithLength(GateRef gate, GateRef glue, size_t arrayLength); GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector &args, bool useLabel = false); + void ReplaceGateWithPendingException(GateRef gate, GateRef state, GateRef depend, GateRef value); GateRef GetFrameState(GateRef gate) const { diff --git a/ecmascript/compiler/number_speculative_retype.cpp b/ecmascript/compiler/number_speculative_retype.cpp index 1e5d43c820..60fb76a586 100644 --- a/ecmascript/compiler/number_speculative_retype.cpp +++ b/ecmascript/compiler/number_speculative_retype.cpp @@ -143,6 +143,8 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate) case OpCode::STORE_CONST_OFFSET: case OpCode::LEX_VAR_IS_HOLE_CHECK: case OpCode::TYPE_OF_CHECK: + // case OpCode::ARRAY_CONSTRUCTOR: + case OpCode::LD_LOCAL_MODULE_VAR: return VisitOthers(gate); default: return Circuit::NullGate(); diff --git a/ecmascript/compiler/pass.h b/ecmascript/compiler/pass.h index d5a1310c17..17788e4c2a 100644 --- a/ecmascript/compiler/pass.h +++ b/ecmascript/compiler/pass.h @@ -299,7 +299,7 @@ public: bool enableLog = data->GetLog()->EnableMethodCIRLog(); bool enableTypeLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType(); TypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), - enableLog, enableTypeLog, data->GetMethodName()); + enableLog, enableTypeLog, data->GetMethodName(), passOptions->EnableFastModule()); bool success = lowering.RunTypeBytecodeLowering(); if (!success) { data->MarkAsTypeAbort(); @@ -329,7 +329,7 @@ public: TimeScope timescope("NTypeBytecodeLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); bool enableLog = data->GetLog()->EnableMethodCIRLog(); NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), data->GetTSManager(), - enableLog, data->GetMethodName()); + enableLog, data->GetMethodName(), passOptions->EnableFastModule()); lowering.RunNTypeBytecodeLowering(); Chunk chunk(data->GetNativeAreaAllocator()); CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); diff --git a/ecmascript/compiler/pass_manager.h b/ecmascript/compiler/pass_manager.h index 7de90652ae..7686f9b0d7 100644 --- a/ecmascript/compiler/pass_manager.h +++ b/ecmascript/compiler/pass_manager.h @@ -135,7 +135,8 @@ public: bool enableLaterElimination, bool enableValueNumbering, bool enableTypeInfer, bool enableOptInlining, bool enableOptPGOType, bool enableOptTrackField, bool enableOptLoopPeeling, bool enableOptOnHeapCheck, bool enableOptLoopInvariantCodeMotion, bool enableCollectLiteralInfo, - bool enableOptConstantFolding, bool enableLexenvSpecialization, bool enableInlineNative) + bool enableOptConstantFolding, bool enableLexenvSpecialization, bool enableInlineNative, + bool enableFastModule) : enableArrayBoundsCheckElimination_(enableArrayBoundsCheckElimination), enableTypeLowering_(enableTypeLowering), enableEarlyElimination_(enableEarlyElimination), @@ -151,7 +152,8 @@ public: enableCollectLiteralInfo_(enableCollectLiteralInfo), enableOptConstantFolding_(enableOptConstantFolding), enableLexenvSpecialization_(enableLexenvSpecialization), - enableInlineNative_(enableInlineNative) + enableInlineNative_(enableInlineNative), + enableFastModule_(enableFastModule) { } @@ -173,7 +175,8 @@ public: V(CollectLiteralInfo, false) \ V(OptConstantFolding, true) \ V(LexenvSpecialization, false) \ - V(InlineNative, false) + V(InlineNative, false) \ + V(FastModule, false) #define DECL_OPTION(NAME, DEFAULT) \ public: \ diff --git a/ecmascript/compiler/share_gate_meta_data.h b/ecmascript/compiler/share_gate_meta_data.h index 71d0ddeceb..316885c87f 100644 --- a/ecmascript/compiler/share_gate_meta_data.h +++ b/ecmascript/compiler/share_gate_meta_data.h @@ -72,6 +72,7 @@ enum class TypedCallTargetCheckOp : uint8_t; V(IteratorFunctionDisMactch, ITERATORFUNCTIONDISMATCH) \ V(NativeCallTargetDisMatch, NATIVECALLTARGETDISMATCH) \ V(ProtoTypeChanged, PROTOTYPECHANGED) \ + V(NewBuiltinCtorFail, NEWBUILTINCTORFAIL) \ enum class DeoptType : uint8_t { NOTCHECK = 0, diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index 836aa64577..1f17aa3e30 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -200,7 +200,7 @@ inline GateRef StubBuilder::CallRuntime(GateRef glue, int index, const std::init SavePcIfNeeded(glue); const std::string name = RuntimeStubCSigns::GetRTName(index); GateRef result = env_->GetBuilder()->CallRuntime(glue, index, Gate::InvalidGateRef, args, - Circuit::NullGate(), name.c_str()); + glue, name.c_str()); return result; } diff --git a/ecmascript/compiler/type_bytecode_lowering.cpp b/ecmascript/compiler/type_bytecode_lowering.cpp index 9d68b9e4ec..ea412f7312 100644 --- a/ecmascript/compiler/type_bytecode_lowering.cpp +++ b/ecmascript/compiler/type_bytecode_lowering.cpp @@ -283,6 +283,7 @@ void TypeBytecodeLowering::Lower(GateRef gate) case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: + LowerTypedNewObjRange(gate); break; case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8: case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8: @@ -1472,27 +1473,33 @@ void TypeBytecodeLowering::LowerTypedNewObjRange(GateRef gate) { GateRef ctor = acc_.GetValueIn(gate, 0); GateType ctorType = acc_.GetGateType(ctor); - if (!tsManager_->IsClassTypeKind(ctorType)) { - return; + GlobalTSTypeRef ctorGT = ctorType.GetGTRef(); + if (ctorGT.IsBuiltinModule()) { + if (TryLowerNewBuiltinConstructor(gate)) { + return; + } } +} - AddProfiling(gate); - - int hclassIndex = tsManager_->GetHClassIndexByClassGateType(ctorType); - GateRef stateSplit = acc_.GetDep(gate); - - GateRef frameState = acc_.FindNearestFrameState(stateSplit); - GateRef thisObj = builder_.TypedNewAllocateThis(ctor, builder_.IntPtr(hclassIndex), frameState); - - // call constructor - size_t range = acc_.GetNumValueIn(gate); - GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(range, EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8)); - std::vector args { glue_, actualArgc, ctor, ctor, thisObj }; - for (size_t i = 1; i < range; ++i) { // 1:skip ctor - args.emplace_back(acc_.GetValueIn(gate, i)); +bool TypeBytecodeLowering::TryLowerNewBuiltinConstructor(GateRef gate) +{ + GateRef ctor = acc_.GetValueIn(gate, 0); + GateType ctorType = acc_.GetGateType(ctor); + GlobalTSTypeRef ctorGT = ctorType.GetGTRef(); + GateRef constructGate = Circuit::NullGate(); + if (tsManager_->IsBuiltinConstructor(BuiltinTypeId::ARRAY, ctorGT) && enableNewArrayInline_) { + if (acc_.GetNumValueIn(gate) <= 2) { // 2: ctor and first arg + if (!Uncheck()) { + builder_.ArrayConstructorCheck(ctor); + } + constructGate = builder_.BuiltinConstructor(BuiltinTypeId::ARRAY, gate); + } + } + if (constructGate == Circuit::NullGate()) { + return false; } - GateRef constructGate = builder_.Construct(gate, args); acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate); + return true; } void TypeBytecodeLowering::LowerTypedSuperCall(GateRef gate) diff --git a/ecmascript/compiler/type_bytecode_lowering.h b/ecmascript/compiler/type_bytecode_lowering.h index b40dafc4ec..6eda1e3b32 100644 --- a/ecmascript/compiler/type_bytecode_lowering.h +++ b/ecmascript/compiler/type_bytecode_lowering.h @@ -29,7 +29,7 @@ class TypeBytecodeLowering { public: TypeBytecodeLowering(Circuit *circuit, PassContext *ctx, bool enableLog, bool enableTypeLog, - const std::string& name) + const std::string& name, bool enableNewArrayInline) : circuit_(circuit), acc_(circuit), builder_(circuit, ctx->GetCompilerConfig()), @@ -45,7 +45,8 @@ public: argAcc_(circuit), pgoTypeLog_(circuit), noCheck_(ctx->GetEcmaVM()->GetJSOptions().IsCompilerNoCheck()), - thread_(ctx->GetEcmaVM()->GetJSThread()) {} + thread_(ctx->GetEcmaVM()->GetJSThread()), + enableNewArrayInline_(enableNewArrayInline) {} ~TypeBytecodeLowering() = default; @@ -172,6 +173,7 @@ private: BuiltinsStubCSigns::ID GetBuiltinId(BuiltinTypeId id, GateRef func); BuiltinsStubCSigns::ID GetPGOBuiltinId(GateRef gate); void DeleteConstDataIfNoUser(GateRef gate); + bool TryLowerNewBuiltinConstructor(GateRef gate); void AddProfiling(GateRef gate); @@ -202,6 +204,7 @@ private: std::unordered_map bytecodeHitTimeMap_; bool noCheck_ {false}; const JSThread *thread_ {nullptr}; + bool enableNewArrayInline_ {false}; }; } // panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_TYPE_BYTECODE_LOWERING_H diff --git a/ecmascript/compiler/type_hcr_lowering.cpp b/ecmascript/compiler/type_hcr_lowering.cpp index 581d95eefa..14b9bd649b 100644 --- a/ecmascript/compiler/type_hcr_lowering.cpp +++ b/ecmascript/compiler/type_hcr_lowering.cpp @@ -138,6 +138,12 @@ GateRef TypeHCRLowering::VisitGate(GateRef gate) case OpCode::TYPE_OF: LowerTypeOf(gate, glue); break; + case OpCode::ARRAY_CONSTRUCTOR_CHECK: + LowerArrayConstructorCheck(gate, glue); + break; + case OpCode::ARRAY_CONSTRUCTOR: + LowerArrayConstructor(gate, glue); + break; default: break; } @@ -1801,4 +1807,164 @@ void TypeHCRLowering::LowerTypeOf(GateRef gate, GateRef glue) GateRef result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, builder_.GetGlobalConstantOffset(index)); acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); } + +void TypeHCRLowering::LowerArrayConstructorCheck(GateRef gate, GateRef glue) +{ + Environment env(gate, circuit_, &builder_); + GateRef frameState = GetFrameState(gate); + GateRef newTarget = acc_.GetValueIn(gate, 0); + Label isHeapObject(&builder_); + Label exit(&builder_); + DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True()); + check = builder_.TaggedIsHeapObject(newTarget); + builder_.Branch(*check, &isHeapObject, &exit); + builder_.Bind(&isHeapObject); + { + Label isJSFunction(&builder_); + check = builder_.IsJSFunction(newTarget); + builder_.Branch(*check, &isJSFunction, &exit); + builder_.Bind(&isJSFunction); + { + Label getHclass(&builder_); + GateRef glueGlobalEnvOffset = builder_.IntPtr( + JSThread::GlueData::GetGlueGlobalEnvOffset(builder_.GetCurrentEnvironment()->Is32Bit())); + GateRef glueGlobalEnv = builder_.Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); + GateRef arrayFunc = + builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); + check = builder_.Equal(arrayFunc, newTarget); + builder_.Branch(*check, &getHclass, &exit); + builder_.Bind(&getHclass); + { + GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), newTarget, + builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); + check = builder_.IsJSHClass(intialHClass); + builder_.Jump(&exit); + } + } + } + builder_.Bind(&exit); + builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORFAIL); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); +} + +void TypeHCRLowering::LowerArrayConstructor(GateRef gate, GateRef glue) +{ + Environment env(gate, circuit_, &builder_); + if (acc_.GetNumValueIn(gate) == 1) { + NewArrayConstructorWithNoArgs(gate, glue); + return; + } + ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0 + DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); + Label slowPath(&builder_); + Label exit(&builder_); + GateRef newTarget = acc_.GetValueIn(gate, 0); + GateRef arg0 = acc_.GetValueIn(gate, 1); + GateRef intialHClass = + builder_.Load(VariableType::JS_ANY(), newTarget, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); + DEFVALUE(arrayLength, (&builder_), VariableType::INT64(), builder_.Int64(0)); + Label argIsNumber(&builder_); + Label arrayCreate(&builder_); + builder_.Branch(builder_.TaggedIsNumber(arg0), &argIsNumber, &slowPath); + builder_.Bind(&argIsNumber); + { + Label argIsInt(&builder_); + Label argIsDouble(&builder_); + builder_.Branch(builder_.TaggedIsInt(arg0), &argIsInt, &argIsDouble); + builder_.Bind(&argIsInt); + { + Label validIntLength(&builder_); + GateRef intLen = builder_.GetInt64OfTInt(arg0); + GateRef isGEZero = builder_.Int64GreaterThanOrEqual(intLen, builder_.Int64(0)); + GateRef isLEMaxLen = builder_.Int64LessThanOrEqual(intLen, builder_.Int64(JSArray::MAX_ARRAY_INDEX)); + builder_.Branch(builder_.BoolAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath); + builder_.Bind(&validIntLength); + { + arrayLength = intLen; + builder_.Jump(&arrayCreate); + } + } + builder_.Bind(&argIsDouble); + { + Label validDoubleLength(&builder_); + Label GetDoubleToIntValue(&builder_); + GateRef doubleLength = builder_.GetDoubleOfTDouble(arg0); + GateRef doubleToInt = builder_.DoubleToInt(doubleLength, &GetDoubleToIntValue); + GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt)); + GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble); + GateRef doubleLEMaxLen = + builder_.DoubleLessThanOrEqual(doubleLength, builder_.Double(JSArray::MAX_ARRAY_INDEX)); + builder_.Branch(builder_.BoolAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath); + builder_.Bind(&validDoubleLength); + { + arrayLength = builder_.SExtInt32ToInt64(doubleToInt); + builder_.Jump(&arrayCreate); + } + } + } + builder_.Bind(&arrayCreate); + { + Label lengthValid(&builder_); + builder_.Branch( + builder_.Int64GreaterThan(*arrayLength, builder_.Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid); + builder_.Bind(&lengthValid); + { + NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment()); + newBuilder.SetParameters(glue, 0); + res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength); + GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET); + builder_.Store(VariableType::INT32(), glue, *res, lengthOffset, builder_.TruncInt64ToInt32(*arrayLength)); + GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR); + builder_.SetPropertyInlinedProps(glue, *res, intialHClass, accessor, + builder_.Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY()); + builder_.SetExtensibleToBitfield(glue, *res, true); + builder_.Jump(&exit); + } + } + builder_.Bind(&slowPath); + { + size_t range = acc_.GetNumValueIn(gate); + std::vector args(range); + for (size_t i = 0; i < range; ++i) { + args[i] = acc_.GetValueIn(gate, i); + } + res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true); + builder_.Jump(&exit); + } + builder_.Bind(&exit); + ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *res); +} + +void TypeHCRLowering::NewArrayConstructorWithNoArgs(GateRef gate, GateRef glue) +{ + GateRef newTarget = acc_.GetValueIn(gate, 0); + GateRef intialHClass = + builder_.Load(VariableType::JS_ANY(), newTarget, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); + GateRef arrayLength = builder_.Int64(0); + NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment()); + newBuilder.SetParameters(glue, 0); + GateRef res = newBuilder.NewJSArrayWithSize(intialHClass, arrayLength); + GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET); + builder_.Store(VariableType::INT32(), glue, res, lengthOffset, builder_.TruncInt64ToInt32(arrayLength)); + GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR); + builder_.SetPropertyInlinedProps(glue, res, intialHClass, accessor, + builder_.Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY()); + builder_.SetExtensibleToBitfield(glue, res, true); + ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), res); +} + +void TypeHCRLowering::ReplaceGateWithPendingException(GateRef glue, GateRef gate, GateRef state, GateRef depend, + GateRef value) +{ + auto condition = builder_.HasPendingException(glue); + GateRef ifBranch = builder_.Branch(state, condition); + GateRef ifTrue = builder_.IfTrue(ifBranch); + GateRef ifFalse = builder_.IfFalse(ifBranch); + GateRef eDepend = builder_.DependRelay(ifTrue, depend); + GateRef sDepend = builder_.DependRelay(ifFalse, depend); + + StateDepend success(ifFalse, sDepend); + StateDepend exception(ifTrue, eDepend); + acc_.ReplaceHirWithIfBranch(gate, success, exception, value); +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/type_hcr_lowering.h b/ecmascript/compiler/type_hcr_lowering.h index 4f59fa2c30..9b29226ed0 100644 --- a/ecmascript/compiler/type_hcr_lowering.h +++ b/ecmascript/compiler/type_hcr_lowering.h @@ -188,6 +188,10 @@ private: void LowerStringAdd(GateRef gate, GateRef glue); void LowerTypeOfCheck(GateRef gate); void LowerTypeOf(GateRef gate, GateRef glue); + void LowerArrayConstructorCheck(GateRef gate, GateRef glue); + void NewArrayConstructorWithNoArgs(GateRef gate, GateRef glue); + void LowerArrayConstructor(GateRef gate, GateRef glue); + void ReplaceGateWithPendingException(GateRef glue, GateRef gate, GateRef state, GateRef depend, GateRef value); GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector &args, bool useLabel = false); diff --git a/ecmascript/js_runtime_options.cpp b/ecmascript/js_runtime_options.cpp index 517e8f988d..9f3bfcaa53 100644 --- a/ecmascript/js_runtime_options.cpp +++ b/ecmascript/js_runtime_options.cpp @@ -154,6 +154,7 @@ const std::string PUBLIC_API HELP_OPTION_MSG = "--compiler-enable-external-pkg Enable compile with external package for ark aot compiler\n" "--compiler-enable-lexenv-specialization: Enable replace ldlexvar with specific values: Default: 'true'\n" "--compiler-enable-native-inline: Enable inline native function: Default: 'false'\n" + "--compiler-enable-fast-module: Enable fast module bytecode: Default: 'false'\n" "--compiler-opt-array-onheap-check: Enable TypedArray on heap check for aot compiler: Default: 'false'\n\n"; bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) @@ -246,7 +247,8 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) {"compiler-enable-external-pkg", required_argument, nullptr, OPTION_COMPILER_ENABLE_EXTERNAL_PKG}, {"compiler-enable-lexenv-specialization", required_argument, nullptr, OPTION_COMPILER_ENABLE_LEXENV_SPECIALIZATION}, - {"compiler-enable-native-inline", required_argument, nullptr, OPTION_COMPILER_ENBALE_NATIVE_INLINE}, + {"compiler-enable-native-inline", required_argument, nullptr, OPTION_COMPILER_ENABLE_NATIVE_INLINE}, + {"compiler-enable-fast-module", required_argument, nullptr, OPTION_COMPILER_ENABLE_FAST_MODULE}, {nullptr, 0, nullptr, 0}, }; @@ -840,7 +842,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) return false; } break; - case OPTION_COMPILER_ENBALE_NATIVE_INLINE: + case OPTION_COMPILER_ENABLE_NATIVE_INLINE: ret = ParseBoolParam(&argBool); if (ret) { SetEnableNativeInline(argBool); @@ -848,6 +850,15 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv) return false; } break; + case OPTION_COMPILER_ENABLE_FAST_MODULE: + ret = ParseBoolParam(&argBool); + if (ret) { + SetEnableFastModule(argBool); + } else { + return false; + } + break; + default: LOG_ECMA(ERROR) << "Invalid option\n"; return false; diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 225d486b98..135a5654a9 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -150,7 +150,8 @@ enum CommandValues { OPTION_COMPILER_TRACE_VALUE_NUMBERING, OPTION_COMPILER_OPT_INSTRUCTIONE_COMBINE, OPTION_COMPILER_OPT_NEW_VALUE_NUMBERING, - OPTION_COMPILER_ENBALE_NATIVE_INLINE, + OPTION_COMPILER_ENABLE_NATIVE_INLINE, + OPTION_COMPILER_ENABLE_FAST_MODULE }; class PUBLIC_API JSRuntimeOptions { @@ -1323,6 +1324,16 @@ public: enableNativeInline_ = value; } + bool IsEnableFastModule() const + { + return enableFastModule_; + } + + void SetEnableFastModule(bool value) + { + enableFastModule_ = value; + } + private: static bool StartsWith(const std::string &haystack, const std::string &needle) { @@ -1431,6 +1442,7 @@ private: bool enableOptLoopInvariantCodeMotion_ {false}; bool enableLexenvSpecialization_ {true}; bool enableNativeInline_ {false}; + bool enableFastModule_ {false}; }; } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_manager.cpp b/ecmascript/ts_types/ts_manager.cpp index a834194223..1283d3d71e 100644 --- a/ecmascript/ts_types/ts_manager.cpp +++ b/ecmascript/ts_types/ts_manager.cpp @@ -1434,4 +1434,22 @@ int TSModuleTable::GetGlobalModuleID(JSThread *thread, JSHandle amiP } return NOT_FOUND; } + +bool TSManager::IsBuiltinConstructor(BuiltinTypeId id, GlobalTSTypeRef ctorGT) const +{ + ASSERT(ctorGT.IsBuiltinModule()); + if (IsBuiltinsDTSEnabled()) { + uint32_t idx = static_cast(id); + const JSPandaFile *builtinPandaFile = GetBuiltinPandaFile(); + uint32_t builtinOffset = GetBuiltinOffset(idx); + GlobalTypeID gId(builtinPandaFile, builtinOffset); + bool hasCreatedGT = HasCreatedGT(gId); + if (hasCreatedGT) { + auto gt = GetGTByGlobalTypeID(gId); + return ctorGT == gt; + } + } + + return false; +} } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_manager.h b/ecmascript/ts_types/ts_manager.h index 59b4b73260..505cdcebf9 100644 --- a/ecmascript/ts_types/ts_manager.h +++ b/ecmascript/ts_types/ts_manager.h @@ -509,6 +509,7 @@ public: } bool PUBLIC_API IsBuiltinObjectMethod(BuiltinTypeId id, kungfu::GateType funcType) const; + bool PUBLIC_API IsBuiltinConstructor(BuiltinTypeId id, GlobalTSTypeRef ctorType) const; inline const JSPandaFile *GetBuiltinPandaFile() const { diff --git a/test/aottest/BUILD.gn b/test/aottest/BUILD.gn index beb0ed7496..40bf934693 100644 --- a/test/aottest/BUILD.gn +++ b/test/aottest/BUILD.gn @@ -158,6 +158,7 @@ group("ark_aot_ts_test") { "lexenv_specialization", "lexenv_specialization", "lexenv_specialization_noopt", + "load_local_module_var", "logic_op", "loop_peeling", "loop_phi", diff --git a/test/aottest/load_local_module_var/BUILD.gn b/test/aottest/load_local_module_var/BUILD.gn new file mode 100644 index 0000000000..402fea1f67 --- /dev/null +++ b/test/aottest/load_local_module_var/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("load_local_module_var") { + deps = [] +} diff --git a/test/aottest/load_local_module_var/expect_output.txt b/test/aottest/load_local_module_var/expect_output.txt new file mode 100644 index 0000000000..11e347853e --- /dev/null +++ b/test/aottest/load_local_module_var/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +2 diff --git a/test/aottest/load_local_module_var/load_local_module_var.ts b/test/aottest/load_local_module_var/load_local_module_var.ts new file mode 100644 index 0000000000..923c635fc8 --- /dev/null +++ b/test/aottest/load_local_module_var/load_local_module_var.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function print(arg:any) : string; + +export function RunNormalCall():number { + let res : number = 1; + res++; + return res + +} +let num = RunNormalCall() +print(num) \ No newline at end of file