From fc5f3c47762d19918e16e6f502762d33e9c42103 Mon Sep 17 00:00:00 2001 From: schernykh Date: Tue, 18 Apr 2023 15:23:47 +0300 Subject: [PATCH] Support ecma static inlininig Signed-off-by: Sergey Chernykh --- .../intrinsics_type_resolving_ecmascript.cpp | 32 +--- .../optimizer/optimizations/ecma_inlining.cpp | 47 ++++-- .../optimizer/optimizations/ecma_inlining.h | 6 + .../compiler/ecmascript_runtime_interface.cpp | 146 +++++++++--------- .../compiler/ecmascript_runtime_interface.h | 17 +- runtime/ecma_compiler.cpp | 4 + tests/CMakeLists.txt | 2 +- tests/checked/CMakeLists.txt | 1 + tests/checked/ecma_inlining_static.js | 65 ++++++++ 9 files changed, 196 insertions(+), 124 deletions(-) create mode 100644 tests/checked/ecma_inlining_static.js diff --git a/compiler/intrinsics_type_resolving_ecmascript.cpp b/compiler/intrinsics_type_resolving_ecmascript.cpp index c5cae8209..3a6b14605 100644 --- a/compiler/intrinsics_type_resolving_ecmascript.cpp +++ b/compiler/intrinsics_type_resolving_ecmascript.cpp @@ -429,42 +429,26 @@ bool TypesResolving::InlineStObjByValue(IntrinsicInst *intrinsic) bool TypesResolving::GetICForMemNamedAccess(IntrinsicInst *intrinsic) { - auto pc = intrinsic->GetPc(); - auto runtime = GetGraph()->GetRuntime(); + auto method = GetGraph()->GetMethod(); auto save_state = intrinsic->GetSaveState(); ASSERT(save_state != nullptr); - auto caller_inst = save_state->GetCallerInst(); - if (caller_inst != nullptr) { + if (auto caller_inst = save_state->GetCallerInst(); caller_inst != nullptr) { ASSERT(caller_inst->IsInlined()); - auto func = caller_inst->GetFunctionObject(); - ASSERT(func != 0); - if (!runtime->GetProfileDataForNamedAccess(GetGraph()->GetMethod(), func, pc, &named_access_profile_)) { - return false; - } - } else if (!runtime->GetProfileDataForNamedAccess(GetGraph()->GetMethod(), pc, &named_access_profile_)) { - return false; + method = caller_inst->GetCallMethod(); } - return true; + return GetGraph()->GetRuntime()->GetProfileDataForNamedAccess(method, intrinsic->GetPc(), &named_access_profile_); } bool TypesResolving::GetICForMemValueAccess(IntrinsicInst *intrinsic) { - auto pc = intrinsic->GetPc(); - auto runtime = GetGraph()->GetRuntime(); + auto method = GetGraph()->GetMethod(); auto save_state = intrinsic->GetSaveState(); ASSERT(save_state != nullptr); - auto caller_inst = save_state->GetCallerInst(); - if (caller_inst != nullptr) { + if (auto caller_inst = save_state->GetCallerInst(); caller_inst != nullptr) { ASSERT(caller_inst->IsInlined()); - auto func = caller_inst->GetFunctionObject(); - ASSERT(func != 0); - if (!runtime->GetProfileDataForValueAccess(GetGraph()->GetMethod(), func, pc, &named_access_profile_)) { - return false; - } - } else if (!runtime->GetProfileDataForValueAccess(GetGraph()->GetMethod(), pc, &named_access_profile_)) { - return false; + method = caller_inst->GetCallMethod(); } - return true; + return GetGraph()->GetRuntime()->GetProfileDataForValueAccess(method, intrinsic->GetPc(), &named_access_profile_); } Inst *TypesResolving::InsertCheckAndCastInstructions(IntrinsicInst *intrinsic) diff --git a/compiler/optimizer/optimizations/ecma_inlining.cpp b/compiler/optimizer/optimizations/ecma_inlining.cpp index 071666464..dd3ffc224 100644 --- a/compiler/optimizer/optimizations/ecma_inlining.cpp +++ b/compiler/optimizer/optimizations/ecma_inlining.cpp @@ -68,14 +68,42 @@ bool EcmaInlining::CheckCallKind(CallInst *call_inst) return true; } +bool EcmaInlining::IsInstSuitableForEcmaStaticInlining(Inst *define_func) const +{ + if (define_func->GetOpcode() != Opcode::Intrinsic) { + return false; + } + switch (define_func->CastToIntrinsic()->GetIntrinsicId()) { + case RuntimeInterface::IntrinsicId::INTRINSIC_DEFINEFUNC_DYN: + case RuntimeInterface::IntrinsicId::INTRINSIC_DEFINE_NC_FUNC_DYN: + case RuntimeInterface::IntrinsicId::INTRINSIC_DEFINE_METHOD: + return true; + default: + return false; + } +} + +RuntimeInterface::MethodPtr EcmaInlining::TryResolveTargetStatic(CallInst *call_inst) const +{ + auto define_func = call_inst->GetDataFlowInput(0); + if (IsInstSuitableForEcmaStaticInlining(define_func)) { + return GetGraph()->GetRuntime()->GetMethodByIdAndSaveJsFunction(GetGraph()->GetMethod(), + define_func->CastToIntrinsic()->GetImm(0)); + } + return nullptr; +} + InlineContext EcmaInlining::ResolveTargets(CallInst *call_inst) { js_functions_.clear(); - if (!CheckCallKind(call_inst)) { - return {}; + if (auto method = TryResolveTargetStatic(call_inst); method != nullptr) { + return {method}; + } + if (CheckCallKind(call_inst)) { + ASSERT(js_functions_[0] != 0); + return {GetGraph()->GetRuntime()->GetMethodFromFunctionAndSaveJsFunction(js_functions_[0])}; } - ASSERT(js_functions_[0] != 0); - return {GetGraph()->GetRuntime()->GetMethodFromFunction(js_functions_[0])}; + return {}; } bool EcmaInlining::CheckMethod(CallInst *call_inst, InlineContext *ctx) @@ -159,7 +187,9 @@ void EcmaInlining::InsertGraph(CallInst *call_inst, const InlineContext &ctx, Gr GetGraph()->SetCurrentInstructionId(graph_inl->GetCurrentInstructionId()); GetGraph()->SetMaxInliningDepth(graph_inl->GetMaxInliningDepth() + 1); - BuildGuard(call_inst); + if (!IsStaticInlining()) { + BuildGuard(call_inst); + } auto call_bb = call_inst->GetBasicBlock(); auto call_cont_bb = call_bb->SplitBlockAfterInstruction(call_inst, false); @@ -180,10 +210,6 @@ void EcmaInlining::InsertGraph(CallInst *call_inst, const InlineContext &ctx, Gr call_inst->SetCallMethod(ctx.method); call_inst->SetCallMethodId(GetGraph()->GetRuntime()->GetMethodId(ctx.method)); - - CHECK_EQ(js_functions_.size(), 1U); - ASSERT(js_functions_[0] != 0); - call_inst->SetFunctionObject(js_functions_[0]); } bool EcmaInlining::TryInline(CallInst *call_inst) @@ -215,7 +241,8 @@ bool EcmaInlining::TryInline(CallInst *call_inst) methods_inlined_++; EVENT_INLINE(GetGraph()->GetRuntime()->GetMethodFullName(GetGraph()->GetMethod()), GetGraph()->GetRuntime()->GetMethodFullName(ctx.method), call_inst->GetId(), - events::InlineKind::DYNAMIC_MONOMORPHIC, events::InlineResult::SUCCESS); + js_functions_.empty() ? events::InlineKind::STATIC : events::InlineKind::DYNAMIC_MONOMORPHIC, + events::InlineResult::SUCCESS); LOG_INLINING(DEBUG) << "Successfully inlined: " << GetGraph()->GetRuntime()->GetMethodFullName(ctx.method); return true; } diff --git a/compiler/optimizer/optimizations/ecma_inlining.h b/compiler/optimizer/optimizations/ecma_inlining.h index 413e61e5c..5f9789a60 100644 --- a/compiler/optimizer/optimizations/ecma_inlining.h +++ b/compiler/optimizer/optimizations/ecma_inlining.h @@ -39,11 +39,17 @@ private: bool TryInline(CallInst *call_inst) override; InlineContext ResolveTargets(CallInst *call_inst); + RuntimeInterface::MethodPtr TryResolveTargetStatic(CallInst *call_inst) const; + bool IsInstSuitableForEcmaStaticInlining(Inst *define_func) const; bool CheckCallKind(CallInst *call_inst); bool CheckMethod(CallInst *call_inst, InlineContext *ctx); Graph *BuildGraph(CallInst *call_inst, InlineContext *ctx); void BuildGuard(CallInst *call_inst); void InsertGraph(CallInst *call_inst, const InlineContext &ctx, Graph *graph_inl); + bool IsStaticInlining() const + { + return js_functions_.empty(); + } private: // This vector contains pointers to element in EcmaCallProfilingTable diff --git a/runtime/compiler/ecmascript_runtime_interface.cpp b/runtime/compiler/ecmascript_runtime_interface.cpp index 9ecb89da6..d48b0f074 100644 --- a/runtime/compiler/ecmascript_runtime_interface.cpp +++ b/runtime/compiler/ecmascript_runtime_interface.cpp @@ -520,44 +520,22 @@ bool EcmaRuntimeInterface::AddProfileValueInfo(PandaRuntimeInterface::MethodPtr inline ProfileTypeInfo *EcmaRuntimeInterface::GetProfileTypeInfo(PandaRuntimeInterface::MethodPtr m, uintptr_t slot_id, uint8_t *slot) { - os::memory::LockHolder lock_m(mutex_); + // ProfileTypeInfo is manage object + // We need to have lock in caller method, because we return ProfileTypeInfo + ASSERT(ecma_vm_->GetMutatorLock()->HasLock()); uint8_t *mapping = JsMethodCast(m)->GetICMapping(); if (mapping == nullptr) { return nullptr; } // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) *slot = mapping[slot_id]; - auto it = js_function_table_.find(MethodCast(m)); - if (it == js_function_table_.end()) { - return nullptr; - } - - auto func = JSFunction::Cast(ecma_vm_->GetGlobalObjectStorage()->Get(it->second)); - return ProfileTypeInfo::Cast(func->GetProfileTypeInfo().GetTaggedObject()); -} - -inline ProfileTypeInfo *EcmaRuntimeInterface::GetProfileTypeInfo(uintptr_t func_address, uintptr_t slot_id, - uint8_t *slot) -{ - os::memory::LockHolder lock_m(mutex_); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - auto js_func = TaggedValue(reinterpret_cast(func_address)[0]); - if (!js_func.IsHeapObject()) { - return nullptr; - } - auto func = JSFunction::Cast(js_func.GetHeapObject()); - uint8_t *mapping = func->GetMethod()->GetICMapping(); - if (mapping == nullptr) { - return nullptr; - } - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *slot = mapping[slot_id]; - auto profile_info_obj = func->GetProfileTypeInfo(); - if (profile_info_obj.IsUndefined()) { - return nullptr; + if (auto func = GetJSFunctionByMethod(m); func != nullptr) { + auto pti = func->GetProfileTypeInfo(); + if (pti.IsHeapObject()) { + return ProfileTypeInfo::Cast(pti.GetTaggedObject()); + } } - - return ProfileTypeInfo::Cast(profile_info_obj.GetTaggedObject()); + return nullptr; } bool EcmaRuntimeInterface::GetProfileDataForNamedAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t slot_id, @@ -580,28 +558,6 @@ bool EcmaRuntimeInterface::GetProfileDataForNamedAccess(PandaRuntimeInterface::M return false; } -bool EcmaRuntimeInterface::GetProfileDataForNamedAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t func_address, - uintptr_t slot_id, ArenaVector *profile) -{ - if (profile == nullptr) { - return false; - } - profile->clear(); - ASSERT(func_address != 0); - ScopedMutatorLock lock; - - uint8_t slot; - ProfileTypeInfo *profile_type_info = GetProfileTypeInfo(func_address, slot_id, &slot); - if (profile_type_info == nullptr) { - return false; - } - if (AddProfileInfo(m, profile, profile_type_info, slot)) { - AddProfileInfo(m, profile, profile_type_info, slot + 2); - return true; - } - return false; -} - bool EcmaRuntimeInterface::GetProfileDataForValueAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t slot_id, ArenaVector *profile) { @@ -619,24 +575,6 @@ bool EcmaRuntimeInterface::GetProfileDataForValueAccess(PandaRuntimeInterface::M return AddProfileValueInfo(m, profile, profile_type_info, slot); } -bool EcmaRuntimeInterface::GetProfileDataForValueAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t func_address, - uintptr_t slot_id, ArenaVector *profile) -{ - if (profile == nullptr) { - return false; - } - profile->clear(); - ASSERT(func_address != 0); - ScopedMutatorLock lock; - - uint8_t slot; - ProfileTypeInfo *profile_type_info = GetProfileTypeInfo(func_address, slot_id, &slot); - if (profile_type_info == nullptr) { - return false; - } - - return AddProfileValueInfo(m, profile, profile_type_info, slot); -} void EcmaRuntimeInterface::CleanFunction(Method *method) { os::memory::LockHolder lock(mutex_); @@ -771,20 +709,21 @@ PandaRuntimeInterface::GlobalVarInfo EcmaRuntimeInterface::GetGlobalVarInfo(Pand return {GlobalVarInfo::Type::NON_CONFIGURABLE, address}; } - os::memory::LockHolder lock_m(mutex_); uint8_t *mapping = JsMethodCast(method)->GetICMapping(); if (mapping == nullptr) { return {}; } // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) auto slot = mapping[slot_id]; - auto it = js_function_table_.find(MethodCast(method)); - if (it == js_function_table_.end()) { + auto func = GetJSFunctionByMethod(method); + if (func == nullptr) { return {}; } - - auto func = JSFunction::Cast(ecma_vm_->GetGlobalObjectStorage()->Get(it->second)); - ProfileTypeInfo *profile_type_info = ProfileTypeInfo::Cast(func->GetProfileTypeInfo().GetTaggedObject()); + auto pti = func->GetProfileTypeInfo(); + if (!pti.IsHeapObject()) { + return {}; + } + ProfileTypeInfo *profile_type_info = ProfileTypeInfo::Cast(pti.GetTaggedObject()); JSTaggedValue handler = profile_type_info->Get(slot); if (!handler.IsHeapObject()) { @@ -835,4 +774,57 @@ std::pair EcmaRuntimeInterface::GetGlobalDictionaryEntr auto dict = GlobalDictionary::Cast(array); return {dict, dict->FindEntry(key)}; } + +JSFunction *EcmaRuntimeInterface::GetJSFunctionByMethod(PandaRuntimeInterface::MethodPtr m) const +{ + // JSFunction is manage object + // We need to have lock in caller method, because we return JSFunction + ASSERT(ecma_vm_->GetMutatorLock()->HasLock()); + os::memory::LockHolder lock(mutex_); + auto it = js_function_table_.find(MethodCast(m)); + if (it == js_function_table_.end()) { + return nullptr; + } + auto func = JSFunction::Cast(ecma_vm_->GetGlobalObjectStorage()->Get(it->second)); + ASSERT(func->GetCallTarget() == MethodCast(m)); + return func; +} + +PandaRuntimeInterface::MethodPtr EcmaRuntimeInterface::GetMethodByIdAndSaveJsFunction( + PandaRuntimeInterface::MethodPtr parent_method, MethodId id) +{ + ScopedMutatorLock lock; + auto func = GetJSFunctionByMethod(parent_method); + if (func == nullptr) { + return nullptr; + } + auto constpool = ConstantPool::Cast(func->GetConstantPool().GetHeapObject()); + auto target = JSFunction::Cast(constpool->GetObjectFromCache(id).GetHeapObject()); + auto method = target->GetCallTarget(); + + // Store JsFunction for recursive static inlining and futher optimizations + auto gos = ecma_vm_->GetGlobalObjectStorage(); + auto func_ref = gos->Add(JSTaggedValue(target).GetHeapObject(), panda::mem::Reference::ObjectType::GLOBAL); + AddFunctionInMap(method, func_ref); + + return method; +} + +PandaRuntimeInterface::MethodPtr EcmaRuntimeInterface::GetMethodFromFunctionAndSaveJsFunction(uintptr_t function) +{ + ScopedMutatorLock lock; + auto *js_func = *(reinterpret_cast(function)); + if (js_func == nullptr) { + return nullptr; + } + auto method = js_func->GetCallTarget(); + + // Store JsFunction for futher optimizations + auto gos = ecma_vm_->GetGlobalObjectStorage(); + auto func_ref = gos->Add(JSTaggedValue(js_func).GetHeapObject(), panda::mem::Reference::ObjectType::GLOBAL); + AddFunctionInMap(method, func_ref); + + return method; +} + } // namespace panda::ecmascript diff --git a/runtime/compiler/ecmascript_runtime_interface.h b/runtime/compiler/ecmascript_runtime_interface.h index 04ef97c43..00ee1f086 100644 --- a/runtime/compiler/ecmascript_runtime_interface.h +++ b/runtime/compiler/ecmascript_runtime_interface.h @@ -139,12 +139,9 @@ public: return utf::Mutf8AsCString(JsMethodCast(method)->GetName().data); } - MethodPtr GetMethodFromFunction(uintptr_t function) const override - { - ScopedMutatorLock lock; - auto *js_func = *(reinterpret_cast(function)); - return js_func == nullptr ? nullptr : js_func->GetCallTarget(); - } + MethodPtr GetMethodByIdAndSaveJsFunction(MethodPtr parent_method, MethodId id) override; + + MethodPtr GetMethodFromFunctionAndSaveJsFunction(uintptr_t function) override; compiler::AnyBaseType GetProfilingAnyType(RuntimeInterface::BytecodeProfile profile, const BytecodeInstruction *bc_inst, unsigned index, @@ -157,13 +154,8 @@ public: NewObjDynInfo GetNewObjDynInfo(uintptr_t ctor) const override; bool GetProfileDataForNamedAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t slot_id, ArenaVector *profile) override; - bool GetProfileDataForNamedAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t func_address, uintptr_t slot_id, - ArenaVector *profile) override; bool GetProfileDataForValueAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t slot_id, ArenaVector *profile) override; - bool GetProfileDataForValueAccess(PandaRuntimeInterface::MethodPtr m, uintptr_t func_address, uintptr_t slot_id, - ArenaVector *profile) override; - void CleanFunction(Method *method); void AddFunctionInMap(Method *method, panda::mem::Reference *func) @@ -183,6 +175,8 @@ public: } private: + JSFunction *GetJSFunctionByMethod(PandaRuntimeInterface::MethodPtr m) const; + void CleanObjectHandles(Method *method); void AddObjectHandle(Method *method, ObjectHeader *obj); uintptr_t AddFixedObjectHandle(Method *method, ObjectHeader *obj); @@ -192,7 +186,6 @@ private: ProfileTypeInfo *profile_type_info, uint8_t slot); bool AddElementInfo(ArenaVector *profile, ProfileTypeInfo *profile_type_info, uint8_t slot); ProfileTypeInfo *GetProfileTypeInfo(PandaRuntimeInterface::MethodPtr m, uintptr_t slot_id, uint8_t *slot); - ProfileTypeInfo *GetProfileTypeInfo(uintptr_t func_address, uintptr_t slot_id, uint8_t *slot); size_t GetLexicalEnvParentEnvIndex() const override; diff --git a/runtime/ecma_compiler.cpp b/runtime/ecma_compiler.cpp index 1f65697ba..73f7b6a2f 100644 --- a/runtime/ecma_compiler.cpp +++ b/runtime/ecma_compiler.cpp @@ -38,7 +38,11 @@ void EcmaCompiler::AddTask(CompilerTask &&task, TaggedValue func) } } } + if (func.IsHole()) { + func = GetJSThread()->GetFunctionalObject(); + } if (!func.IsHole()) { + ASSERT(JSFunction::Cast(func.GetHeapObject())->GetCallTarget() == task.GetMethod()); auto gos = task.GetVM()->GetGlobalObjectStorage(); auto func_ref = gos->Add(func.GetHeapObject(), panda::mem::Reference::ObjectType::GLOBAL); static_cast(GetRuntimeInterface())->AddFunctionInMap(task.GetMethod(), func_ref); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cc748bed2..c35cfd61d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -274,7 +274,7 @@ function(compile_file_ecma) if (${FILE_TYPE} MATCHES "js") add_custom_command(OUTPUT "${ARG_OUTPUT_FILE}" COMMENT "Run es2panda for ${ARG_FILE}" - COMMAND ${es2panda_bin} ${ARG_OPTIONS} --opt-level 0 --output ${ARG_OUTPUT_FILE} "${ARG_FILE}" + COMMAND ${es2panda_bin} ${ARG_OPTIONS} --opt-level 2 --output ${ARG_OUTPUT_FILE} "${ARG_FILE}" DEPENDS ${es2panda_target} "${ARG_FILE}" WORKING_DIRECTORY "${ARG_WORKING_DIR}") else() diff --git a/tests/checked/CMakeLists.txt b/tests/checked/CMakeLists.txt index d3bf71611..3746fce9f 100644 --- a/tests/checked/CMakeLists.txt +++ b/tests/checked/CMakeLists.txt @@ -107,6 +107,7 @@ if (NOT PANDA_TARGET_ARM32) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/obj_by_name.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/obj_by_value.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining.js SUPPORT_RELEASE true) + panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_static.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_megamorphic.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_deoptimize.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_call_profile_clear.js SUPPORT_RELEASE true) diff --git a/tests/checked/ecma_inlining_static.js b/tests/checked/ecma_inlining_static.js new file mode 100644 index 000000000..b384a9737 --- /dev/null +++ b/tests/checked/ecma_inlining_static.js @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +//! CHECKER Ecma Static Inlining. Must inline. +//! RUN options: "--no-async-jit --compiler-hotness-threshold=0", entry: "_GLOBAL::func_main_0" +//! EVENT_NOT /Inline,_GLOBAL::main,_GLOBAL::global,.*STATIC,SUCCESS/ +//! EVENT /Inline,_GLOBAL::global,_GLOBAL::test_inside_func1,.*STATIC,SUCCESS/ +//! EVENT /Inline,_GLOBAL::global,_GLOBAL::test_inside_func2,.*STATIC,SUCCESS/ +//! EVENT /Inline,_GLOBAL::main,_GLOBAL::test_global_anonimus,.*STATIC,SUCCESS/ +//! EVENT /Inline,_GLOBAL::main,_GLOBAL::arrow_func,.*STATIC,SUCCESS/ +//! EVENT /Compilation,_GLOBAL::main,.*,COMPILED/ +//! EVENT_NOT /Deoptimization,.*,.*,.*/ + +// we can't statically inline global functions +// because we need to eliminate StoreGlobalVar/LoadGlobalVar befor +function global() { + let x = 1; + let test_inside_func1 = function() { + return x + 10; + } + let t1 = test_inside_func1() + if (t1 != 11) { + throw new Error("Wrong anonimus inside function result") + } + + function test_inside_func2() { + return x + 9; + } + let t2 = test_inside_func2() + if (t2 != 10) { + throw new Error("Wrong anonimus inside function result") + } + + return 21 + t1 + t2; +} +if (global() != 42) { + throw new Error("Wrong named function result") +} + + +let test_global_anonimus = function() { + return 42; +} +if (test_global_anonimus() != 42) { + throw new Error("Wrong anonimus function result") +} + + +let a = 10; +let arrow_func = (a) => (a + 21) +if (arrow_func(21) != 42) { + throw new Error("Wrong lambda function result") +} \ No newline at end of file -- Gitee