diff --git a/BUILD.gn b/BUILD.gn index da0e9f22..aac22250 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -28,14 +28,10 @@ group("ark_js_packages") { group("ark_js_host_linux_tools_packages") { deps = [] if (host_os != "mac") { - deps += [ - "//ark/js_runtime:libark_jsruntime(${host_toolchain})", - "//ark/js_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})", - ] + deps += [ "//ark/js_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})" ] if (is_standard_system) { deps += [ "//ark/js_runtime/ecmascript/compiler:ark_stub_opt(${host_toolchain})", - "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", ] } } @@ -48,6 +44,7 @@ group("ark_js_unittest") { deps += [ "//ark/js_runtime/ecmascript/builtins/tests:unittest", "//ark/js_runtime/ecmascript/hprof/tests:unittest", + "//ark/js_runtime/ecmascript/ic/tests:unittest", "//ark/js_runtime/ecmascript/napi/test:unittest", "//ark/js_runtime/ecmascript/regexp/tests:unittest", "//ark/js_runtime/ecmascript/snapshot/tests:unittest", @@ -63,10 +60,9 @@ group("ark_js_host_unittest") { if (host_os != "mac") { # js unittest deps += [ - "//ark/js_runtime:libark_jsruntime(${host_toolchain})", "//ark/js_runtime/ecmascript/builtins/tests:host_unittest", "//ark/js_runtime/ecmascript/hprof/tests:host_unittest", - "//ark/js_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})", + "//ark/js_runtime/ecmascript/ic/tests:host_unittest", "//ark/js_runtime/ecmascript/napi/test:host_unittest", "//ark/js_runtime/ecmascript/regexp/tests:host_unittest", "//ark/js_runtime/ecmascript/snapshot/tests:host_unittest", @@ -135,6 +131,9 @@ config("ark_jsruntime_common_config") { if (enable_stub_aot) { defines += [ "ECMASCRIPT_ENABLE_STUB_AOT" ] } + if (enable_specific_stubs) { + defines += [ "ECMASCRIPT_ENABLE_SPECIFIC_STUBS" ] + } if (is_standard_system) { defines += [ "IS_STANDARD_SYSTEM" ] @@ -175,10 +174,12 @@ config("ark_jsruntime_common_config") { "-pipe", "-Wdate-time", "-Wformat=2", - "-flto", ] - ldflags = [ "-flto" ] + if (!use_libfuzzer) { + cflags_cc += [ "-flto" ] + ldflags = [ "-flto" ] + } if (is_debug) { cflags_cc += [ @@ -203,6 +204,7 @@ config("ark_jsruntime_common_config") { defines += [ "PANDA_TARGET_ARM32_ABI_SOFT=1", "PANDA_TARGET_ARM32", + "PANDA_TARGET_32", ] } else if (current_cpu == "arm64") { defines += [ @@ -279,6 +281,9 @@ ecma_source = [ "ecmascript/builtins/builtins_weak_map.cpp", "ecmascript/builtins/builtins_weak_set.cpp", "ecmascript/class_linker/panda_file_translator.cpp", + "ecmascript/cpu_profiler/cpu_profiler.cpp", + "ecmascript/cpu_profiler/profile_processor.cpp", + "ecmascript/cpu_profiler/profile_generator.cpp", "ecmascript/dump.cpp", "ecmascript/ecma_class_linker_extension.cpp", "ecmascript/ecma_exceptions.cpp", @@ -298,8 +303,10 @@ ecma_source = [ "ecmascript/hprof/heap_snapshot_json_serializer.cpp", "ecmascript/hprof/heap_tracker.cpp", "ecmascript/hprof/string_hashmap.cpp", - "ecmascript/ic/profile_type_info.cpp", "ecmascript/ic/ic_runtime.cpp", + "ecmascript/ic/ic_compare_op.cpp", + "ecmascript/ic/invoke_cache.cpp", + "ecmascript/ic/profile_type_info.cpp", "ecmascript/ic/property_box.cpp", "ecmascript/ic/proto_change_details.cpp", "ecmascript/internal_call_params.cpp", @@ -342,20 +349,22 @@ ecma_source = [ "ecmascript/mem/c_string.cpp", "ecmascript/mem/chunk.cpp", "ecmascript/mem/compress_collector.cpp", + "ecmascript/mem/concurrent_marker.cpp", "ecmascript/mem/concurrent_sweeper.cpp", "ecmascript/mem/ecma_heap_manager.cpp", + "ecmascript/mem/evacuation_allocator.cpp", "ecmascript/mem/free_object_kind.cpp", "ecmascript/mem/free_object_list.cpp", "ecmascript/mem/gc_stats.cpp", "ecmascript/mem/heap.cpp", "ecmascript/mem/mem_controller.cpp", - "ecmascript/mem/old_space_collector.cpp", + "ecmascript/mem/mix_space_collector.cpp", + "ecmascript/mem/parallel_work_helper.cpp", + "ecmascript/mem/parallel_evacuation.cpp", + "ecmascript/mem/parallel_marker.cpp", "ecmascript/mem/region_factory.cpp", "ecmascript/mem/semi_space_collector.cpp", - "ecmascript/mem/semi_space_marker.cpp", - "ecmascript/mem/semi_space_worker.cpp", "ecmascript/mem/space.cpp", - "ecmascript/mem/tagged_object.cpp", "ecmascript/mem/verification.cpp", "ecmascript/napi/jsnapi.cpp", "ecmascript/object_factory.cpp", @@ -369,6 +378,7 @@ ecma_source = [ "ecmascript/regexp/regexp_opcode.cpp", "ecmascript/regexp/regexp_parser.cpp", "ecmascript/regexp/regexp_parser_cache.cpp", + "ecmascript/runtime_api.cpp", "ecmascript/runtime_trampolines.cpp", "ecmascript/snapshot/mem/slot_bit.cpp", "ecmascript/snapshot/mem/snapshot.cpp", @@ -420,10 +430,10 @@ ohos_shared_library("libark_jsruntime") { deps = [ ":libark_js_intl_static", ":libark_jsruntime_static", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", ] + configs = [ ":ark_jsruntime_config" ] + install_enable = true part_name = "ark_js_runtime" diff --git a/README.md b/README.md index f9ba018a..9c855877 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ For more infomation, see: [ARK Runtime Subsystem](https://gitee.com/openharmony/ │ ├─ builtins # ECMAScript library │ ├─ class_linker # Bytecode pre-processing module │ ├─ compiler # JS compiler +│ ├─ cpu_profiler # CPU Performance Analyzer │ ├─ hprof # Memory analysis utility class │ ├─ ic # Inline cache module │ ├─ interpreter # JS interpreter diff --git a/README_zh.md b/README_zh.md index 952dce67..fb041d75 100644 --- a/README_zh.md +++ b/README_zh.md @@ -28,6 +28,7 @@ │ ├─ builtins # ECMAScript标准库 │ ├─ class_linker # 字节码预处理模块 │ ├─ compiler # JS编译器 +│ ├─ cpu_profiler # CPU性能分析器 │ ├─ hprof # 内存分析工具 │ ├─ ic # 内联缓存模块 │ ├─ interpreter # JS解释器 diff --git a/ecmascript/base/config.h b/ecmascript/base/config.h index 229c2eba..a269f314 100644 --- a/ecmascript/base/config.h +++ b/ecmascript/base/config.h @@ -20,9 +20,40 @@ namespace panda::ecmascript { #define ARK_INLINE __attribute__((always_inline)) #define ARK_NOINLINE __attribute__((noinline)) +#define ECMASCRIPT_ENABLE_DEBUG_MODE 0 #define ECMASCRIPT_ENABLE_RUNTIME_STAT 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ECMASCRIPT_ENABLE_IC 1 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ECMASCRIPT_ENABLE_THREAD_CHECK 0 + +/* + * 1. close ic + * 2. close parallel gc + * 3. enable gc logs + * 4. enable handle-scope zap, zap reclaimed regions + * 5. switch gc mode to full gc + * 6. enable Cast() check + * 7. enable verify heap + * 9. enable Proactively interrogating and collecting information in the call stack + */ +#if ECMASCRIPT_ENABLE_DEBUG_MODE + #define ECMASCRIPT_ENABLE_IC 0 + #define ECMASCRIPT_DISABLE_PARALLEL_GC 1 + #define ECMASCRIPT_ENABLE_GC_LOG 1 + #define ECMASCRIPT_ENABLE_ZAP_MEM 1 + #define ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC 1 + #define ECMASCRIPT_ENABLE_CAST_CHECK 1 + #define ECMASCRIPT_ENABLE_HEAP_VERIFY 1 + #define ECMASCRIPT_ENABLE_THREAD_CHECK 1 + #define ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER 0 +#else + #define ECMASCRIPT_ENABLE_IC 1 + #define ECMASCRIPT_DISABLE_PARALLEL_GC 0 + #define ECMASCRIPT_ENABLE_GC_LOG 0 + #define ECMASCRIPT_ENABLE_ZAP_MEM 0 + #define ECMASCRIPT_SWITCH_GC_MODE_TO_COMPRESS_GC 0 + #define ECMASCRIPT_ENABLE_CAST_CHECK 0 + #define ECMASCRIPT_ENABLE_HEAP_VERIFY 0 + #define ECMASCRIPT_ENABLE_THREAD_CHECK 0 + #define ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER 0 +#endif } // namespace panda::ecmascript #endif // ECMASCRIPT_BASE_CONFIG_H diff --git a/ecmascript/base/json_stringifier.cpp b/ecmascript/base/json_stringifier.cpp index 56b1a5e0..e59bfa92 100644 --- a/ecmascript/base/json_stringifier.cpp +++ b/ecmascript/base/json_stringifier.cpp @@ -665,7 +665,7 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl JSHandle jsHclass(thread_, obj->GetJSHClass()); JSTaggedValue enumCache = jsHclass->GetEnumCache(); if (!enumCache.IsNull()) { - int propsNumber = jsHclass->GetPropertiesNumber(); + int propsNumber = jsHclass->NumberOfProps(); JSHandle cache(thread_, enumCache); uint32_t length = cache->GetLength(); for (uint32_t i = 0; i < length; i++) { @@ -675,13 +675,13 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl } handleKey_.Update(key); JSTaggedValue value; - LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetAttributes().GetTaggedObject()); + LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()); int index = layoutInfo->FindElementWithCache(thread_, *jsHclass, key, propsNumber); PropertyAttributes attr(layoutInfo->GetAttr(index)); ASSERT(static_cast(attr.GetOffset()) == index); value = attr.IsInlinedProps() ? obj->GetPropertyInlinedProps(index) - : propertiesArr->Get(index - JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); + : propertiesArr->Get(index - jsHclass->GetInlinedProperties()); if (UNLIKELY(value.IsAccessor())) { value = JSObject::CallGetter(thread_, AccessorData::Cast(value.GetTaggedObject()), JSHandle(obj)); @@ -692,13 +692,13 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl } return hasContent; } - int end = jsHclass->GetPropertiesNumber(); + int end = jsHclass->NumberOfProps(); if (end <= 0) { return hasContent; } - int propsNumber = jsHclass->GetPropertiesNumber(); + int propsNumber = jsHclass->NumberOfProps(); for (int i = 0; i < end; i++) { - LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetAttributes().GetTaggedObject()); + LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject()); JSTaggedValue key = layoutInfo->GetKey(i); if (key.IsString() && layoutInfo->GetAttr(i).IsEnumerable()) { handleKey_.Update(key); @@ -708,7 +708,7 @@ bool JsonStringifier::SerializeKeys(const JSHandle &obj, const JSHandl ASSERT(static_cast(attr.GetOffset()) == index); value = attr.IsInlinedProps() ? obj->GetPropertyInlinedProps(index) - : propertiesArr->Get(index - JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); + : propertiesArr->Get(index - jsHclass->GetInlinedProperties()); if (UNLIKELY(value.IsAccessor())) { value = JSObject::CallGetter(thread_, AccessorData::Cast(value.GetTaggedObject()), JSHandle(obj)); diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index 5c32ec61..b073d9e3 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -154,7 +154,8 @@ void Builtins::Initialize(const JSHandle &env, JSThread *thread) // GLobalObject.prototype_or_dynclass JSHandle globalObjFuncDynclass = - factory_->NewEcmaDynClass(JSObject::SIZE, JSType::JS_GLOBAL_OBJECT, objFuncPrototypeVal); + factory_->NewEcmaDynClass(JSObject::SIZE, JSType::JS_GLOBAL_OBJECT, 0); + globalObjFuncDynclass->SetPrototype(thread_, objFuncPrototypeVal.GetTaggedValue()); globalObjFuncDynclass->SetIsDictionaryMode(true); // Function.prototype_or_dynclass JSHandle emptyFuncDynclass( @@ -1586,7 +1587,7 @@ void Builtins::InitializeArray(const JSHandle &env, const JSHandle lexicalEnv = factory_->NewLexicalEnv(0); lexicalEnv->SetParentEnv(thread_, env.GetTaggedValue()); - arrayFuncFunction->SetLexicalEnv(thread_, lexicalEnv.GetTaggedValue(), SKIP_BARRIER); + arrayFuncFunction->SetLexicalEnv(thread_, lexicalEnv.GetTaggedValue()); arrayFuncFunction->SetFunctionPrototype(thread_, arrFuncInstanceDynclass.GetTaggedValue()); diff --git a/ecmascript/builtins/builtins_map.cpp b/ecmascript/builtins/builtins_map.cpp index 0d7df757..458ff2cd 100644 --- a/ecmascript/builtins/builtins_map.cpp +++ b/ecmascript/builtins/builtins_map.cpp @@ -44,7 +44,7 @@ JSTaggedValue BuiltinsMap::MapConstructor(EcmaRuntimeCallInfo *argv) JSHandle map = JSHandle::Cast(obj); // 4.Set map’s [[MapData]] internal slot to a new empty List. - JSTaggedValue linkedMap = LinkedHashMap::Create(thread); + JSHandle linkedMap = LinkedHashMap::Create(thread); map->SetLinkedMap(thread, linkedMap); // add data into set from iterable // 5.If iterable is not present, let iterable be undefined. diff --git a/ecmascript/builtins/builtins_number.cpp b/ecmascript/builtins/builtins_number.cpp index bbce150e..dddc9e1c 100644 --- a/ecmascript/builtins/builtins_number.cpp +++ b/ecmascript/builtins/builtins_number.cpp @@ -213,7 +213,7 @@ JSTaggedValue BuiltinsNumber::ToExponential(EcmaRuntimeCallInfo *argv) BUILTINS_API_TRACE(argv->GetThread(), Number, ToExponential); JSThread *thread = argv->GetThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); - // 1. Let x be thisNumberValue(this value). + // 1. Let x be ? thisNumberValue(this value). JSTaggedNumber value = ThisNumberValue(argv); // 2. ReturnIfAbrupt(x). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -261,7 +261,7 @@ JSTaggedValue BuiltinsNumber::ToFixed(EcmaRuntimeCallInfo *argv) BUILTINS_API_TRACE(argv->GetThread(), Number, ToFixed); JSThread *thread = argv->GetThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); - // 1. Let x be thisNumberValue(this value). + // 1. Let x be ? thisNumberValue(this value). JSTaggedNumber value = ThisNumberValue(argv); // 2. ReturnIfAbrupt(x). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -301,13 +301,14 @@ JSTaggedValue BuiltinsNumber::ToLocaleString(EcmaRuntimeCallInfo *argv) JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, Number, ToLocaleString); [[maybe_unused]] EcmaHandleScope handleScope(thread); - // 1. Let x be thisNumberValue(this value). + // 1. Let x be ? thisNumberValue(this value). JSTaggedNumber x = ThisNumberValue(argv); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 2. Let numberFormat be ? Construct(%NumberFormat%, « locales, options »). - JSHandle func = thread->GetEcmaVM()->GetGlobalEnv()->GetNumberFormatFunction(); + JSHandle ctor = thread->GetEcmaVM()->GetGlobalEnv()->GetNumberFormatFunction(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle numberFormat = - JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(func), func)); + JSHandle obj = factory->NewJSObjectByConstructor(JSHandle(ctor), ctor); + JSHandle numberFormat = JSHandle::Cast(obj); JSHandle locales = GetCallArg(argv, 0); JSHandle options = GetCallArg(argv, 1); JSNumberFormat::InitializeNumberFormat(thread, numberFormat, locales, options); @@ -326,7 +327,7 @@ JSTaggedValue BuiltinsNumber::ToPrecision(EcmaRuntimeCallInfo *argv) BUILTINS_API_TRACE(argv->GetThread(), Number, ToPrecision); JSThread *thread = argv->GetThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); - // 1. Let x be thisNumberValue(this value). + // 1. Let x be ? thisNumberValue(this value). JSTaggedNumber value = ThisNumberValue(argv); // 2. ReturnIfAbrupt(x). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -370,7 +371,7 @@ JSTaggedValue BuiltinsNumber::ToString(EcmaRuntimeCallInfo *argv) BUILTINS_API_TRACE(argv->GetThread(), Number, ToString); JSThread *thread = argv->GetThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); - // 1. Let x be thisNumberValue(this value). + // 1. Let x be ? thisNumberValue(this value). JSTaggedNumber value = ThisNumberValue(argv); // 2. ReturnIfAbrupt(x). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -417,8 +418,11 @@ JSTaggedValue BuiltinsNumber::ValueOf(EcmaRuntimeCallInfo *argv) { ASSERT(argv); BUILTINS_API_TRACE(argv->GetThread(), Number, ValueOf); - // 1. Let x be thisNumberValue(this value). - return ThisNumberValue(argv); + // 1. Let x be ? thisNumberValue(this value). + JSTaggedValue x = ThisNumberValue(argv); + JSThread *thread = argv->GetThread(); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return x; } JSTaggedNumber BuiltinsNumber::ThisNumberValue(EcmaRuntimeCallInfo *argv) diff --git a/ecmascript/builtins/builtins_promise.cpp b/ecmascript/builtins/builtins_promise.cpp index 5cdd765d..e1f25d58 100644 --- a/ecmascript/builtins/builtins_promise.cpp +++ b/ecmascript/builtins/builtins_promise.cpp @@ -419,10 +419,16 @@ JSTaggedValue BuiltinsPromise::PerformPromiseThen(JSThread *thread, const JSHand JSHandle argv = factory->NewTaggedArray(2); // 2: 2 means two args stored in array argv->Set(thread, 0, rejectReaction.GetTaggedValue()); argv->Set(thread, 1, promise->GetPromiseResult()); - + // When a handler is added to a rejected promise for the first time, it is called with its operation + // argument set to "handle". + if (!promise->GetPromiseIsHandled().ToBoolean()) { + JSHandle reason(thread, JSTaggedValue::Null()); + thread->GetEcmaVM()->PromiseRejectionTracker(promise, reason, ecmascript::PromiseRejectionEvent::HANDLE); + } JSHandle promiseReactionsJob(env->GetPromiseReactionJob()); job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, promiseReactionsJob, argv); } + promise->SetPromiseIsHandled(thread, JSTaggedValue::True()); return capability->GetPromise(); } diff --git a/ecmascript/builtins/builtins_regexp.cpp b/ecmascript/builtins/builtins_regexp.cpp index fd7c25e6..804cbbea 100644 --- a/ecmascript/builtins/builtins_regexp.cpp +++ b/ecmascript/builtins/builtins_regexp.cpp @@ -66,9 +66,8 @@ JSTaggedValue BuiltinsRegExp::RegExpConstructor(EcmaRuntimeCallInfo *argv) // 4.b If patternIsRegExp is true and flags is undefined if (patternIsRegExp && flags->IsUndefined()) { // 4.b.i Let patternConstructor be Get(pattern, "constructor"). - JSTaggedValue patternConstructor = - FastRuntimeStub::FastGetPropertyByName(thread, pattern.GetTaggedValue(), - constructorString.GetTaggedValue()); + JSTaggedValue patternConstructor = FastRuntimeStub::FastGetPropertyByName( + thread, pattern.GetTaggedValue(), constructorString.GetTaggedValue()); // 4.b.ii ReturnIfAbrupt(patternConstructor). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 4.b.iii If SameValue(newTarget, patternConstructor) is true, return pattern. @@ -251,8 +250,7 @@ JSTaggedValue BuiltinsRegExp::GetFlags(EcmaRuntimeCallInfo *argv) // 3. Let result be the empty String. // 4. ~ 19. ASSERT(JSHandle::Cast(thisObj)->IsJSRegExp()); - uint8_t flagsBits = static_cast( - JSRegExp::Cast(thisObj->GetTaggedObject())->GetOriginalFlags().GetInt()); + uint8_t flagsBits = static_cast(JSRegExp::Cast(thisObj->GetTaggedObject())->GetOriginalFlags().GetInt()); return FlagsBitsToString(thread, flagsBits); } @@ -384,8 +382,8 @@ JSTaggedValue BuiltinsRegExp::Match(EcmaRuntimeCallInfo *argv) // 5. Let global be ToBoolean(Get(rx, "global")). const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle global = globalConst->GetHandledGlobalString(); - JSTaggedValue globalValue = FastRuntimeStub::FastGetPropertyByName(thread, thisObj.GetTaggedValue(), - global.GetTaggedValue()); + JSTaggedValue globalValue = + FastRuntimeStub::FastGetPropertyByName(thread, thisObj.GetTaggedValue(), global.GetTaggedValue()); // 6. ReturnIfAbrupt(global). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); bool isGlobal = globalValue.ToBoolean(); @@ -396,12 +394,15 @@ JSTaggedValue BuiltinsRegExp::Match(EcmaRuntimeCallInfo *argv) return JSTaggedValue(result); } JSHandle regexpObj(thisObj); - JSHandle pattern(thread, regexpObj->GetOriginalSource()); - JSHandle flags(thread, regexpObj->GetOriginalFlags()); + JSMutableHandle pattern(thread, JSTaggedValue::Undefined()); + JSMutableHandle flags(thread, JSTaggedValue::Undefined()); + if (thisObj->IsJSRegExp()) { + pattern.Update(regexpObj->GetOriginalSource()); + flags.Update(regexpObj->GetOriginalFlags()); + } if (isCached) { - JSTaggedValue cacheResult = - cacheTable->FindCachedResult(thread, pattern, flags, inputString, - RegExpExecResultCache::MATCH_TYPE, thisObj); + JSTaggedValue cacheResult = cacheTable->FindCachedResult(thread, pattern, flags, inputString, + RegExpExecResultCache::MATCH_TYPE, thisObj); if (cacheResult != JSTaggedValue::Undefined()) { return cacheResult; } @@ -409,8 +410,8 @@ JSTaggedValue BuiltinsRegExp::Match(EcmaRuntimeCallInfo *argv) // 8. Else global is true // a. Let fullUnicode be ToBoolean(Get(rx, "unicode")). JSHandle unicode = globalConst->GetHandledUnicodeString(); - JSTaggedValue uincodeValue = FastRuntimeStub::FastGetProperty(thread, thisObj.GetTaggedValue(), - unicode.GetTaggedValue()); + JSTaggedValue uincodeValue = + FastRuntimeStub::FastGetProperty(thread, thisObj.GetTaggedValue(), unicode.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); bool fullUnicode = uincodeValue.ToBoolean(); // b. ReturnIfAbrupt(fullUnicode) @@ -441,8 +442,9 @@ JSTaggedValue BuiltinsRegExp::Match(EcmaRuntimeCallInfo *argv) return JSTaggedValue::Null(); } if (isCached) { - cacheTable->AddResultInCache(thread, pattern, flags, inputString, array.GetTaggedValue(), - RegExpExecResultCache::MATCH_TYPE, 0); + RegExpExecResultCache::AddResultInCache(thread, cacheTable, pattern, flags, inputString, + JSHandle(array), + RegExpExecResultCache::MATCH_TYPE, 0); } // 2. Else, return A. return array.GetTaggedValue(); @@ -462,8 +464,8 @@ JSTaggedValue BuiltinsRegExp::Match(EcmaRuntimeCallInfo *argv) if (JSTaggedValue::ToString(thread, matchValue)->GetLength() == 0) { // a. Let thisIndex be ToLength(Get(rx, "lastIndex")). JSHandle lastIndexHandle( - thread, FastRuntimeStub::FastGetProperty( - thread, thisObj.GetTaggedValue(), lastIndexString.GetTaggedValue())); + thread, + FastRuntimeStub::FastGetProperty(thread, thisObj.GetTaggedValue(), lastIndexString.GetTaggedValue())); JSTaggedNumber thisIndex = JSTaggedValue::ToLength(thread, lastIndexHandle); // b. ReturnIfAbrupt(thisIndex). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); @@ -510,8 +512,12 @@ JSTaggedValue BuiltinsRegExp::RegExpReplaceFast(JSThread *thread, JSHandle tagInputString = JSHandle::Cast(inputString); - JSHandle pattern(thread, regexpHandle->GetOriginalSource()); - JSHandle flagsBits(thread, regexpHandle->GetOriginalFlags()); + JSMutableHandle pattern(thread, JSTaggedValue::Undefined()); + JSMutableHandle flagsBits(thread, JSTaggedValue::Undefined()); + if (regexp->IsJSRegExp()) { + pattern.Update(regexpHandle->GetOriginalSource()); + flagsBits.Update(regexpHandle->GetOriginalFlags()); + } JSHandle cacheTable(thread->GetEcmaVM()->GetRegExpCache()); uint32_t length = inputString->GetLength(); uint32_t largeStrCount = cacheTable->GetLargeStrCount(); @@ -526,9 +532,8 @@ JSTaggedValue BuiltinsRegExp::RegExpReplaceFast(JSThread *thread, JSHandleFindCachedResult(thread, pattern, flagsBits, tagInputString, - RegExpExecResultCache::REPLACE_TYPE, regexp); + JSTaggedValue cacheResult = cacheTable->FindCachedResult(thread, pattern, flagsBits, tagInputString, + RegExpExecResultCache::REPLACE_TYPE, regexp); if (cacheResult != JSTaggedValue::Undefined()) { return cacheResult; } @@ -591,12 +596,13 @@ JSTaggedValue BuiltinsRegExp::RegExpReplaceFast(JSThread *thread, JSHandleNewFromStdString(resultString).GetTaggedValue(); + auto resultValue = factory->NewFromStdString(resultString); if (isCached) { - cacheTable->AddResultInCache(thread, pattern, flagsBits, tagInputString, resultValue, - RegExpExecResultCache::REPLACE_TYPE, lastIndex); + RegExpExecResultCache::AddResultInCache(thread, cacheTable, pattern, flagsBits, tagInputString, + JSHandle(resultValue), + RegExpExecResultCache::REPLACE_TYPE, lastIndex); } - return resultValue; + return resultValue.GetTaggedValue(); } // 21.2.5.8 @@ -635,8 +641,8 @@ JSTaggedValue BuiltinsRegExp::Replace(EcmaRuntimeCallInfo *argv) // 8. Let global be ToBoolean(Get(rx, "global")). ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle global = globalConst->GetHandledGlobalString(); - JSTaggedValue globalValue = FastRuntimeStub::FastGetProperty(thread, thisObj.GetTaggedValue(), - global.GetTaggedValue()); + JSTaggedValue globalValue = + FastRuntimeStub::FastGetProperty(thread, thisObj.GetTaggedValue(), global.GetTaggedValue()); // 9. ReturnIfAbrupt(global). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); bool isGlobal = globalValue.ToBoolean(); @@ -652,8 +658,8 @@ JSTaggedValue BuiltinsRegExp::Replace(EcmaRuntimeCallInfo *argv) // b. ReturnIfAbrupt(fullUnicode). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // c. Let setStatus be Set(rx, "lastIndex", 0, true). - FastRuntimeStub::FastSetProperty( - thread, thisObj.GetTaggedValue(), lastIndex.GetTaggedValue(), JSTaggedValue(0), true); + FastRuntimeStub::FastSetProperty(thread, thisObj.GetTaggedValue(), lastIndex.GetTaggedValue(), JSTaggedValue(0), + true); // d. ReturnIfAbrupt(setStatus). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } @@ -713,8 +719,8 @@ JSTaggedValue BuiltinsRegExp::Replace(EcmaRuntimeCallInfo *argv) uint32_t nextIndex = AdvanceStringIndex(thread, inputStr, thisIndex, fullUnicode); nextIndexHandle.Update(JSTaggedValue(nextIndex)); // d. Let setStatus be Set(rx, "lastIndex", nextIndex, true). - FastRuntimeStub::FastSetProperty( - thread, thisObj.GetTaggedValue(), lastIndex.GetTaggedValue(), nextIndexHandle.GetTaggedValue(), true); + FastRuntimeStub::FastSetProperty(thread, thisObj.GetTaggedValue(), lastIndex.GetTaggedValue(), + nextIndexHandle.GetTaggedValue(), true); // e. ReturnIfAbrupt(setStatus). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } @@ -968,13 +974,16 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv) } JSHandle regexpHandle(thisObj); - JSHandle pattern(thread, regexpHandle->GetOriginalSource()); - JSHandle flagsBits(thread, regexpHandle->GetOriginalFlags()); + JSMutableHandle pattern(thread, JSTaggedValue::Undefined()); + JSMutableHandle flagsBits(thread, JSTaggedValue::Undefined()); + if (thisObj->IsJSRegExp()) { + pattern.Update(regexpHandle->GetOriginalSource()); + flagsBits.Update(regexpHandle->GetOriginalFlags()); + } JSHandle cacheTable(thread->GetEcmaVM()->GetRegExpCache()); if (isCached) { - JSTaggedValue cacheResult = - cacheTable->FindCachedResult(thread, pattern, flagsBits, inputString, - RegExpExecResultCache::SPLIT_TYPE, thisObj); + JSTaggedValue cacheResult = cacheTable->FindCachedResult(thread, pattern, flagsBits, inputString, + RegExpExecResultCache::SPLIT_TYPE, thisObj); if (cacheResult != JSTaggedValue::Undefined()) { return cacheResult; } @@ -1064,8 +1073,9 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv) // 5. If lengthA = lim, return A. if (aLength == lim) { if (isCached) { - cacheTable->AddResultInCache(thread, pattern, flagsBits, inputString, array.GetTaggedValue(), - RegExpExecResultCache::SPLIT_TYPE, lastIndex); + RegExpExecResultCache::AddResultInCache(thread, cacheTable, pattern, flagsBits, inputString, + JSHandle(array), + RegExpExecResultCache::SPLIT_TYPE, lastIndex); } return array.GetTaggedValue(); } @@ -1098,9 +1108,9 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv) // f. If lengthA = lim, return A. if (aLength == lim) { if (isCached) { - cacheTable->AddResultInCache(thread, pattern, flagsBits, inputString, - array.GetTaggedValue(), - RegExpExecResultCache::SPLIT_TYPE, lastIndex); + RegExpExecResultCache::AddResultInCache(thread, cacheTable, pattern, flagsBits, inputString, + JSHandle(array), + RegExpExecResultCache::SPLIT_TYPE, lastIndex); } return array.GetTaggedValue(); } @@ -1119,8 +1129,9 @@ JSTaggedValue BuiltinsRegExp::Split(EcmaRuntimeCallInfo *argv) JSHandle tValue(factory->NewFromStdString(stdStrT)); JSObject::CreateDataProperty(thread, array, aLength, tValue); if (lim == MAX_SPLIT_LIMIT) { - cacheTable->AddResultInCache(thread, pattern, flagsBits, inputString, array.GetTaggedValue(), - RegExpExecResultCache::SPLIT_TYPE, endIndex); + RegExpExecResultCache::AddResultInCache(thread, cacheTable, pattern, flagsBits, inputString, + JSHandle(array), RegExpExecResultCache::SPLIT_TYPE, + endIndex); } // 28. Return A. return array.GetTaggedValue(); @@ -1180,8 +1191,7 @@ uint32_t BuiltinsRegExp::AdvanceStringIndex(JSThread *thread, const JSHandle &obj, - const uint8_t mask) +bool BuiltinsRegExp::GetFlagsInternal(JSThread *thread, const JSHandle &obj, const uint8_t mask) { // 1. Let R be the this value. // 2. If Type(R) is not Object, throw a TypeError exception. @@ -1213,8 +1223,8 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle lastIndexHandle = globalConst->GetHandledLastIndexString(); - JSTaggedValue result = FastRuntimeStub::FastGetProperty(thread, regexp.GetTaggedValue(), - lastIndexHandle.GetTaggedValue()); + JSTaggedValue result = + FastRuntimeStub::FastGetProperty(thread, regexp.GetTaggedValue(), lastIndexHandle.GetTaggedValue()); int32_t lastIndex = 0; if (result.IsInt()) { lastIndex = result.GetInt(); @@ -1236,13 +1246,16 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle lastIndex = 0; } JSHandle regexpObj(regexp); - JSHandle pattern(thread, regexpObj->GetOriginalSource()); - JSHandle flags(thread, regexpObj->GetOriginalFlags()); + JSMutableHandle pattern(thread, JSTaggedValue::Undefined()); + JSMutableHandle flags(thread, JSTaggedValue::Undefined()); + if (regexp->IsJSRegExp()) { + pattern.Update(regexpObj->GetOriginalSource()); + flags.Update(regexpObj->GetOriginalFlags()); + } JSHandle cacheTable(thread->GetEcmaVM()->GetRegExpCache()); if (lastIndex == 0 && isCached) { JSTaggedValue cacheResult = - cacheTable->FindCachedResult(thread, pattern, flags, inputStr, - RegExpExecResultCache::EXEC_TYPE, regexp); + cacheTable->FindCachedResult(thread, pattern, flags, inputStr, RegExpExecResultCache::EXEC_TYPE, regexp); if (cacheResult != JSTaggedValue::Undefined()) { return cacheResult; } @@ -1253,8 +1266,8 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle JSHandle uString(globalConst->GetHandledUString()); [[maybe_unused]] bool fullUnicode = base::StringHelper::Contains(*flagsStr, *uString); if (lastIndex > length) { - FastRuntimeStub::FastSetPropertyByValue( - thread, regexp.GetTaggedValue(), lastIndexHandle.GetTaggedValue(), JSTaggedValue(0)); + FastRuntimeStub::FastSetPropertyByValue(thread, regexp.GetTaggedValue(), lastIndexHandle.GetTaggedValue(), + JSTaggedValue(0)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::Null(); } @@ -1286,8 +1299,8 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle uint32_t endIndex = matchResult.endIndex_; if (global || sticky) { // a. Let setStatus be Set(R, "lastIndex", e, true). - FastRuntimeStub::FastSetPropertyByValue( - thread, regexp.GetTaggedValue(), lastIndexHandle.GetTaggedValue(), JSTaggedValue(endIndex)); + FastRuntimeStub::FastSetPropertyByValue(thread, regexp.GetTaggedValue(), lastIndexHandle.GetTaggedValue(), + JSTaggedValue(endIndex)); // b. ReturnIfAbrupt(setStatus). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } @@ -1319,8 +1332,9 @@ JSTaggedValue BuiltinsRegExp::RegExpBuiltinExec(JSThread *thread, const JSHandle JSObject::CreateDataProperty(thread, results, i, iValue); } if (lastIndex == 0 && isCached) { - cacheTable->AddResultInCache(thread, pattern, flags, inputStr, results.GetTaggedValue(), - RegExpExecResultCache::EXEC_TYPE, endIndex); + RegExpExecResultCache::AddResultInCache(thread, cacheTable, pattern, flags, inputStr, + JSHandle(results), RegExpExecResultCache::EXEC_TYPE, + endIndex); } // 29. Return A. return results.GetTaggedValue(); @@ -1433,9 +1447,9 @@ uint32_t BuiltinsRegExp::UpdateExpressionFlags(JSThread *thread, const CString & JSTaggedValue BuiltinsRegExp::FlagsBitsToString(JSThread *thread, uint8_t flags) { - ASSERT((flags & 0xC0) == 0); // 0xC0: first 2 bits of flags must be 0 + ASSERT((flags & 0xC0) == 0); // 0xC0: first 2 bits of flags must be 0 - uint8_t *flagsStr = new uint8_t[7]; // 7: maximum 6 flags + '\0' + uint8_t *flagsStr = new uint8_t[7]; // 7: maximum 6 flags + '\0' size_t flagsLen = 0; if (flags & RegExpParser::FLAG_GLOBAL) { flagsStr[flagsLen] = 'g'; @@ -1583,15 +1597,16 @@ EcmaString *BuiltinsRegExp::EscapeRegExpPattern(JSThread *thread, const JSHandle JSTaggedValue RegExpExecResultCache::CreateCacheTable(JSThread *thread) { - int length = CACHE_TABLE_HEADER_SIZE + DEFAULT_CACHE_NUMBER * ENTRY_SIZE; + int length = CACHE_TABLE_HEADER_SIZE + INITIAL_CACHE_NUMBER * ENTRY_SIZE; - auto table = static_cast(*thread->GetEcmaVM()->GetFactory()->NewDictionaryArray(length)); + auto table = static_cast( + *thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length, JSTaggedValue::Undefined())); table->SetLargeStrCount(thread, DEFAULT_LARGE_STRING_COUNT); table->SetConflictCount(thread, DEFAULT_CONFLICT_COUNT); table->SetStrLenThreshold(thread, 0); table->SetHitCount(thread, 0); table->SetCacheCount(thread, 0); - + table->SetCacheLength(thread, INITIAL_CACHE_NUMBER); return JSTaggedValue(table); } @@ -1609,9 +1624,9 @@ JSTaggedValue RegExpExecResultCache::FindCachedResult(JSThread *thread, const JS } uint32_t hash = pattern->GetKeyHashCode() + flags->GetInt() + input->GetKeyHashCode(); - uint32_t entry = hash & (RegExpExecResultCache::DEFAULT_CACHE_NUMBER - 1); + uint32_t entry = hash & (GetCacheLength() - 1); if (!Match(entry, patternValue, flagsValue, inputValue)) { - uint32_t entry2 = (entry + 1) & (DEFAULT_CACHE_NUMBER - 1); + uint32_t entry2 = (entry + 1) & (GetCacheLength() - 1); if (!Match(entry2, patternValue, flagsValue, inputValue)) { return JSTaggedValue::Undefined(); } @@ -1643,9 +1658,11 @@ JSTaggedValue RegExpExecResultCache::FindCachedResult(JSThread *thread, const JS return result; } -void RegExpExecResultCache::AddResultInCache(JSThread *thread, const JSHandle &pattern, +void RegExpExecResultCache::AddResultInCache(JSThread *thread, JSHandle cache, + const JSHandle &pattern, const JSHandle &flags, const JSHandle &input, - JSTaggedValue resultArray, CacheType type, uint32_t lastIndex) + const JSHandle &resultArray, CacheType type, + uint32_t lastIndex) { if (!pattern->IsString() || !flags->IsInt() || !input->IsString()) { return; @@ -1657,33 +1674,52 @@ void RegExpExecResultCache::AddResultInCache(JSThread *thread, const JSHandleGetKeyHashCode() + flags->GetInt() + input->GetKeyHashCode(); - uint32_t entry = hash & (DEFAULT_CACHE_NUMBER - 1); + uint32_t entry = hash & (cache->GetCacheLength() - 1); uint32_t index = CACHE_TABLE_HEADER_SIZE + entry * ENTRY_SIZE; - if (Get(index) == JSTaggedValue::Undefined()) { - SetCacheCount(thread, GetCacheCount() + 1); - SetEntry(thread, entry, patternValue, flagsValue, inputValue, lastIndexValue); - UpdateResultArray(thread, entry, resultArray, type); - } else if (Match(entry, patternValue, flagsValue, inputValue)) { - UpdateResultArray(thread, entry, resultArray, type); + if (cache->Get(index) == JSTaggedValue::Undefined()) { + cache->SetCacheCount(thread, cache->GetCacheCount() + 1); + cache->SetEntry(thread, entry, patternValue, flagsValue, inputValue, lastIndexValue); + cache->UpdateResultArray(thread, entry, resultArray.GetTaggedValue(), type); + } else if (cache->Match(entry, patternValue, flagsValue, inputValue)) { + cache->UpdateResultArray(thread, entry, resultArray.GetTaggedValue(), type); } else { - uint32_t entry2 = (entry + 1) & (DEFAULT_CACHE_NUMBER - 1); + uint32_t entry2 = (entry + 1) & (cache->GetCacheLength() - 1); uint32_t index2 = CACHE_TABLE_HEADER_SIZE + entry2 * ENTRY_SIZE; - if (Get(index2) == JSTaggedValue::Undefined()) { - SetCacheCount(thread, GetCacheCount() + 1); - SetEntry(thread, entry2, patternValue, flagsValue, inputValue, lastIndexValue); - UpdateResultArray(thread, entry2, resultArray, type); - } else if (Match(entry2, patternValue, flagsValue, inputValue)) { - UpdateResultArray(thread, entry2, resultArray, type); + if (cache->GetCacheLength() < DEFAULT_CACHE_NUMBER) { + GrowRegexpCache(thread, cache); + // update value after gc. + patternValue = pattern.GetTaggedValue(); + flagsValue = flags.GetTaggedValue(); + inputValue = input.GetTaggedValue(); + + cache->SetCacheLength(thread, DEFAULT_CACHE_NUMBER); + entry2 = hash & (cache->GetCacheLength() - 1); + index2 = CACHE_TABLE_HEADER_SIZE + entry2 * ENTRY_SIZE; + } + if (cache->Get(index2) == JSTaggedValue::Undefined()) { + cache->SetCacheCount(thread, cache->GetCacheCount() + 1); + cache->SetEntry(thread, entry2, patternValue, flagsValue, inputValue, lastIndexValue); + cache->UpdateResultArray(thread, entry2, resultArray.GetTaggedValue(), type); + } else if (cache->Match(entry2, patternValue, flagsValue, inputValue)) { + cache->UpdateResultArray(thread, entry2, resultArray.GetTaggedValue(), type); } else { - SetConflictCount(thread, GetConflictCount() - 1); - SetCacheCount(thread, GetCacheCount() - 1); - ClearEntry(thread, entry2); - SetEntry(thread, entry, patternValue, flagsValue, inputValue, lastIndexValue); - UpdateResultArray(thread, entry, resultArray, type); + cache->SetConflictCount(thread, cache->GetConflictCount() > 1 ? (cache->GetConflictCount() - 1) : 0); + cache->SetCacheCount(thread, cache->GetCacheCount() - 1); + cache->ClearEntry(thread, entry2); + cache->SetEntry(thread, entry, patternValue, flagsValue, inputValue, lastIndexValue); + cache->UpdateResultArray(thread, entry, resultArray.GetTaggedValue(), type); } } } +void RegExpExecResultCache::GrowRegexpCache(JSThread *thread, JSHandle cache) +{ + int length = CACHE_TABLE_HEADER_SIZE + DEFAULT_CACHE_NUMBER * ENTRY_SIZE; + auto factory = thread->GetEcmaVM()->GetFactory(); + auto newCache = factory->ExtendArray(JSHandle(cache), length, JSTaggedValue::Undefined()); + thread->GetEcmaVM()->SetRegExpCache(newCache.GetTaggedValue()); +} + void RegExpExecResultCache::SetEntry(JSThread *thread, int entry, JSTaggedValue &pattern, JSTaggedValue &flags, JSTaggedValue &input, JSTaggedValue &lastIndexValue) { diff --git a/ecmascript/builtins/builtins_regexp.h b/ecmascript/builtins/builtins_regexp.h index 16391de2..71ebcd37 100644 --- a/ecmascript/builtins/builtins_regexp.h +++ b/ecmascript/builtins/builtins_regexp.h @@ -115,9 +115,12 @@ public: JSTaggedValue FindCachedResult(JSThread *thread, const JSHandle &patten, const JSHandle &flags, const JSHandle &input, CacheType type, const JSHandle ®exp); - void AddResultInCache(JSThread *thread, const JSHandle &patten, const JSHandle &flags, - const JSHandle &input, JSTaggedValue resultArray, CacheType type, - uint32_t lastIndex); + static void AddResultInCache(JSThread *thread, JSHandle cache, + const JSHandle &patten, const JSHandle &flags, + const JSHandle &input, const JSHandle &resultArray, + CacheType type, uint32_t lastIndex); + + static void GrowRegexpCache(JSThread *thread, JSHandle cache); void ClearEntry(JSThread *thread, int entry); void SetEntry(JSThread *thread, int entry, JSTaggedValue &patten, JSTaggedValue &flags, JSTaggedValue &input, @@ -180,16 +183,28 @@ public: return Get(STRING_LENGTH_THRESHOLD_INDEX).GetInt(); } + inline void SetCacheLength(JSThread *thread, int length) + { + Set(thread, CACHE_LENGTH_INDEX, JSTaggedValue(length)); + } + + inline int GetCacheLength() + { + return Get(CACHE_LENGTH_INDEX).GetInt(); + } + private: static constexpr int DEFAULT_LARGE_STRING_COUNT = 10; static constexpr int DEFAULT_CONFLICT_COUNT = 100; + static constexpr int INITIAL_CACHE_NUMBER = 0x10; static constexpr int DEFAULT_CACHE_NUMBER = 0x1000; static constexpr int CACHE_COUNT_INDEX = 0; static constexpr int CACHE_HIT_COUNT_INDEX = 1; static constexpr int LARGE_STRING_COUNT_INDEX = 2; static constexpr int CONFLICT_COUNT_INDEX = 3; static constexpr int STRING_LENGTH_THRESHOLD_INDEX = 4; - static constexpr int CACHE_TABLE_HEADER_SIZE = 5; + static constexpr int CACHE_LENGTH_INDEX = 5; + static constexpr int CACHE_TABLE_HEADER_SIZE = 6; static constexpr int PATTERN_INDEX = 0; static constexpr int FLAG_INDEX = 1; static constexpr int INPUT_STRING_INDEX = 2; diff --git a/ecmascript/builtins/builtins_set.cpp b/ecmascript/builtins/builtins_set.cpp index a4fb5559..a9710d85 100644 --- a/ecmascript/builtins/builtins_set.cpp +++ b/ecmascript/builtins/builtins_set.cpp @@ -46,7 +46,7 @@ JSTaggedValue BuiltinsSet::SetConstructor(EcmaRuntimeCallInfo *argv) JSHandle set = JSHandle::Cast(obj); // 3.ReturnIfAbrupt(set). // 4.Set set’s [[SetData]] internal slot to a new empty List. - JSTaggedValue linkedSet = LinkedHashSet::Create(thread); + JSHandle linkedSet = LinkedHashSet::Create(thread); set->SetLinkedSet(thread, linkedSet); // add data into set from iterable @@ -116,7 +116,7 @@ JSTaggedValue BuiltinsSet::Add(EcmaRuntimeCallInfo *argv) } JSHandle value(GetCallArg(argv, 0)); - JSHandle set(thread, JSSet::Cast(*JSTaggedValue::ToObject(thread, self))); + JSHandle set(JSTaggedValue::ToObject(thread, self)); JSSet::Add(thread, set, value); return set.GetTaggedValue(); diff --git a/ecmascript/builtins/builtins_weak_map.cpp b/ecmascript/builtins/builtins_weak_map.cpp index 6541f8c2..1d81874c 100644 --- a/ecmascript/builtins/builtins_weak_map.cpp +++ b/ecmascript/builtins/builtins_weak_map.cpp @@ -45,7 +45,7 @@ JSTaggedValue BuiltinsWeakMap::WeakMapConstructor(EcmaRuntimeCallInfo *argv) JSHandle weakMap = JSHandle::Cast(obj); // 4.Set weakmap’s [[WeakMapData]] internal slot to a new empty List. - JSTaggedValue linkedMap = LinkedHashMap::Create(thread); + JSHandle linkedMap = LinkedHashMap::Create(thread); weakMap->SetLinkedMap(thread, linkedMap); // add data into set from iterable // 5.If iterable is not present, let iterable be undefined. diff --git a/ecmascript/builtins/builtins_weak_set.cpp b/ecmascript/builtins/builtins_weak_set.cpp index 814e746a..d1674862 100644 --- a/ecmascript/builtins/builtins_weak_set.cpp +++ b/ecmascript/builtins/builtins_weak_set.cpp @@ -45,7 +45,7 @@ JSTaggedValue BuiltinsWeakSet::WeakSetConstructor(EcmaRuntimeCallInfo *argv) JSHandle weakSet = JSHandle::Cast(obj); // 3.ReturnIfAbrupt(weakSet). // 4.WeakSet set’s [[WeakSetData]] internal slot to a new empty List. - JSTaggedValue linkedSet = LinkedHashSet::Create(thread); + JSHandle linkedSet = LinkedHashSet::Create(thread); weakSet->SetLinkedSet(thread, linkedSet); // add data into weakset from iterable diff --git a/ecmascript/builtins/tests/builtins_object_test.cpp b/ecmascript/builtins/tests/builtins_object_test.cpp index aebf11a9..509993ac 100644 --- a/ecmascript/builtins/tests/builtins_object_test.cpp +++ b/ecmascript/builtins/tests/builtins_object_test.cpp @@ -84,7 +84,7 @@ JSFunction *BuiltinsObjectTestCreate(JSThread *thread) JSObject *TestNewJSObject(JSThread *thread, const JSHandle &dynClass) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSObject *obj = JSObject::Cast(factory->NewDynObject(dynClass, JSObject::MIN_PROPERTIES_LENGTH)); + JSObject *obj = JSObject::Cast(factory->NewDynObject(dynClass)); obj->SetElements(thread, factory->EmptyArray().GetTaggedValue(), SKIP_BARRIER); return obj; diff --git a/ecmascript/class_linker/panda_file_translator.cpp b/ecmascript/class_linker/panda_file_translator.cpp index 3d15a234..c4bf2e63 100644 --- a/ecmascript/class_linker/panda_file_translator.cpp +++ b/ecmascript/class_linker/panda_file_translator.cpp @@ -109,6 +109,7 @@ void PandaFileTranslator::TranslateClasses(const panda_file::File &pf, const CSt InitializeMemory(method, nullptr, &pf, mda.GetMethodId(), codeDataAccessor.GetCodeId(), mda.GetAccessFlags(), codeDataAccessor.GetNumArgs(), nullptr); method->SetHotnessCounter(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD); + method->SetCallTypeFromAnnotation(); const uint8_t *insns = codeDataAccessor.GetInstructions(); if (this->translated_code_.find(insns) == this->translated_code_.end()) { this->translated_code_.insert(insns); @@ -241,13 +242,7 @@ Program *PandaFileTranslator::GenerateProgram(const panda_file::File &pf) array_size_t length = literal->GetLength(); JSHandle arr(JSArray::ArrayCreate(thread_, JSTaggedNumber(length))); - JSMutableHandle key(thread_, JSTaggedValue::Undefined()); - JSMutableHandle arrValue(thread_, JSTaggedValue::Undefined()); - for (array_size_t i = 0; i < length; i++) { - key.Update(JSTaggedValue(static_cast(i))); - arrValue.Update(literal->Get(i)); - JSObject::DefinePropertyByLiteral(thread_, JSHandle::Cast(arr), key, arrValue); - } + arr->SetElements(thread_, literal); constpool->Set(thread_, value.GetConstpoolIndex(), arr.GetTaggedValue()); } else if (value.GetConstpoolType() == ConstPoolType::CLASS_LITERAL) { size_t index = it.first; @@ -350,6 +345,23 @@ void PandaFileTranslator::UpdateICOffset(JSMethod *method, uint8_t *pc) const case EcmaOpcode::TRYSTGLOBALBYNAME_PREF_ID32: case EcmaOpcode::LDGLOBALVAR_PREF_ID32: case EcmaOpcode::STGLOBALVAR_PREF_ID32: + case EcmaOpcode::ADD2DYN_PREF_V8: + case EcmaOpcode::SUB2DYN_PREF_V8: + case EcmaOpcode::MUL2DYN_PREF_V8: + case EcmaOpcode::DIV2DYN_PREF_V8: + case EcmaOpcode::MOD2DYN_PREF_V8: + case EcmaOpcode::SHL2DYN_PREF_V8: + case EcmaOpcode::SHR2DYN_PREF_V8: + case EcmaOpcode::ASHR2DYN_PREF_V8: + case EcmaOpcode::AND2DYN_PREF_V8: + case EcmaOpcode::OR2DYN_PREF_V8: + case EcmaOpcode::XOR2DYN_PREF_V8: + case EcmaOpcode::EQDYN_PREF_V8: + case EcmaOpcode::NOTEQDYN_PREF_V8: + case EcmaOpcode::LESSDYN_PREF_V8: + case EcmaOpcode::LESSEQDYN_PREF_V8: + case EcmaOpcode::GREATERDYN_PREF_V8: + case EcmaOpcode::GREATEREQDYN_PREF_V8: method->UpdateSlotSize(1); break; case EcmaOpcode::LDOBJBYVALUE_PREF_V8_V8: diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index a2884c97..c89b0445 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -44,11 +44,13 @@ source_set("libark_jsoptimizer_static") { "circuit_builder.cpp", "fast_stub.cpp", "gate.cpp", + "js_thread_offset_table.cpp", "llvm_codegen.cpp", "llvm_ir_builder.cpp", "scheduler.cpp", "stub.cpp", "stub_descriptor.cpp", + "triple.cpp", "type.cpp", "verifier.cpp", ] @@ -67,8 +69,6 @@ source_set("libark_jsoptimizer_static") { } libs = [ - "stdc++", - "z", "LLVMTarget", "LLVMObject", "LLVMMC", diff --git a/ecmascript/compiler/circuit.cpp b/ecmascript/compiler/circuit.cpp index e469311c..f084e5bd 100644 --- a/ecmascript/compiler/circuit.cpp +++ b/ecmascript/compiler/circuit.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/compiler/circuit.h" +#include "ecmascript/compiler/compiler_macros.h" namespace kungfu { Circuit::Circuit() : space({}), circuitSize(0), gateCounter(0), time(1), dataSection({}) @@ -56,8 +57,8 @@ Gate *Circuit::AllocateGateSpace(size_t numIns) } // NOLINTNEXTLINE(modernize-avoid-c-arrays) -AddrShift Circuit::NewGate( - OpCode opcode, BitField bitfield, size_t numIns, const AddrShift inList[], TypeCode type, MarkCode mark) +GateRef Circuit::NewGate( + OpCode opcode, BitField bitfield, size_t numIns, const GateRef inList[], TypeCode type, MarkCode mark) { #ifndef NDEBUG if (numIns != opcode.GetOpCodeNumIns(bitfield)) { @@ -79,54 +80,56 @@ AddrShift Circuit::NewGate( return this->SaveGatePtr(newGate); } -AddrShift Circuit::NewGate( - OpCode opcode, BitField bitfield, const std::vector &inList, TypeCode type, MarkCode mark) +GateRef Circuit::NewGate( + OpCode opcode, BitField bitfield, const std::vector &inList, TypeCode type, MarkCode mark) { return this->NewGate(opcode, bitfield, inList.size(), inList.data(), type, mark); } void Circuit::PrintAllGates() const { +#if ECMASCRIPT_ENABLE_COMPILER_LOG const auto &gateList = this->GetAllGates(); for (auto &gate : gateList) { this->LoadGatePtrConst(gate)->Print(); } +#endif } -std::vector Circuit::GetAllGates() const +std::vector Circuit::GetAllGates() const { - std::vector gateList; + std::vector gateList; gateList.push_back(0); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) for (size_t out = sizeof(Gate); out < this->circuitSize; out += Gate::GetGateSize( // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - reinterpret_cast(this->LoadGatePtrConst(AddrShift(out)))->GetIndex() + 1)) { + reinterpret_cast(this->LoadGatePtrConst(GateRef(out)))->GetIndex() + 1)) { gateList.push_back( - this->SaveGatePtr(reinterpret_cast(this->LoadGatePtrConst(AddrShift(out)))->GetGateConst())); + this->SaveGatePtr(reinterpret_cast(this->LoadGatePtrConst(GateRef(out)))->GetGateConst())); } return gateList; } -AddrShift Circuit::SaveGatePtr(const Gate *gate) const +GateRef Circuit::SaveGatePtr(const Gate *gate) const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return static_cast(reinterpret_cast(gate) - this->GetDataPtrConst(0)); + return static_cast(reinterpret_cast(gate) - this->GetDataPtrConst(0)); } -Gate *Circuit::LoadGatePtr(AddrShift shift) +Gate *Circuit::LoadGatePtr(GateRef shift) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) return reinterpret_cast(this->GetDataPtr(shift)); } -const Gate *Circuit::LoadGatePtrConst(AddrShift shift) const +const Gate *Circuit::LoadGatePtrConst(GateRef shift) const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) return reinterpret_cast(this->GetDataPtrConst(shift)); } -AddrShift Circuit::GetCircuitRoot(OpCode opcode) +GateRef Circuit::GetCircuitRoot(OpCode opcode) { switch (opcode) { case OpCode::CIRCUIT_ROOT: @@ -177,32 +180,27 @@ TimeStamp Circuit::GetTime() const return this->time; } -MarkCode Circuit::GetMark(AddrShift gate) const +MarkCode Circuit::GetMark(GateRef gate) const { return this->LoadGatePtrConst(gate)->GetMark(this->GetTime()); } -TypeCode Circuit::GetTypeCode(AddrShift gate) const -{ - return this->LoadGatePtrConst(gate)->GetTypeCode(); -} - -void Circuit::SetMark(AddrShift gate, MarkCode mark) const +void Circuit::SetMark(GateRef gate, MarkCode mark) const { const_cast(this->LoadGatePtrConst(gate))->SetMark(mark, this->GetTime()); } -bool Circuit::Verify(AddrShift gate) const +bool Circuit::Verify(GateRef gate) const { return this->LoadGatePtrConst(gate)->Verify(); } -AddrShift Circuit::NullGate() +GateRef Circuit::NullGate() { return -1; } -bool Circuit::IsLoopHead(AddrShift gate) const +bool Circuit::IsLoopHead(GateRef gate) const { if (gate != NullGate()) { const Gate *curGate = this->LoadGatePtrConst(gate); @@ -211,7 +209,7 @@ bool Circuit::IsLoopHead(AddrShift gate) const return false; } -bool Circuit::IsControlCase(AddrShift gate) const +bool Circuit::IsControlCase(GateRef gate) const { if (gate != NullGate()) { const Gate *curGate = this->LoadGatePtrConst(gate); @@ -220,7 +218,7 @@ bool Circuit::IsControlCase(AddrShift gate) const return false; } -bool Circuit::IsSelector(AddrShift gate) const +bool Circuit::IsSelector(GateRef gate) const { if (gate != NullGate()) { const Gate *curGate = this->LoadGatePtrConst(gate); @@ -230,9 +228,9 @@ bool Circuit::IsSelector(AddrShift gate) const return false; } -std::vector Circuit::GetInVector(AddrShift gate) const +std::vector Circuit::GetInVector(GateRef gate) const { - std::vector result; + std::vector result; const Gate *curGate = this->LoadGatePtrConst(gate); for (size_t idx = 0; idx < curGate->GetNumIns(); idx++) { result.push_back(this->SaveGatePtr(curGate->GetInGateConst(idx))); @@ -240,27 +238,27 @@ std::vector Circuit::GetInVector(AddrShift gate) const return result; } -AddrShift Circuit::GetIn(AddrShift gate, size_t idx) const +GateRef Circuit::GetIn(GateRef gate, size_t idx) const { const Gate *curGate = this->LoadGatePtrConst(gate); return this->SaveGatePtr(curGate->GetInGateConst(idx)); } -bool Circuit::IsInGateNull(AddrShift gate, size_t idx) const +bool Circuit::IsInGateNull(GateRef gate, size_t idx) const { const Gate *curGate = this->LoadGatePtrConst(gate); return curGate->GetInConst(idx)->IsGateNull(); } -bool Circuit::IsFirstOutNull(AddrShift gate) const +bool Circuit::IsFirstOutNull(GateRef gate) const { const Gate *curGate = this->LoadGatePtrConst(gate); return curGate->IsFirstOutNull(); } -std::vector Circuit::GetOutVector(AddrShift gate) const +std::vector Circuit::GetOutVector(GateRef gate) const { - std::vector result; + std::vector result; const Gate *curGate = this->LoadGatePtrConst(gate); if (!curGate->IsFirstOutNull()) { const Out *curOut = curGate->GetFirstOutConst(); @@ -273,47 +271,57 @@ std::vector Circuit::GetOutVector(AddrShift gate) const return result; } -void Circuit::NewIn(AddrShift gate, size_t idx, AddrShift in) +void Circuit::NewIn(GateRef gate, size_t idx, GateRef in) { this->LoadGatePtr(gate)->NewIn(idx, this->LoadGatePtr(in)); } -void Circuit::ModifyIn(AddrShift gate, size_t idx, AddrShift in) +void Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in) { this->LoadGatePtr(gate)->ModifyIn(idx, this->LoadGatePtr(in)); } -void Circuit::DeleteIn(AddrShift gate, size_t idx) +void Circuit::DeleteIn(GateRef gate, size_t idx) { this->LoadGatePtr(gate)->DeleteIn(idx); } -void Circuit::DeleteGate(AddrShift gate) +void Circuit::DeleteGate(GateRef gate) { this->LoadGatePtr(gate)->DeleteGate(); } -void Circuit::SetOpCode(AddrShift gate, OpCode opcode) +void Circuit::SetOpCode(GateRef gate, OpCode opcode) { this->LoadGatePtr(gate)->SetOpCode(opcode); } -OpCode Circuit::GetOpCode(AddrShift gate) const +void Circuit::SetTypeCode(GateRef gate, TypeCode type) +{ + this->LoadGatePtr(gate)->SetTypeCode(type); +} + +TypeCode Circuit::GetTypeCode(GateRef gate) const +{ + return this->LoadGatePtrConst(gate)->GetTypeCode(); +} + +OpCode Circuit::GetOpCode(GateRef gate) const { return this->LoadGatePtrConst(gate)->GetOpCode(); } -GateId Circuit::GetId(AddrShift gate) const +GateId Circuit::GetId(GateRef gate) const { return this->LoadGatePtrConst(gate)->GetId(); } -BitField Circuit::GetBitField(AddrShift gate) const +BitField Circuit::GetBitField(GateRef gate) const { return this->LoadGatePtrConst(gate)->GetBitField(); } -void Circuit::Print(AddrShift gate) const +void Circuit::Print(GateRef gate) const { this->LoadGatePtrConst(gate)->Print(); } diff --git a/ecmascript/compiler/circuit.h b/ecmascript/compiler/circuit.h index 51da2c17..83a0b6d0 100644 --- a/ecmascript/compiler/circuit.h +++ b/ecmascript/compiler/circuit.h @@ -23,10 +23,9 @@ #include #include "ecmascript/compiler/gate.h" +#include "ecmascript/frames.h" #include "libpandabase/macros.h" #include "securec.h" -#include "ecmascript/frames.h" - namespace kungfu { const size_t INITIAL_SPACE = 1U << 0U; // this should be tuned @@ -43,41 +42,42 @@ public: Circuit(Circuit &&circuit) = default; Circuit &operator=(Circuit &&circuit) = default; // NOLINTNEXTLINE(modernize-avoid-c-arrays) - AddrShift NewGate(OpCode op, BitField bitfield, size_t numIns, const AddrShift inList[], TypeCode type, + GateRef NewGate(OpCode op, BitField bitfield, size_t numIns, const GateRef inList[], TypeCode type, MarkCode mark = MarkCode::EMPTY); - AddrShift NewGate(OpCode op, BitField bitfield, const std::vector &inList, TypeCode type, + GateRef NewGate(OpCode op, BitField bitfield, const std::vector &inList, TypeCode type, MarkCode mark = MarkCode::EMPTY); void PrintAllGates() const; - [[nodiscard]] std::vector GetAllGates() const; - [[nodiscard]] static AddrShift GetCircuitRoot(OpCode opcode); + [[nodiscard]] std::vector GetAllGates() const; + [[nodiscard]] static GateRef GetCircuitRoot(OpCode opcode); void AdvanceTime() const; void ResetAllGateTimeStamps() const; - [[nodiscard]] static AddrShift NullGate(); - [[nodiscard]] bool IsLoopHead(AddrShift gate) const; - [[nodiscard]] bool IsSelector(AddrShift gate) const; - [[nodiscard]] bool IsControlCase(AddrShift gate) const; - [[nodiscard]] AddrShift GetIn(AddrShift gate, size_t idx) const; - [[nodiscard]] bool IsInGateNull(AddrShift gate, size_t idx) const; - [[nodiscard]] bool IsFirstOutNull(AddrShift gate) const; - [[nodiscard]] std::vector GetInVector(AddrShift gate) const; - [[nodiscard]] std::vector GetOutVector(AddrShift gate) const; - void NewIn(AddrShift gate, size_t idx, AddrShift in); - void ModifyIn(AddrShift gate, size_t idx, AddrShift in); - void DeleteIn(AddrShift gate, size_t idx); - void DeleteGate(AddrShift gate); - [[nodiscard]] GateId GetId(AddrShift gate) const; - [[nodiscard]] BitField GetBitField(AddrShift gate) const; - void Print(AddrShift gate) const; - void SetOpCode(AddrShift gate, OpCode opcode); - [[nodiscard]] OpCode GetOpCode(AddrShift gate) const; + [[nodiscard]] static GateRef NullGate(); + [[nodiscard]] bool IsLoopHead(GateRef gate) const; + [[nodiscard]] bool IsSelector(GateRef gate) const; + [[nodiscard]] bool IsControlCase(GateRef gate) const; + [[nodiscard]] GateRef GetIn(GateRef gate, size_t idx) const; + [[nodiscard]] bool IsInGateNull(GateRef gate, size_t idx) const; + [[nodiscard]] bool IsFirstOutNull(GateRef gate) const; + [[nodiscard]] std::vector GetInVector(GateRef gate) const; + [[nodiscard]] std::vector GetOutVector(GateRef gate) const; + void NewIn(GateRef gate, size_t idx, GateRef in); + void ModifyIn(GateRef gate, size_t idx, GateRef in); + void DeleteIn(GateRef gate, size_t idx); + void DeleteGate(GateRef gate); + [[nodiscard]] GateId GetId(GateRef gate) const; + [[nodiscard]] BitField GetBitField(GateRef gate) const; + void Print(GateRef gate) const; + void SetOpCode(GateRef gate, OpCode opcode); + void SetTypeCode(GateRef gate, TypeCode type); + [[nodiscard]] OpCode GetOpCode(GateRef gate) const; [[nodiscard]] TimeStamp GetTime() const; - [[nodiscard]] MarkCode GetMark(AddrShift gate) const; - [[nodiscard]] TypeCode GetTypeCode(AddrShift gate) const; - void SetMark(AddrShift gate, MarkCode mark) const; - [[nodiscard]] bool Verify(AddrShift gate) const; - [[nodiscard]] Gate *LoadGatePtr(AddrShift shift); - [[nodiscard]] const Gate *LoadGatePtrConst(AddrShift shift) const; - [[nodiscard]] AddrShift SaveGatePtr(const Gate *gate) const; + [[nodiscard]] MarkCode GetMark(GateRef gate) const; + [[nodiscard]] TypeCode GetTypeCode(GateRef gate) const; + void SetMark(GateRef gate, MarkCode mark) const; + [[nodiscard]] bool Verify(GateRef gate) const; + [[nodiscard]] Gate *LoadGatePtr(GateRef shift); + [[nodiscard]] const Gate *LoadGatePtrConst(GateRef shift) const; + [[nodiscard]] GateRef SaveGatePtr(const Gate *gate) const; [[nodiscard]] std::vector GetDataSection() const; void SetDataSection(const std::vector &data); [[nodiscard]] size_t GetCircuitDataSize() const; diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index ff9f0ba9..393e2198 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -15,203 +15,230 @@ #include "ecmascript/compiler/circuit_builder.h" #include "include/coretypes/tagged_value.h" +#include "triple.h" #include "utils/bit_utils.h" namespace kungfu { -AddrShift CircuitBuilder::NewArguments(size_t index) +using TaggedValue = panda::coretypes::TaggedValue; +GateRef CircuitBuilder::NewArguments(size_t index) { auto argListOfCircuit = Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST)); return circuit_->NewGate(OpCode(OpCode::JS_ARG), index, {argListOfCircuit}, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewMerge(AddrShift *inList, size_t controlCount) +GateRef CircuitBuilder::NewMerge(GateRef *inList, size_t controlCount) { return circuit_->NewGate(OpCode(OpCode::MERGE), controlCount, controlCount, inList, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewSelectorGate(OpCode opCode, AddrShift control, int valueCounts) +GateRef CircuitBuilder::NewSelectorGate(OpCode opCode, GateRef control, int valueCounts, MachineType type) { - std::vector inList; + std::vector inList; inList.push_back(control); for (int i = 0; i < valueCounts; i++) { inList.push_back(Circuit::NullGate()); } - return circuit_->NewGate(opCode, valueCounts, inList, TypeCode::NOTYPE); + return circuit_->NewGate(opCode, valueCounts, inList, MachineType2TypeCode(type)); } -AddrShift CircuitBuilder::NewSelectorGate(OpCode opCode, AddrShift control, std::vector &values, - int valueCounts) +GateRef CircuitBuilder::NewSelectorGate(OpCode opCode, GateRef control, std::vector &values, + int valueCounts, MachineType type) { - std::vector inList; + std::vector inList; inList.push_back(control); for (int i = 0; i < valueCounts; i++) { inList.push_back(values[i]); } - return circuit_->NewGate(opCode, valueCounts, inList, TypeCode::NOTYPE); + return circuit_->NewGate(opCode, valueCounts, inList, MachineType2TypeCode(type)); } -AddrShift CircuitBuilder::NewIntegerConstant(int32_t val) +GateRef CircuitBuilder::NewIntegerConstant(int32_t val) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); return circuit_->NewGate(OpCode(OpCode::INT32_CONSTANT), val, {constantList}, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewInteger64Constant(int64_t val) +GateRef CircuitBuilder::NewInteger64Constant(int64_t val) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); return circuit_->NewGate(OpCode(OpCode::INT64_CONSTANT), val, {constantList}, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewBooleanConstant(bool val) +GateRef CircuitBuilder::NewBooleanConstant(bool val) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); return circuit_->NewGate(OpCode(OpCode::INT32_CONSTANT), val ? 1 : 0, {constantList}, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewDoubleConstant(double val) +GateRef CircuitBuilder::NewDoubleConstant(double val) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); return circuit_->NewGate(OpCode(OpCode::FLOAT64_CONSTANT), bit_cast(val), {constantList}, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::UndefineConstant() +GateRef CircuitBuilder::UndefineConstant(TypeCode type) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); - return circuit_->NewGate(OpCode(OpCode::INT64_CONSTANT), panda::coretypes::TaggedValue::VALUE_UNDEFINED, - {constantList}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::INT64_CONSTANT), TaggedValue::VALUE_UNDEFINED, { constantList }, type); } -AddrShift CircuitBuilder::HoleConstant() +GateRef CircuitBuilder::HoleConstant(TypeCode type) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); // NOTE: add bitfield value here - return circuit_->NewGate(OpCode(OpCode::JS_CONSTANT), panda::coretypes::TaggedValue::VALUE_HOLE, {constantList}, - TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::JS_CONSTANT), TaggedValue::VALUE_HOLE, { constantList }, + type); } -AddrShift CircuitBuilder::ExceptionConstant() +GateRef CircuitBuilder::NullConstant(TypeCode type) { auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); // NOTE: add bitfield value here - return circuit_->NewGate(OpCode(OpCode::JS_CONSTANT), panda::coretypes::TaggedValue::VALUE_EXCEPTION, - {constantList}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::JS_CONSTANT), TaggedValue::VALUE_NULL, { constantList }, + type); } -AddrShift CircuitBuilder::Branch(AddrShift state, AddrShift condition) +GateRef CircuitBuilder::ExceptionConstant(TypeCode type) { - return circuit_->NewGate(OpCode(OpCode::IF_BRANCH), 0, {state, condition}, TypeCode::NOTYPE); + auto constantList = Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST)); + // NOTE: add bitfield value here + return circuit_->NewGate(OpCode(OpCode::JS_CONSTANT), TaggedValue::VALUE_EXCEPTION, { constantList }, type); } -AddrShift CircuitBuilder::SwitchBranch(AddrShift state, AddrShift index, int caseCounts) +GateRef CircuitBuilder::Branch(GateRef state, GateRef condition) { - return circuit_->NewGate(OpCode(OpCode::SWITCH_BRANCH), caseCounts, {state, index}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::IF_BRANCH), 0, { state, condition }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::Return(AddrShift state, AddrShift depend, AddrShift value) +GateRef CircuitBuilder::SwitchBranch(GateRef state, GateRef index, int caseCounts) +{ + return circuit_->NewGate(OpCode(OpCode::SWITCH_BRANCH), caseCounts, { state, index }, TypeCode::NOTYPE); +} + +GateRef CircuitBuilder::Return(GateRef state, GateRef depend, GateRef value) { auto returnList = Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST)); - return circuit_->NewGate(OpCode(OpCode::RETURN), 0, {state, depend, value, returnList}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::RETURN), 0, { state, depend, value, returnList }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::Goto(AddrShift state) +GateRef CircuitBuilder::ReturnVoid(GateRef state, GateRef depend) { - return circuit_->NewGate(OpCode(OpCode::ORDINARY_BLOCK), 0, {state}, TypeCode::NOTYPE); + auto returnList = Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST)); + return circuit_->NewGate(OpCode(OpCode::RETURN_VOID), 0, { state, depend, returnList }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::LoopBegin(AddrShift state) +GateRef CircuitBuilder::Goto(GateRef state) +{ + return circuit_->NewGate(OpCode(OpCode::ORDINARY_BLOCK), 0, { state }, TypeCode::NOTYPE); +} + +GateRef CircuitBuilder::LoopBegin(GateRef state) { auto nullGate = Circuit::NullGate(); - return circuit_->NewGate(OpCode(OpCode::LOOP_BEGIN), 0, {state, nullGate}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::LOOP_BEGIN), 0, { state, nullGate }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::LoopEnd(AddrShift state) +GateRef CircuitBuilder::LoopEnd(GateRef state) { - return circuit_->NewGate(OpCode(OpCode::LOOP_BACK), 0, {state}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::LOOP_BACK), 0, { state }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewIfTrue(AddrShift ifBranch) +GateRef CircuitBuilder::NewIfTrue(GateRef ifBranch) { - return circuit_->NewGate(OpCode(OpCode::IF_TRUE), 0, {ifBranch}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::IF_TRUE), 0, { ifBranch }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewIfFalse(AddrShift ifBranch) +GateRef CircuitBuilder::NewIfFalse(GateRef ifBranch) { - return circuit_->NewGate(OpCode(OpCode::IF_FALSE), 0, {ifBranch}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::IF_FALSE), 0, { ifBranch }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewSwitchCase(AddrShift switchBranch, int32_t value) +GateRef CircuitBuilder::NewSwitchCase(GateRef switchBranch, int32_t value) { - return circuit_->NewGate(OpCode(OpCode::SWITCH_CASE), value, {switchBranch}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::SWITCH_CASE), value, { switchBranch }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewDefaultCase(AddrShift switchBranch) +GateRef CircuitBuilder::NewDefaultCase(GateRef switchBranch) { - return circuit_->NewGate(OpCode(OpCode::DEFAULT_CASE), 0, {switchBranch}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::DEFAULT_CASE), 0, { switchBranch }, TypeCode::NOTYPE); } -OpCode CircuitBuilder::GetStoreOpCodeFromMachineType(MachineType type) +OpCode CircuitBuilder::GetStoreOpCodeFromMachineType(MachineType type, const char *triple) { switch (type) { - case MachineType::INT8_TYPE: + case MachineType::INT8: return OpCode(OpCode::INT8_STORE); - case MachineType::INT16_TYPE: + case MachineType::INT16: return OpCode(OpCode::INT16_STORE); - case MachineType::INT32_TYPE: + case MachineType::INT32: return OpCode(OpCode::INT32_STORE); - case MachineType::INT64_TYPE: + case MachineType::INT64: return OpCode(OpCode::INT64_STORE); - case MachineType::BOOL_TYPE: + case MachineType::BOOL: return OpCode(OpCode::INT32_STORE); - case MachineType::UINT8_TYPE: + case MachineType::UINT8: return OpCode(OpCode::INT8_STORE); - case MachineType::UINT16_TYPE: + case MachineType::UINT16: return OpCode(OpCode::INT16_STORE); - case MachineType::UINT32_TYPE: + case MachineType::UINT32: return OpCode(OpCode::INT32_STORE); - case MachineType::UINT64_TYPE: - case MachineType::POINTER_TYPE: - case MachineType::TAGGED_TYPE: - case MachineType::TAGGED_POINTER_TYPE: + case MachineType::NATIVE_POINTER: + { + if (triple == TripleConst::GetLLVMArm32Triple()) { + return OpCode(OpCode::INT32_STORE); + } else { + return OpCode(OpCode::INT64_STORE); + } + } + case MachineType::UINT64: + case MachineType::TAGGED: + case MachineType::TAGGED_POINTER: return OpCode(OpCode::INT64_STORE); - case MachineType::FLOAT32_TYPE: + case MachineType::FLOAT32: return OpCode(OpCode::FLOAT32_STORE); - case MachineType::FLOAT64_TYPE: + case MachineType::FLOAT64: return OpCode(OpCode::FLOAT64_STORE); default: UNREACHABLE(); } } -OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type) +OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type, const char *triple) { switch (type) { - case MachineType::INT8_TYPE: + case MachineType::INT8: return OpCode(OpCode::INT8_LOAD); - case MachineType::INT16_TYPE: + case MachineType::INT16: return OpCode(OpCode::INT16_LOAD); - case MachineType::INT32_TYPE: + case MachineType::INT32: return OpCode(OpCode::INT32_LOAD); - case MachineType::INT64_TYPE: + case MachineType::INT64: return OpCode(OpCode::INT64_LOAD); - case MachineType::BOOL_TYPE: + case MachineType::BOOL: return OpCode(OpCode::INT32_LOAD); - case MachineType::UINT8_TYPE: + case MachineType::UINT8: return OpCode(OpCode::INT8_LOAD); - case MachineType::UINT16_TYPE: + case MachineType::UINT16: return OpCode(OpCode::INT16_LOAD); - case MachineType::UINT32_TYPE: + case MachineType::UINT32: return OpCode(OpCode::INT32_LOAD); - case MachineType::UINT64_TYPE: - case MachineType::POINTER_TYPE: - case MachineType::TAGGED_TYPE: - case MachineType::TAGGED_POINTER_TYPE: + case MachineType::NATIVE_POINTER: { + if (ArchRelatePtrValueCode(triple) == ValueCode::INT32) { + return OpCode(OpCode::INT32_LOAD); + } else { + return OpCode(OpCode::INT64_LOAD); + } + } + case MachineType::UINT64: + case MachineType::TAGGED: + case MachineType::TAGGED_POINTER: return OpCode(OpCode::INT64_LOAD); - case MachineType::FLOAT32_TYPE: + case MachineType::FLOAT32: return OpCode(OpCode::FLOAT32_LOAD); - case MachineType::FLOAT64_TYPE: + case MachineType::FLOAT64: return OpCode(OpCode::FLOAT64_LOAD); default: UNREACHABLE(); @@ -221,157 +248,159 @@ OpCode CircuitBuilder::GetLoadOpCodeFromMachineType(MachineType type) OpCode CircuitBuilder::GetSelectOpCodeFromMachineType(MachineType type) { switch (type) { - case MachineType::NONE_TYPE: + case MachineType::NONE: return OpCode(OpCode::DEPEND_SELECTOR); - case MachineType::INT8_TYPE: + case MachineType::INT8: return OpCode(OpCode::VALUE_SELECTOR_INT8); - case MachineType::INT16_TYPE: + case MachineType::INT16: return OpCode(OpCode::VALUE_SELECTOR_INT16); - case MachineType::INT32_TYPE: + case MachineType::INT32: return OpCode(OpCode::VALUE_SELECTOR_INT32); - case MachineType::INT64_TYPE: + case MachineType::INT64: return OpCode(OpCode::VALUE_SELECTOR_INT64); - case MachineType::BOOL_TYPE: + case MachineType::BOOL: return OpCode(OpCode::VALUE_SELECTOR_INT1); - case MachineType::UINT8_TYPE: + case MachineType::UINT8: return OpCode(OpCode::VALUE_SELECTOR_INT8); - case MachineType::UINT16_TYPE: + case MachineType::UINT16: return OpCode(OpCode::VALUE_SELECTOR_INT16); - case MachineType::UINT32_TYPE: + case MachineType::UINT32: return OpCode(OpCode::VALUE_SELECTOR_INT32); - case MachineType::UINT64_TYPE: - case MachineType::POINTER_TYPE: - case MachineType::TAGGED_TYPE: - case MachineType::TAGGED_POINTER_TYPE: + case MachineType::NATIVE_POINTER: + return OpCode(OpCode::VALUE_SELECTOR_ANYVALUE); + case MachineType::UINT64: + case MachineType::TAGGED: + case MachineType::TAGGED_POINTER: return OpCode(OpCode::VALUE_SELECTOR_INT64); - case MachineType::FLOAT32_TYPE: + case MachineType::FLOAT32: return OpCode(OpCode::VALUE_SELECTOR_FLOAT32); - case MachineType::FLOAT64_TYPE: + case MachineType::FLOAT64: return OpCode(OpCode::VALUE_SELECTOR_FLOAT64); default: UNREACHABLE(); } } -AddrShift CircuitBuilder::NewDependRelay(AddrShift state, AddrShift depend) +GateRef CircuitBuilder::NewDependRelay(GateRef state, GateRef depend) { - return circuit_->NewGate(OpCode(OpCode::DEPEND_RELAY), 0, {state, depend}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::DEPEND_RELAY), 0, { state, depend }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewDependAnd(std::initializer_list args) +GateRef CircuitBuilder::NewDependAnd(std::initializer_list args) { - std::vector inputs; + std::vector inputs; for (auto arg : args) { inputs.push_back(arg); } return circuit_->NewGate(OpCode(OpCode::DEPEND_AND), args.size(), inputs, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewLoadGate(MachineType type, AddrShift val, AddrShift depend) +GateRef CircuitBuilder::NewLoadGate(MachineType type, GateRef val, GateRef depend, const char *triple) { - OpCode op = GetLoadOpCodeFromMachineType(type); - return circuit_->NewGate(op, static_cast(type), {depend, val}, TypeCode::NOTYPE); + OpCode op = GetLoadOpCodeFromMachineType(type, triple); + return circuit_->NewGate(op, static_cast(type), { depend, val }, MachineType2TypeCode(type)); } -AddrShift CircuitBuilder::NewStoreGate(MachineType type, AddrShift ptr, AddrShift val, AddrShift depend) +GateRef CircuitBuilder::NewStoreGate(MachineType type, GateRef ptr, GateRef val, GateRef depend, const char *triple) { - OpCode op = GetStoreOpCodeFromMachineType(type); - return circuit_->NewGate(op, static_cast(type), {depend, val, ptr}, TypeCode::NOTYPE); + OpCode op = GetStoreOpCodeFromMachineType(type, triple); + return circuit_->NewGate(op, static_cast(type), { depend, val, ptr }, MachineType2TypeCode(type)); } -AddrShift CircuitBuilder::NewArithMeticGate(OpCode opcode, AddrShift left, AddrShift right) +GateRef CircuitBuilder::NewArithMeticGate(OpCode opcode, GateRef left, GateRef right) { - return circuit_->NewGate(opcode, 0, {left, right}, TypeCode::NOTYPE); + TypeCode type = circuit_->LoadGatePtr(left)->GetTypeCode(); + return circuit_->NewGate(opcode, 0, { left, right }, type); } -AddrShift CircuitBuilder::NewArithMeticGate(OpCode opcode, AddrShift value) +GateRef CircuitBuilder::NewArithMeticGate(OpCode opcode, GateRef value) { - return circuit_->NewGate(opcode, 0, {value}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, 0, { value }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewLogicGate(OpCode opcode, AddrShift left, AddrShift right) +GateRef CircuitBuilder::NewLogicGate(OpCode opcode, GateRef left, GateRef right) { - return circuit_->NewGate(opcode, static_cast(MachineType::BOOL_TYPE), {left, right}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, static_cast(MachineType::BOOL), { left, right }, TypeCode::NOTYPE); } -AddrShift CircuitBuilder::NewLogicGate(OpCode opcode, AddrShift value) +GateRef CircuitBuilder::NewLogicGate(OpCode opcode, GateRef value) { - return circuit_->NewGate(opcode, static_cast(MachineType::BOOL_TYPE), {value}, TypeCode::NOTYPE); + return circuit_->NewGate(opcode, static_cast(MachineType::BOOL), { value }, TypeCode::NOTYPE); } OpCode CircuitBuilder::GetCallOpCodeFromMachineType(MachineType type) { switch (type) { - case MachineType::NONE_TYPE: + case MachineType::NONE: return OpCode(OpCode::CALL); - case MachineType::INT8_TYPE: + case MachineType::INT8: return OpCode(OpCode::INT8_CALL); - case MachineType::INT16_TYPE: + case MachineType::INT16: return OpCode(OpCode::INT16_CALL); - case MachineType::INT32_TYPE: + case MachineType::INT32: return OpCode(OpCode::INT32_CALL); - case MachineType::INT64_TYPE: + case MachineType::INT64: return OpCode(OpCode::INT64_CALL); - case MachineType::BOOL_TYPE: + case MachineType::BOOL: return OpCode(OpCode::INT1_CALL); - case MachineType::UINT8_TYPE: + case MachineType::UINT8: return OpCode(OpCode::INT8_CALL); - case MachineType::UINT16_TYPE: + case MachineType::UINT16: return OpCode(OpCode::INT16_CALL); - case MachineType::UINT32_TYPE: + case MachineType::UINT32: return OpCode(OpCode::INT32_CALL); - case MachineType::UINT64_TYPE: - case MachineType::POINTER_TYPE: - case MachineType::TAGGED_TYPE: - case MachineType::TAGGED_POINTER_TYPE: + case MachineType::NATIVE_POINTER: + return OpCode(OpCode::ANYVALUE_CALL); + case MachineType::UINT64: + case MachineType::TAGGED: + case MachineType::TAGGED_POINTER: return OpCode(OpCode::INT64_CALL); - case MachineType::FLOAT32_TYPE: + case MachineType::FLOAT32: return OpCode(OpCode::FLOAT32_CALL); - case MachineType::FLOAT64_TYPE: + case MachineType::FLOAT64: return OpCode(OpCode::FLOAT64_CALL); default: UNREACHABLE(); } } -AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, - std::initializer_list args) +GateRef CircuitBuilder::NewCallGate(StubDescriptor *descriptor, GateRef glue, GateRef target, + std::initializer_list args) { - std::vector inputs; - // 2 means extra two input gates (target thread) + std::vector inputs; + // 2 means extra two input gates (target glue) const size_t extraparamCnt = 2; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); inputs.push_back(target); - inputs.push_back(thread); + inputs.push_back(glue); for (auto arg : args) { inputs.push_back(arg); } OpCode opcode = GetCallOpCodeFromMachineType(descriptor->GetReturnType()); - if (descriptor->GetReturnType() == MachineType::TAGGED_POINTER_TYPE) { - return circuit_->NewGate(opcode, args.size() + extraparamCnt, inputs, TypeCode::TAGGED_POINTER_TYPE); - } - return circuit_->NewGate(opcode, args.size() + extraparamCnt, inputs, TypeCode::JS_ANY); + TypeCode type = MachineType2TypeCode(descriptor->GetReturnType()); + return circuit_->NewGate(opcode, args.size() + extraparamCnt, inputs, type); } -AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, - AddrShift depend, std::initializer_list args) +GateRef CircuitBuilder::NewCallGate(StubDescriptor *descriptor, GateRef glue, GateRef target, + GateRef depend, std::initializer_list args) { - std::vector inputs; + std::vector inputs; inputs.push_back(depend); inputs.push_back(target); - inputs.push_back(thread); + inputs.push_back(glue); for (auto arg : args) { inputs.push_back(arg); } OpCode opcode = GetCallOpCodeFromMachineType(descriptor->GetReturnType()); - // 2 : 2 means extra two input gates (target thread ) - return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::JS_ANY); + TypeCode type = MachineType2TypeCode(descriptor->GetReturnType()); + // 2 : 2 means extra two input gates (target glue) + return circuit_->NewGate(opcode, args.size() + 2, inputs, type); } -AddrShift CircuitBuilder::Alloca(int size) +GateRef CircuitBuilder::Alloca(int size, TypeCode type) { auto allocaList = Circuit::GetCircuitRoot(OpCode(OpCode::ALLOCA_LIST)); - return circuit_->NewGate(OpCode(OpCode::ALLOCA), size, {allocaList}, TypeCode::NOTYPE); + return circuit_->NewGate(OpCode(OpCode::ALLOCA), size, { allocaList }, type); } } // namespace kungfu diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 11e12674..f808be11 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -28,46 +28,62 @@ public: ~CircuitBuilder() = default; NO_MOVE_SEMANTIC(CircuitBuilder); NO_COPY_SEMANTIC(CircuitBuilder); - AddrShift NewArguments(size_t index); - AddrShift NewMerge(AddrShift *in, size_t controlCount); - AddrShift NewSelectorGate(OpCode opcode, AddrShift control, int valueCounts); - AddrShift NewSelectorGate(OpCode opcode, AddrShift control, std::vector &values, int valueCounts); - AddrShift NewIntegerConstant(int32_t value); - AddrShift NewInteger64Constant(int64_t value); - AddrShift NewWord64Constant(uint64_t val); - AddrShift NewBooleanConstant(bool value); - AddrShift NewDoubleConstant(double value); - AddrShift UndefineConstant(); - AddrShift HoleConstant(); - AddrShift ExceptionConstant(); - AddrShift Alloca(int size); - AddrShift Branch(AddrShift state, AddrShift condition); - AddrShift SwitchBranch(AddrShift state, AddrShift index, int caseCounts); - AddrShift Return(AddrShift state, AddrShift depend, AddrShift value); - AddrShift Goto(AddrShift state); - AddrShift LoopBegin(AddrShift state); - AddrShift LoopEnd(AddrShift state); - AddrShift NewIfTrue(AddrShift ifBranch); - AddrShift NewIfFalse(AddrShift ifBranch); - AddrShift NewSwitchCase(AddrShift switchBranch, int32_t value); - AddrShift NewDefaultCase(AddrShift switchBranch); - AddrShift NewLoadGate(MachineType type, AddrShift val, AddrShift depend); - AddrShift NewStoreGate(MachineType type, AddrShift ptr, AddrShift val, AddrShift depend); - AddrShift NewDependRelay(AddrShift state, AddrShift depend); - AddrShift NewDependAnd(std::initializer_list args); - AddrShift NewArithMeticGate(OpCode opcode, AddrShift left, AddrShift right); - AddrShift NewArithMeticGate(OpCode opcode, AddrShift value); - AddrShift NewLogicGate(OpCode opcode, AddrShift left, AddrShift right); - AddrShift NewLogicGate(OpCode opcode, AddrShift value); - AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, - std::initializer_list args); - AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, - AddrShift depend, std::initializer_list args); - static OpCode GetLoadOpCodeFromMachineType(MachineType type); - static OpCode GetStoreOpCodeFromMachineType(MachineType type); + GateRef NewArguments(size_t index); + GateRef NewMerge(GateRef *in, size_t controlCount); + GateRef NewSelectorGate(OpCode opcode, GateRef control, int valueCounts, + MachineType type = MachineType::NONE); + GateRef NewSelectorGate(OpCode opcode, GateRef control, std::vector &values, int valueCounts, + MachineType type = MachineType::NONE); + GateRef NewIntegerConstant(int32_t value); + GateRef NewInteger64Constant(int64_t value); + GateRef NewWord64Constant(uint64_t val); + GateRef NewBooleanConstant(bool value); + GateRef NewDoubleConstant(double value); + GateRef UndefineConstant(TypeCode type); + GateRef HoleConstant(TypeCode type); + GateRef NullConstant(TypeCode type); + GateRef ExceptionConstant(TypeCode type); + GateRef Alloca(int size, TypeCode type); + GateRef Branch(GateRef state, GateRef condition); + GateRef SwitchBranch(GateRef state, GateRef index, int caseCounts); + GateRef Return(GateRef state, GateRef depend, GateRef value); + GateRef ReturnVoid(GateRef state, GateRef depend); + GateRef Goto(GateRef state); + GateRef LoopBegin(GateRef state); + GateRef LoopEnd(GateRef state); + GateRef NewIfTrue(GateRef ifBranch); + GateRef NewIfFalse(GateRef ifBranch); + GateRef NewSwitchCase(GateRef switchBranch, int32_t value); + GateRef NewDefaultCase(GateRef switchBranch); + GateRef NewLoadGate(MachineType type, GateRef val, GateRef depend, const char *triple); + GateRef NewStoreGate(MachineType type, GateRef ptr, GateRef val, GateRef depend, const char *triple); + GateRef NewDependRelay(GateRef state, GateRef depend); + GateRef NewDependAnd(std::initializer_list args); + GateRef NewArithMeticGate(OpCode opcode, GateRef left, GateRef right); + GateRef NewArithMeticGate(OpCode opcode, GateRef value); + GateRef NewLogicGate(OpCode opcode, GateRef left, GateRef right); + GateRef NewLogicGate(OpCode opcode, GateRef value); + GateRef NewCallGate(StubDescriptor *descriptor, GateRef glue, GateRef target, + std::initializer_list args); + GateRef NewCallGate(StubDescriptor *descriptor, GateRef glue, GateRef target, + GateRef depend, std::initializer_list args); + static OpCode GetLoadOpCodeFromMachineType(MachineType type, const char *triple); + static OpCode GetStoreOpCodeFromMachineType(MachineType type, const char *triple); static OpCode GetSelectOpCodeFromMachineType(MachineType type); static OpCode GetCallOpCodeFromMachineType(MachineType type); + static TypeCode MachineType2TypeCode(MachineType type) + { + switch (type) { + case MachineType::TAGGED_POINTER: + return TypeCode::TAGGED_POINTER; + case MachineType::TAGGED: + return TypeCode::JS_ANY; + default: + return TypeCode::NOTYPE; + } + } + private: Circuit *circuit_; }; diff --git a/ecmascript/compiler/code_generator.h b/ecmascript/compiler/code_generator.h index 10ffe6f5..94661fb8 100644 --- a/ecmascript/compiler/code_generator.h +++ b/ecmascript/compiler/code_generator.h @@ -19,7 +19,7 @@ #include "circuit.h" namespace kungfu { -using ControlFlowGraph = std::vector>; +using ControlFlowGraph = std::vector>; class CodeGeneratorImpl { public: CodeGeneratorImpl() = default; @@ -29,7 +29,7 @@ public: class CodeGenerator { public: - explicit CodeGenerator(CodeGeneratorImpl *impl) : impl_(impl) {} + explicit CodeGenerator(std::unique_ptr &impl, const char* triple) : impl_(std::move(impl)) {} ~CodeGenerator() = default; void Run(Circuit *circuit, const ControlFlowGraph &graph, int index) { @@ -37,7 +37,7 @@ public: } private: - CodeGeneratorImpl *impl_; + std::unique_ptr impl_{nullptr}; }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_CODE_GENERATOR_H \ No newline at end of file diff --git a/ecmascript/compiler/compile_llvm_lib.sh b/ecmascript/compiler/compile_llvm_lib.sh index 0891662c..71e06e55 100755 --- a/ecmascript/compiler/compile_llvm_lib.sh +++ b/ecmascript/compiler/compile_llvm_lib.sh @@ -33,8 +33,8 @@ fi cd ${BASE_HOME}/third_party/llvm-project if [ ! -d "build" ];then git checkout -b local llvmorg-10.0.1 - cp ../../ark/js_runtime/ecmascript/compiler/llvm/llvm.patch . - git apply --reject llvm.patch + cp ../../ark/js_runtime/ecmascript/compiler/llvm/llvm_new.patch . + git apply --reject llvm_new.patch mkdir build && cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_ARK_GC_SUPPORT=ON -DLLVM_ENABLE_TERMINFO=OFF DLLVM_STATIC_LINK_CXX_STDLIB=OFF -DLLVM_ENABLE_ZLIB=OFF ../llvm ninja diff --git a/ecmascript/mem/tagged_object.cpp b/ecmascript/compiler/compiler_macros.h similarity index 66% rename from ecmascript/mem/tagged_object.cpp rename to ecmascript/compiler/compiler_macros.h index 49d82618..d8b56cbd 100644 --- a/ecmascript/mem/tagged_object.cpp +++ b/ecmascript/compiler/compiler_macros.h @@ -13,14 +13,14 @@ * limitations under the License. */ -#include "ecmascript/mem/tagged_object.h" +#ifndef ECMASCRIPT_COMPILER_MACROS_H +#define ECMASCRIPT_COMPILER_MACROS_H -#include "ecmascript/js_hclass-inl.h" +#include "ecmascript/base/config.h" +#include "ecmascript/ecma_macros.h" -namespace panda::ecmascript { -size_t TaggedObject::GetObjectSize() -{ - JSHClass *cls = GetClass(); - return cls->SizeFromJSHClass(cls->GetObjectType(), this); -} -} // namespace panda::ecmascript +#define ECMASCRIPT_ENABLE_COMPILER_LOG 0 + +#define COMPILER_LOG(level) ECMASCRIPT_ENABLE_COMPILER_LOG &&LOG_ECMA(level) + +#endif // ECMASCRIPT_COMPILER_MACROS_H diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp index 9e125fa8..45233433 100644 --- a/ecmascript/compiler/fast_stub.cpp +++ b/ecmascript/compiler/fast_stub.cpp @@ -14,48 +14,28 @@ */ #include "fast_stub.h" + #include "ecmascript/base/number_helper.h" +#include "ecmascript/compiler/js_thread_offset_table.h" +#include "ecmascript/compiler/llvm_ir_builder.h" +#include "ecmascript/compiler/machine_type.h" #include "ecmascript/js_array.h" #include "ecmascript/message_string.h" #include "ecmascript/tagged_hash_table-inl.h" -#include "llvm_ir_builder.h" namespace kungfu { using namespace panda::ecmascript; -void FastArrayLoadElementStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift aVal = Int64Argument(0); - AddrShift indexVal = Int32Argument(1); - - // load a.length - AddrShift lengthOffset = GetInt32Constant(JSArray::GetArrayLengthOffset()); - if (PtrValueCode() == ValueCode::INT64) { - lengthOffset = SExtInt32ToInt64(lengthOffset); - } else if (PtrValueCode() == ValueCode::INT32) { - aVal = TruncInt64ToInt32(aVal); - } - AddrShift taggedLength = Load(MachineType::TAGGED_TYPE, aVal, lengthOffset); - AddrShift intLength = TaggedCastToInt32(taggedLength); - // if index < length - Label ifTrue(env); - Label ifFalse(env); - Branch(Int32LessThan(indexVal, intLength), &ifTrue, &ifFalse); - Bind(&ifTrue); - Return(LoadFromObject(MachineType::TAGGED_TYPE, aVal, indexVal)); - Bind(&ifFalse); - Return(GetUndefinedConstant()); -} +#ifdef ECMASCRIPT_ENABLE_SPECIFIC_STUBS void FastAddStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, 0); + DEFVARIABLE(intY, MachineType::INT32, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64, 0); Label xIsNumber(env); Label xNotNumberOryNotNumber(env); Label xIsNumberAndyIsNumber(env); @@ -85,7 +65,7 @@ void FastAddStub::GenerateCircuit() } } Bind(&xNotNumberOryNotNumber); - Return(GetHoleConstant()); + Return(GetHoleConstant(MachineType::UINT64)); Label yIsInt(env); Label yNotInt(env); Bind(&xIsNumberAndyIsNumber); @@ -105,18 +85,96 @@ void FastAddStub::GenerateCircuit() } Bind(&xIsDoubleAndyIsDouble); doubleX = DoubleAdd(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); } +#ifndef NDEBUG +void FastMulGCTestStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); + GateRef glue = PtrArgument(0); + GateRef x = Int64Argument(1); + GateRef y = Int64Argument(2); // 2: 3rd argument + + DEFVARIABLE(intX, MachineType::INT64, GetWord64Constant(0)); + DEFVARIABLE(intY, MachineType::INT64, GetWord64Constant(0)); + DEFVARIABLE(valuePtr, MachineType::INT64, GetWord64Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt64(x); + doubleX = CastInt64ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant(MachineType::UINT64)); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt64(y); + doubleY = CastInt64ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleMul(*doubleX, *doubleY); + StubDescriptor *getTaggedArrayPtr = GET_STUBDESCRIPTOR(GetTaggedArrayPtrTest); + GateRef ptr1 = CallRuntime(getTaggedArrayPtr, glue, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), { + glue + }); + GateRef ptr2 = CallRuntime(getTaggedArrayPtr, glue, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), { + glue + }); + (void)ptr2; + auto value = Load(MachineType::UINT64, ptr1); + GateRef value2 = CastInt64ToFloat64(value); + doubleX = DoubleMul(*doubleX, value2); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); +} +#endif + void FastSubStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); Label xIsNumber(env); Label xNotNumberOryNotNumber(env); Label xNotIntOryNotInt(env); @@ -175,23 +233,23 @@ void FastSubStub::GenerateCircuit() } } Bind(&xNotNumberOryNotNumber); - Return(GetHoleConstant()); + Return(GetHoleConstant(MachineType::UINT64)); Bind(&xNotIntOryNotInt); doubleX = DoubleSub(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); Bind(&xIsIntAndyIsInt); - Return(IntBuildTagged(*intX)); + Return(IntBuildTaggedWithNoGC(*intX)); } void FastMulStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); Label xIsNumber(env); Label xNotNumberOryNotNumber(env); Label xIsNumberAndyIsNumber(env); @@ -221,7 +279,7 @@ void FastMulStub::GenerateCircuit() } } Bind(&xNotNumberOryNotNumber); - Return(GetHoleConstant()); + Return(GetHoleConstant(MachineType::UINT64)); Label yIsInt(env); Label yNotInt(env); Bind(&xIsNumberAndyIsNumber); @@ -241,18 +299,18 @@ void FastMulStub::GenerateCircuit() } Bind(&xIsDoubleAndyIsDouble); doubleX = DoubleMul(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); } void FastDivStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); Label xIsNumber(env); Label xNotNumberOryNotNumber(env); Label xIsNumberAndyIsNumber(env); @@ -282,7 +340,7 @@ void FastDivStub::GenerateCircuit() } } Bind(&xNotNumberOryNotNumber); - Return(GetHoleConstant()); + Return(GetHoleConstant(MachineType::UINT64)); Label yIsInt(env); Label yNotInt(env); Bind(&xIsNumberAndyIsNumber); @@ -324,687 +382,21 @@ void FastDivStub::GenerateCircuit() Jump(&xNeiZeroOrNan); } Bind(&xIsZeroOrNan); - Return(DoubleBuildTagged(GetDoubleConstant(base::NAN_VALUE))); + Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE))); Bind(&xNeiZeroOrNan); { - AddrShift intXTmp = CastDoubleToInt64(*doubleX); - AddrShift intYtmp = CastDoubleToInt64(*doubleY); + GateRef intXTmp = CastDoubleToInt64(*doubleX); + GateRef intYtmp = CastDoubleToInt64(*doubleY); intXTmp = Word64And(Word64Xor(intXTmp, intYtmp), GetWord64Constant(base::DOUBLE_SIGN_MASK)); intXTmp = Word64Xor(intXTmp, CastDoubleToInt64(GetDoubleConstant(base::POSITIVE_INFINITY))); doubleX = CastInt64ToFloat64(intXTmp); - Return(DoubleBuildTagged(*doubleX)); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); } } Bind(&divisorNotZero); { doubleX = DoubleDiv(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); - } - } -} - -void FindOwnElementStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift obj = PtrArgument(1); - AddrShift index = Int32Argument(2); // 2: 3rd parameter - index - Label notDict(env); - Label isDict(env); - Label invalidValue(env); - Label end(env); - AddrShift elements = Load(MachineType::POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); - Branch(IsDictionaryMode(elements), &isDict, ¬Dict); - Bind(¬Dict); - { - Label outOfArray(env); - Label notOutOfArray(env); - AddrShift arrayLength = Load(MachineType::UINT32_TYPE, elements, - GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); - Branch(Int32LessThanOrEqual(arrayLength, index), &outOfArray, ¬OutOfArray); - Bind(&outOfArray); - Jump(&invalidValue); - Bind(¬OutOfArray); - { - AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); - AddrShift dataIndex = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - AddrShift value = Load(MachineType::TAGGED_TYPE, elements, dataIndex); - Label isHole1(env); - Label notHole1(env); - Branch(TaggedIsHole(value), &isHole1, ¬Hole1); - Bind(&isHole1); - Jump(&invalidValue); - Bind(¬Hole1); - Return(value); - } - Bind(&invalidValue); - Return(GetHoleConstant()); - } - Bind(&isDict); - { - AddrShift taggedIndex = IntBuildTagged(index); - AddrShift entry = FindElementFromNumberDictionary(thread, elements, taggedIndex); - Label notNegtiveOne(env); - Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); - Bind(¬NegtiveOne); - { - Return(GetValueFromDictionary(elements, entry)); - } - Bind(&negtiveOne); - Jump(&end); - } - Bind(&end); - Return(GetHoleConstant()); -} - -void GetElementStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = Int64Argument(1); - AddrShift index = Int64Argument(2); // 2: 3rd parameter - index - Label isHole(env); - Label notHole(env); - Label loopHead(env); - Label loopEnd(env); - Label afterLoop(env); - Label notHeapObj(env); - - Jump(&loopHead); - LoopBegin(&loopHead); - AddrShift objPtr = ChangeInt64ToPointer(receiver); - auto findOwnElementDescriptor = GET_STUBDESCRIPTOR(FindOwnElement); - AddrShift callFindOwnElementVal = - CallStub(findOwnElementDescriptor, thread, GetWord64Constant(FAST_STUB_ID(FindOwnElement)), - {thread, objPtr, index}); - Branch(TaggedIsHole(callFindOwnElementVal), &isHole, ¬Hole); - Bind(¬Hole); - Return(callFindOwnElementVal); - Bind(&isHole); - receiver = Load(MachineType::TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET)); - Branch(TaggedIsHeapObject(receiver), &loopEnd, ¬HeapObj); - Bind(¬HeapObj); - Return(GetUndefinedConstant()); - Bind(&loopEnd); - LoopEnd(&loopHead); -} - -void FindOwnElement2Stub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift elements = PtrArgument(1); - AddrShift index = Int32Argument(2); // 2 : 3rd parameter - AddrShift isDict = Int32Argument(3); // 3 : 4th parameter - AddrShift attr = PtrArgument(4); // 4 : 5th parameter - AddrShift indexOrEntry = PtrArgument(5); // 5 : 6rd parameter - isDict = ZExtInt1ToInt32(isDict); - Label notDictionary(env); - Label isDictionary(env); - Label end(env); - Branch(Word32Equal(isDict, GetInt32Constant(0)), ¬Dictionary, &isDictionary); - Bind(¬Dictionary); - { - AddrShift elementsLength = - Load(MachineType::UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); - Label outOfElements(env); - Label notOutOfElements(env); - Branch(Int32LessThanOrEqual(elementsLength, index), &outOfElements, ¬OutOfElements); - Bind(&outOfElements); - { - Return(GetHoleConstant()); - } - Bind(¬OutOfElements); - { - AddrShift value = GetValueFromTaggedArray(elements, index); - Label isHole(env); - Label notHole(env); - Branch(TaggedIsHole(value), &isHole, ¬Hole); - Bind(&isHole); - Jump(&end); - Bind(¬Hole); - { - Store(MachineType::UINT32_TYPE, attr, GetPtrConstant(0), - GetInt32Constant(PropertyAttributes::GetDefaultAttributes())); - Store(MachineType::UINT32_TYPE, indexOrEntry, GetPtrConstant(0), index); - Return(value); - } - } - } - Bind(&isDictionary); - { - AddrShift entry = FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); - Label notNegtiveOne(env); - Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); - Bind(¬NegtiveOne); - { - Store(MachineType::UINT32_TYPE, attr, GetPtrConstant(0), GetAttributesFromDictionary(elements, entry)); - Store(MachineType::UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry); - Return(GetValueFromDictionary(elements, entry)); - } - Bind(&negtiveOne); - Jump(&end); - } - Bind(&end); - Return(GetHoleConstant()); -} - -void SetElementStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = PtrArgument(1); - DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver); - AddrShift index = Int32Argument(2); // 2 : 3rd argument - AddrShift value = Int64Argument(3); // 3 : 4th argument - AddrShift mayThrow = Int32Argument(4); // 4 : 5th argument - DEFVARIABLE(onPrototype, MachineType::BOOL_TYPE, FalseConstant()); - - AddrShift pattr = Alloca(static_cast(MachineRep::K_WORD32)); - AddrShift pindexOrEntry = Alloca(static_cast(MachineRep::K_WORD32)); - Label loopHead(env); - Label loopEnd(env); - Jump(&loopHead); - LoopBegin(&loopHead); - { - AddrShift elements = GetElements(*holder); - AddrShift isDictionary = IsDictionaryMode(elements); - StubDescriptor *findOwnElemnt2 = GET_STUBDESCRIPTOR(FindOwnElement2); - AddrShift val = CallStub(findOwnElemnt2, thread, GetWord64Constant(FAST_STUB_ID(FindOwnElement2)), - {thread, elements, index, isDictionary, pattr, pindexOrEntry}); - Label notHole(env); - Label isHole(env); - Branch(TaggedIsNotHole(val), ¬Hole, &isHole); - Bind(¬Hole); - { - Label isOnProtoType(env); - Label notOnProtoType(env); - Label afterOnProtoType(env); - Branch(*onPrototype, &isOnProtoType, ¬OnProtoType); - Bind(¬OnProtoType); - Jump(&afterOnProtoType); - Bind(&isOnProtoType); - { - Label isExtensible(env); - Label notExtensible(env); - Label nextExtensible(env); - Branch(IsExtensible(receiver), &isExtensible, ¬Extensible); - Bind(&isExtensible); - Jump(&nextExtensible); - Bind(¬Extensible); - { - Label isThrow(env); - Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); - Bind(&isThrow); - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); - Bind(¬Throw); - Return(FalseConstant()); - } - Bind(&nextExtensible); - StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); - Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), - {thread, receiver, index, value, - GetInt32Constant(PropertyAttributes::GetDefaultAttributes())})); - } - Bind(&afterOnProtoType); - { - AddrShift attr = Load(MachineType::INT32_TYPE, pattr); - Label isAccessor(env); - Label notAccessor(env); - Branch(IsAccessor(attr), &isAccessor, ¬Accessor); - Bind(¬Accessor); - { - Label isWritable(env); - Label notWritable(env); - Branch(IsWritable(attr), &isWritable, ¬Writable); - Bind(&isWritable); - { - AddrShift elements = GetElements(receiver); - Label isDict(env); - Label notDict(env); - AddrShift indexOrEntry = Load(MachineType::INT32_TYPE, pindexOrEntry); - Branch(isDictionary, &isDict, ¬Dict); - Bind(¬Dict); - { - StoreElement(thread, elements, indexOrEntry, value); - UpdateRepresention(LoadHClass(receiver), value); - Return(TrueConstant()); - } - Bind(&isDict); - { - UpdateValueAndAttributes(thread, elements, indexOrEntry, value, attr); - Return(TrueConstant()); - } - } - Bind(¬Writable); - { - Label isThrow(env); - Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); - Bind(&isThrow); - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), FalseConstant()); - Bind(¬Throw); - Return(FalseConstant()); - } - } - Bind(&isAccessor); - { - StubDescriptor *callsetter = GET_STUBDESCRIPTOR(CallSetter); - AddrShift setter = GetSetterFromAccessor(val); - Return(CallRuntime(callsetter, thread, GetWord64Constant(FAST_STUB_ID(CallSetter)), - {thread, setter, receiver, value, TruncInt32ToInt1(mayThrow)})); - } - } - } - Bind(&isHole); - { - // holder equals to - holder = GetPrototypeFromHClass(LoadHClass(*holder)); - Label isHeapObj(env); - Label notHeapObj(env); - Branch(TaggedIsObject(*holder), &isHeapObj, ¬HeapObj); - Bind(¬HeapObj); - { - Label isExtensible(env); - Label notExtensible(env); - Label nextExtensible(env); - Branch(IsExtensible(receiver), &isExtensible, ¬Extensible); - Bind(&isExtensible); - Jump(&nextExtensible); - Bind(¬Extensible); - { - Label isThrow(env); - Label notThrow(env); - Branch(Word32NotEqual(mayThrow, GetInt32Constant(0)), &isThrow, ¬Throw); - Bind(&isThrow); - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); - Bind(¬Throw); - Return(FalseConstant()); - } - Bind(&nextExtensible); - { - StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); - Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), - {thread, receiver, index, value, - GetInt32Constant(PropertyAttributes::GetDefaultAttributes())})); - } - } - Bind(&isHeapObj); - { - Label isJsProxy(env); - Label notJsProxy(env); - Branch(IsJsProxy(*holder), &isJsProxy, ¬JsProxy); - Bind(&isJsProxy); - { - StubDescriptor *setProperty = GET_STUBDESCRIPTOR(JSProxySetProperty); - Return(CallRuntime( - setProperty, thread, GetWord64Constant(FAST_STUB_ID(JSProxySetProperty)), - {thread, *holder, IntBuildTagged(index), value, receiver, TruncInt32ToInt1(mayThrow)})); - } - Bind(¬JsProxy); - onPrototype = TrueConstant(); - Jump(&loopEnd); - } - } - } - Bind(&loopEnd); - LoopEnd(&loopHead); -} - -void GetPropertyByIndexStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = PtrArgument(1); - AddrShift index = Int32Argument(2); /* 2 : 3rd parameter is index */ - - DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver); - Label loopHead(env); - Label loopEnd(env); - Label loopExit(env); - Label afterLoop(env); - Jump(&loopHead); - LoopBegin(&loopHead); - { - AddrShift hclass = LoadHClass(*holder); - AddrShift jsType = GetObjectType(hclass); - Label isSpecialIndexed(env); - Label notSpecialIndexed(env); - Label loopEnd(env); - Branch(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed); - Bind(&isSpecialIndexed); - { - Return(GetHoleConstant()); - } - Bind(¬SpecialIndexed); - { - AddrShift elements = GetElements(*holder); - Label isDictionaryElement(env); - Label notDictionaryElement(env); - Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement); - Bind(¬DictionaryElement); - { - Label lessThanLength(env); - Label notLessThanLength(env); - Branch(Word32LessThan(index, GetLengthofElements(elements)), &lessThanLength, ¬LessThanLength); - Bind(&lessThanLength); - { - Label notHole(env); - Label isHole(env); - AddrShift value = GetValueFromTaggedArray(elements, index); - Branch(TaggedIsNotHole(value), ¬Hole, &isHole); - Bind(¬Hole); - { - Return(value); - } - Bind(&isHole); - { - Jump(&loopExit); - } - } - Bind(¬LessThanLength); - { - Return(GetHoleConstant()); - } - } - Bind(&isDictionaryElement); - { - AddrShift entry = - FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); - Label notNegtiveOne(env); - Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); - Bind(¬NegtiveOne); - { - AddrShift attr = GetAttributesFromDictionary(elements, entry); - AddrShift value = GetValueFromDictionary(elements, entry); - Label isAccessor(env); - Label notAccessor(env); - Branch(IsAccessor(attr), &isAccessor, ¬Accessor); - Bind(&isAccessor); - { - Label isInternal(env); - Label notInternal(env); - Branch(IsAccessorInternal(value), &isInternal, ¬Internal); - Bind(&isInternal); - { - StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); - Return(CallRuntime(callAccessorGetter, thread, - GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, value, *holder})); - } - Bind(¬Internal); - { - StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); - Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, value, receiver})); - } - } - Bind(¬Accessor); - { - Return(value); - } - } - Bind(&negtiveOne); - Jump(&loopExit); - } - Bind(&loopExit); - { - holder = GetPrototypeFromHClass(LoadHClass(*holder)); - Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop); - } - } - Bind(&loopEnd); - LoopEnd(&loopHead); - Bind(&afterLoop); - { - Return(GetUndefinedConstant()); - } - } -} - -void SetPropertyByIndexStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = PtrArgument(1); - AddrShift index = Int32Argument(2); /* 2 : 3rd parameter is index */ - AddrShift value = Int64Argument(3); /* 3 : 4th parameter is value */ - - DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver); - Label loopHead(env); - Label loopEnd(env); - Label loopExit(env); - Label afterLoop(env); - Jump(&loopHead); - LoopBegin(&loopHead); - { - AddrShift hclass = LoadHClass(*holder); - AddrShift jsType = GetObjectType(hclass); - Label isSpecialIndex(env); - Label notSpecialIndex(env); - Branch(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex); - Bind(&isSpecialIndex); - Return(GetHoleConstant()); - Bind(¬SpecialIndex); - { - AddrShift elements = GetElements(*holder); - Label isDictionaryElement(env); - Label notDictionaryElement(env); - Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement); - Bind(¬DictionaryElement); - { - Label isReceiver(env); - Label notReceiver(env); - Branch(Word64Equal(*holder, receiver), &isReceiver, ¬Receiver); - Bind(&isReceiver); - { - AddrShift length = GetLengthofElements(elements); - Label inRange(env); - Branch(Word64LessThan(index, length), &inRange, &loopExit); - Bind(&inRange); - { - AddrShift value1 = GetValueFromTaggedArray(elements, index); - Label notHole(env); - Branch(Word64NotEqual(value1, GetHoleConstant()), ¬Hole, &loopExit); - Bind(¬Hole); - { - StoreElement(thread, elements, index, value); - Return(GetUndefinedConstant()); - } - } - } - Bind(¬Receiver); - Jump(&afterLoop); - } - Bind(&isDictionaryElement); - Return(GetHoleConstant()); - } - Bind(&loopExit); - { - holder = GetPrototypeFromHClass(LoadHClass(*holder)); - Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop); - } - } - Bind(&loopEnd); - LoopEnd(&loopHead); - Bind(&afterLoop); - { - Label isExtensible(env); - Label notExtensible(env); - Branch(IsExtensible(receiver), &isExtensible, ¬Extensible); - Bind(&isExtensible); - { - StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); - AddrShift result = CallRuntime(addElementInternal, thread, - GetWord64Constant(FAST_STUB_ID(AddElementInternal)), - {thread, receiver, index, value, - GetInt32Constant(PropertyAttributes::GetDefaultAttributes())}); - Label success(env); - Label failed(env); - Branch(result, &success, &failed); - Bind(&success); - Return(GetUndefinedConstant()); - Bind(&failed); - Return(GetExceptionConstant()); - } - Bind(¬Extensible); - { - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), GetExceptionConstant()); - } - } -} - -void GetPropertyByNameStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = Int64Argument(1); - AddrShift key = Int64Argument(2); // 2 : 3rd 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) - StubDescriptor *findElemWithCache = GET_STUBDESCRIPTOR(FindElementWithCache); - AddrShift entry = CallRuntime(findElemWithCache, 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); - // auto value = JSObject::Cast(holder)->GetProperty(hclass, attr) - AddrShift value = JSObjectGetProperty(*holder, hClass, attr); - Label isAccessor(env); - Label notAccessor(env); - Branch(IsAccessor(attr), &isAccessor, ¬Accessor); - Bind(&isAccessor); - { - Label isInternal(env); - Label notInternal(env); - Branch(IsAccessorInternal(value), &isInternal, ¬Internal); - Bind(&isInternal); - { - StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); - Return(CallRuntime(callAccessorGetter, thread, - GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, value, *holder})); - } - Bind(¬Internal); - { - StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); - Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, value, receiver})); - } - } - Bind(¬Accessor); - { - Return(value); - } - } - 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 entry = FindEntryFromNameDictionary(thread, array, key); - Label notNegtiveOne(env); - Label negtiveOne(env); - // if branch condition : entry != -1 - Branch(Word32NotEqual(entry, GetInt32Constant(-1)), ¬NegtiveOne, &negtiveOne); - Bind(¬NegtiveOne); - { - // auto value = dict->GetValue(entry) - AddrShift attr = GetAttributesFromDictionary(array, entry); - // auto attr = dict->GetAttributes(entry) - AddrShift value = GetValueFromDictionary(array, entry); - Label isAccessor1(env); - Label notAccessor1(env); - // if branch condition : UNLIKELY(attr.IsAccessor()) - Branch(IsAccessor(attr), &isAccessor1, ¬Accessor1); - Bind(&isAccessor1); - { - Label isInternal1(env); - Label notInternal1(env); - Branch(IsAccessorInternal(value), &isInternal1, ¬Internal1); - Bind(&isInternal1); - { - StubDescriptor *callAccessorGetter1 = GET_STUBDESCRIPTOR(AccessorGetter); - Return(CallRuntime(callAccessorGetter1, thread, - GetWord64Constant(FAST_STUB_ID(AccessorGetter)), - {thread, value, *holder})); - } - Bind(¬Internal1); - { - StubDescriptor *callGetter1 = GET_STUBDESCRIPTOR(CallGetter); - Return(CallRuntime(callGetter1, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), - {thread, value, receiver})); - } - } - Bind(¬Accessor1); - { - Return(value); - } - } - Bind(&negtiveOne); - Jump(&loopExit); - } - Bind(&loopExit); - { - // 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(GetUndefinedConstant()); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); } } } @@ -1012,13 +404,13 @@ void GetPropertyByNameStub::GenerateCircuit() void FastModStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift x = Int64Argument(1); - AddrShift y = Int64Argument(2); - DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + GateRef glue = PtrArgument(0); + GateRef x = TaggedArgument(1); + GateRef y = TaggedArgument(2); // 2: 3rd argument + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); Label xIsInt(env); Label xNotIntOryNotInt(env); Branch(TaggedIsInt(x), &xIsInt, &xNotIntOryNotInt); @@ -1045,7 +437,7 @@ void FastModStub::GenerateCircuit() Bind(&xGtZeroAndyGtZero); { intX = Int32Mod(*intX, *intY); - Return(IntBuildTagged(*intX)); + Return(IntBuildTaggedWithNoGC(*intX)); } } } @@ -1081,7 +473,7 @@ void FastModStub::GenerateCircuit() } } Bind(&xNotNumberOryNotNumber); - Return(GetHoleConstant()); + Return(GetHoleConstant(MachineType::UINT64)); Label yIfInt(env); Label yIfNotInt(env); Bind(&xIsNumberAndyIsNumber); @@ -1134,7 +526,7 @@ void FastModStub::GenerateCircuit() } } Bind(&yIsZeroOrNanOrxIsNanOrInf); - Return(DoubleBuildTagged(GetDoubleConstant(base::NAN_VALUE))); + Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE))); Bind(&yNeiZeroOrNanAndxNeiNanOrInf); { Label xIsFloatZero(env); @@ -1152,110 +544,34 @@ void FastModStub::GenerateCircuit() Bind(&yNotInf); { StubDescriptor *floatMod = GET_STUBDESCRIPTOR(FloatMod); - doubleX =CallRuntime(floatMod, thread, GetWord64Constant(FAST_STUB_ID(FloatMod)), - {*doubleX, *doubleY}); - Return(DoubleBuildTagged(*doubleX)); + doubleX = CallRuntime(floatMod, glue, GetWord64Constant(FAST_STUB_ID(FloatMod)), { + *doubleX, *doubleY + }); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); } Bind(&xIsZeroOryIsInf); - Return(DoubleBuildTagged(*doubleX)); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); } } } } -#ifndef NDEBUG -void FastMulGCTestStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); - AddrShift thread = PtrArgument(0); - (void)thread; - AddrShift x = Int64Argument(1); - AddrShift y = Int64Argument(2); - - DEFVARIABLE(intX, MachineType::INT64_TYPE, 0); - DEFVARIABLE(intY, MachineType::INT64_TYPE, 0); - DEFVARIABLE(valuePtr, MachineType::INT64_TYPE, 0); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); - Label xIsNumber(env); - Label xNotNumberOryNotNumber(env); - Label xIsNumberAndyIsNumber(env); - Label xIsDoubleAndyIsDouble(env); - Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); - Bind(&xIsNumber); - { - Label yIsNumber(env); - // if right.IsNumber() - Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); - Bind(&yIsNumber); - { - Label xIsInt(env); - Label xNotInt(env); - Branch(TaggedIsInt(x), &xIsInt, &xNotInt); - Bind(&xIsInt); - { - intX = TaggedCastToInt64(x); - doubleX = CastInt64ToFloat64(*intX); - Jump(&xIsNumberAndyIsNumber); - } - Bind(&xNotInt); - { - doubleX = TaggedCastToDouble(x); - Jump(&xIsNumberAndyIsNumber); - } - } - } - Bind(&xNotNumberOryNotNumber); - Return(GetHoleConstant()); - Label yIsInt(env); - Label yNotInt(env); - Bind(&xIsNumberAndyIsNumber); - { - Branch(TaggedIsInt(y), &yIsInt, &yNotInt); - Bind(&yIsInt); - { - intY = TaggedCastToInt64(y); - doubleY = CastInt64ToFloat64(*intY); - Jump(&xIsDoubleAndyIsDouble); - } - Bind(&yNotInt); - { - doubleY = TaggedCastToDouble(y); - Jump(&xIsDoubleAndyIsDouble); - } - } - Bind(&xIsDoubleAndyIsDouble); - doubleX = DoubleMul(*doubleX, *doubleY); - StubDescriptor *getTaggedArrayPtr = GET_STUBDESCRIPTOR(GetTaggedArrayPtrTest); - AddrShift ptr1 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), - {thread}); - AddrShift ptr2 = CallRuntime(getTaggedArrayPtr, thread, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), - {thread}); - (void)ptr2; - auto value = Load(MachineType::INT64_TYPE, ptr1); - AddrShift value2 = CastInt64ToFloat64(value); - doubleX = DoubleMul(*doubleX, value2); - Return(DoubleBuildTagged(*doubleX)); -} -#endif - void FastTypeOfStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift obj = PtrArgument(1); - DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, obj); - AddrShift gConstOffset = PtrAdd(thread, GetPtrConstant(panda::ecmascript::JSThread::GetGlobalConstantOffset())); - AddrShift booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX); - AddrShift gConstUndefindStr = Load(MachineType::TAGGED_TYPE, gConstOffset, booleanIndex); - DEFVARIABLE(resultRep, MachineType::TAGGED_TYPE, gConstUndefindStr); + GateRef glue = PtrArgument(0); + GateRef obj = TaggedArgument(1); + DEFVARIABLE(holder, MachineType::TAGGED, obj); + GateRef gConstOffset = PtrAdd(glue, GetArchRelateConstant(OffsetTable::GetOffset(JSThread::GlueID::GLOBAL_CONST))); + GateRef booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX); + GateRef gConstUndefindStr = Load(MachineType::TAGGED_POINTER, gConstOffset, booleanIndex); + DEFVARIABLE(resultRep, MachineType::TAGGED_POINTER, gConstUndefindStr); Label objIsTrue(env); Label objNotTrue(env); Label exit(env); Label defaultLabel(env); - AddrShift gConstBooleanStr = Load( - MachineType::TAGGED_TYPE, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); + GateRef gConstBooleanStr = Load( + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue); Bind(&objIsTrue); { @@ -1280,7 +596,7 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsNull); { resultRep = Load( - MachineType::TAGGED_TYPE, gConstOffset, + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } @@ -1292,7 +608,7 @@ void FastTypeOfStub::GenerateCircuit() &objNotUndefined); Bind(&objIsUndefined); { - resultRep = Load(MachineType::TAGGED_TYPE, gConstOffset, + resultRep = Load(MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX)); Jump(&exit); } @@ -1314,7 +630,7 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsString); { resultRep = Load( - MachineType::TAGGED_TYPE, gConstOffset, + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); Jump(&exit); } @@ -1325,7 +641,7 @@ void FastTypeOfStub::GenerateCircuit() Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol); Bind(&objIsSymbol); { - resultRep = Load(MachineType::TAGGED_TYPE, gConstOffset, + resultRep = Load(MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX)); Jump(&exit); } @@ -1337,14 +653,14 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsCallable); { resultRep = Load( - MachineType::TAGGED_TYPE, gConstOffset, + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); Jump(&exit); } Bind(&objNotCallable); { resultRep = Load( - MachineType::TAGGED_TYPE, gConstOffset, + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); Jump(&exit); } @@ -1359,7 +675,7 @@ void FastTypeOfStub::GenerateCircuit() Bind(&objIsNum); { resultRep = Load( - MachineType::TAGGED_TYPE, gConstOffset, + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); Jump(&exit); } @@ -1371,192 +687,11 @@ void FastTypeOfStub::GenerateCircuit() Return(*resultRep); } -void FunctionCallInternalStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift func = PtrArgument(1); - AddrShift thisArg = Int64Argument(2); /* 2 : 3rd parameter is value */ - AddrShift argc = Int32Argument(3); /* 3 : 4th parameter is value */ - AddrShift argv = PtrArgument(4); /* 4 : 5th parameter is ptr */ - Label funcNotBuiltinsConstructor(env); - Label funcIsBuiltinsConstructorOrFuncNotClassConstructor(env); - Label funcIsClassConstructor(env); - Branch(NotBuiltinsConstructor(func), &funcNotBuiltinsConstructor, - &funcIsBuiltinsConstructorOrFuncNotClassConstructor); - Bind(&funcNotBuiltinsConstructor); - { - Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor); - Bind(&funcIsClassConstructor); - ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), GetExceptionConstant()); - } - Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor); - StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute); - Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)), - {thread, func, thisArg, argc, argv})); -} - -void GetPropertyByValueStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = PtrArgument(1); - DEFVARIABLE(key, MachineType::TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ - - Label isNumberOrStringSymbol(env); - Label notNumber(env); - Label isStringOrSymbol(env); - Label notStringOrSymbol(env); - Label exit(env); - - Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number); - Bind(¬Number); - { - Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol); - Bind(¬StringOrSymbol); - { - Return(GetHoleConstant()); - } - } - Bind(&isNumberOrStringSymbol); - { - AddrShift index = TryToElementsIndex(*key); - Label validIndex(env); - Label notValidIndex(env); - Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex); - Bind(&validIndex); - { - auto getPropertyByIndex = GET_STUBDESCRIPTOR(GetPropertyByIndex); - Return(CallStub(getPropertyByIndex, thread, GetWord64Constant(FAST_STUB_ID(GetPropertyByIndex)), - {thread, receiver, index})); - } - Bind(¬ValidIndex); - { - Label notNumber(env); - Label getByName(env); - Branch(TaggedIsNumber(*key), &exit, ¬Number); - Bind(¬Number); - { - Label isString(env); - Label notString(env); - Label isInternalString(env); - Label notIntenalString(env); - Branch(TaggedIsString(*key), &isString, ¬String); - Bind(&isString); - { - Branch(IsInternalString(*key), &isInternalString, ¬IntenalString); - Bind(&isInternalString); - Jump(&getByName); - Bind(¬IntenalString); - { - StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString); - key = CallRuntime(newInternalString, thread, - GetWord64Constant(FAST_STUB_ID(NewInternalString)), - {thread, *key}); - Jump(&getByName); - } - } - Bind(¬String); - { - Jump(&getByName); - } - } - Bind(&getByName); - { - auto getPropertyByName = GET_STUBDESCRIPTOR(GetPropertyByName); - Return(CallStub(getPropertyByName, thread, GetWord64Constant(FAST_STUB_ID(GetPropertyByName)), - {thread, receiver, *key})); - } - } - } - Bind(&exit); - Return(GetHoleConstant()); -} - -void SetPropertyByValueStub::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift receiver = PtrArgument(1); - DEFVARIABLE(key, MachineType::TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */ - AddrShift value = Int64Argument(3); /* 3 : 4th parameter is value */ - - Label isNumberOrStringSymbol(env); - Label notNumber(env); - Label isStringOrSymbol(env); - Label notStringOrSymbol(env); - Label exit(env); - - Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number); - Bind(¬Number); - { - Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol); - Bind(¬StringOrSymbol); - { - Return(GetHoleConstant()); - } - } - Bind(&isNumberOrStringSymbol); - { - AddrShift index = TryToElementsIndex(*key); - Label validIndex(env); - Label notValidIndex(env); - Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex); - Bind(&validIndex); - { - auto setPropertyByIndex = GET_STUBDESCRIPTOR(SetPropertyByIndex); - Return(CallStub(setPropertyByIndex, thread, GetWord64Constant(FAST_STUB_ID(SetPropertyByIndex)), - {thread, receiver, index, value})); - } - Bind(¬ValidIndex); - { - Label notNumber(env); - Label getByName(env); - Branch(TaggedIsNumber(*key), &exit, ¬Number); - Bind(¬Number); - { - Label isString(env); - Label notString(env); - Label isInternalString(env); - Label notIntenalString(env); - Branch(TaggedIsString(*key), &isString, ¬String); - Bind(&isString); - { - Branch(IsInternalString(*key), &isInternalString, ¬IntenalString); - Bind(&isInternalString); - Jump(&getByName); - Bind(¬IntenalString); - { - StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString); - key = CallRuntime(newInternalString, thread, - GetWord64Constant(FAST_STUB_ID(NewInternalString)), - {thread, *key}); - Jump(&getByName); - } - } - Bind(¬String); - { - Jump(&getByName); - } - } - Bind(&getByName); - { - auto setPropertyByName = GET_STUBDESCRIPTOR(SetPropertyByName); - Return(CallStub(setPropertyByName, thread, GetWord64Constant(FAST_STUB_ID(SetPropertyByName)), - {thread, receiver, *key, value})); - } - } - } - Bind(&exit); - Return(GetHoleConstant()); -} - void FastEqualStub::GenerateCircuit() { auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); Label xIsEqualy(env); Label xIsNotEqualy(env); Branch(Word64Equal(x, y), &xIsEqualy, &xIsNotEqualy); @@ -1567,7 +702,7 @@ void FastEqualStub::GenerateCircuit() Branch(TaggedIsDouble(x), &xIsDouble, &xNotDoubleOrxNotNan); Bind(&xIsDouble); { - AddrShift doubleX = TaggedCastToDouble(x); + GateRef doubleX = TaggedCastToDouble(x); Label xIsNan(env); Branch(DoubleIsNAN(doubleX), &xIsNan, &xNotDoubleOrxNotNan); Bind(&xIsNan); @@ -1627,10 +762,1111 @@ void FastEqualStub::GenerateCircuit() } Bind(&xNotBooleanAndyNotSpecial); { - Return(GetHoleConstant()); + Return(GetHoleConstant(MachineType::UINT64)); } } } } } + +void GetPropertyByIndexStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */ + Return(GetPropertyByIndex(glue, receiver, index)); +} + +void SetPropertyByIndexStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */ + GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */ + Return(SetPropertyByIndex(glue, receiver, index, value)); +} + +void GetPropertyByNameStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef key = TaggedArgument(2); // 2 : 3rd para + Return(GetPropertyByName(glue, receiver, key)); +} +#endif + +#ifndef ECMASCRIPT_ENABLE_SPECIFIC_STUBS +void FastAddStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, 0); + DEFVARIABLE(intY, MachineType::INT32, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = ChangeInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant(MachineType::UINT64)); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = ChangeInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleAdd(*doubleX, *doubleY); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); +} + +void FastSubStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xNotIntOryNotInt(env); + Label xIsIntAndyIsInt(env); + // if x is number + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if y is number + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + { + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + Label yIsInt(env); + Label yNotInt(env); + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + intX = Int32Sub(*intX, *intY); + Jump(&xIsIntAndyIsInt); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + doubleX = ChangeInt32ToFloat64(*intX); + Jump(&xNotIntOryNotInt); + } + } + Bind(&xNotInt); + { + Label yIsInt(env); + Label yNotInt(env); + doubleX = TaggedCastToDouble(x); + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = ChangeInt32ToFloat64(*intY); + Jump(&xNotIntOryNotInt); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xNotIntOryNotInt); + } + } + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant(MachineType::UINT64)); + Bind(&xNotIntOryNotInt); + doubleX = DoubleSub(*doubleX, *doubleY); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); + Bind(&xIsIntAndyIsInt); + Return(IntBuildTaggedWithNoGC(*intX)); +} + +void FastMulStub::GenerateCircuit() +{ + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + + GateRef intX = TaggedCastToInt32(x); + GateRef intY = TaggedCastToInt32(y); + GateRef result = Int32Mul(intX, intY); + Return(IntBuildTaggedWithNoGC(result)); +} + +void FastDivStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = ChangeInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant(MachineType::UINT64)); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = ChangeInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&xIsDoubleAndyIsDouble); + { + Label divisorIsZero(env); + Label divisorNotZero(env); + Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &divisorIsZero, &divisorNotZero); + Bind(&divisorIsZero); + { + Label xIsZeroOrNan(env); + Label xNeiZeroOrNan(env); + Label xIsZero(env); + Label xNotZero(env); + // dLeft == 0.0 || std::isnan(dLeft) + Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsZero, &xNotZero); + Bind(&xIsZero); + Jump(&xIsZeroOrNan); + Bind(&xNotZero); + { + Label xIsNan(env); + Label xNotNan(env); + Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan); + Bind(&xIsNan); + Jump(&xIsZeroOrNan); + Bind(&xNotNan); + Jump(&xNeiZeroOrNan); + } + Bind(&xIsZeroOrNan); + Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE))); + Bind(&xNeiZeroOrNan); + { + GateRef intXTmp = CastDoubleToInt64(*doubleX); + GateRef intYtmp = CastDoubleToInt64(*doubleY); + intXTmp = Word64And(Word64Xor(intXTmp, intYtmp), GetWord64Constant(base::DOUBLE_SIGN_MASK)); + intXTmp = Word64Xor(intXTmp, CastDoubleToInt64(GetDoubleConstant(base::POSITIVE_INFINITY))); + doubleX = CastInt64ToFloat64(intXTmp); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); + } + } + Bind(&divisorNotZero); + { + doubleX = DoubleDiv(*doubleX, *doubleY); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); + } + } +} + +void FindOwnElement2Stub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef elements = TaggedArgument(1); + GateRef index = Int32Argument(2); // 2 : 3rd parameter + GateRef isDict = Int32Argument(3); // 3 : 4th parameter + GateRef attr = PtrArgument(4); // 4 : 5th parameter + GateRef indexOrEntry = PtrArgument(5); // 5 : 6rd parameter + Return(FindOwnElement2(glue, elements, index, isDict, attr, indexOrEntry)); +} + +void GetPropertyByIndexStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */ + Return(GetPropertyByIndex(glue, receiver, index)); +} + +void SetPropertyByIndexStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */ + GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */ + Return(SetPropertyByIndex(glue, receiver, index, value)); +} + +void GetPropertyByNameStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef key = TaggedArgument(2); // 2 : 3rd para + Return(GetPropertyByName(glue, receiver, key)); +} + +void SetPropertyByNameStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef key = TaggedArgument(2); // 2 : 3rd para + GateRef value = TaggedArgument(3); // 3 : 4th para + Return(SetPropertyByName(glue, receiver, key, value)); +} + +void SetPropertyByNameWithOwnStub::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef key = TaggedArgument(2); // 2 : 3rd para + GateRef value = TaggedArgument(3); // 3 : 4th para + Return(SetPropertyByNameWithOwn(glue, receiver, key, value)); +} + +void FastModStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef x = TaggedArgument(1); + GateRef y = TaggedArgument(2); // 2: 3rd argument + DEFVARIABLE(intX, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(intY, MachineType::INT32, GetInt32Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); + Label xIsInt(env); + Label xNotIntOryNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotIntOryNotInt); + Bind(&xIsInt); + { + Label yIsInt(env); + Label xIsIntAndyIsInt(env); + // if right.IsInt() + Branch(TaggedIsInt(y), &yIsInt, &xNotIntOryNotInt); + Bind(&yIsInt); + { + intX = TaggedCastToInt32(x); + intY = TaggedCastToInt32(y); + Jump(&xIsIntAndyIsInt); + } + Bind(&xIsIntAndyIsInt); + { + Label xGtZero(env); + Label xGtZeroAndyGtZero(env); + Branch(Int32GreaterThan(*intX, GetInt32Constant(0)), &xGtZero, &xNotIntOryNotInt); + Bind(&xGtZero); + { + Branch(Int32GreaterThan(*intY, GetInt32Constant(0)), &xGtZeroAndyGtZero, &xNotIntOryNotInt); + Bind(&xGtZeroAndyGtZero); + { + intX = Int32Mod(*intX, *intY); + Return(IntBuildTaggedWithNoGC(*intX)); + } + } + } + } + Bind(&xNotIntOryNotInt); + { + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIfInt(env); + Label xIfNotInt(env); + Branch(TaggedIsInt(x), &xIfInt, &xIfNotInt); + Bind(&xIfInt); + { + intX = TaggedCastToInt32(x); + doubleX = ChangeInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xIfNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant(MachineType::UINT64)); + Label yIfInt(env); + Label yIfNotInt(env); + Bind(&xIsNumberAndyIsNumber); + Branch(TaggedIsInt(y), &yIfInt, &yIfNotInt); + Bind(&yIfInt); + { + intY = TaggedCastToInt32(y); + doubleY = ChangeInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yIfNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&xIsDoubleAndyIsDouble); + { + Label yIsZero(env); + Label yNotZero(env); + Label yIsZeroOrNanOrxIsNanOrInf(env); + Label yNeiZeroOrNanAndxNeiNanOrInf(env); + // dRight == 0.0 or std::isnan(dRight) or std::isnan(dLeft) or std::isinf(dLeft) + Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &yIsZero, &yNotZero); + Bind(&yIsZero); + Jump(&yIsZeroOrNanOrxIsNanOrInf); + Bind(&yNotZero); + { + Label yIsNan(env); + Label yNotNan(env); + Branch(DoubleIsNAN(*doubleY), &yIsNan, &yNotNan); + Bind(&yIsNan); + Jump(&yIsZeroOrNanOrxIsNanOrInf); + Bind(&yNotNan); + { + Label xIsNan(env); + Label xNotNan(env); + Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan); + Bind(&xIsNan); + Jump(&yIsZeroOrNanOrxIsNanOrInf); + Bind(&xNotNan); + { + Label xIsInf(env); + Label xNotInf(env); + Branch(DoubleIsINF(*doubleX), &xIsInf, &xNotInf); + Bind(&xIsInf); + Jump(&yIsZeroOrNanOrxIsNanOrInf); + Bind(&xNotInf); + Jump(&yNeiZeroOrNanAndxNeiNanOrInf); + } + } + } + Bind(&yIsZeroOrNanOrxIsNanOrInf); + Return(DoubleBuildTaggedWithNoGC(GetDoubleConstant(base::NAN_VALUE))); + Bind(&yNeiZeroOrNanAndxNeiNanOrInf); + { + Label xIsFloatZero(env); + Label xIsZeroOryIsInf(env); + Label xNotZeroAndyNotInf(env); + Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsFloatZero, &xNotZeroAndyNotInf); + Bind(&xIsFloatZero); + Jump(&xIsZeroOryIsInf); + Label yIsInf(env); + Label yNotInf(env); + Bind(&xNotZeroAndyNotInf); + Branch(DoubleIsINF(*doubleY), &yIsInf, &yNotInf); + Bind(&yIsInf); + Jump(&xIsZeroOryIsInf); + Bind(&yNotInf); + { + StubDescriptor *floatMod = GET_STUBDESCRIPTOR(FloatMod); + doubleX = CallRuntime(floatMod, glue, GetWord64Constant(FAST_STUB_ID(FloatMod)), { + *doubleX, *doubleY + }); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); + } + Bind(&xIsZeroOryIsInf); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); + } + } + } +} + +#ifndef NDEBUG +void FastMulGCTestStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + env->GetCircuit()->SetFrameType(FrameType::OPTIMIZED_ENTRY_FRAME); + GateRef glue = PtrArgument(0); + GateRef x = Int64Argument(1); + GateRef y = Int64Argument(2); // 2: 3rd argument + + DEFVARIABLE(intX, MachineType::INT64, GetWord64Constant(0)); + DEFVARIABLE(intY, MachineType::INT64, GetWord64Constant(0)); + DEFVARIABLE(valuePtr, MachineType::INT64, GetWord64Constant(0)); + DEFVARIABLE(doubleX, MachineType::FLOAT64, GetDoubleConstant(0)); + DEFVARIABLE(doubleY, MachineType::FLOAT64, GetDoubleConstant(0)); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt64(x); + doubleX = CastInt64ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant(MachineType::UINT64)); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt64(y); + doubleY = CastInt64ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleMul(*doubleX, *doubleY); + StubDescriptor *getTaggedArrayPtr = GET_STUBDESCRIPTOR(GetTaggedArrayPtrTest); + GateRef ptr1 = CallRuntime(getTaggedArrayPtr, glue, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), { + glue + }); + GateRef ptr2 = CallRuntime(getTaggedArrayPtr, glue, GetWord64Constant(FAST_STUB_ID(GetTaggedArrayPtrTest)), { + glue + }); + (void)ptr2; + auto value = Load(MachineType::UINT64, ptr1); + GateRef value2 = CastInt64ToFloat64(value); + doubleX = DoubleMul(*doubleX, value2); + Return(DoubleBuildTaggedWithNoGC(*doubleX)); +} +#endif + +void FastTypeOfStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef obj = TaggedArgument(1); + DEFVARIABLE(holder, MachineType::TAGGED, obj); + GateRef gConstOffset = PtrAdd(glue, GetArchRelateConstant(OffsetTable::GetOffset(JSThread::GlueID::GLOBAL_CONST))); + GateRef booleanIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX); + GateRef gConstUndefindStr = Load(MachineType::TAGGED_POINTER, gConstOffset, booleanIndex); + DEFVARIABLE(resultRep, MachineType::TAGGED_POINTER, gConstUndefindStr); + Label objIsTrue(env); + Label objNotTrue(env); + Label exit(env); + Label defaultLabel(env); + GateRef gConstBooleanStr = Load( + MachineType::TAGGED_POINTER, gConstOffset, GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX)); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_TRUE)), &objIsTrue, &objNotTrue); + Bind(&objIsTrue); + { + resultRep = gConstBooleanStr; + Jump(&exit); + } + Bind(&objNotTrue); + { + Label objIsFalse(env); + Label objNotFalse(env); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_FALSE)), &objIsFalse, &objNotFalse); + Bind(&objIsFalse); + { + resultRep = gConstBooleanStr; + Jump(&exit); + } + Bind(&objNotFalse); + { + Label objIsNull(env); + Label objNotNull(env); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_NULL)), &objIsNull, &objNotNull); + Bind(&objIsNull); + { + resultRep = Load( + MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotNull); + { + Label objIsUndefined(env); + Label objNotUndefined(env); + Branch(Word64Equal(obj, GetWord64Constant(JSTaggedValue::VALUE_UNDEFINED)), &objIsUndefined, + &objNotUndefined); + Bind(&objIsUndefined); + { + resultRep = Load(MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotUndefined); + Jump(&defaultLabel); + } + } + } + Bind(&defaultLabel); + { + Label objIsHeapObject(env); + Label objNotHeapObject(env); + Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject); + Bind(&objIsHeapObject); + { + Label objIsString(env); + Label objNotString(env); + Branch(IsString(obj), &objIsString, &objNotString); + Bind(&objIsString); + { + resultRep = Load( + MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotString); + { + Label objIsSymbol(env); + Label objNotSymbol(env); + Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol); + Bind(&objIsSymbol); + { + resultRep = Load(MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotSymbol); + { + Label objIsCallable(env); + Label objNotCallable(env); + Branch(IsCallable(obj), &objIsCallable, &objNotCallable); + Bind(&objIsCallable); + { + resultRep = Load( + MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotCallable); + { + resultRep = Load( + MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX)); + Jump(&exit); + } + } + } + } + Bind(&objNotHeapObject); + { + Label objIsNum(env); + Label objNotNum(env); + Branch(TaggedIsNumber(obj), &objIsNum, &objNotNum); + Bind(&objIsNum); + { + resultRep = Load( + MachineType::TAGGED_POINTER, gConstOffset, + GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX)); + Jump(&exit); + } + Bind(&objNotNum); + Jump(&exit); + } + } + Bind(&exit); + Return(*resultRep); +} + +void FunctionCallInternalStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef func = PtrArgument(1, TypeCode::TAGGED_POINTER); + GateRef thisArg = TaggedArgument(2); /* 2 : 3rd parameter is value */ + GateRef argc = Int32Argument(3); /* 3 : 4th parameter is value */ + GateRef argv = PtrArgument(4); /* 4 : 5th parameter is ptr */ + Label funcNotBuiltinsConstructor(env); + Label funcIsBuiltinsConstructorOrFuncNotClassConstructor(env); + Label funcIsClassConstructor(env); + Branch(NotBuiltinsConstructor(func), &funcNotBuiltinsConstructor, + &funcIsBuiltinsConstructorOrFuncNotClassConstructor); + Bind(&funcNotBuiltinsConstructor); + { + Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcIsBuiltinsConstructorOrFuncNotClassConstructor); + Bind(&funcIsClassConstructor); + ThrowTypeAndReturn(glue, GET_MESSAGE_STRING_ID(FunctionCallNotConstructor), + GetExceptionConstant(MachineType::UINT64)); + } + Bind(&funcIsBuiltinsConstructorOrFuncNotClassConstructor); + StubDescriptor *execute = GET_STUBDESCRIPTOR(Execute); + Return(CallRuntime(execute, glue, GetWord64Constant(FAST_STUB_ID(Execute)), { + glue, func, thisArg, argc, argv + })); +} + +void GetPropertyByValueStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + DEFVARIABLE(key, MachineType::TAGGED, TaggedArgument(2)); /* 2 : 3rd parameter is key */ + + Label isNumberOrStringSymbol(env); + Label notNumber(env); + Label isStringOrSymbol(env); + Label notStringOrSymbol(env); + Label exit(env); + + Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number); + Bind(¬Number); + { + Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol); + Bind(¬StringOrSymbol); + { + Return(GetHoleConstant()); + } + } + Bind(&isNumberOrStringSymbol); + { + GateRef index = TryToElementsIndex(*key); + Label validIndex(env); + Label notValidIndex(env); + Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex); + Bind(&validIndex); + { + Return(GetPropertyByIndex(glue, receiver, index)); + } + Bind(¬ValidIndex); + { + Label notNumber(env); + Label getByName(env); + Branch(TaggedIsNumber(*key), &exit, ¬Number); + Bind(¬Number); + { + Label isString(env); + Label notString(env); + Label isInternalString(env); + Label notIntenalString(env); + Branch(TaggedIsString(*key), &isString, ¬String); + Bind(&isString); + { + Branch(IsInternalString(*key), &isInternalString, ¬IntenalString); + Bind(&isInternalString); + Jump(&getByName); + Bind(¬IntenalString); + { + StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString); + key = CallRuntime(newInternalString, glue, + GetWord64Constant(FAST_STUB_ID(NewInternalString)), { glue, *key }); + Jump(&getByName); + } + } + Bind(¬String); + { + Jump(&getByName); + } + } + Bind(&getByName); + { + Return(GetPropertyByName(glue, receiver, *key)); + } + } + } + Bind(&exit); + Return(GetHoleConstant()); +} + +void SetPropertyByValueStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + DEFVARIABLE(key, MachineType::TAGGED, TaggedArgument(2)); /* 2 : 3rd parameter is key */ + GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */ + + Label isNumberOrStringSymbol(env); + Label notNumber(env); + Label isStringOrSymbol(env); + Label notStringOrSymbol(env); + Label exit(env); + + Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number); + Bind(¬Number); + { + Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol); + Bind(¬StringOrSymbol); + { + Return(GetHoleConstant(MachineType::UINT64)); + } + } + Bind(&isNumberOrStringSymbol); + { + GateRef index = TryToElementsIndex(*key); + Label validIndex(env); + Label notValidIndex(env); + Branch(Int32GreaterThanOrEqual(index, GetInt32Constant(0)), &validIndex, ¬ValidIndex); + Bind(&validIndex); + { + Return(SetPropertyByIndex(glue, receiver, index, value)); + } + Bind(¬ValidIndex); + { + Label notNumber(env); + Label getByName(env); + Branch(TaggedIsNumber(*key), &exit, ¬Number); + Bind(¬Number); + { + Label isString(env); + Label notString(env); + Label isInternalString(env); + Label notIntenalString(env); + Branch(TaggedIsString(*key), &isString, ¬String); + Bind(&isString); + { + Branch(IsInternalString(*key), &isInternalString, ¬IntenalString); + Bind(&isInternalString); + Jump(&getByName); + Bind(¬IntenalString); + { + StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString); + key = CallRuntime(newInternalString, glue, + GetWord64Constant(FAST_STUB_ID(NewInternalString)), { glue, *key }); + Jump(&getByName); + } + } + Bind(¬String); + { + Jump(&getByName); + } + } + Bind(&getByName); + { + Return(SetPropertyByName(glue, receiver, *key, value)); + } + } + } + Bind(&exit); + Return(GetHoleConstant(MachineType::UINT64)); +} + +void FastEqualStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef x = TaggedArgument(0); + GateRef y = TaggedArgument(1); + Label xIsEqualy(env); + Label xIsNotEqualy(env); + Branch(Word64Equal(x, y), &xIsEqualy, &xIsNotEqualy); + Bind(&xIsEqualy); + { + Label xIsDouble(env); + Label xNotDoubleOrxNotNan(env); + Branch(TaggedIsDouble(x), &xIsDouble, &xNotDoubleOrxNotNan); + Bind(&xIsDouble); + { + GateRef doubleX = TaggedCastToDouble(x); + Label xIsNan(env); + Branch(DoubleIsNAN(doubleX), &xIsNan, &xNotDoubleOrxNotNan); + Bind(&xIsNan); + Return(TaggedFalse()); + } + Bind(&xNotDoubleOrxNotNan); + Return(TaggedTrue()); + } + Bind(&xIsNotEqualy); + { + Label xIsNumber(env); + Label xNotNumberAndxNotIntAndyNotInt(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberAndxNotIntAndyNotInt); + Bind(&xIsNumber); + { + Label xIsInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotNumberAndxNotIntAndyNotInt); + Bind(&xIsInt); + { + Label yIsInt(env); + Branch(TaggedIsInt(y), &yIsInt, &xNotNumberAndxNotIntAndyNotInt); + Bind(&yIsInt); + Return(TaggedFalse()); + } + } + Bind(&xNotNumberAndxNotIntAndyNotInt); + { + Label yIsUndefinedOrNull(env); + Label xyNotUndefinedAndNull(env); + Branch(TaggedIsUndefinedOrNull(y), &yIsUndefinedOrNull, &xyNotUndefinedAndNull); + Bind(&yIsUndefinedOrNull); + { + Label xIsHeapObject(env); + Label xNotHeapObject(env); + Branch(TaggedIsHeapObject(x), &xIsHeapObject, &xNotHeapObject); + Bind(&xIsHeapObject); + Return(TaggedFalse()); + Bind(&xNotHeapObject); + { + Label xIsUndefinedOrNull(env); + Branch(TaggedIsUndefinedOrNull(x), &xIsUndefinedOrNull, &xyNotUndefinedAndNull); + Bind(&xIsUndefinedOrNull); + Return(TaggedTrue()); + } + } + Bind(&xyNotUndefinedAndNull); + { + Label xIsBoolean(env); + Label xNotBooleanAndyNotSpecial(env); + Branch(TaggedIsBoolean(x), &xIsBoolean, &xNotBooleanAndyNotSpecial); + Bind(&xIsBoolean); + { + Label yIsSpecial(env); + Branch(TaggedIsSpecial(y), &yIsSpecial, &xNotBooleanAndyNotSpecial); + Bind(&yIsSpecial); + Return(TaggedFalse()); + } + Bind(&xNotBooleanAndyNotSpecial); + { + Return(GetHoleConstant(MachineType::UINT64)); + } + } + } + } +} + +void TryLoadICByNameStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */ + GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */ + + Label receiverIsHeapObject(env); + Label receiverNotHeapObject(env); + Label hclassEqualFirstValue(env); + Label hclassNotEqualFirstValue(env); + Label cachedHandlerNotHole(env); + Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject); + Bind(&receiverIsHeapObject); + { + GateRef hclass = LoadHClass(receiver); + Branch(Word64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), + &hclassEqualFirstValue, &hclassNotEqualFirstValue); + Bind(&hclassEqualFirstValue); + { + Return(LoadICWithHandler(glue, receiver, receiver, secondValue)); + } + Bind(&hclassNotEqualFirstValue); + { + GateRef cachedHandler = CheckPolyHClass(firstValue, hclass); + Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole); + Bind(&cachedHandlerNotHole); + { + Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler)); + } + } + } + Bind(&receiverNotHeapObject); + { + Return(GetHoleConstant()); + } +} + +void TryLoadICByValueStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */ + GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */ + GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */ + + Label receiverIsHeapObject(env); + Label receiverNotHeapObject(env); + Label hclassEqualFirstValue(env); + Label hclassNotEqualFirstValue(env); + Label firstValueEqualKey(env); + Label cachedHandlerNotHole(env); + Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject); + Bind(&receiverIsHeapObject); + { + GateRef hclass = LoadHClass(receiver); + Branch(Word64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), + &hclassEqualFirstValue, &hclassNotEqualFirstValue); + Bind(&hclassEqualFirstValue); + Return(LoadElement(receiver, key)); + Bind(&hclassNotEqualFirstValue); + { + Branch(Word64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject); + Bind(&firstValueEqualKey); + { + auto cachedHandler = CheckPolyHClass(secondValue, hclass); + Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole); + Bind(&cachedHandlerNotHole); + Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler)); + } + } + } + Bind(&receiverNotHeapObject); + Return(GetHoleConstant()); +} + +void TryStoreICByNameStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */ + GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */ + GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */ + Label receiverIsHeapObject(env); + Label receiverNotHeapObject(env); + Label hclassEqualFirstValue(env); + Label hclassNotEqualFirstValue(env); + Label cachedHandlerNotHole(env); + Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject); + Bind(&receiverIsHeapObject); + { + GateRef hclass = LoadHClass(receiver); + Branch(Word64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), + &hclassEqualFirstValue, &hclassNotEqualFirstValue); + Bind(&hclassEqualFirstValue); + { + Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue)); + } + Bind(&hclassNotEqualFirstValue); + { + GateRef cachedHandler = CheckPolyHClass(firstValue, hclass); + Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole); + Bind(&cachedHandlerNotHole); + { + Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler)); + } + } + } + Bind(&receiverNotHeapObject); + Return(GetHoleConstant(MachineType::UINT64)); +} + +void TryStoreICByValueStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + GateRef glue = PtrArgument(0); + GateRef receiver = TaggedArgument(1); + GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */ + GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */ + GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */ + GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */ + Label receiverIsHeapObject(env); + Label receiverNotHeapObject(env); + Label hclassEqualFirstValue(env); + Label hclassNotEqualFirstValue(env); + Label firstValueEqualKey(env); + Label cachedHandlerNotHole(env); + Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject); + Bind(&receiverIsHeapObject); + { + GateRef hclass = LoadHClass(receiver); + Branch(Word64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass), + &hclassEqualFirstValue, &hclassNotEqualFirstValue); + Bind(&hclassEqualFirstValue); + GateRef handlerInfo = TaggedCastToInt32(secondValue); + Return(ICStoreElement(glue, receiver, key, value, handlerInfo)); + Bind(&hclassNotEqualFirstValue); + { + Branch(Word64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject); + Bind(&firstValueEqualKey); + { + GateRef cachedHandler = CheckPolyHClass(secondValue, hclass); + Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole); + Bind(&cachedHandlerNotHole); + Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler)); + } + } + } + Bind(&receiverNotHeapObject); + Return(GetHoleConstant(MachineType::UINT64)); +} +#endif } // namespace kungfu diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h index 23f2de65..1a204bc4 100644 --- a/ecmascript/compiler/fast_stub.h +++ b/ecmascript/compiler/fast_stub.h @@ -17,33 +17,36 @@ #define ECMASCRIPT_COMPILER_FASTPATH_STUB_H #include "ecmascript/compiler/fast_stub_define.h" -#include "ecmascript/compiler/stub.h" +#include "ecmascript/compiler/stub-inl.h" namespace kungfu { -class FastArrayLoadElementStub : public Stub { -public: - // 2 : 2 means argument counts - explicit FastArrayLoadElementStub(Circuit *circuit) : Stub("FastArrayLoadElement", 2, circuit) {} - ~FastArrayLoadElementStub() = default; - NO_MOVE_SEMANTIC(FastArrayLoadElementStub); - NO_COPY_SEMANTIC(FastArrayLoadElementStub); - void GenerateCircuit() override; -}; - +#ifdef ECMASCRIPT_ENABLE_SPECIFIC_STUBS class FastAddStub : public Stub { public: // 2 : 2 means argument counts - explicit FastAddStub(Circuit *circuit) : Stub("FastAdd", 2, circuit) {} + explicit FastAddStub(Circuit *circuit, const char* triple) : Stub("FastAdd", 2, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_FRAME); + } ~FastAddStub() = default; NO_MOVE_SEMANTIC(FastAddStub); NO_COPY_SEMANTIC(FastAddStub); void GenerateCircuit() override; }; +class FastMulGCTestStub : public Stub { +public: + // 3 : 3 means argument counts + explicit FastMulGCTestStub(Circuit *circuit, const char* triple) : Stub("FastMulGCTest", 3, circuit, triple) {} + ~FastMulGCTestStub() = default; + NO_MOVE_SEMANTIC(FastMulGCTestStub); + NO_COPY_SEMANTIC(FastMulGCTestStub); + void GenerateCircuit() override; +}; class FastSubStub : public Stub { public: // 2 : 2 means argument counts - explicit FastSubStub(Circuit *circuit) : Stub("FastSub", 2, circuit) {} + explicit FastSubStub(Circuit *circuit, const char* triple) : Stub("FastSub", 2, circuit, triple) {} ~FastSubStub() = default; NO_MOVE_SEMANTIC(FastSubStub); NO_COPY_SEMANTIC(FastSubStub); @@ -53,119 +56,27 @@ public: class FastMulStub : public Stub { public: // 2 : 2 means argument counts - explicit FastMulStub(Circuit *circuit) : Stub("FastMul", 2, circuit) {} + explicit FastMulStub(Circuit *circuit, const char* triple) : Stub("FastMul", 2, circuit, triple) {} ~FastMulStub() = default; NO_MOVE_SEMANTIC(FastMulStub); NO_COPY_SEMANTIC(FastMulStub); void GenerateCircuit() override; }; -class FastMulGCTestStub : public Stub { -public: - // 3 : 3 means argument counts - explicit FastMulGCTestStub(Circuit *circuit) : Stub("FastMulGCTest", 3, circuit) {} - ~FastMulGCTestStub() = default; - NO_MOVE_SEMANTIC(FastMulGCTestStub); - NO_COPY_SEMANTIC(FastMulGCTestStub); - void GenerateCircuit() override; -}; - class FastDivStub : public Stub { public: // 2 : 2 means argument counts - explicit FastDivStub(Circuit *circuit) : Stub("FastDiv", 2, circuit) {} + explicit FastDivStub(Circuit *circuit, const char* triple) : Stub("FastDiv", 2, circuit, triple) {} ~FastDivStub() = default; NO_MOVE_SEMANTIC(FastDivStub); NO_COPY_SEMANTIC(FastDivStub); void GenerateCircuit() override; }; -class FindOwnElementStub : public Stub { -public: - // 3 : 3 means argument counts - explicit FindOwnElementStub(Circuit *circuit) : Stub("FindOwnElement", 3, circuit) {} - ~FindOwnElementStub() = default; - NO_MOVE_SEMANTIC(FindOwnElementStub); - NO_COPY_SEMANTIC(FindOwnElementStub); - void GenerateCircuit() override; -}; - -class GetElementStub : public Stub { -public: - // 3 : 3 means argument counts - explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) - { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); - } - ~GetElementStub() = default; - NO_MOVE_SEMANTIC(GetElementStub); - NO_COPY_SEMANTIC(GetElementStub); - void GenerateCircuit() override; -}; - -class FindOwnElement2Stub : public Stub { -public: - // 6 : 6 means argument counts - explicit FindOwnElement2Stub(Circuit *circuit) : Stub("FindOwnElement2", 6, circuit) {} - ~FindOwnElement2Stub() = default; - NO_MOVE_SEMANTIC(FindOwnElement2Stub); - NO_COPY_SEMANTIC(FindOwnElement2Stub); - void GenerateCircuit() override; -}; - -class SetElementStub : public Stub { -public: - // 5 : 5 means argument counts - explicit SetElementStub(Circuit *circuit) : Stub("SetElement", 5, circuit) {} - ~SetElementStub() = default; - NO_MOVE_SEMANTIC(SetElementStub); - NO_COPY_SEMANTIC(SetElementStub); - void GenerateCircuit() override; -}; - -class GetPropertyByIndexStub : public Stub { -public: - // 3 : 3 means argument counts - explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) - { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); - } - ~GetPropertyByIndexStub() = default; - NO_MOVE_SEMANTIC(GetPropertyByIndexStub); - NO_COPY_SEMANTIC(GetPropertyByIndexStub); - void GenerateCircuit() override; -}; - -class SetPropertyByIndexStub : public Stub { -public: - // 4 : 4 means argument counts - explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) - { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); - } - ~SetPropertyByIndexStub() = default; - NO_MOVE_SEMANTIC(SetPropertyByIndexStub); - NO_COPY_SEMANTIC(SetPropertyByIndexStub); - void GenerateCircuit() override; -}; - -class GetPropertyByNameStub : public Stub { -public: - // 3 : 3 means argument counts - explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) - { - circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); - } - ~GetPropertyByNameStub() = default; - NO_MOVE_SEMANTIC(GetPropertyByNameStub); - NO_COPY_SEMANTIC(GetPropertyByNameStub); - void GenerateCircuit() override; -}; - class FastModStub : public Stub { public: // 3 means argument counts - explicit FastModStub(Circuit *circuit) : Stub("FastMod", 3, circuit) + explicit FastModStub(Circuit *circuit, const char* triple) : Stub("FastMod", 3, circuit, triple) { circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } @@ -178,7 +89,215 @@ public: class FastTypeOfStub : public Stub { public: // 2 means argument counts - explicit FastTypeOfStub(Circuit *circuit) : Stub("FastTypeOf", 2, circuit) {} + explicit FastTypeOfStub(Circuit *circuit, const char* triple) : Stub("FastTypeOf", 2, circuit, triple) {} + ~FastTypeOfStub() = default; + NO_MOVE_SEMANTIC(FastTypeOfStub); + NO_COPY_SEMANTIC(FastTypeOfStub); + void GenerateCircuit() override; +}; + +class FastEqualStub : public Stub { +public: + // 2 means argument counts + explicit FastEqualStub(Circuit *circuit, const char* triple) : Stub("FastEqual", 2, circuit, triple) {} + ~FastEqualStub() = default; + NO_MOVE_SEMANTIC(FastEqualStub); + NO_COPY_SEMANTIC(FastEqualStub); + void GenerateCircuit() override; +}; + +class GetPropertyByIndexStub : public Stub { +public: + // 3 : 3 means argument counts + explicit GetPropertyByIndexStub(Circuit *circuit, const char* triple) + : Stub("GetPropertyByIndex", 3, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~GetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByIndexStub); + NO_COPY_SEMANTIC(GetPropertyByIndexStub); + void GenerateCircuit() override; +}; + +class SetPropertyByIndexStub : public Stub { +public: + // 4 : 4 means argument counts + explicit SetPropertyByIndexStub(Circuit *circuit, const char* triple) + : Stub("SetPropertyByIndex", 4, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~SetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByIndexStub); + NO_COPY_SEMANTIC(SetPropertyByIndexStub); + void GenerateCircuit() override; +}; + +class GetPropertyByNameStub : public Stub { +public: + // 3 : 3 means argument counts + explicit GetPropertyByNameStub(Circuit *circuit, const char* triple) + : Stub("GetPropertyByName", 3, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~GetPropertyByNameStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByNameStub); + NO_COPY_SEMANTIC(GetPropertyByNameStub); + void GenerateCircuit() override; +}; +#else +class FastAddStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastAddStub(Circuit *circuit, const char* triple) : Stub("FastAdd", 2, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_FRAME); + } + ~FastAddStub() = default; + NO_MOVE_SEMANTIC(FastAddStub); + NO_COPY_SEMANTIC(FastAddStub); + void GenerateCircuit() override; +}; + +class FastSubStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastSubStub(Circuit *circuit, const char* triple) : Stub("FastSub", 2, circuit, triple) {} + ~FastSubStub() = default; + NO_MOVE_SEMANTIC(FastSubStub); + NO_COPY_SEMANTIC(FastSubStub); + void GenerateCircuit() override; +}; + +class FastMulStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastMulStub(Circuit *circuit, const char* triple) : Stub("FastMul", 2, circuit, triple) {} + ~FastMulStub() = default; + NO_MOVE_SEMANTIC(FastMulStub); + NO_COPY_SEMANTIC(FastMulStub); + void GenerateCircuit() override; +}; + +class FastMulGCTestStub : public Stub { +public: + // 3 : 3 means argument counts + explicit FastMulGCTestStub(Circuit *circuit, const char* triple) : Stub("FastMulGCTest", 3, circuit, triple) {} + ~FastMulGCTestStub() = default; + NO_MOVE_SEMANTIC(FastMulGCTestStub); + NO_COPY_SEMANTIC(FastMulGCTestStub); + void GenerateCircuit() override; +}; + +class FastDivStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastDivStub(Circuit *circuit, const char* triple) : Stub("FastDiv", 2, circuit, triple) {} + ~FastDivStub() = default; + NO_MOVE_SEMANTIC(FastDivStub); + NO_COPY_SEMANTIC(FastDivStub); + void GenerateCircuit() override; +}; + +class FindOwnElement2Stub : public Stub { +public: + // 6 : 6 means argument counts + explicit FindOwnElement2Stub(Circuit *circuit, const char* triple) : Stub("FindOwnElement2", 6, circuit, triple) {} + ~FindOwnElement2Stub() = default; + NO_MOVE_SEMANTIC(FindOwnElement2Stub); + NO_COPY_SEMANTIC(FindOwnElement2Stub); + void GenerateCircuit() override; +}; + +class GetPropertyByIndexStub : public Stub { +public: + // 3 : 3 means argument counts + explicit GetPropertyByIndexStub(Circuit *circuit, const char* triple) + : Stub("GetPropertyByIndex", 3, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~GetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByIndexStub); + NO_COPY_SEMANTIC(GetPropertyByIndexStub); + void GenerateCircuit() override; +}; + +class SetPropertyByIndexStub : public Stub { +public: + // 4 : 4 means argument counts + explicit SetPropertyByIndexStub(Circuit *circuit, const char* triple) + : Stub("SetPropertyByIndex", 4, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~SetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByIndexStub); + NO_COPY_SEMANTIC(SetPropertyByIndexStub); + void GenerateCircuit() override; +}; + +class GetPropertyByNameStub : public Stub { +public: + // 3 : 3 means argument counts + explicit GetPropertyByNameStub(Circuit *circuit, const char* triple) + : Stub("GetPropertyByName", 3, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~GetPropertyByNameStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByNameStub); + NO_COPY_SEMANTIC(GetPropertyByNameStub); + void GenerateCircuit() override; +}; + +class SetPropertyByNameStub : public Stub { +public: + // 4 : 4 means argument counts + explicit SetPropertyByNameStub(Circuit *circuit, const char* triple) + : Stub("SetPropertyByName", 4, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~SetPropertyByNameStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByNameStub); + NO_COPY_SEMANTIC(SetPropertyByNameStub); + void GenerateCircuit() override; +}; + +class SetPropertyByNameWithOwnStub : public Stub { +public: + // 4 : 4 means argument counts + explicit SetPropertyByNameWithOwnStub(Circuit *circuit, const char* triple) + : Stub("SetPropertyByNameWithOwn", 4, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~SetPropertyByNameWithOwnStub() = default; + NO_MOVE_SEMANTIC(SetPropertyByNameWithOwnStub); + NO_COPY_SEMANTIC(SetPropertyByNameWithOwnStub); + void GenerateCircuit() override; +}; + +class FastModStub : public Stub { +public: + // 3 means argument counts + explicit FastModStub(Circuit *circuit, const char* triple) : Stub("FastMod", 3, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~FastModStub() = default; + NO_MOVE_SEMANTIC(FastModStub); + NO_COPY_SEMANTIC(FastModStub); + void GenerateCircuit() override; +}; + +class FastTypeOfStub : public Stub { +public: + // 2 means argument counts + explicit FastTypeOfStub(Circuit *circuit, const char* triple) : Stub("FastTypeOf", 2, circuit, triple) {} ~FastTypeOfStub() = default; NO_MOVE_SEMANTIC(FastTypeOfStub); NO_COPY_SEMANTIC(FastTypeOfStub); @@ -188,7 +307,8 @@ public: class FunctionCallInternalStub : public Stub { public: // 5 : 5 means argument counts - explicit FunctionCallInternalStub(Circuit *circuit) : Stub("FunctionCallInternal", 5, circuit) {} + explicit FunctionCallInternalStub(Circuit *circuit, const char* triple) + : Stub("FunctionCallInternal", 5, circuit, triple) {} ~FunctionCallInternalStub() = default; NO_MOVE_SEMANTIC(FunctionCallInternalStub); NO_COPY_SEMANTIC(FunctionCallInternalStub); @@ -198,7 +318,8 @@ public: class GetPropertyByValueStub : public Stub { public: // 3 : 3 means argument counts - explicit GetPropertyByValueStub(Circuit *circuit) : Stub("FastGetPropertyByValue", 3, circuit) + explicit GetPropertyByValueStub(Circuit *circuit, const char* triple) + : Stub("FastGetPropertyByValue", 3, circuit, triple) { circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } @@ -211,7 +332,8 @@ public: class SetPropertyByValueStub : public Stub { public: // 4 : 4 means argument counts - explicit SetPropertyByValueStub(Circuit *circuit) : Stub("FastSetPropertyByValue", 4, circuit) + explicit SetPropertyByValueStub(Circuit *circuit, const char* triple) + : Stub("FastSetPropertyByValue", 4, circuit, triple) { circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); } @@ -224,12 +346,61 @@ public: class FastEqualStub : public Stub { public: // 2 means argument counts - explicit FastEqualStub(Circuit *circuit) : Stub("FastEqual", 2, circuit) {} + explicit FastEqualStub(Circuit *circuit, const char* triple) : Stub("FastEqual", 2, circuit, triple) {} ~FastEqualStub() = default; NO_MOVE_SEMANTIC(FastEqualStub); NO_COPY_SEMANTIC(FastEqualStub); void GenerateCircuit() override; }; + +class TryLoadICByNameStub : public Stub { +public: + // 4 : 4 means argument counts + explicit TryLoadICByNameStub(Circuit *circuit, const char* triple) : Stub("TryLoadICByName", 4, circuit, triple) {} + ~TryLoadICByNameStub() = default; + NO_MOVE_SEMANTIC(TryLoadICByNameStub); + NO_COPY_SEMANTIC(TryLoadICByNameStub); + void GenerateCircuit() override; +}; + +class TryLoadICByValueStub : public Stub { +public: + // 5 : 5 means argument counts + explicit TryLoadICByValueStub(Circuit *circuit, const char* triple) + : Stub("TryLoadICByValue", 5, circuit, triple) {} + ~TryLoadICByValueStub() = default; + NO_MOVE_SEMANTIC(TryLoadICByValueStub); + NO_COPY_SEMANTIC(TryLoadICByValueStub); + void GenerateCircuit() override; +}; + +class TryStoreICByNameStub : public Stub { +public: + // 5 : 5 means argument counts + explicit TryStoreICByNameStub(Circuit *circuit, const char* triple) : Stub("TryStoreICByName", 5, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~TryStoreICByNameStub() = default; + NO_MOVE_SEMANTIC(TryStoreICByNameStub); + NO_COPY_SEMANTIC(TryStoreICByNameStub); + void GenerateCircuit() override; +}; + +class TryStoreICByValueStub : public Stub { +public: + // 6 : 6 means argument counts + explicit TryStoreICByValueStub(Circuit *circuit, const char* triple) + : Stub("TryStoreICByValue", 6, circuit, triple) + { + circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME); + } + ~TryStoreICByValueStub() = default; + NO_MOVE_SEMANTIC(TryStoreICByValueStub); + NO_COPY_SEMANTIC(TryStoreICByValueStub); + void GenerateCircuit() override; +}; +#endif } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index c94c34df..75c43d39 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -18,23 +18,35 @@ namespace kungfu { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define EXTERNAL_RUNTIMESTUB_LIST(V) \ - V(AddElementInternal, 5) \ - V(CallSetter, 4) \ - V(CallGetter, 4) \ - V(AccessorGetter, 4) \ - V(ThrowTypeError, 2) \ - V(JSProxySetProperty, 6) \ - V(GetHash32, 2) \ - V(FindElementWithCache, 4) \ - V(Execute, 5) \ - V(StringGetHashCode, 1) \ - V(FloatMod, 2) \ - V(SetValueWithBarrier, 4) \ - V(GetTaggedArrayPtrTest, 1) \ - V(NewInternalString, 2) +#define EXTERNAL_RUNTIMESTUB_LIST(V) \ + V(AddElementInternal, 5) \ + V(CallSetter, 5) \ + V(CallSetter2, 4) \ + V(CallGetter, 3) \ + V(CallGetter2, 4) \ + V(CallInternalGetter, 3) \ + V(ThrowTypeError, 2) \ + V(JSProxySetProperty, 6) \ + V(GetHash32, 2) \ + V(FindElementWithCache, 4) \ + V(Execute, 5) \ + V(StringGetHashCode, 1) \ + V(FloatMod, 2) \ + V(GetTaggedArrayPtrTest, 1) \ + V(NewInternalString, 2) \ + V(NewTaggedArray, 2) \ + V(CopyArray, 3) \ + V(NameDictPutIfAbsent, 7) \ + V(SetValueWithBarrier, 4) \ + V(PropertiesSetValue, 6) \ + V(TaggedArraySetValue, 6) \ + V(NewEcmaDynClass, 3) \ + V(UpdateLayOutAndAddTransition, 5) \ + V(NoticeThroughChainAndRefreshUser, 3) \ + V(DebugPrint, 1) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#ifdef ECMASCRIPT_ENABLE_SPECIFIC_STUBS #define FAST_RUNTIME_STUB_LIST(V) \ V(FastAdd, 2) \ V(FastSub, 2) \ @@ -47,9 +59,8 @@ namespace kungfu { V(IsSpecialIndexedObjForSet, 1) \ V(IsSpecialIndexedObjForGet, 1) \ V(GetPropertyByName, 3) \ - V(GetElement, 2) \ - V(SetPropertyByName, 5) \ - V(SetElement, 5) \ + V(SetPropertyByName, 4) \ + V(SetPropertyByNameWithOwn, 4) \ V(SetGlobalOwnProperty, 5) \ V(GetGlobalOwnProperty, 3) \ V(SetOwnPropertyByName, 4) \ @@ -57,23 +68,39 @@ namespace kungfu { V(FastSetProperty, 5) \ V(FastGetProperty, 3) \ V(FindOwnProperty, 6) \ - V(FindOwnElement, 2) \ V(NewLexicalEnvDyn, 4) \ V(FindOwnProperty2, 6) \ V(FindOwnElement2, 6) \ V(GetPropertyByIndex, 3) \ - V(FunctionCallInternal, 5) \ V(SetPropertyByIndex, 4) \ V(GetPropertyByValue, 3) \ V(SetPropertyByValue, 4) \ + V(FastMulGCTest, 3) \ + V(TryLoadICByName, 4) \ + V(TryLoadICByValue, 5) \ + V(TryStoreICByName, 5) \ + V(TryStoreICByValue, 6) +#else +#define FAST_RUNTIME_STUB_LIST(V) \ + V(FastAdd, 2) \ + V(FastSub, 2) \ + V(FastMul, 2) \ + V(FastDiv, 2) \ + V(FastMod, 3) \ + V(FastEqual, 2) \ + V(FastTypeOf, 2) \ V(FastMulGCTest, 3) +#endif +#ifndef ECMASCRIPT_ENABLE_SPECIFIC_STUBS // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define TEST_FUNC_LIST(V) \ - V(FastLoadElement, 2) \ V(PhiGateTest, 1) \ V(LoopTest, 1) \ V(LoopTest1, 1) +#else +#define TEST_FUNC_LIST(V) +#endif #define CALL_STUB_LIST(V) \ FAST_RUNTIME_STUB_LIST(V) \ diff --git a/ecmascript/compiler/gate.cpp b/ecmascript/compiler/gate.cpp index 19f6aa8b..eea2a964 100644 --- a/ecmascript/compiler/gate.cpp +++ b/ecmascript/compiler/gate.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/compiler/gate.h" +#include "triple.h" namespace kungfu { constexpr size_t ONE_DEPEND = 1; @@ -41,7 +42,7 @@ Properties OpCode::GetProperties() const #define NO_ROOT (std::nullopt) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GENERAL_STATE (NOP) - switch (this->op) { + switch (op_) { // SHARED case NOP: case CIRCUIT_ROOT: @@ -57,6 +58,8 @@ Properties OpCode::GetProperties() const return {NOVALUE, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CIRCUIT_ROOT)}; case RETURN: return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(ANYVALUE), OpCode(RETURN_LIST)}; + case RETURN_VOID: + return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, NO_VALUE, OpCode(RETURN_LIST)}; case THROW: return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(JSValueCode()), OpCode(THROW_LIST)}; case ORDINARY_BLOCK: @@ -93,6 +96,8 @@ Properties OpCode::GetProperties() const return {FLOAT32, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, MANY_VALUE(FLOAT32), NO_ROOT}; case VALUE_SELECTOR_FLOAT64: return {FLOAT64, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, MANY_VALUE(FLOAT64), NO_ROOT}; + case VALUE_SELECTOR_ANYVALUE: + return {ANYVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, MANY_VALUE(ANYVALUE), NO_ROOT}; case DEPEND_SELECTOR: return {NOVALUE, STATE(OpCode(GENERAL_STATE)), MANY_DEPEND, NO_VALUE, NO_ROOT}; case DEPEND_RELAY: @@ -133,23 +138,25 @@ Properties OpCode::GetProperties() const return {JSValueCode(), NO_STATE, NO_DEPEND, VALUE(JSValueCode()), NO_ROOT}; // Middle Level IR case CALL: - return {NOVALUE, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case INT1_CALL: - return {INT1, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {INT1, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case INT8_CALL: - return {INT8, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {INT8, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case INT16_CALL: - return {INT16, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {INT16, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case INT32_CALL: - return {INT32, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {INT32, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case INT64_CALL: - return {INT64, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {INT64, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case FLOAT32_CALL: - return {FLOAT32, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {FLOAT32, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case FLOAT64_CALL: - return {FLOAT64, NO_STATE, ONE_DEPEND, MANY_VALUE(PtrValueCode(), ANYVALUE), NO_ROOT}; + return {FLOAT64, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; + case ANYVALUE_CALL: + return {ANYVALUE, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT}; case ALLOCA: - return {PtrValueCode(), NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ALLOCA_LIST)}; + return {ANYVALUE, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ALLOCA_LIST)}; case INT1_ARG: return {INT1, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ARG_LIST)}; case INT8_ARG: @@ -166,7 +173,7 @@ Properties OpCode::GetProperties() const return {FLOAT64, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ARG_LIST)}; case MUTABLE_DATA: case CONST_DATA: - return {PtrValueCode(), NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)}; + return {ANYVALUE, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)}; case INT1_CONSTANT: return {INT1, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)}; case INT8_CONSTANT: @@ -273,39 +280,41 @@ Properties OpCode::GetProperties() const case FLOAT64_EQ: return {INT1, NO_STATE, NO_DEPEND, VALUE(FLOAT64, FLOAT64), NO_ROOT}; case INT8_LOAD: - return {INT8, NO_STATE, ONE_DEPEND, VALUE(PtrValueCode()), NO_ROOT}; + return {INT8, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case INT16_LOAD: - return {INT16, NO_STATE, ONE_DEPEND, VALUE(PtrValueCode()), NO_ROOT}; + return {INT16, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case INT32_LOAD: - return {INT32, NO_STATE, ONE_DEPEND, VALUE(PtrValueCode()), NO_ROOT}; + return {INT32, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case INT64_LOAD: - return {INT64, NO_STATE, ONE_DEPEND, VALUE(PtrValueCode()), NO_ROOT}; + return {INT64, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case FLOAT32_LOAD: - return {FLOAT32, NO_STATE, ONE_DEPEND, VALUE(PtrValueCode()), NO_ROOT}; + return {FLOAT32, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case FLOAT64_LOAD: - return {FLOAT64, NO_STATE, ONE_DEPEND, VALUE(PtrValueCode()), NO_ROOT}; + return {FLOAT64, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case INT8_STORE: - return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT8, PtrValueCode()), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT8, ANYVALUE), NO_ROOT}; case INT16_STORE: - return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT16, PtrValueCode()), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT16, ANYVALUE), NO_ROOT}; case INT32_STORE: - return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT32, PtrValueCode()), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT32, ANYVALUE), NO_ROOT}; case INT64_STORE: - return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT64, PtrValueCode()), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(INT64, ANYVALUE), NO_ROOT}; case FLOAT32_STORE: - return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(FLOAT32, PtrValueCode()), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(FLOAT32, ANYVALUE), NO_ROOT}; case FLOAT64_STORE: - return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(FLOAT64, PtrValueCode()), NO_ROOT}; + return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(FLOAT64, ANYVALUE), NO_ROOT}; case INT32_TO_FLOAT64: return {FLOAT64, NO_STATE, NO_DEPEND, VALUE(INT32), NO_ROOT}; case FLOAT64_TO_INT32: return {INT32, NO_STATE, NO_DEPEND, VALUE(FLOAT64), NO_ROOT}; + case TAGGED_POINTER_TO_INT64: + return {INT64, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT}; case BITCAST_INT64_TO_FLOAT64: return {FLOAT64, NO_STATE, NO_DEPEND, VALUE(INT64), NO_ROOT}; case BITCAST_FLOAT64_TO_INT64: return {INT64, NO_STATE, NO_DEPEND, VALUE(FLOAT64), NO_ROOT}; default: - std::cerr << "Please complete OpCode properties (OpCode=" << this->op << ")" << std::endl; + std::cerr << "Please complete OpCode properties (OpCode=" << op_ << ")" << std::endl; UNREACHABLE(); } #undef STATE @@ -333,6 +342,7 @@ std::string OpCode::Str() const {ALLOCA_LIST, "ALLOCA_LIST"}, {ARG_LIST, "ARG_LIST"}, {RETURN, "RETURN"}, + {RETURN_VOID, "RETURN_VOID"}, {THROW, "THROW"}, {ORDINARY_BLOCK, "ORDINARY_BLOCK"}, {IF_BRANCH, "IF_BRANCH"}, @@ -391,6 +401,7 @@ std::string OpCode::Str() const {INT64_CALL, "INT64_CALL"}, {FLOAT32_CALL, "FLOAT32_CALL"}, {FLOAT64_CALL, "FLOAT64_CALL"}, + {ANYVALUE_CALL, "ANYVALUE_CALL"}, {TAGGED_POINTER_CALL, "TAGGED_POINTER_CALL"}, {ALLOCA, "ALLOCA"}, {INT1_ARG, "INT1_ARG"}, @@ -492,19 +503,21 @@ std::string OpCode::Str() const {FLOAT64_STORE, "FLOAT64_STORE"}, {INT32_TO_FLOAT64, "INT32_TO_FLOAT64"}, {FLOAT64_TO_INT32, "FLOAT64_TO_INT32"}, + {TAGGED_POINTER_TO_INT64, "TAGGED_POINTER_TO_INT64"}, {BITCAST_INT64_TO_FLOAT64, "BITCAST_INT64_TO_FLOAT64"}, {BITCAST_FLOAT64_TO_INT64, "BITCAST_FLOAT64_TO_INT64"}, + {VALUE_SELECTOR_ANYVALUE, "VALUE_SELECTOR_ANYVALUE"}, }; - if (strMap.count(this->op) > 0) { - return strMap.at(this->op); + if (strMap.count(op_) > 0) { + return strMap.at(op_); } - return "OP-" + std::to_string(this->op); + return "OP-" + std::to_string(op_); } // 4 : 4 means that there are 4 args in total std::array OpCode::GetOpCodeNumInsArray(BitField bitfield) const { const size_t manyDepend = 2; - auto properties = this->GetProperties(); + auto properties = GetProperties(); auto stateProp = properties.statesIn; auto dependProp = properties.dependsIn; auto valueProp = properties.valuesIn; @@ -518,7 +531,7 @@ std::array OpCode::GetOpCodeNumInsArray(BitField bitfield) const size_t OpCode::GetOpCodeNumIns(BitField bitfield) const { - auto numInsArray = this->GetOpCodeNumInsArray(bitfield); + auto numInsArray = GetOpCodeNumInsArray(bitfield); // 2 : 2 means the third element. // 3 : 3 means the fourth element. return numInsArray[0] + numInsArray[1] + numInsArray[2] + numInsArray[3]; @@ -526,13 +539,13 @@ size_t OpCode::GetOpCodeNumIns(BitField bitfield) const ValueCode OpCode::GetValueCode() const { - return this->GetProperties().returnValue; + return GetProperties().returnValue; } ValueCode OpCode::GetInValueCode(BitField bitfield, size_t idx) const { - auto numInsArray = this->GetOpCodeNumInsArray(bitfield); - auto valueProp = this->GetProperties().valuesIn; + auto numInsArray = GetOpCodeNumInsArray(bitfield); + auto valueProp = GetProperties().valuesIn; idx -= numInsArray[0]; idx -= numInsArray[1]; ASSERT(valueProp.has_value()); @@ -544,7 +557,7 @@ ValueCode OpCode::GetInValueCode(BitField bitfield, size_t idx) const OpCode OpCode::GetInStateCode(size_t idx) const { - auto stateProp = this->GetProperties().statesIn; + auto stateProp = GetProperties().statesIn; ASSERT(stateProp.has_value()); if (stateProp->second) { return stateProp->first.at(std::min(idx, stateProp->first.size() - 1)); @@ -580,9 +593,9 @@ std::string ValueCodeToStr(ValueCode valueCode) std::optional> Gate::CheckNullInput() const { - const auto numIns = this->GetNumIns(); + const auto numIns = GetNumIns(); for (size_t idx = 0; idx < numIns; idx++) { - if (this->IsInGateNull(idx)) { + if (IsInGateNull(idx)) { return std::make_pair("In list contains null", idx); } } @@ -591,14 +604,14 @@ std::optional> Gate::CheckNullInput() const std::optional> Gate::CheckStateInput() const { - const auto numInsArray = this->GetOpCode().GetOpCodeNumInsArray(this->GetBitField()); + const auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField()); size_t stateStart = 0; size_t stateEnd = numInsArray[0]; for (size_t idx = stateStart; idx < stateEnd; idx++) { - auto stateProp = this->GetOpCode().GetProperties().statesIn; + auto stateProp = GetOpCode().GetProperties().statesIn; ASSERT(stateProp.has_value()); - auto expectedIn = this->GetOpCode().GetInStateCode(idx); - auto actualIn = this->GetInGateConst(idx)->GetOpCode(); + auto expectedIn = GetOpCode().GetInStateCode(idx); + auto actualIn = GetInGateConst(idx)->GetOpCode(); if (expectedIn == OpCode::NOP) { // general if (!actualIn.IsGeneralState()) { return std::make_pair( @@ -617,12 +630,12 @@ std::optional> Gate::CheckStateInput() const std::optional> Gate::CheckValueInput() const { - const auto numInsArray = this->GetOpCode().GetOpCodeNumInsArray(this->GetBitField()); + const auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField()); size_t valueStart = numInsArray[0] + numInsArray[1]; size_t valueEnd = numInsArray[0] + numInsArray[1] + numInsArray[2]; // 2 : 2 means the third element. for (size_t idx = valueStart; idx < valueEnd; idx++) { - auto expectedIn = this->GetOpCode().GetInValueCode(this->GetBitField(), idx); - auto actualIn = this->GetInGateConst(idx)->GetOpCode().GetValueCode(); + auto expectedIn = GetOpCode().GetInValueCode(GetBitField(), idx); + auto actualIn = GetInGateConst(idx)->GetOpCode().GetValueCode(); if ((expectedIn != actualIn) && (expectedIn != ANYVALUE)) { return std::make_pair("Value input does not match (expected: " + ValueCodeToStr(expectedIn) + " actual: " + ValueCodeToStr(actualIn) + ")", @@ -634,12 +647,12 @@ std::optional> Gate::CheckValueInput() const std::optional> Gate::CheckDependInput() const { - const auto numInsArray = this->GetOpCode().GetOpCodeNumInsArray(this->GetBitField()); + const auto numInsArray = GetOpCode().GetOpCodeNumInsArray(GetBitField()); size_t dependStart = numInsArray[0]; size_t dependEnd = dependStart + numInsArray[1]; for (size_t idx = dependStart; idx < dependEnd; idx++) { - if (this->GetInGateConst(idx)->GetNumInsArray()[1] == 0 && - this->GetInGateConst(idx)->GetOpCode() != OpCode::DEPEND_ENTRY) { + if (GetInGateConst(idx)->GetNumInsArray()[1] == 0 && + GetInGateConst(idx)->GetOpCode() != OpCode::DEPEND_ENTRY) { return std::make_pair("Depend input is side-effect free", idx); } } @@ -648,7 +661,7 @@ std::optional> Gate::CheckDependInput() const std::optional> Gate::CheckStateOutput() const { - if (this->GetOpCode().IsState()) { + if (GetOpCode().IsState()) { size_t cnt = 0; const Gate *curGate = this; if (!curGate->IsFirstOutNull()) { @@ -665,11 +678,11 @@ std::optional> Gate::CheckStateOutput() const } size_t expected = 0; bool needCheck = true; - if (this->GetOpCode().IsTerminalState()) { + if (GetOpCode().IsTerminalState()) { expected = 0; - } else if (this->GetOpCode() == OpCode::IF_BRANCH) { + } else if (GetOpCode() == OpCode::IF_BRANCH) { expected = 2; // 2: expected number of state out branches - } else if (this->GetOpCode() == OpCode::SWITCH_BRANCH) { + } else if (GetOpCode() == OpCode::SWITCH_BRANCH) { needCheck = false; } else { expected = 1; @@ -686,7 +699,7 @@ std::optional> Gate::CheckStateOutput() const std::optional> Gate::CheckBranchOutput() const { std::map, size_t> setOfOps; - if (this->GetOpCode() == OpCode::IF_BRANCH || this->GetOpCode() == OpCode::SWITCH_BRANCH) { + if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::SWITCH_BRANCH) { size_t cnt = 0; const Gate *curGate = this; if (!curGate->IsFirstOutNull()) { @@ -712,8 +725,8 @@ std::optional> Gate::CheckBranchOutput() const std::optional> Gate::CheckNOP() const { - if (this->GetOpCode() == OpCode::NOP) { - if (!this->IsFirstOutNull()) { + if (GetOpCode() == OpCode::NOP) { + if (!IsFirstOutNull()) { return std::make_pair("NOP gate used by other gates", -1); } } @@ -722,21 +735,21 @@ std::optional> Gate::CheckNOP() const std::optional> Gate::CheckSelector() const { - if (this->GetOpCode() == OpCode::VALUE_SELECTOR_JS || - (OpCode::VALUE_SELECTOR_INT1 <= this->GetOpCode() && this->GetOpCode() <= OpCode::VALUE_SELECTOR_FLOAT64) || - this->GetOpCode() == OpCode::DEPEND_SELECTOR) { - auto stateOp = this->GetInGateConst(0)->GetOpCode(); + if (GetOpCode() == OpCode::VALUE_SELECTOR_JS || + (OpCode::VALUE_SELECTOR_INT1 <= GetOpCode() && GetOpCode() <= OpCode::VALUE_SELECTOR_FLOAT64) || + GetOpCode() == OpCode::DEPEND_SELECTOR) { + auto stateOp = GetInGateConst(0)->GetOpCode(); if (stateOp == OpCode::MERGE || stateOp == OpCode::LOOP_BEGIN) { - if (this->GetInGateConst(0)->GetNumIns() != this->GetNumIns() - 1) { - if (this->GetOpCode() == OpCode::DEPEND_SELECTOR) { + if (GetInGateConst(0)->GetNumIns() != GetNumIns() - 1) { + if (GetOpCode() == OpCode::DEPEND_SELECTOR) { return std::make_pair("Number of depend flows does not match control flows (expected:" + - std::to_string(this->GetInGateConst(0)->GetNumIns()) + - " actual:" + std::to_string(this->GetNumIns() - 1) + ")", + std::to_string(GetInGateConst(0)->GetNumIns()) + + " actual:" + std::to_string(GetNumIns() - 1) + ")", -1); } else { return std::make_pair("Number of data flows does not match control flows (expected:" + - std::to_string(this->GetInGateConst(0)->GetNumIns()) + - " actual:" + std::to_string(this->GetNumIns() - 1) + ")", + std::to_string(GetInGateConst(0)->GetNumIns()) + + " actual:" + std::to_string(GetNumIns() - 1) + ")", -1); } } @@ -750,8 +763,8 @@ std::optional> Gate::CheckSelector() const std::optional> Gate::CheckRelay() const { - if (this->GetOpCode() == OpCode::DEPEND_RELAY) { - auto stateOp = this->GetInGateConst(0)->GetOpCode(); + if (GetOpCode() == OpCode::DEPEND_RELAY) { + auto stateOp = GetInGateConst(0)->GetOpCode(); if (!(stateOp == OpCode::IF_TRUE || stateOp == OpCode::IF_FALSE || stateOp == OpCode::SWITCH_CASE || stateOp == OpCode::DEFAULT_CASE)) { return std::make_pair( @@ -766,19 +779,19 @@ std::optional> Gate::CheckRelay() const std::optional> Gate::SpecialCheck() const { { - auto ret = this->CheckNOP(); + auto ret = CheckNOP(); if (ret.has_value()) { return ret; } } { - auto ret = this->CheckSelector(); + auto ret = CheckSelector(); if (ret.has_value()) { return ret; } } { - auto ret = this->CheckRelay(); + auto ret = CheckRelay(); if (ret.has_value()) { return ret; } @@ -792,49 +805,49 @@ bool Gate::Verify() const size_t highlightIdx = -1; bool failed = false; { - auto ret = this->CheckNullInput(); + auto ret = CheckNullInput(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); } } if (!failed) { - auto ret = this->CheckStateInput(); + auto ret = CheckStateInput(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); } } if (!failed) { - auto ret = this->CheckValueInput(); + auto ret = CheckValueInput(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); } } if (!failed) { - auto ret = this->CheckDependInput(); + auto ret = CheckDependInput(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); } } if (!failed) { - auto ret = this->CheckStateOutput(); + auto ret = CheckStateOutput(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); } } if (!failed) { - auto ret = this->CheckBranchOutput(); + auto ret = CheckBranchOutput(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); } } if (!failed) { - auto ret = this->SpecialCheck(); + auto ret = SpecialCheck(); if (ret.has_value()) { failed = true; std::tie(errorString, highlightIdx) = ret.value(); @@ -842,7 +855,7 @@ bool Gate::Verify() const } if (failed) { std::cerr << "[Verifier][Error] Gate level input list schema verify failed" << std::endl; - this->Print(true, highlightIdx); + Print(true, highlightIdx); std::cerr << "Note: " << errorString << std::endl; } return !failed; @@ -869,6 +882,15 @@ ValueCode PtrValueCode() #endif } +ValueCode ArchRelatePtrValueCode(const char *triple) +{ + if (triple == TripleConst::GetLLVMArm32Triple()) { + return ValueCode::INT32; + } else { + return ValueCode::INT64; + } +} + size_t GetValueBits(ValueCode valueCode) { switch (valueCode) { @@ -900,127 +922,127 @@ size_t GetOpCodeNumIns(OpCode opcode, BitField bitfield) void Out::SetNextOut(const Out *ptr) { - this->nextOut = + nextOut_ = // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - static_cast((reinterpret_cast(ptr)) - (reinterpret_cast(this))); + static_cast((reinterpret_cast(ptr)) - (reinterpret_cast(this))); } Out *Out::GetNextOut() { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->nextOut); + return reinterpret_cast((reinterpret_cast(this)) + nextOut_); } const Out *Out::GetNextOutConst() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->nextOut); + return reinterpret_cast((reinterpret_cast(this)) + nextOut_); } void Out::SetPrevOut(const Out *ptr) { - this->prevOut = + prevOut_ = // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - static_cast((reinterpret_cast(ptr)) - (reinterpret_cast(this))); + static_cast((reinterpret_cast(ptr)) - (reinterpret_cast(this))); } Out *Out::GetPrevOut() { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->prevOut); + return reinterpret_cast((reinterpret_cast(this)) + prevOut_); } const Out *Out::GetPrevOutConst() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->prevOut); + return reinterpret_cast((reinterpret_cast(this)) + prevOut_); } void Out::SetIndex(OutIdx idx) { - this->idx = idx; + idx_ = idx; } OutIdx Out::GetIndex() const { - return this->idx; + return idx_; } Gate *Out::GetGate() { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast(&this[this->idx + 1]); + return reinterpret_cast(&this[idx_ + 1]); } const Gate *Out::GetGateConst() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast(&this[this->idx + 1]); + return reinterpret_cast(&this[idx_ + 1]); } void Out::SetPrevOutNull() { - this->prevOut = 0; + prevOut_ = 0; } bool Out::IsPrevOutNull() const { - return this->prevOut == 0; + return prevOut_ == 0; } void Out::SetNextOutNull() { - this->nextOut = 0; + nextOut_ = 0; } bool Out::IsNextOutNull() const { - return this->nextOut == 0; + return nextOut_ == 0; } void In::SetGate(const Gate *ptr) { - this->gatePtr = + gatePtr_ = // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - static_cast((reinterpret_cast(ptr)) - (reinterpret_cast(this))); + static_cast((reinterpret_cast(ptr)) - (reinterpret_cast(this))); } Gate *In::GetGate() { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->gatePtr); + return reinterpret_cast((reinterpret_cast(this)) + gatePtr_); } const Gate *In::GetGateConst() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->gatePtr); + return reinterpret_cast((reinterpret_cast(this)) + gatePtr_); } void In::SetGateNull() { - this->gatePtr = 0; + gatePtr_ = 0; } bool In::IsGateNull() const { - return this->gatePtr == 0; + return gatePtr_ == 0; } // NOLINTNEXTLINE(modernize-avoid-c-arrays) Gate::Gate(GateId id, OpCode opcode, BitField bitfield, Gate *inList[], TypeCode type, MarkCode mark) - : id(id), opcode(opcode), type(type), stamp(1), mark(mark), bitfield(bitfield), firstOut(0) + : id_(id), opcode_(opcode), type_(type), stamp_(1), mark_(mark), bitfield_(bitfield), firstOut_(0) { - auto numIns = this->GetNumIns(); + auto numIns = GetNumIns(); for (size_t idx = 0; idx < numIns; idx++) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) auto in = inList[idx]; if (in == nullptr) { - this->GetIn(idx)->SetGateNull(); + GetIn(idx)->SetGateNull(); } else { - this->NewIn(idx, in); + NewIn(idx, in); } - auto curOut = this->GetOut(idx); + auto curOut = GetOut(idx); curOut->SetIndex(idx); } } @@ -1032,7 +1054,7 @@ size_t Gate::GetOutListSize(size_t numIns) size_t Gate::GetOutListSize() const { - return Gate::GetOutListSize(this->GetNumIns()); + return Gate::GetOutListSize(GetNumIns()); } size_t Gate::GetInListSize(size_t numIns) @@ -1042,7 +1064,7 @@ size_t Gate::GetInListSize(size_t numIns) size_t Gate::GetInListSize() const { - return Gate::GetInListSize(this->GetNumIns()); + return Gate::GetInListSize(GetNumIns()); } size_t Gate::GetGateSize(size_t numIns) @@ -1052,13 +1074,13 @@ size_t Gate::GetGateSize(size_t numIns) size_t Gate::GetGateSize() const { - return Gate::GetGateSize(this->GetNumIns()); + return Gate::GetGateSize(GetNumIns()); } void Gate::NewIn(size_t idx, Gate *in) { - this->GetIn(idx)->SetGate(in); - auto curOut = this->GetOut(idx); + GetIn(idx)->SetGate(in); + auto curOut = GetOut(idx); if (in->IsFirstOutNull()) { curOut->SetNextOutNull(); } else { @@ -1071,33 +1093,33 @@ void Gate::NewIn(size_t idx, Gate *in) void Gate::ModifyIn(size_t idx, Gate *in) { - this->DeleteIn(idx); - this->NewIn(idx, in); + DeleteIn(idx); + NewIn(idx, in); } void Gate::DeleteIn(size_t idx) { - if (!this->GetOut(idx)->IsNextOutNull() && !this->GetOut(idx)->IsPrevOutNull()) { - this->GetOut(idx)->GetPrevOut()->SetNextOut(this->GetOut(idx)->GetNextOut()); - this->GetOut(idx)->GetNextOut()->SetPrevOut(this->GetOut(idx)->GetPrevOut()); - } else if (this->GetOut(idx)->IsNextOutNull() && !this->GetOut(idx)->IsPrevOutNull()) { - this->GetOut(idx)->GetPrevOut()->SetNextOutNull(); - } else if (!this->GetOut(idx)->IsNextOutNull()) { // then this->GetOut(idx)->IsPrevOutNull() is true - this->GetIn(idx)->GetGate()->SetFirstOut(this->GetOut(idx)->GetNextOut()); - this->GetOut(idx)->GetNextOut()->SetPrevOutNull(); + if (!GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) { + GetOut(idx)->GetPrevOut()->SetNextOut(GetOut(idx)->GetNextOut()); + GetOut(idx)->GetNextOut()->SetPrevOut(GetOut(idx)->GetPrevOut()); + } else if (GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) { + GetOut(idx)->GetPrevOut()->SetNextOutNull(); + } else if (!GetOut(idx)->IsNextOutNull()) { // then GetOut(idx)->IsPrevOutNull() is true + GetIn(idx)->GetGate()->SetFirstOut(GetOut(idx)->GetNextOut()); + GetOut(idx)->GetNextOut()->SetPrevOutNull(); } else { // only this out now - this->GetIn(idx)->GetGate()->SetFirstOutNull(); + GetIn(idx)->GetGate()->SetFirstOutNull(); } - this->GetIn(idx)->SetGateNull(); + GetIn(idx)->SetGateNull(); } void Gate::DeleteGate() { - auto numIns = this->GetNumIns(); + auto numIns = GetNumIns(); for (size_t idx = 0; idx < numIns; idx++) { - this->DeleteIn(idx); + DeleteIn(idx); } - this->SetOpCode(OpCode(OpCode::NOP)); + SetOpCode(OpCode(OpCode::NOP)); } Out *Gate::GetOut(size_t idx) @@ -1109,38 +1131,38 @@ Out *Gate::GetOut(size_t idx) Out *Gate::GetFirstOut() { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->firstOut); + return reinterpret_cast((reinterpret_cast(this)) + firstOut_); } const Out *Gate::GetFirstOutConst() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - return reinterpret_cast((reinterpret_cast(this)) + this->firstOut); + return reinterpret_cast((reinterpret_cast(this)) + firstOut_); } void Gate::SetFirstOutNull() { - this->firstOut = 0; + firstOut_ = 0; } bool Gate::IsFirstOutNull() const { - return this->firstOut == 0; + return firstOut_ == 0; } void Gate::SetFirstOut(const Out *firstOut) { - this->firstOut = + firstOut_ = // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - static_cast(reinterpret_cast(firstOut) - reinterpret_cast(this)); + static_cast(reinterpret_cast(firstOut) - reinterpret_cast(this)); } In *Gate::GetIn(size_t idx) { #ifndef NDEBUG - if (idx >= this->GetNumIns()) { + if (idx >= GetNumIns()) { std::cerr << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")" << std::endl; - this->Print(); + Print(); ASSERT(false); } #endif @@ -1151,9 +1173,9 @@ In *Gate::GetIn(size_t idx) const In *Gate::GetInConst(size_t idx) const { #ifndef NDEBUG - if (idx >= this->GetNumIns()) { + if (idx >= GetNumIns()) { std::cerr << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")" << std::endl; - this->Print(); + Print(); ASSERT(false); } #endif @@ -1163,72 +1185,82 @@ const In *Gate::GetInConst(size_t idx) const Gate *Gate::GetInGate(size_t idx) { - return this->GetIn(idx)->GetGate(); + return GetIn(idx)->GetGate(); } const Gate *Gate::GetInGateConst(size_t idx) const { - return this->GetInConst(idx)->GetGateConst(); + return GetInConst(idx)->GetGateConst(); } bool Gate::IsInGateNull(size_t idx) const { - return this->GetInConst(idx)->IsGateNull(); + return GetInConst(idx)->IsGateNull(); } GateId Gate::GetId() const { - return id; + return id_; } OpCode Gate::GetOpCode() const { - return this->opcode; + return opcode_; } void Gate::SetOpCode(OpCode opcode) { - this->opcode = opcode; + opcode_ = opcode; +} + +TypeCode Gate::GetTypeCode() const +{ + return type_; +} + +void Gate::SetTypeCode(TypeCode type) +{ + type_ = type; } size_t Gate::GetNumIns() const { - return GetOpCodeNumIns(this->GetOpCode(), this->GetBitField()); + return GetOpCodeNumIns(GetOpCode(), GetBitField()); } std::array Gate::GetNumInsArray() const // 4 : 4 means that there are 4 args. { - return this->GetOpCode().GetOpCodeNumInsArray(this->GetBitField()); + return GetOpCode().GetOpCodeNumInsArray(GetBitField()); } BitField Gate::GetBitField() const { - return this->bitfield; + return bitfield_; } void Gate::SetBitField(BitField bitfield) { - this->bitfield = bitfield; + bitfield_ = bitfield; } void Gate::Print(bool inListPreview, size_t highlightIdx) const { - if (this->GetOpCode() != OpCode::NOP) { + if (GetOpCode() != OpCode::NOP) { std::cerr << std::dec << "(" - << "id=" << this->id << ", " - << "op=" << this->GetOpCode().Str() << ", " - << "bitfield=" << std::to_string(this->bitfield) << ", " - << "type=" << static_cast(this->type) << ", " - << "stamp=" << static_cast(this->stamp) << ", " - << "mark=" << static_cast(this->mark) << ", "; + << "id=" << id_ << ", " + << "op=" << GetOpCode().Str() << ", " + << "bitfield=" << std::to_string(bitfield_) << ", " + << "type=" << static_cast(type_) << ", " + << "stamp=" << static_cast(stamp_) << ", " + << "mark=" << static_cast(mark_) << ", "; std::cerr << "in=" << "["; - for (size_t idx = 0; idx < this->GetNumIns(); idx++) { + for (size_t idx = 0; idx < GetNumIns(); idx++) { std::cerr << std::dec << ((idx == 0) ? "" : " ") << ((idx == highlightIdx) ? "\033[4;31m" : "") - << ((this->IsInGateNull(idx) + << ((IsInGateNull(idx) ? "N" - : (std::to_string(this->GetInGateConst(idx)->GetId()) + - (inListPreview ? std::string(":" + this->GetInGateConst(idx)->GetOpCode().Str()) + : (std::to_string(GetInGateConst(idx)->GetId()) + + (inListPreview ? std::string(":" + GetInGateConst(idx)->GetOpCode().Str()) : std::string(""))))) << ((idx == highlightIdx) ? "\033[0m" : ""); } @@ -1236,8 +1268,8 @@ void Gate::Print(bool inListPreview, size_t highlightIdx) const << ", "; std::cerr << "out=" << "["; - if (!this->IsFirstOutNull()) { - const Out *curOut = this->GetFirstOutConst(); + if (!IsFirstOutNull()) { + const Out *curOut = GetFirstOutConst(); std::cerr << std::dec << "" << std::to_string(curOut->GetGateConst()->GetId()) + (inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str()) : std::string("")); @@ -1256,79 +1288,75 @@ void Gate::Print(bool inListPreview, size_t highlightIdx) const MarkCode Gate::GetMark(TimeStamp stamp) const { - return (this->stamp == stamp) ? this->mark : MarkCode::EMPTY; + return (stamp_ == stamp) ? mark_ : MarkCode::EMPTY; } void Gate::SetMark(MarkCode mark, TimeStamp stamp) { - this->stamp = stamp; - this->mark = mark; -} - -TypeCode Gate::GetTypeCode() const -{ - return type; + stamp_ = stamp; + mark_ = mark; } bool OpCode::IsRoot() const { - return (this->GetProperties().states == OpCode::CIRCUIT_ROOT) || (this->op == OpCode::CIRCUIT_ROOT); + return (GetProperties().states == OpCode::CIRCUIT_ROOT) || (op_ == OpCode::CIRCUIT_ROOT); } bool OpCode::IsProlog() const { - return (this->GetProperties().states == OpCode::ARG_LIST); + return (GetProperties().states == OpCode::ARG_LIST); } bool OpCode::IsFixed() const { - return (this->GetOpCodeNumInsArray(1)[0] > 0) && - ((this->GetValueCode() != NOVALUE) || - ((this->GetOpCodeNumInsArray(1)[1] > 0) && (this->GetOpCodeNumInsArray(1)[2] == 0))); + return (GetOpCodeNumInsArray(1)[0] > 0) && + ((GetValueCode() != NOVALUE) || + ((GetOpCodeNumInsArray(1)[1] > 0) && (GetOpCodeNumInsArray(1)[2] == 0) && + (GetOpCodeNumInsArray(1)[3] == 0))); } bool OpCode::IsSchedulable() const { - return (this->op != OpCode::NOP) && (!this->IsProlog()) && (!this->IsRoot()) && (!this->IsFixed()) && - (this->GetOpCodeNumInsArray(1)[0] == 0); + return (op_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) && (!IsFixed()) && + (GetOpCodeNumInsArray(1)[0] == 0); } bool OpCode::IsState() const { - return (this->op != OpCode::NOP) && (!this->IsProlog()) && (!this->IsRoot()) && (!this->IsFixed()) && - (this->GetOpCodeNumInsArray(1)[0] > 0); + return (op_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) && (!IsFixed()) && + (GetOpCodeNumInsArray(1)[0] > 0); } bool OpCode::IsGeneralState() const { - return ((this->op == OpCode::IF_TRUE) || (this->op == OpCode::IF_FALSE) || (this->op == OpCode::SWITCH_CASE) || - (this->op == OpCode::DEFAULT_CASE) || (this->op == OpCode::MERGE) || (this->op == OpCode::LOOP_BEGIN) || - (this->op == OpCode::ORDINARY_BLOCK) || (this->op == OpCode::STATE_ENTRY)); + return ((op_ == OpCode::IF_TRUE) || (op_ == OpCode::IF_FALSE) || (op_ == OpCode::SWITCH_CASE) || + (op_ == OpCode::DEFAULT_CASE) || (op_ == OpCode::MERGE) || (op_ == OpCode::LOOP_BEGIN) || + (op_ == OpCode::ORDINARY_BLOCK) || (op_ == OpCode::STATE_ENTRY)); } bool OpCode::IsTerminalState() const { - return ((this->op == OpCode::RETURN) || (this->op == OpCode::THROW)); + return ((op_ == OpCode::RETURN) || (op_ == OpCode::THROW) || (op_ == OpCode::RETURN_VOID)); } bool OpCode::IsCFGMerge() const { - return (this->op == OpCode::MERGE) || (this->op == OpCode::LOOP_BEGIN); + return (op_ == OpCode::MERGE) || (op_ == OpCode::LOOP_BEGIN); } bool OpCode::IsControlCase() const { - return (this->op == OpCode::IF_BRANCH) || (this->op == OpCode::SWITCH_BRANCH) || (this->op == OpCode::IF_TRUE) || - (this->op == OpCode::IF_FALSE) || (this->op == OpCode::SWITCH_CASE) || (this->op == OpCode::DEFAULT_CASE); + return (op_ == OpCode::IF_BRANCH) || (op_ == OpCode::SWITCH_BRANCH) || (op_ == OpCode::IF_TRUE) || + (op_ == OpCode::IF_FALSE) || (op_ == OpCode::SWITCH_CASE) || (op_ == OpCode::DEFAULT_CASE); } bool OpCode::IsLoopHead() const { - return (this->op == OpCode::LOOP_BEGIN); + return (op_ == OpCode::LOOP_BEGIN); } bool OpCode::IsNop() const { - return (this->op == OpCode::NOP); + return (op_ == OpCode::NOP); } } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/gate.h b/ecmascript/compiler/gate.h index c41de70e..6c9620d0 100644 --- a/ecmascript/compiler/gate.h +++ b/ecmascript/compiler/gate.h @@ -30,11 +30,12 @@ #include "ecmascript/compiler/type.h" namespace kungfu { +using GateRef = int32_t; // for external users using GateId = uint32_t; using GateOp = uint8_t; using GateMark = uint8_t; using TimeStamp = uint8_t; -using AddrShift = int32_t; +using GateRef = int32_t; using BitField = uint64_t; using OutIdx = uint32_t; class Gate; @@ -49,7 +50,6 @@ enum ValueCode { INT64, FLOAT32, FLOAT64, - TAGGED_POINTER, }; std::string ValueCodeToStr(ValueCode valueCode); @@ -71,6 +71,7 @@ public: ALLOCA_LIST, ARG_LIST, RETURN, + RETURN_VOID, THROW, ORDINARY_BLOCK, IF_BRANCH, @@ -90,6 +91,7 @@ public: VALUE_SELECTOR_INT64, VALUE_SELECTOR_FLOAT32, VALUE_SELECTOR_FLOAT64, + VALUE_SELECTOR_ANYVALUE, DEPEND_SELECTOR, DEPEND_RELAY, DEPEND_AND, @@ -130,6 +132,7 @@ public: FLOAT32_CALL, FLOAT64_CALL, TAGGED_POINTER_CALL, + ANYVALUE_CALL, ALLOCA, INT1_ARG, INT8_ARG, @@ -231,16 +234,17 @@ public: FLOAT64_STORE, INT32_TO_FLOAT64, FLOAT64_TO_INT32, + TAGGED_POINTER_TO_INT64, BITCAST_INT64_TO_FLOAT64, BITCAST_FLOAT64_TO_INT64, TAG64_TO_INT1, }; OpCode() = default; - explicit constexpr OpCode(Op op) : op(op) {} + explicit constexpr OpCode(Op op) : op_(op) {} operator Op() const { - return this->op; + return op_; } explicit operator bool() const = delete; [[nodiscard]] Properties GetProperties() const; @@ -264,7 +268,7 @@ public: ~OpCode() = default; private: - Op op; + Op op_; }; struct Properties { @@ -283,6 +287,7 @@ enum MarkCode : GateMark { ValueCode JSValueCode(); ValueCode PtrValueCode(); +ValueCode ArchRelatePtrValueCode(const char *triple); size_t GetValueBits(ValueCode valueCode); class Out { @@ -305,9 +310,9 @@ public: ~Out() = default; private: - OutIdx idx; - AddrShift nextOut; - AddrShift prevOut; + OutIdx idx_; + GateRef nextOut_; + GateRef prevOut_; }; class In { @@ -321,7 +326,7 @@ public: ~In() = default; private: - AddrShift gatePtr; + GateRef gatePtr_; }; class Gate { @@ -356,6 +361,8 @@ public: [[nodiscard]] bool IsInGateNull(size_t idx) const; [[nodiscard]] OpCode GetOpCode() const; void SetOpCode(OpCode opcode); + [[nodiscard]] TypeCode GetTypeCode() const; + void SetTypeCode(TypeCode type); [[nodiscard]] GateId GetId() const; [[nodiscard]] size_t GetNumIns() const; [[nodiscard]] std::array GetNumInsArray() const; @@ -376,7 +383,6 @@ public: [[nodiscard]] bool Verify() const; [[nodiscard]] MarkCode GetMark(TimeStamp stamp) const; void SetMark(MarkCode mark, TimeStamp stamp); - TypeCode GetTypeCode() const; ~Gate() = default; private: @@ -384,13 +390,13 @@ private: // out(2) // out(1) // out(0) - GateId id; - OpCode opcode; - TypeCode type; - TimeStamp stamp; - MarkCode mark; - BitField bitfield; - AddrShift firstOut; + GateId id_; + OpCode opcode_; + TypeCode type_; + TimeStamp stamp_; + MarkCode mark_; + BitField bitfield_; + GateRef firstOut_; // in(0) // in(1) // in(2) diff --git a/ecmascript/compiler/js_thread_offset_table.cpp b/ecmascript/compiler/js_thread_offset_table.cpp new file mode 100644 index 00000000..416d32b3 --- /dev/null +++ b/ecmascript/compiler/js_thread_offset_table.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 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. + */ + +#include "ecmascript/compiler/js_thread_offset_table.h" +#include "ecmascript/compiler/triple.h" + +namespace kungfu { +using namespace panda::ecmascript; +OffsetTable *OffsetTable::instance_ = nullptr; +OffsetTable::OffsetTable(const char* triple) +{ + if (triple == TripleConst::GetLLVMArm32Triple()) { + offsetTable_ = { + GLUE_EXCEPTION_OFFSET_32, GLUE_GLOBAL_CONSTANTS_OFFSET_32, GLUE_PROPERTIES_CACHE_OFFSET_32, + GLUE_GLOBAL_STORAGE_OFFSET_32, GLUE_CURRENT_FRAME_OFFSET_32, GLUE_LAST_IFRAME_OFFSET_32, + GLUE_RUNTIME_FUNCTIONS_OFFSET_32, GLUE_FASTSTUB_ENTRIES_OFFSET_32 + }; + } else if (triple == TripleConst::GetLLVMArm64Triple() || triple == TripleConst::GetLLVMAmd64Triple()) { + offsetTable_ = { + GLUE_EXCEPTION_OFFSET_64, GLUE_GLOBAL_CONSTANTS_OFFSET_64, GLUE_PROPERTIES_CACHE_OFFSET_64, + GLUE_GLOBAL_STORAGE_OFFSET_64, GLUE_CURRENT_FRAME_OFFSET_64, GLUE_LAST_IFRAME_OFFSET_64, + GLUE_RUNTIME_FUNCTIONS_OFFSET_64, GLUE_FASTSTUB_ENTRIES_OFFSET_64 + }; + } else { + UNREACHABLE(); + } +} +// static +void OffsetTable::CreateInstance(const char* triple) +{ + instance_ = new OffsetTable(triple); +} +// static +void OffsetTable::Destroy() +{ + if (instance_) { + delete instance_; + instance_ = nullptr; + } +} +} // namespace kungfu diff --git a/ecmascript/compiler/js_thread_offset_table.h b/ecmascript/compiler/js_thread_offset_table.h new file mode 100644 index 00000000..13f425da --- /dev/null +++ b/ecmascript/compiler/js_thread_offset_table.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef ECMASCRIPT_COMPILER_JS_THREAD_OFFSET_TABLE_H +#define ECMASCRIPT_COMPILER_JS_THREAD_OFFSET_TABLE_H + +#include +#include "ecmascript/js_thread.h" + +// this class only use in host compiling +namespace kungfu { +using JSThread = panda::ecmascript::JSThread; +class OffsetTable { +public: + static void CreateInstance(const char* triple); + static void Destroy(); + static OffsetTable *GetInstance() + { + ASSERT(instance_); + return instance_; + } + + static uint32_t GetOffset(JSThread::GlueID id) + { + ASSERT(instance_); + return instance_->offsetTable_[static_cast(id)]; + } + +private: + explicit OffsetTable(const char* triple); + ~OffsetTable() = default; + + static OffsetTable *instance_; + std::array(JSThread::GlueID::NUMBER_OF_GLUE)> offsetTable_ {}; + + NO_COPY_SEMANTIC(OffsetTable); + NO_MOVE_SEMANTIC(OffsetTable); +}; +} // namespace kungfu +#endif // ECMASCRIPT_COMPILER_JS_THREAD_OFFSET_TABLE_H diff --git a/ecmascript/compiler/llvm/llvm.patch b/ecmascript/compiler/llvm/llvm.patch deleted file mode 100644 index bfd0c418..00000000 --- a/ecmascript/compiler/llvm/llvm.patch +++ /dev/null @@ -1,125 +0,0 @@ -diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt -index 0e85afa82c7..43756892e40 100644 ---- a/llvm/CMakeLists.txt -+++ b/llvm/CMakeLists.txt -@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME - "Build the LLVM runtime libraries." ON) - option(LLVM_BUILD_EXAMPLES - "Build the LLVM example programs. If OFF, just generate build targets." OFF) -+option(BUILD_ARK_GC_SUPPORT -+ "ARK support GC. If ON, support GC." OFF) -+if(BUILD_ARK_GC_SUPPORT) -+ add_definitions(-DARK_GC_SUPPORT) -+endif(BUILD_ARK_GC_SUPPORT) -+ - option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) - -+ - if(LLVM_BUILD_EXAMPLES) - add_definitions(-DBUILD_EXAMPLES) - endif(LLVM_BUILD_EXAMPLES) -diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..e0264827556 100644 ---- a/llvm/lib/Target/X86/X86FrameLowering.cpp -+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp -@@ -1168,6 +1168,25 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, - else - MFI.setOffsetAdjustment(-StackSize); - } -+#ifdef ARK_GC_SUPPORT -+ // push marker -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) -+ { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); -+ } -+ } -+#endif - - // For EH funclets, only allocate enough space for outgoing calls. Save the - // NumBytes value that we would've used for the parent frame. -@@ -1635,6 +1654,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, - uint64_t SEHStackAllocAmt = NumBytes; - - if (HasFP) { -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) -+ { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ -+ // pop marker -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ // pop thread.fp -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ } -+ } -+#endif - // Pop EBP. - BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), - MachineFramePtr) -@@ -1993,8 +2033,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( - - if (hasFP(MF)) { - // emitPrologue always spills frame register the first thing. -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += (2 * SlotSize); -+ } else { -+ SpillSlotOffset -= 2 * SlotSize; // add type -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += SlotSize; -+ } -+ } else { -+ SpillSlotOffset -= SlotSize; // add type and thread.fp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ } -+#else - SpillSlotOffset -= SlotSize; - MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+#endif - - // Since emitPrologue and emitEpilogue will handle spilling and restoring of - // the frame register, we can delete it from CSI list and not have to worry -diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h -index 2103d6471ea..3fd89b0d9ee 100644 ---- a/llvm/lib/Target/X86/X86FrameLowering.h -+++ b/llvm/lib/Target/X86/X86FrameLowering.h -@@ -15,6 +15,8 @@ - - #include "llvm/CodeGen/TargetFrameLowering.h" - -+#define JS_ENTRY_FRAME_MARK 1 -+ - namespace llvm { - - class MachineInstrBuilder; diff --git a/ecmascript/compiler/llvm/llvm_new.patch b/ecmascript/compiler/llvm/llvm_new.patch new file mode 100644 index 00000000..ab346589 --- /dev/null +++ b/ecmascript/compiler/llvm/llvm_new.patch @@ -0,0 +1,928 @@ +diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt +index 0e85afa82c7..43756892e40 100644 +--- a/llvm/CMakeLists.txt ++++ b/llvm/CMakeLists.txt +@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME + "Build the LLVM runtime libraries." ON) + option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) ++option(BUILD_ARK_GC_SUPPORT ++ "ARK support GC. If ON, support GC." OFF) ++if(BUILD_ARK_GC_SUPPORT) ++ add_definitions(-DARK_GC_SUPPORT) ++endif(BUILD_ARK_GC_SUPPORT) ++ + option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) + ++ + if(LLVM_BUILD_EXAMPLES) + add_definitions(-DBUILD_EXAMPLES) + endif(LLVM_BUILD_EXAMPLES) +diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h +index c7d4c4d7e5d..1df40696dd0 100644 +--- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h ++++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h +@@ -15,6 +15,9 @@ + + #include "llvm/CodeGen/MachineBasicBlock.h" + #include "llvm/ADT/StringSwitch.h" ++#ifdef ARK_GC_SUPPORT ++#include "llvm/ADT/Triple.h" ++#endif + #include + #include + +@@ -177,7 +180,12 @@ public: + MachineBasicBlock &MBB) const = 0; + virtual void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; +- ++#ifdef ARK_GC_SUPPORT ++ virtual Triple::ArchType GetArkSupportTarget() const ++ { ++ return Triple::UnknownArch; ++ } ++#endif + /// Replace a StackProbe stub (if any) with the actual probe code inline + virtual void inlineStackProbe(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} +diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp +index 3909b571728..c8b3c1c2928 100644 +--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp ++++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp +@@ -79,6 +79,8 @@ using MBBVector = SmallVector; + STATISTIC(NumLeafFuncWithSpills, "Number of leaf functions with CSRs"); + STATISTIC(NumFuncSeen, "Number of functions seen in PEI"); + ++#define JS_ENTRY_FRAME_MARK 1 ++#define JS_FRAME_MARK 0 + + namespace { + +@@ -878,6 +880,35 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { + int64_t FixedCSEnd = Offset; + unsigned MaxAlign = MFI.getMaxAlignment(); + ++ #ifdef ARK_GC_SUPPORT ++ unsigned CalleeSavedFrameSize = 0; ++ Triple::ArchType archType = TFI.GetArkSupportTarget(); ++ if (archType != Triple::UnknownArch) { ++ int slotSize = 4; ++ if (archType == Triple::aarch64) { ++ slotSize = 8; ++ } ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ CalleeSavedFrameSize = 3 * slotSize;/* frameType + threadSP */ ++ } else if (marker == JS_FRAME_MARK){ ++ CalleeSavedFrameSize = 2 * slotSize; /* frameType */ ++ } else { ++ assert("js-stub-call is illeagl ! "); ++ } ++ if (archType == Triple::aarch64) { ++ CalleeSavedFrameSize += slotSize; /* current SP */ ++ } ++ Offset += CalleeSavedFrameSize; ++ } ++ } ++ #endif ++ + // Make sure the special register scavenging spill slot is closest to the + // incoming stack pointer if a frame pointer is required and is closer + // to the incoming rather than the final stack pointer. +diff --git a/llvm/lib/CodeGen/StackMaps.cpp b/llvm/lib/CodeGen/StackMaps.cpp +index e16587c44a5..bd3e99c6600 100644 +--- a/llvm/lib/CodeGen/StackMaps.cpp ++++ b/llvm/lib/CodeGen/StackMaps.cpp +@@ -29,6 +29,9 @@ + #include "llvm/Support/ErrorHandling.h" + #include "llvm/Support/MathExtras.h" + #include "llvm/Support/raw_ostream.h" ++#ifdef ARK_GC_SUPPORT ++#include "llvm/Target/TargetMachine.h" ++#endif + #include + #include + #include +@@ -442,7 +445,11 @@ void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) { + LLVM_DEBUG(dbgs() << WSMP << "function addr: " << FR.first + << " frame size: " << FR.second.StackSize + << " callsite count: " << FR.second.RecordCount << '\n'); ++#ifdef ARK_GC_SUPPORT ++ OS.EmitSymbolValue(FR.first, AP.TM.getProgramPointerSize()); ++#else + OS.EmitSymbolValue(FR.first, 8); ++#endif + OS.EmitIntValue(FR.second.StackSize, 8); + OS.EmitIntValue(FR.second.RecordCount, 8); + } +diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +index 6da089d1859..271b4e157d9 100644 +--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp ++++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +@@ -95,6 +95,10 @@ public: + const MachineInstr &MI); + void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, + const MachineInstr &MI); ++#ifdef ARK_GC_SUPPORT ++ void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI); ++#endif + + void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); + void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); +@@ -936,6 +940,49 @@ void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, + EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0)); + } + ++#ifdef ARK_GC_SUPPORT ++void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI) { ++ StatepointOpers SOpers(&MI); ++ if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { ++ assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); ++ for (unsigned i = 0; i < PatchBytes; i += 4) ++ EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0)); ++ } else { ++ // Lower call target and choose correct opcode ++ const MachineOperand &CallTarget = SOpers.getCallTarget(); ++ MCOperand CallTargetMCOp; ++ unsigned CallOpcode; ++ switch (CallTarget.getType()) { ++ case MachineOperand::MO_GlobalAddress: ++ case MachineOperand::MO_ExternalSymbol: ++ MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp); ++ CallOpcode = AArch64::BL; ++ break; ++ case MachineOperand::MO_Immediate: ++ CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); ++ CallOpcode = AArch64::BL; ++ break; ++ case MachineOperand::MO_Register: ++ CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); ++ CallOpcode = AArch64::BLR; ++ break; ++ default: ++ llvm_unreachable("Unsupported operand type in statepoint call target"); ++ break; ++ } ++ ++ EmitToStreamer(OutStreamer, ++ MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp)); ++ } ++ ++ auto &Ctx = OutStreamer.getContext(); ++ MCSymbol *MILabel = Ctx.createTempSymbol(); ++ OutStreamer.EmitLabel(MILabel); ++ SM.recordStatepoint(*MILabel, MI); ++} ++#endif ++ + void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) { + Register DestReg = MI.getOperand(0).getReg(); + if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) { +@@ -1198,6 +1245,11 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) { + case TargetOpcode::PATCHPOINT: + return LowerPATCHPOINT(*OutStreamer, SM, *MI); + ++#ifdef ARK_GC_SUPPORT ++ case TargetOpcode::STATEPOINT: ++ return LowerSTATEPOINT(*OutStreamer, SM, *MI); ++#endif ++ + case TargetOpcode::PATCHABLE_FUNCTION_ENTER: + LowerPATCHABLE_FUNCTION_ENTER(*MI); + return; +diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +index 651ad9ad4c8..6e4a674be51 100644 +--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp ++++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +@@ -872,6 +872,13 @@ static bool IsSVECalleeSave(MachineBasicBlock::iterator I) { + } + } + ++#ifdef ARK_GC_SUPPORT ++Triple::ArchType AArch64FrameLowering::GetArkSupportTarget() const ++{ ++ return Triple::aarch64; ++} ++#endif ++ + void AArch64FrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.begin(); +diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h +index b5719feb6b1..b09aa05176d 100644 +--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h ++++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h +@@ -15,6 +15,11 @@ + + #include "AArch64StackOffset.h" + #include "llvm/CodeGen/TargetFrameLowering.h" ++#ifdef ARK_GC_SUPPORT ++#include "llvm/ADT/Triple.h" ++#endif ++ ++#define JS_ENTRY_FRAME_MARK 1 + + namespace llvm { + +@@ -35,6 +40,9 @@ public: + /// the function. + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; ++#ifdef ARK_GC_SUPPORT ++ Triple::ArchType GetArkSupportTarget() const override; ++#endif + + bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; + +diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +index 23f05eaad94..9d42a9d9af9 100644 +--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp ++++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +@@ -1498,6 +1498,9 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( + + case TargetOpcode::STACKMAP: + case TargetOpcode::PATCHPOINT: ++#ifdef ARK_GC_SUPPORT ++ case TargetOpcode::STATEPOINT: ++#endif + return emitPatchPoint(MI, BB); + + case AArch64::CATCHRET: +diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +index 54f3f7c1013..c57374c9c78 100644 +--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp ++++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +@@ -107,6 +107,15 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { + NumBytes = PatchPointOpers(&MI).getNumPatchBytes(); + assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); + break; ++#ifdef ARK_GC_SUPPORT ++ case TargetOpcode::STATEPOINT: ++ NumBytes = StatepointOpers(&MI).getNumPatchBytes(); ++ assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); ++ // No patch bytes means a normal call inst is emitted ++ if (NumBytes == 0) ++ NumBytes = 4; ++ break; ++#endif + case AArch64::TLSDESC_CALLSEQ: + // This gets lowered to an instruction sequence which takes 16 bytes + NumBytes = 16; +diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +index 14f839cd4f8..f305d3abdbf 100644 +--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp ++++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +@@ -464,8 +464,14 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + unsigned FrameReg; + + // Special handling of dbg_value, stackmap and patchpoint instructions. ++#ifdef ARK_GC_SUPPORT ++ if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || ++ MI.getOpcode() == TargetOpcode::PATCHPOINT || ++ MI.getOpcode() == TargetOpcode::STATEPOINT) { ++#else + if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || + MI.getOpcode() == TargetOpcode::PATCHPOINT) { ++#endif + StackOffset Offset = + TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, + /*PreferFP=*/true, +diff --git a/llvm/lib/Target/AArch64/AArch64StackOffset.h b/llvm/lib/Target/AArch64/AArch64StackOffset.h +index f95b5dc5246..99f5905565a 100644 +--- a/llvm/lib/Target/AArch64/AArch64StackOffset.h ++++ b/llvm/lib/Target/AArch64/AArch64StackOffset.h +@@ -37,7 +37,7 @@ namespace llvm { + class StackOffset { + int64_t Bytes; + int64_t ScalableBytes; +- ++public: + explicit operator int() const; + + public: +diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +index 4724d6b8dae..2155ad923f9 100644 +--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp ++++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +@@ -189,6 +189,12 @@ int AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, + if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) + return TTI::TCC_Free; + break; ++#ifdef ARK_GC_SUPPORT ++ case Intrinsic::experimental_gc_statepoint: ++ if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) ++ return TTI::TCC_Free; ++ break; ++#endif + } + return AArch64TTIImpl::getIntImmCost(Imm, Ty); + } +diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +index 6f26ca127f9..8db2d2c4b0b 100644 +--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp ++++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +@@ -55,7 +55,11 @@ using namespace llvm; + ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), AFI(nullptr), ++#ifdef ARK_GC_SUPPORT ++ MCP(nullptr), InConstantPool(false), OptimizationGoals(-1), SM(*this) {} ++#else + MCP(nullptr), InConstantPool(false), OptimizationGoals(-1) {} ++#endif + + void ARMAsmPrinter::EmitFunctionBodyEnd() { + // Make sure to terminate any constant pools that were at the end +@@ -567,6 +571,10 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { + OptimizationGoals = -1; + + ATS.finishAttributeSection(); ++ ++#ifdef ARK_GC_SUPPORT ++ SM.serializeToStackMapSection(); ++#endif + } + + //===----------------------------------------------------------------------===// +@@ -2135,6 +2143,14 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { + case ARM::PATCHABLE_TAIL_CALL: + LowerPATCHABLE_TAIL_CALL(*MI); + return; ++#ifdef ARK_GC_SUPPORT ++ case TargetOpcode::STACKMAP: ++ return LowerSTACKMAP(*OutStreamer, SM, *MI); ++ case TargetOpcode::PATCHPOINT: ++ return LowerPATCHPOINT(*OutStreamer, SM, *MI); ++ case TargetOpcode::STATEPOINT: ++ return LowerSTATEPOINT(*OutStreamer, SM, *MI); ++#endif + } + + MCInst TmpInst; +@@ -2143,6 +2159,75 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { + EmitToStreamer(*OutStreamer, TmpInst); + } + ++#ifdef ARK_GC_SUPPORT ++static unsigned roundUpTo4ByteAligned(unsigned n) { ++ unsigned mask = 3; ++ unsigned rev = ~3; ++ n = (n & rev) + (((n & mask) + mask) & rev); ++ return n; ++} ++ ++void ARMAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI) { ++ llvm_unreachable("Stackmap lowering is not implemented"); ++} ++ ++void ARMAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI) { ++ llvm_unreachable("Patchpoint lowering is not implemented"); ++} ++ ++void ARMAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI) { ++ assert(!AFI->isThumbFunction()); ++ ++ StatepointOpers SOpers(&MI); ++ MCInst Noop; ++ Subtarget->getInstrInfo()->getNoop(Noop); ++ if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { ++ unsigned NumBytes = roundUpTo4ByteAligned(PatchBytes); ++ unsigned EncodedBytes = 0; ++ assert(NumBytes >= EncodedBytes && ++ "Statepoint can't request size less than the length of a call."); ++ assert((NumBytes - EncodedBytes) % 4 == 0 && ++ "Invalid number of NOP bytes requested!"); ++ MCInst Noop; ++ Subtarget->getInstrInfo()->getNoop(Noop); ++ for (unsigned i = EncodedBytes; i < NumBytes; i += 4) ++ EmitToStreamer(OutStreamer, Noop); ++ } else { ++ const MachineOperand &CallTarget = SOpers.getCallTarget(); ++ MCOperand CallTargetMCOp; ++ unsigned CallOpcode; ++ switch (CallTarget.getType()) { ++ case MachineOperand::MO_GlobalAddress: ++ case MachineOperand::MO_ExternalSymbol: ++ ARMAsmPrinter::lowerOperand(CallTarget, CallTargetMCOp); ++ CallOpcode = ARM::BL; ++ break; ++ case MachineOperand::MO_Immediate: ++ CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); ++ CallOpcode = ARM::BL; ++ break; ++ case MachineOperand::MO_Register: ++ CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); ++ CallOpcode = ARM::BLX; ++ break; ++ default: ++ llvm_unreachable("Unsupported operand type in statepoint call target"); ++ break; ++ } ++ ++ EmitToStreamer(OutStreamer, ++ MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp)); ++ } ++ auto &Ctx = OutStreamer.getContext(); ++ MCSymbol *MILabel = Ctx.createTempSymbol(); ++ OutStreamer.EmitLabel(MILabel); ++ SM.recordStatepoint(*MILabel, MI); ++} ++#endif ++ + //===----------------------------------------------------------------------===// + // Target Registry Stuff + //===----------------------------------------------------------------------===// +diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h +index a4b37fa2331..be62b1875f4 100644 +--- a/llvm/lib/Target/ARM/ARMAsmPrinter.h ++++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h +@@ -11,6 +11,9 @@ + + #include "ARMSubtarget.h" + #include "llvm/CodeGen/AsmPrinter.h" ++#ifdef ARK_GC_SUPPORT ++#include "llvm/CodeGen/StackMaps.h" ++#endif + #include "llvm/Target/TargetMachine.h" + + namespace llvm { +@@ -65,6 +68,10 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { + /// debug info can link properly. + SmallPtrSet EmittedPromotedGlobalLabels; + ++#ifdef ARK_GC_SUPPORT ++ StackMaps SM; ++#endif ++ + public: + explicit ARMAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer); +@@ -129,6 +136,17 @@ private: + bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, + const MachineInstr *MI); + ++#ifdef ARK_GC_SUPPORT ++ void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI); ++ ++ void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI); ++ ++ void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, ++ const MachineInstr &MI); ++#endif ++ + public: + unsigned getISAEncoding() override { + // ARM/Darwin adds ISA to the DWARF info for each function. +diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +index 48f78151025..0970a6259ad 100644 +--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp ++++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +@@ -712,6 +712,11 @@ unsigned ARMBaseInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { + return 0; + case TargetOpcode::BUNDLE: + return getInstBundleLength(MI); ++#ifdef ARK_GC_SUPPORT ++ case TargetOpcode::PATCHPOINT: ++ case TargetOpcode::STATEPOINT: ++ return MI.getOperand(1).getImm(); ++#endif + case ARM::MOVi16_ga_pcrel: + case ARM::MOVTi16_ga_pcrel: + case ARM::t2MOVi16_ga_pcrel: +diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp +index cb98b2b34ef..b39bdf6f48e 100644 +--- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp ++++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp +@@ -353,6 +353,13 @@ static int getMaxFPOffset(const Function &F, const ARMFunctionInfo &AFI) { + return -AFI.getArgRegsSaveSize() - (8 * 4); + } + ++#ifdef ARK_GC_SUPPORT ++Triple::ArchType ARMFrameLowering::GetArkSupportTarget() const ++{ ++ return Triple::arm; ++} ++#endif ++ + void ARMFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.begin(); +@@ -967,6 +974,33 @@ ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF, + return Offset; + } + ++void ARMFrameLowering::emitPushJSInfo(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ unsigned StrOpc, unsigned MIFlags) const ++{ ++ using RegAndKill = std::pair; ++ MachineFunction &MF = *MBB.getParent(); ++ const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); ++ bool isLiveIn = true; ++ DebugLoc DL; ++ SmallVector Regs; ++ Regs.push_back(std::make_pair(ARM::R11, /*isKill=*/!isLiveIn)); ++ BuildMI(MBB, MI, DL, TII.get(StrOpc), ARM::SP) ++ .addReg(Regs[0].first, getKillRegState(Regs[0].second)) ++ .addReg(ARM::SP) ++ .setMIFlags(MIFlags) ++ .addImm(-4) ++ .add(predOps(ARMCC::AL)); ++} ++#ifdef ARK_GC_SUPPORT ++void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MI, ++ const std::vector &CSI, ++ unsigned StmOpc, unsigned StrOpc, ++ bool NoGap, ++ bool(*Func)(unsigned, bool), ++ unsigned NumAlignedDPRCS2Regs, ++ unsigned MIFlags, int multiCall) const { ++#else + void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, +@@ -975,6 +1009,7 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, + bool(*Func)(unsigned, bool), + unsigned NumAlignedDPRCS2Regs, + unsigned MIFlags) const { ++#endif + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); +@@ -1019,7 +1054,26 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, + llvm::sort(Regs, [&](const RegAndKill &LHS, const RegAndKill &RHS) { + return TRI.getEncodingValue(LHS.first) < TRI.getEncodingValue(RHS.first); + }); ++#ifdef ARK_GC_SUPPORT ++ SmallVector BeforeRegs = Regs; ++ if (multiCall != 0) { ++ Regs.clear(); ++ } ++ if (multiCall == 1) { ++ for (auto it: BeforeRegs) { ++ if (it.first == ARM::LR || it.first == ARM::R11) { ++ Regs.push_back(it); ++ } ++ } + ++ } else if (multiCall == 2) { ++ for (auto it: BeforeRegs) { ++ if ((it.first != ARM::LR) && (it.first != ARM::R11)) { ++ Regs.push_back(it); ++ } ++ } ++ } ++#endif + if (Regs.size() > 1 || StrOpc== 0) { + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP) + .addReg(ARM::SP) +@@ -1045,6 +1099,38 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, + } + } + ++void ARMFrameLowering::emitPopJSInfo(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ unsigned LdrOpc) const ++{ ++ MachineFunction &MF = *MBB.getParent(); ++ const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); ++ SmallVector Regs; ++ unsigned Reg = ARM::R11; ++ Regs.push_back(Reg); ++ DebugLoc DL; ++ MachineInstrBuilder MIB = ++ BuildMI(MBB, MI, DL, TII.get(LdrOpc), Regs[0]) ++ .addReg(ARM::SP, RegState::Define) ++ .addReg(ARM::SP); ++ // ARM mode needs an extra reg0 here due to addrmode2. Will go away once ++ // that refactoring is complete (eventually). ++ if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) { ++ MIB.addReg(0); ++ MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift)); ++ } else ++ MIB.addImm(4); ++ MIB.add(predOps(ARMCC::AL)); ++} ++ ++#ifdef ARK_GC_SUPPORT ++void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, ++ MachineBasicBlock::iterator MI, ++ std::vector &CSI, ++ unsigned LdmOpc, unsigned LdrOpc, ++ bool isVarArg, bool NoGap, ++ bool(*Func)(unsigned, bool), ++ unsigned NumAlignedDPRCS2Regs, int multiCall) const { ++#else + void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + std::vector &CSI, +@@ -1052,6 +1138,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, + bool isVarArg, bool NoGap, + bool(*Func)(unsigned, bool), + unsigned NumAlignedDPRCS2Regs) const { ++#endif + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); +@@ -1116,6 +1203,26 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, + return TRI.getEncodingValue(LHS) < TRI.getEncodingValue(RHS); + }); + ++#ifdef ARK_GC_SUPPORT ++ SmallVector BeforeRegs = Regs; ++ if (multiCall != 0) { ++ Regs.clear(); ++ } ++ if (multiCall == 1) { ++ for (auto it: BeforeRegs) { ++ if ((it != ARM::LR) && (it != ARM::R11)) { ++ Regs.push_back(it); ++ } ++ } ++ } else if (multiCall == 2) { ++ for (auto it: BeforeRegs) { ++ if ((it == ARM::LR) || (it == ARM::R11)) { ++ Regs.push_back(it); ++ } ++ } ++ } ++#endif ++ + if (Regs.size() > 1 || LdrOpc == 0) { + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP) + .addReg(ARM::SP) +@@ -1422,6 +1529,27 @@ static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, + std::prev(MI)->addRegisterKilled(ARM::R4, TRI); + } + ++#ifdef ARK_GC_SUPPORT ++int ARMFrameLowering::GetSlotForJSInfo(const MachineFunction &MF) const { ++ int reserverSlot = 0; ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ reserverSlot = 3; // 3 * slotSize;/* frameType + threadSP */ ++ } else if (marker == JS_FRAME_MARK){ ++ reserverSlot = 2; /* frameType */ ++ } else { ++ assert("js-stub-call is illeagl ! "); ++ } ++ } ++ return reserverSlot; ++} ++#endif ++ + bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, +@@ -1436,9 +1564,23 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + unsigned PushOneOpc = AFI->isThumbFunction() ? + ARM::t2STR_PRE : ARM::STR_PRE_IMM; + unsigned FltOpc = ARM::VSTMDDB_UPD; ++#ifdef ARK_GC_SUPPORT ++ DebugLoc DL; ++ const ARMBaseInstrInfo &TII = ++ *static_cast(MF.getSubtarget().getInstrInfo()); + unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs(); ++ emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, 0, ++ MachineInstr::FrameSetup, 1); ++ for (int i = 0; i < GetSlotForJSInfo(MF); i++) { ++ emitPushJSInfo(MBB, MI, PushOneOpc, MachineInstr::FrameSetup); ++ } ++ ++ emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, 0, ++ MachineInstr::FrameSetup, 2); ++#else + emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, 0, + MachineInstr::FrameSetup); ++#endif + emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register, 0, + MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register, +@@ -1477,8 +1619,20 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + NumAlignedDPRCS2Regs); + emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, + &isARMArea2Register, 0); ++#ifdef ARK_GC_SUPPORT ++ emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, ++ &isARMArea1Register, 0, 1); ++ ++ for (int i = 0; i < GetSlotForJSInfo(MF); i++) { ++ emitPopJSInfo(MBB, MI, LdrOpc); ++ } ++ ++ emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, ++ &isARMArea1Register, 0, 2); ++#else + emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, + &isARMArea1Register, 0); ++#endif + + return true; + } +@@ -1573,7 +1727,7 @@ static unsigned estimateRSStackSizeLimit(MachineFunction &MF, + Limit = std::min(Limit, ((1U << 7) - 1) * 4); + break; + default: +- llvm_unreachable("Unhandled addressing mode in stack size limit calculation"); ++ break; + } + break; // At most one FI per instruction + } +diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.h b/llvm/lib/Target/ARM/ARMFrameLowering.h +index 0462b01af70..c410326f432 100644 +--- a/llvm/lib/Target/ARM/ARMFrameLowering.h ++++ b/llvm/lib/Target/ARM/ARMFrameLowering.h +@@ -13,6 +13,9 @@ + #include "llvm/CodeGen/TargetFrameLowering.h" + #include + ++#define JS_ENTRY_FRAME_MARK 1 ++#define JS_FRAME_MARK 0 ++ + namespace llvm { + + class ARMSubtarget; +@@ -30,6 +33,9 @@ public: + /// the function. + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; ++#ifdef ARK_GC_SUPPORT ++ Triple::ArchType GetArkSupportTarget() const override; ++#endif + + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, +@@ -72,6 +78,24 @@ public: + } + + private: ++ ++#ifdef ARK_GC_SUPPORT ++ void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ const std::vector &CSI, unsigned StmOpc, ++ unsigned StrOpc, bool NoGap, ++ bool(*Func)(unsigned, bool), unsigned NumAlignedDPRCS2Regs, ++ unsigned MIFlags = 0, int multiCall = 0) const; ++ void emitPushJSInfo(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ unsigned StrOpc, unsigned MIFlags) const; ++ void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ std::vector &CSI, unsigned LdmOpc, ++ unsigned LdrOpc, bool isVarArg, bool NoGap, ++ bool(*Func)(unsigned, bool), ++ unsigned NumAlignedDPRCS2Regs, int multiCall = 0) const; ++ void emitPopJSInfo(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ++ unsigned LdrOpc) const; ++ int GetSlotForJSInfo(const MachineFunction &MF) const; ++#else + void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, unsigned StmOpc, + unsigned StrOpc, bool NoGap, +@@ -82,7 +106,7 @@ private: + unsigned LdrOpc, bool isVarArg, bool NoGap, + bool(*Func)(unsigned, bool), + unsigned NumAlignedDPRCS2Regs) const; +- ++#endif + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, +diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp +index 9f504b1eaa4..cf2f5f50b14 100644 +--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp ++++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp +@@ -10551,6 +10551,13 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, + llvm_unreachable("Unexpected instr type to insert"); + } + ++#ifdef ARK_GC_SUPPORT ++ case TargetOpcode::STATEPOINT: ++ case TargetOpcode::STACKMAP: ++ case TargetOpcode::PATCHPOINT: ++ return emitPatchPoint(MI, BB); ++#endif ++ + // Thumb1 post-indexed loads are really just single-register LDMs. + case ARM::tLDR_postidx: { + MachineOperand Def(MI.getOperand(1)); +diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp +index 1da20371caf..a73d3cd8053 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.cpp ++++ b/llvm/lib/Target/X86/X86FrameLowering.cpp +@@ -1168,6 +1168,25 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, + else + MFI.setOffsetAdjustment(-StackSize); + } ++#ifdef ARK_GC_SUPPORT ++ // push marker ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) ++ .addImm(marker) ++ .setMIFlag(MachineInstr::FrameSetup); ++ } ++ } ++#endif + + // For EH funclets, only allocate enough space for outgoing calls. Save the + // NumBytes value that we would've used for the parent frame. +@@ -1635,6 +1654,27 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, + uint64_t SEHStackAllocAmt = NumBytes; + + if (HasFP) { ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) ++ { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ ++ // pop marker ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ // pop thread.fp ++ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), ++ MachineFramePtr) ++ .setMIFlag(MachineInstr::FrameDestroy); ++ } ++ } ++#endif + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) +@@ -1993,8 +2033,33 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( + + if (hasFP(MF)) { + // emitPrologue always spills frame register the first thing. ++#ifdef ARK_GC_SUPPORT ++ if (MF.getFunction().hasFnAttribute("js-stub-call")) { ++ int64_t marker = 0x0; ++ MF.getFunction() ++ .getFnAttribute("js-stub-call") ++ .getValueAsString() ++ .getAsInteger(10, marker);//marker 1 break frame ++ if (marker == JS_ENTRY_FRAME_MARK) { ++ SpillSlotOffset -= 3 * SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += (2 * SlotSize); ++ } else { ++ SpillSlotOffset -= 2 * SlotSize; // add type ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ CalleeSavedFrameSize += SlotSize; ++ } ++ } else { ++ SpillSlotOffset -= SlotSize; // add type and thread.fp ++ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++ } ++#else + SpillSlotOffset -= SlotSize; + MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); ++#endif + + // Since emitPrologue and emitEpilogue will handle spilling and restoring of + // the frame register, we can delete it from CSI list and not have to worry +diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h +index 2103d6471ea..3fd89b0d9ee 100644 +--- a/llvm/lib/Target/X86/X86FrameLowering.h ++++ b/llvm/lib/Target/X86/X86FrameLowering.h +@@ -15,6 +15,8 @@ + + #include "llvm/CodeGen/TargetFrameLowering.h" + ++#define JS_ENTRY_FRAME_MARK 1 ++ + namespace llvm { + + class MachineInstrBuilder; diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index df7c4527..4485161f 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -14,9 +14,14 @@ */ #include "llvm_stackmap_parser.h" -#include + #include +#include #include +#include "ecmascript/compiler/compiler_macros.h" +#include "ecmascript/frames.h" +#include "ecmascript/mem/heap_roots.h" +#include "ecmascript/mem/slots.h" namespace kungfu { std::string LocationTy::TypeToString(Kind loc) const @@ -37,51 +42,80 @@ std::string LocationTy::TypeToString(Kind loc) const } } -bool LLVMStackMapParser::StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos) +const DwarfRegAndOffsetTypeVector* LLVMStackMapParser::StackMapByAddr(uintptr_t callSiteAddr) const { - bool found = false; - for (auto it: callSiteInfos_) { -#ifndef NDEBUG - LOG_ECMA(INFO) << __FUNCTION__ << std::hex << " addr:" << it.first << std::endl; -#endif - if (it.first == funcAddr) { - DwarfRegAndOffsetType info = it.second; -#ifndef NDEBUG - LOG_ECMA(INFO) << __FUNCTION__ << " info <" << info.first << " ," << info.second << " >" << std::endl; -#endif - infos.push_back(info); - found = true; - } + auto it = callSiteInfos_.find(callSiteAddr); + if (it != callSiteInfos_.end()) { + return &(it->second); } - return found; + return nullptr; } -bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, - std::set &slotAddrs) +bool LLVMStackMapParser::StackMapByFuncAddrFp(uintptr_t callSiteAddr, uintptr_t frameFp, + const RootVisitor &v0, const RootRangeVisitor &v1, + panda::ecmascript::ChunkVector *data, + [[maybe_unused]] bool isVerifying) const { - DwarfRegAndOffsetTypeVector infos; - if (!StackMapByAddr(funcAddr, infos)) { + const DwarfRegAndOffsetTypeVector *infos = StackMapByAddr(callSiteAddr); + if (infos == nullptr) { return false; } uintptr_t *fp = reinterpret_cast(frameFp); - uintptr_t **address = nullptr; - for (auto &info: infos) { - if (info.first == SP_DWARF_REG_NUM) { - uintptr_t *rsp = fp + SP_OFFSET; - address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - } else if (info.first == FP_DWARF_REG_NUM) { - fp = reinterpret_cast(*fp); - address = reinterpret_cast(reinterpret_cast(fp) + info.second); + uintptr_t address = 0; + uintptr_t base = 0; + uintptr_t derived = 0; + int i = 0; + for (auto &info: *infos) { + if (info.first == panda::ecmascript::FrameConst::SP_DWARF_REG_NUM) { +#ifdef PANDA_TARGET_ARM64 + uintptr_t *curFp = reinterpret_cast(*fp); + uintptr_t *rsp = reinterpret_cast(*(curFp + panda::ecmascript::FrameConst::SP_OFFSET)); +#else + uintptr_t *rsp = fp + panda::ecmascript::FrameConst::SP_OFFSET; +#endif + address = reinterpret_cast(rsp) + info.second; +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << "SP_DWARF_REG_NUM: info.second:" << info.second << " rbp offset:" << + reinterpret_cast(*fp) - address << "rsp :" << rsp; +#endif + } else if (info.first == panda::ecmascript::FrameConst::FP_DWARF_REG_NUM) { + uintptr_t tmpFp = *fp; + address = tmpFp + info.second; +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << "FP_DWARF_REG_NUM: info.second:" << info.second; +#endif } else { - address = nullptr; +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << "REG_NUM : info.first:" << info.first; +#endif abort(); } -#ifndef NDEBUG - LOG_ECMA(INFO) << std::hex << "stackMap ref addr:" << address; - LOG_ECMA(INFO) << " value:" << *address; - LOG_ECMA(INFO) << " *value :" << **address << std::endl; + + if (i & 0x1) { + derived = reinterpret_cast(address); + if (base == derived) { +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << std::hex << "visit base:" << base << " base Value: " << + *reinterpret_cast(base); #endif - slotAddrs.insert(reinterpret_cast(address)); + v0(panda::ecmascript::Root::ROOT_FRAME, panda::ecmascript::ObjectSlot(base)); + } else { +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << std::hex << "push base:" << base << " base Value: " << + *reinterpret_cast(base) << " derived:" << derived; +#endif +#if ECMASCRIPT_ENABLE_HEAP_VERIFY + if (!isVerifying) { +#endif + data->emplace_back(std::make_tuple(base, *reinterpret_cast(base), derived)); +#if ECMASCRIPT_ENABLE_HEAP_VERIFY + } +#endif + } + } else { + base = reinterpret_cast(address); + } + i++; } return true; } @@ -96,9 +130,18 @@ void LLVMStackMapParser::CalcCallSite() uint32_t instructionOffset = recordHead.InstructionOffset; uintptr_t callsite = address + instructionOffset; if (loc.location == LocationTy::Kind::INDIRECT) { +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << "DwarfRegNum:" << loc.DwarfRegNum << " loc.OffsetOrSmallConstant:" << + loc.OffsetOrSmallConstant << "address:" << address << " instructionOffset:" << + instructionOffset << " callsite:" << callsite; +#endif DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant); - Fun2InfoType callSiteInfo {callsite, info}; - callSiteInfos_.push_back(callSiteInfo); + auto it = callSiteInfos_.find(callsite); + if (callSiteInfos_.find(callsite) == callSiteInfos_.end()) { + callSiteInfos_.insert(std::pair(callsite, {info})); + } else { + it->second.emplace_back(info); + } } } }; @@ -112,14 +155,14 @@ void LLVMStackMapParser::CalcCallSite() } } -bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) +bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr stackMapAddr) { - stackMapAddr_ = stackMapAddr; + stackMapAddr_ = std::move(stackMapAddr); if (!stackMapAddr_) { LOG_ECMA(ERROR) << "stackMapAddr_ nullptr error ! " << std::endl; return false; } - dataInfo_ = std::make_unique(stackMapAddr_); + dataInfo_ = std::make_unique(std::move(stackMapAddr_)); llvmStackMap_.head = dataInfo_->Read(); uint32_t numFunctions, numConstants, numRecords; numFunctions = dataInfo_->Read(); @@ -161,24 +204,23 @@ bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr) return true; } -bool LLVMStackMapParser::CalculateStackMap(const uint8_t *stackMapAddr, +bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr stackMapAddr, uintptr_t hostCodeSectionAddr, uintptr_t deviceCodeSectionAddr) { - bool ret = CalculateStackMap(stackMapAddr); + bool ret = CalculateStackMap(std::move(stackMapAddr)); if (!ret) { return ret; } // update functionAddress from host side to device side -#ifndef NDEBUG - LOG_ECMA(INFO) << "stackmap calculate update funcitonaddress " << std::endl; +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << "stackmap calculate update funcitonaddress "; #endif for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) { uintptr_t hostAddr = llvmStackMap_.StkSizeRecords[i].functionAddress; uintptr_t deviceAddr = hostAddr - hostCodeSectionAddr + deviceCodeSectionAddr; llvmStackMap_.StkSizeRecords[i].functionAddress = deviceAddr; -#ifndef NDEBUG - LOG_ECMA(INFO) << std::dec << i << "th function " << std::hex << hostAddr << " ---> " << deviceAddr - << std::endl; +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LOG_ECMA(DEBUG) << std::dec << i << "th function " << std::hex << hostAddr << " ---> " << deviceAddr; #endif } callSiteInfos_.clear(); diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h index 37b4afb4..99dfacca 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -1,230 +1,230 @@ -/* - * Copyright (c) 2021 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. - */ - -#ifndef ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H -#define ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H - -#include -#include -#include -#include -#include "ecmascript/common.h" -#include "ecmascript/ecma_macros.h" - -#ifdef PANDA_TARGET_AMD64 -#define SP_DWARF_REG_NUM 7 -#define FP_DWARF_REG_NUM 6 -#define SP_OFFSET 2 -#else -#define SP_DWARF_REG_NUM 0 -#define FP_DWARF_REG_NUM 0 -#define SP_OFFSET 0 -#endif - -namespace kungfu { -using OffsetType = int32_t; -using DwarfRegType = uint16_t; -using DwarfRegAndOffsetType = std::pair; -using DwarfRegAndOffsetTypeVector = std::vector; -using Fun2InfoType = std::pair; - -struct Header { - uint8_t stackmapversion; // Stack Map Version (current version is 3) - uint8_t Reserved0; // Reserved (expected to be 0) - uint16_t Reserved1; // Reserved (expected to be 0) - void Print() const - { - LOG_ECMA(INFO) << "----- head ----" << std::endl; - LOG_ECMA(INFO) << " version:" << static_cast(stackmapversion) << std::endl; - LOG_ECMA(INFO) << "+++++ head ++++" << std::endl; - } -}; - -struct StkSizeRecordTy { - uint64_t functionAddress; - uint64_t stackSize; - uint64_t recordCount; - void Print() const - { - LOG_ECMA(INFO) << " functionAddress:0x" << std::hex << functionAddress << std::endl; - LOG_ECMA(INFO) << " stackSize:" << std::dec << stackSize << std::endl; - LOG_ECMA(INFO) << " recordCount:" << std::dec << recordCount << std::endl; - } -}; - -struct ConstantsTy { - uint64_t LargeConstant; - void Print() const - { - LOG_ECMA(INFO) << " LargeConstant:" << LargeConstant << std::endl; - } -}; - -struct StkMapRecordHeadTy { - uint64_t PatchPointID; - uint32_t InstructionOffset; - uint16_t Reserved; - uint16_t NumLocations; - void Print() const - { - LOG_ECMA(INFO) << " PatchPointID:" << std::hex << PatchPointID << std::endl; - LOG_ECMA(INFO) << " instructionOffset:" << std::hex << InstructionOffset << std::endl; - LOG_ECMA(INFO) << " Reserved:" << Reserved << std::endl; - LOG_ECMA(INFO) << " NumLocations:" << NumLocations << std::endl; - } -}; - -struct LocationTy { - enum class Kind: uint8_t { - REGISTER = 1, - DIRECT = 2, - INDIRECT = 3, - CONSTANT = 4, - CONSTANTNDEX = 5, - }; - Kind location; - uint8_t Reserved_0; - uint16_t LocationSize; - uint16_t DwarfRegNum; - uint16_t Reserved_1; - OffsetType OffsetOrSmallConstant; - - std::string PUBLIC_API TypeToString(Kind loc) const; - - void Print() const - { - LOG_ECMA(INFO) << TypeToString(location); - LOG_ECMA(INFO) << ", size:" << std::dec << LocationSize; - LOG_ECMA(INFO) << "\tDwarfRegNum:" << DwarfRegNum; - LOG_ECMA(INFO) << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant << std::endl; - } -}; - -struct LiveOutsTy { - DwarfRegType DwarfRegNum; - uint8_t Reserved; - uint8_t SizeinBytes; - void Print() const - { - LOG_ECMA(INFO) << " Dwarf RegNum:" << DwarfRegNum << std::endl; - LOG_ECMA(INFO) << " Reserved:" << Reserved << std::endl; - LOG_ECMA(INFO) << " SizeinBytes:" << SizeinBytes << std::endl; - } -}; - -struct StkMapRecordTy { - struct StkMapRecordHeadTy head; - std::vector Locations; - std::vector LiveOuts; - void Print() const - { - head.Print(); - auto size = Locations.size(); - for (size_t i = 0; i < size; i++) { - LOG_ECMA(INFO) << " #" << std::dec << i << ":"; - Locations[i].Print(); - } - size = LiveOuts.size(); - for (size_t i = 0; i < size; i++) { - LOG_ECMA(INFO) << " liveOuts[" << i << "] info:" << std::endl; - } - } -}; - -class DataInfo { -public: - explicit DataInfo(const uint8_t *data): data_(data), offset_(0) {} - ~DataInfo() - { - data_ = nullptr; - offset_ = 0; - } - template - T Read() - { - T t = *reinterpret_cast(data_ + offset_); - offset_ += sizeof(T); - return t; - } - unsigned int GetOffset() const - { - return offset_; - } -private: - const uint8_t *data_; - unsigned int offset_; -}; - -struct LLVMStackMap { - struct Header head; - std::vector StkSizeRecords; - std::vector Constants; - std::vector StkMapRecord; - void Print() const - { - head.Print(); - for (size_t i = 0; i < StkSizeRecords.size(); i++) { - LOG_ECMA(INFO) << "stkSizeRecord[" << i << "] info:" << std::endl; - StkSizeRecords[i].Print(); - } - for (size_t i = 0; i < Constants.size(); i++) { - LOG_ECMA(INFO) << "constants[" << i << "] info:" << std::endl; - Constants[i].Print(); - } - for (size_t i = 0; i < StkMapRecord.size(); i++) { - LOG_ECMA(INFO) << "StkMapRecord[" << i << "] info:" << std::endl; - StkMapRecord[i].Print(); - } - } -}; - -class LLVMStackMapParser { -public: - static LLVMStackMapParser& GetInstance() - { - static LLVMStackMapParser instance; - return instance; - } - bool PUBLIC_API CalculateStackMap(const uint8_t *stackMapAddr); - bool PUBLIC_API CalculateStackMap(const uint8_t *stackMapAddr, - uintptr_t hostCodeSectionAddr, uintptr_t deviceCodeSectionAddr); - void PUBLIC_API Print() const - { - llvmStackMap_.Print(); - } - bool StackMapByAddr(uintptr_t funcAddr, DwarfRegAndOffsetTypeVector &infos); - bool StackMapByFuncAddrFp(uintptr_t funcAddr, uintptr_t frameFp, - std::set &slotAddrs); -private: - LLVMStackMapParser() - { - stackMapAddr_ = nullptr; - callSiteInfos_.clear(); - dataInfo_ = nullptr; - } - ~LLVMStackMapParser() - { - stackMapAddr_ = nullptr; - callSiteInfos_.clear(); - dataInfo_ = nullptr; - } - void CalcCallSite(); - const uint8_t *stackMapAddr_; - struct LLVMStackMap llvmStackMap_; - std::vector callSiteInfos_; - [[maybe_unused]] std::unique_ptr dataInfo_; -}; -} // namespace kungfu +/* + * Copyright (c) 2021 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. + */ + +#ifndef ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H +#define ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H + +#include +#include +#include +#include +#include +#include "ecmascript/common.h" +#include "ecmascript/ecma_macros.h" + + +namespace kungfu { +using OffsetType = int32_t; +using DwarfRegType = uint16_t; +using DwarfRegAndOffsetType = std::pair; +using DwarfRegAndOffsetTypeVector = std::vector; +using Fun2InfoType = std::pair; +using DerivedData = panda::ecmascript::DerivedData; +using RootVisitor = panda::ecmascript::RootVisitor; +using RootRangeVisitor = panda::ecmascript::RootRangeVisitor; + +struct Header { + uint8_t stackmapversion; // Stack Map Version (current version is 3) + uint8_t Reserved0; // Reserved (expected to be 0) + uint16_t Reserved1; // Reserved (expected to be 0) + void Print() const + { + LOG_ECMA(DEBUG) << "----- head ----"; + LOG_ECMA(DEBUG) << " version:" << static_cast(stackmapversion); + LOG_ECMA(DEBUG) << "+++++ head ++++"; + } +}; + +#pragma pack(1) +struct StkSizeRecordTy { + uintptr_t functionAddress; + uint64_t stackSize; + uint64_t recordCount; + void Print() const + { + LOG_ECMA(DEBUG) << " functionAddress:0x" << std::hex << functionAddress; + LOG_ECMA(DEBUG) << " stackSize:0x" << std::hex << stackSize; + LOG_ECMA(DEBUG) << " recordCount:" << std::hex << recordCount; + } +}; +#pragma pack() + +struct ConstantsTy { + uintptr_t LargeConstant; + void Print() const + { + LOG_ECMA(DEBUG) << " LargeConstant:0x" << std::hex << LargeConstant; + } +}; + +struct StkMapRecordHeadTy { + uint64_t PatchPointID; + uint32_t InstructionOffset; + uint16_t Reserved; + uint16_t NumLocations; + void Print() const + { + LOG_ECMA(DEBUG) << " PatchPointID:0x" << std::hex << PatchPointID; + LOG_ECMA(DEBUG) << " instructionOffset:0x" << std::hex << InstructionOffset; + LOG_ECMA(DEBUG) << " Reserved:0x" << std::hex << Reserved; + LOG_ECMA(DEBUG) << " NumLocations:0x" << std::hex << NumLocations; + } +}; + +struct LocationTy { + enum class Kind: uint8_t { + REGISTER = 1, + DIRECT = 2, + INDIRECT = 3, + CONSTANT = 4, + CONSTANTNDEX = 5, + }; + Kind location; + uint8_t Reserved_0; + uint16_t LocationSize; + uint16_t DwarfRegNum; + uint16_t Reserved_1; + OffsetType OffsetOrSmallConstant; + + std::string PUBLIC_API TypeToString(Kind loc) const; + + void Print() const + { + LOG_ECMA(DEBUG) << TypeToString(location); + LOG_ECMA(DEBUG) << ", size:" << std::dec << LocationSize; + LOG_ECMA(DEBUG) << "\tDwarfRegNum:" << DwarfRegNum; + LOG_ECMA(DEBUG) << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant; + } +}; + +struct LiveOutsTy { + DwarfRegType DwarfRegNum; + uint8_t Reserved; + uint8_t SizeinBytes; + void Print() const + { + LOG_ECMA(DEBUG) << " Dwarf RegNum:" << DwarfRegNum; + LOG_ECMA(DEBUG) << " Reserved:" << Reserved; + LOG_ECMA(DEBUG) << " SizeinBytes:" << SizeinBytes; + } +}; + +struct StkMapRecordTy { + struct StkMapRecordHeadTy head; + std::vector Locations; + std::vector LiveOuts; + void Print() const + { + head.Print(); + auto size = Locations.size(); + for (size_t i = 0; i < size; i++) { + LOG_ECMA(DEBUG) << " #" << std::dec << i << ":"; + Locations[i].Print(); + } + size = LiveOuts.size(); + for (size_t i = 0; i < size; i++) { + LOG_ECMA(DEBUG) << " liveOuts[" << i << "] info:"; + } + } +}; + +class DataInfo { +public: + explicit DataInfo(std::unique_ptr data): data_(std::move(data)), offset_(0) {} + ~DataInfo() + { + data_.reset(); + offset_ = 0; + } + template + T Read() + { + T t = *reinterpret_cast(data_.get() + offset_); + offset_ += sizeof(T); + return t; + } + unsigned int GetOffset() const + { + return offset_; + } +private: + std::unique_ptr data_ {nullptr}; + unsigned int offset_ {0}; +}; + +struct LLVMStackMap { + struct Header head; + std::vector StkSizeRecords; + std::vector Constants; + std::vector StkMapRecord; + void Print() const + { + head.Print(); + for (size_t i = 0; i < StkSizeRecords.size(); i++) { + LOG_ECMA(DEBUG) << "stkSizeRecord[" << i << "] info:"; + StkSizeRecords[i].Print(); + } + for (size_t i = 0; i < Constants.size(); i++) { + LOG_ECMA(DEBUG) << "constants[" << i << "] info:"; + Constants[i].Print(); + } + for (size_t i = 0; i < StkMapRecord.size(); i++) { + LOG_ECMA(DEBUG) << "StkMapRecord[" << i << "] info:"; + StkMapRecord[i].Print(); + } + } +}; + +class LLVMStackMapParser { +public: + static LLVMStackMapParser& GetInstance() + { + static LLVMStackMapParser instance; + return instance; + } + bool PUBLIC_API CalculateStackMap(std::unique_ptr stackMapAddr); + bool PUBLIC_API CalculateStackMap(std::unique_ptr stackMapAddr, + uintptr_t hostCodeSectionAddr, uintptr_t deviceCodeSectionAddr); + void PUBLIC_API Print() const + { + llvmStackMap_.Print(); + } + const DwarfRegAndOffsetTypeVector *StackMapByAddr(uintptr_t funcAddr) const; + bool StackMapByFuncAddrFp(uintptr_t callSiteAddr, uintptr_t frameFp, const RootVisitor &v0, + const RootRangeVisitor &v1, panda::ecmascript::ChunkVector *data, + [[maybe_unused]] bool isVerifying) const; +private: + LLVMStackMapParser() + { + stackMapAddr_ = nullptr; + callSiteInfos_.clear(); + dataInfo_ = nullptr; + } + ~LLVMStackMapParser() + { + if (stackMapAddr_) { + stackMapAddr_.release(); + } + callSiteInfos_.clear(); + dataInfo_ = nullptr; + } + void CalcCallSite(); + std::unique_ptr stackMapAddr_; + struct LLVMStackMap llvmStackMap_; + std::unordered_map callSiteInfos_; + [[maybe_unused]] std::unique_ptr dataInfo_; +}; +} // namespace kungfu #endif // ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H \ No newline at end of file diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index 18c787cc..22f7e8ef 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -1,277 +1,320 @@ -/* - * Copyright (c) 2021 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. - */ - -#include "llvm_codegen.h" -#include -#include "ecmascript/object_factory.h" -#include "stub_descriptor.h" -#include "ecmascript/ecma_macros.h" -#include "llvm/ADT/APInt.h" -#include "llvm/CodeGen/BuiltinGCs.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/IR/Argument.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Verifier.h" -#include "llvm/IRReader/IRReader.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/llvm_stackmap_parser.h" -#include "llvm-c/Analysis.h" -#include "llvm-c/Core.h" -#include "llvm-c/Disassembler.h" -#include "llvm-c/DisassemblerTypes.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm-c/Transforms/Scalar.h" - -using namespace panda::ecmascript; -namespace kungfu { -void LLVMCodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) -{ - auto function = module_->GetStubFunction(index); - - LLVMIRBuilder builder(&graph, circuit, module_, function); - builder.Build(); -} - -void LLVMModuleAssembler::AssembleModule() -{ - assembler_.Run(); -} - -void LLVMModuleAssembler::AssembleStubModule(StubModule *module) -{ - auto codeBuff = reinterpret_cast(assembler_.GetCodeBuffer()); - auto engine = assembler_.GetEngine(); - std::map addr2name; - for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { - auto stubfunction = stubmodule_->GetStubFunction(i); -#ifndef NDEBUG - LOG_ECMA(INFO) << " AssembleStubModule :" << i << " th " << std::endl; -#endif - if (stubfunction != nullptr) { - uintptr_t stubEntry = reinterpret_cast(LLVMGetPointerToGlobal(engine, stubfunction)); - module->SetStubEntry(i, stubEntry - codeBuff); - addr2name[stubEntry] = FastStubDescriptors::GetInstance().GetStubDescriptor(i)->GetName(); -#ifndef NDEBUG - LOG_ECMA(INFO) << "name : " << addr2name[codeBuff] << std::endl; -#endif - } - } - module->SetHostCodeSectionAddr(codeBuff); - // stackmaps ptr and size - module->SetStackMapAddr(reinterpret_cast(assembler_.GetStackMapsSection())); - module->SetStackMapSize(assembler_.GetStackMapsSize()); -#ifndef NDEBUG - assembler_.Disassemble(addr2name); -#endif -} - -static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, - [[maybe_unused]] unsigned sectionID, const char *sectionName) -{ - LOG_ECMA(INFO) << "RoundTripAllocateCodeSection object " << object << " - "; - struct CodeInfo& state = *static_cast(object); - uint8_t *addr = state.AllocaCodeSection(size, sectionName); - LOG_ECMA(INFO) << "RoundTripAllocateCodeSection addr:" << std::hex << reinterpret_cast(addr) << - addr << " size:0x" << size << " + "; - return addr; -} - -static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, - [[maybe_unused]] unsigned sectionID, const char *sectionName, - [[maybe_unused]] LLVMBool isReadOnly) -{ - struct CodeInfo& state = *static_cast(object); - return state.AllocaDataSection(size, sectionName); -} - -static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **errMsg) -{ - LOG_ECMA(INFO) << "RoundTripFinalizeMemory object " << object << " - "; - return 0; -} - -static void RoundTripDestroy(void *object) -{ - LOG_ECMA(INFO) << "RoundTripDestroy object " << object << " - "; -} - -void LLVMAssembler::UseRoundTripSectionMemoryManager() -{ - auto sectionMemoryManager = std::make_unique(); - options_.MCJMM = - LLVMCreateSimpleMCJITMemoryManager(&codeInfo_, RoundTripAllocateCodeSection, - RoundTripAllocateDataSection, RoundTripFinalizeMemory, RoundTripDestroy); -} - -bool LLVMAssembler::BuildMCJITEngine() -{ - LOG_ECMA(INFO) << " BuildMCJITEngine - "; - LLVMBool ret = LLVMCreateMCJITCompilerForModule(&engine_, module_, &options_, sizeof(options_), &error_); - if (ret) { - LOG_ECMA(ERROR) << "error_ : " << error_; - return false; - } - LOG_ECMA(INFO) << " BuildMCJITEngine + "; - return true; -} - -void LLVMAssembler::BuildAndRunPasses() const -{ - LOG_ECMA(INFO) << "BuildAndRunPasses - "; - LLVMPassManagerRef pm = LLVMCreatePassManager(); - LLVMAddConstantPropagationPass(pm); - LLVMAddInstructionCombiningPass(pm); - llvm::unwrap(pm)->add(llvm::createRewriteStatepointsForGCLegacyPass()); -#ifndef NDEBUG - char *info = LLVMPrintModuleToString(module_); - LOG_ECMA(INFO) << "Current Module: " << info; - LLVMDumpModule(module_); - LLVMDisposeMessage(info); -#endif - LLVMRunPassManager(pm, module_); - LLVMDisposePassManager(pm); - LOG_ECMA(INFO) << "BuildAndRunPasses + "; -} - -LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple): module_(module), engine_(nullptr), - hostTriple_(triple), error_(nullptr) -{ - Initialize(); -} - -LLVMAssembler::~LLVMAssembler() -{ - module_ = nullptr; - if (engine_ != nullptr) { - LLVMDisposeExecutionEngine(engine_); - } - hostTriple_ = ""; - error_ = nullptr; -} - -void LLVMAssembler::Run() -{ - char *error = nullptr; - LLVMVerifyModule(module_, LLVMAbortProcessAction, &error); - LLVMDisposeMessage(error); - UseRoundTripSectionMemoryManager(); - if (!BuildMCJITEngine()) { - return; - } - BuildAndRunPasses(); -} - -void LLVMAssembler::Initialize() -{ - if (hostTriple_.compare(AMD64_TRIPLE) == 0) { - LLVMInitializeX86TargetInfo(); - LLVMInitializeX86TargetMC(); - LLVMInitializeX86Disassembler(); - /* this method must be called, ohterwise "Target does not support MC emission" */ - LLVMInitializeX86AsmPrinter(); - LLVMInitializeX86AsmParser(); - LLVMInitializeX86Target(); - } else if (hostTriple_.compare(ARM64_TRIPLE) == 0) { - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAArch64Disassembler(); - LLVMInitializeAArch64AsmPrinter(); - LLVMInitializeAArch64AsmParser(); - LLVMInitializeAArch64Target(); - } else if (hostTriple_.compare(ARM32_TRIPLE) == 0) { - LLVMInitializeARMTargetInfo(); - LLVMInitializeARMTargetMC(); - LLVMInitializeARMDisassembler(); - LLVMInitializeARMAsmPrinter(); - LLVMInitializeARMAsmParser(); - LLVMInitializeARMTarget(); - } else { - UNREACHABLE(); - } - llvm::linkAllBuiltinGCs(); - LLVMInitializeMCJITCompilerOptions(&options_, sizeof(options_)); - options_.OptLevel = 2; // opt level 2 - // Just ensure that this field still exists. - options_.NoFramePointerElim = true; -} - -static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue, - uint64_t *referenceType, [[maybe_unused]]uint64_t referencePC, - [[maybe_unused]] const char **referenceName) -{ - *referenceType = LLVMDisassembler_ReferenceType_InOut_None; - return nullptr; -} - -void LLVMAssembler::Disassemble(std::map addr2name) const -{ - LLVMDisasmContextRef dcr = LLVMCreateDisasm(hostTriple_.c_str(), nullptr, 0, nullptr, SymbolLookupCallback); - std::cout << "========================================================================" << std::endl; - for (auto it : codeInfo_.GetCodeInfo()) { - uint8_t *byteSp; - uintptr_t numBytes; - byteSp = it.first; - numBytes = it.second; - std::cout << " byteSp:" << std::hex << reinterpret_cast(byteSp) << " numBytes:0x" << numBytes - << std::endl; - - unsigned pc = 0; - const char outStringSize = 100; - char outString[outStringSize]; - while (numBytes != 0) { - size_t InstSize = LLVMDisasmInstruction(dcr, byteSp, numBytes, pc, outString, outStringSize); - if (InstSize == 0) { - std::cerr.fill('0'); - std::cerr.width(8); // 8: fixed hex print width - std::cerr << std::hex << pc << ":"; - std::cerr.width(8); // 8: fixed hex print width - std::cerr << std::hex << *reinterpret_cast(byteSp) << "maybe constant" << std::endl; - pc += 4; // 4 pc length - byteSp += 4; // 4 sp offset - numBytes -= 4; // 4 num bytes - } - uint64_t addr = reinterpret_cast(byteSp); - if (addr2name.find(addr) != addr2name.end()) { - std::cout << addr2name[addr].c_str() << ":" << std::endl; - } - std::cerr.fill('0'); - std::cerr.width(8); // 8: fixed hex print width - std::cerr << std::hex << pc << ":"; - std::cerr.width(8); // 8: fixed hex print width - std::cerr << std::hex << *reinterpret_cast(byteSp) << " " << outString << std::endl; - pc += InstSize; - byteSp += InstSize; - numBytes -= InstSize; - } - } - std::cout << "========================================================================" << std::endl; - LLVMDisasmDispose(dcr); -} -} // namespace kungfu +/* + * Copyright (c) 2021 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. + */ + +#include "llvm_codegen.h" +#include +#include +#include "ecmascript/compiler/compiler_macros.h" +#include "ecmascript/compiler/triple.h" +#include "ecmascript/ecma_macros.h" +#include "ecmascript/object_factory.h" +#include "llvm-c/Analysis.h" +#include "llvm-c/Core.h" +#include "llvm-c/Disassembler.h" +#include "llvm-c/DisassemblerTypes.h" +#include "llvm-c/Target.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" +#include "llvm-c/Transforms/Scalar.h" +#include "llvm/ADT/APInt.h" +#include "llvm/CodeGen/BuiltinGCs.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/llvm_stackmap_parser.h" +#include "stub_descriptor.h" + +using namespace panda::ecmascript; +namespace kungfu { +void LLVMCodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) +{ + auto function = module_->GetStubFunction(index); + + LLVMIRBuilder builder(&graph, circuit, module_, function, TripleConst::GetLLVMAmd64Triple()); + builder.Build(); +} + +void LLVMAarch64CodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) +{ + auto function = module_->GetStubFunction(index); + + LLVMIRBuilder builder(&graph, circuit, module_, function, TripleConst::GetLLVMArm64Triple()); + builder.Build(); +} + +void LLVMArm32CodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) +{ + auto function = module_->GetStubFunction(index); + + LLVMIRBuilder builder(&graph, circuit, module_, function, TripleConst::GetLLVMArm32Triple()); + builder.Build(); +} + +void LLVMModuleAssembler::AssembleModule() +{ + assembler_.Run(); +} + +void LLVMModuleAssembler::AssembleStubModule(StubModule *module) +{ + auto codeBuff = reinterpret_cast(assembler_.GetCodeBuffer()); + auto engine = assembler_.GetEngine(); + std::map addr2name; + for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + auto stubfunction = stubmodule_->GetStubFunction(i); +#ifndef NDEBUG + COMPILER_LOG(DEBUG) << " AssembleStubModule :" << i << " th " << std::endl; +#endif + if (stubfunction != nullptr) { + uintptr_t stubEntry = reinterpret_cast(LLVMGetPointerToGlobal(engine, stubfunction)); + module->SetStubEntry(i, stubEntry - codeBuff); + addr2name[stubEntry] = FastStubDescriptors::GetInstance().GetStubDescriptor(i)->GetName(); +#ifndef NDEBUG + COMPILER_LOG(DEBUG) << "name : " << addr2name[codeBuff] << std::endl; +#endif + } + } + module->SetHostCodeSectionAddr(codeBuff); + // stackmaps ptr and size + module->SetStackMapAddr(reinterpret_cast(assembler_.GetStackMapsSection())); + module->SetStackMapSize(assembler_.GetStackMapsSize()); +#ifndef NDEBUG + assembler_.Disassemble(addr2name); +#endif +} + +static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, + [[maybe_unused]] unsigned sectionID, const char *sectionName) +{ + COMPILER_LOG(DEBUG) << "RoundTripAllocateCodeSection object " << object << " - "; + struct CodeInfo& state = *static_cast(object); + uint8_t *addr = state.AllocaCodeSection(size, sectionName); + COMPILER_LOG(DEBUG) << "RoundTripAllocateCodeSection addr:" << std::hex << + reinterpret_cast(addr) << addr << " size:0x" << size << " + "; + return addr; +} + +static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, + [[maybe_unused]] unsigned sectionID, const char *sectionName, + [[maybe_unused]] LLVMBool isReadOnly) +{ + struct CodeInfo& state = *static_cast(object); + return state.AllocaDataSection(size, sectionName); +} + +static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **errMsg) +{ + COMPILER_LOG(DEBUG) << "RoundTripFinalizeMemory object " << object << " - "; + return 0; +} + +static void RoundTripDestroy(void *object) +{ + COMPILER_LOG(DEBUG) << "RoundTripDestroy object " << object << " - "; +} + +void LLVMAssembler::UseRoundTripSectionMemoryManager() +{ + auto sectionMemoryManager = std::make_unique(); + options_.MCJMM = + LLVMCreateSimpleMCJITMemoryManager(&codeInfo_, RoundTripAllocateCodeSection, + RoundTripAllocateDataSection, RoundTripFinalizeMemory, RoundTripDestroy); +} + +bool LLVMAssembler::BuildMCJITEngine() +{ + COMPILER_LOG(DEBUG) << " BuildMCJITEngine - "; + LLVMBool ret = LLVMCreateMCJITCompilerForModule(&engine_, module_, &options_, sizeof(options_), &error_); + if (ret) { + LOG_ECMA(FATAL) << "error_ : " << error_; + return false; + } + COMPILER_LOG(DEBUG) << " BuildMCJITEngine + "; + return true; +} + +void LLVMAssembler::BuildAndRunPasses() const +{ + COMPILER_LOG(DEBUG) << "BuildAndRunPasses - "; + LLVMPassManagerBuilderRef pmBuilder = LLVMPassManagerBuilderCreate(); + LLVMPassManagerBuilderSetOptLevel(pmBuilder, 3); // using O3 optimization level + LLVMPassManagerBuilderSetSizeLevel(pmBuilder, 0); + LLVMPassManagerRef funcPass = LLVMCreateFunctionPassManagerForModule(module_); + LLVMPassManagerRef modPass = LLVMCreatePassManager(); + LLVMPassManagerBuilderPopulateFunctionPassManager(pmBuilder, funcPass); + llvm::unwrap(modPass)->add(llvm::createRewriteStatepointsForGCLegacyPass()); + LLVMPassManagerBuilderPopulateModulePassManager(pmBuilder, modPass); + LLVMPassManagerBuilderDispose(pmBuilder); + LLVMInitializeFunctionPassManager(funcPass); + for (LLVMValueRef fn = LLVMGetFirstFunction(module_); fn; fn = LLVMGetNextFunction(fn)) { + LLVMRunFunctionPassManager(funcPass, fn); + } + LLVMFinalizeFunctionPassManager(funcPass); + LLVMRunPassManager(modPass, module_); + LLVMDisposePassManager(funcPass); + LLVMDisposePassManager(modPass); + COMPILER_LOG(DEBUG) << "BuildAndRunPasses + "; +} + +LLVMAssembler::LLVMAssembler(LLVMModuleRef module, const char* triple) + : module_(module), triple_(triple) +{ + Initialize(); +} + +LLVMAssembler::~LLVMAssembler() +{ + 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; + error_ = nullptr; +} + +void LLVMAssembler::Run() +{ + char *error = nullptr; +#if ECMASCRIPT_ENABLE_COMPILER_LOG + char *info = LLVMPrintModuleToString(module_); + COMPILER_LOG(INFO) << "Current Module: " << info; + LLVMDisposeMessage(info); + LLVMDumpModule(module_); +#endif + LLVMPrintModuleToFile(module_, "stub.ll", &error); + LLVMVerifyModule(module_, LLVMAbortProcessAction, &error); + LLVMDisposeMessage(error); + UseRoundTripSectionMemoryManager(); + if (!BuildMCJITEngine()) { + return; + } + BuildAndRunPasses(); + LLVMPrintModuleToFile(module_, "opt_stub.ll", &error); +} + +void LLVMAssembler::Initialize() +{ + if (triple_ == TripleConst::GetLLVMAmd64Triple()) { + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86Disassembler(); + /* this method must be called, ohterwise "Target does not support MC emission" */ + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86AsmParser(); + LLVMInitializeX86Target(); + } else if (triple_ == TripleConst::GetLLVMArm64Triple()) { + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64TargetMC(); + LLVMInitializeAArch64Disassembler(); + LLVMInitializeAArch64AsmPrinter(); + LLVMInitializeAArch64AsmParser(); + LLVMInitializeAArch64Target(); + } else if (triple_ == TripleConst::GetLLVMArm32Triple()) { + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTargetMC(); + LLVMInitializeARMDisassembler(); + LLVMInitializeARMAsmPrinter(); + LLVMInitializeARMAsmParser(); + LLVMInitializeARMTarget(); + } else { + UNREACHABLE(); + } + llvm::linkAllBuiltinGCs(); + LLVMInitializeMCJITCompilerOptions(&options_, sizeof(options_)); + options_.OptLevel = 2; // opt level 2 + // Just ensure that this field still exists. + options_.NoFramePointerElim = true; +} + +#if ECMASCRIPT_ENABLE_COMPILER_LOG +static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue, + uint64_t *referenceType, [[maybe_unused]]uint64_t referencePC, + [[maybe_unused]] const char **referenceName) +{ + *referenceType = LLVMDisassembler_ReferenceType_InOut_None; + return nullptr; +} +#endif + +void LLVMAssembler::Disassemble(std::map addr2name) const +{ +#if ECMASCRIPT_ENABLE_COMPILER_LOG + LLVMDisasmContextRef dcr = LLVMCreateDisasm(triple_, nullptr, 0, nullptr, SymbolLookupCallback); + std::cout << "========================================================================" << std::endl; + for (auto it : codeInfo_.GetCodeInfo()) { + uint8_t *byteSp; + uintptr_t numBytes; + byteSp = it.first; + numBytes = it.second; + std::cout << " byteSp:" << std::hex << reinterpret_cast(byteSp) << " numBytes:0x" << numBytes + << std::endl; + + unsigned pc = 0; + const char outStringSize = 100; + char outString[outStringSize]; + while (numBytes != 0) { + size_t InstSize = LLVMDisasmInstruction(dcr, byteSp, numBytes, pc, outString, outStringSize); + if (InstSize == 0) { + std::cerr.fill('0'); + std::cerr.width(8); // 8:fixed hex print width + std::cerr << std::hex << pc << ":"; + std::cerr.width(8); // 8:fixed hex print width + std::cerr << std::hex << *reinterpret_cast(byteSp) << "maybe constant" << std::endl; + pc += 4; // 4 pc length + byteSp += 4; // 4 sp offset + numBytes -= 4; // 4 num bytes + } + uint64_t addr = reinterpret_cast(byteSp); + if (addr2name.find(addr) != addr2name.end()) { + std::cout << addr2name[addr].c_str() << ":" << std::endl; + } + std::cerr.fill('0'); + std::cerr.width(8); // 8:fixed hex print width + std::cerr << std::hex << pc << ":"; + std::cerr.width(8); // 8:fixed hex print width + std::cerr << std::hex << *reinterpret_cast(byteSp) << " " << outString << std::endl; + pc += InstSize; + byteSp += InstSize; + numBytes -= InstSize; + } + } + std::cout << "========================================================================" << std::endl; + LLVMDisasmDispose(dcr); +#endif +} +} // namespace kungfu diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index a4f1b897..9f49a3c5 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -27,18 +27,18 @@ #include "ecmascript/ecma_macros.h" #include "ecmascript/js_thread.h" #include "ecmascript/stub_module.h" -#include "llvm-c/Types.h" #include "llvm-c/Analysis.h" #include "llvm-c/Core.h" #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm-c/Transforms/Scalar.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Support/Host.h" +#include "llvm-c/Types.h" #include "llvm/ExecutionEngine/Interpreter.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Host.h" namespace kungfu { struct CodeInfo { @@ -51,11 +51,20 @@ struct CodeInfo { static constexpr int prot = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise) static constexpr int flags = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise) machineCode_ = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, prot, flags, -1, 0)); + if (machineCode_ == reinterpret_cast(-1)) { + machineCode_ = nullptr; + } + if (machineCode_ != nullptr) { + ASAN_UNPOISON_MEMORY_REGION(machineCode_, MAX_MACHINE_CODE_SIZE); + } } ~CodeInfo() { Reset(); - munmap(machineCode_, MAX_MACHINE_CODE_SIZE); + if (machineCode_ != nullptr) { + ASAN_POISON_MEMORY_REGION(machineCode_, MAX_MACHINE_CODE_SIZE); + munmap(machineCode_, MAX_MACHINE_CODE_SIZE); + } machineCode_ = nullptr; } uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName) @@ -67,11 +76,8 @@ struct CodeInfo { return nullptr; } LOG_ECMA(INFO) << "AllocaCodeSection size:" << size; - std::vector codeBuffer(machineCode_[codeBufferPos_], size); - LOG_ECMA(INFO) << " codeBuffer size: " << codeBuffer.size(); codeSectionNames_.push_back(sectionName); addr = machineCode_ + codeBufferPos_; - LOG_ECMA(INFO) << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr); codeInfo_.push_back({addr, size}); codeBufferPos_ += size; return addr; @@ -85,7 +91,7 @@ struct CodeInfo { dataSectionNames_.push_back(sectionName); addr = static_cast(dataSectionList_.back().data()); if (!strcmp(sectionName, ".llvm_stackmaps")) { - LOG_ECMA(INFO) << "llvm_stackmaps : " << addr << " size:" << size << std::endl; + LOG_ECMA(INFO) << "llvm_stackmaps : " << addr << " size:" << size; stackMapsSection_ = addr; stackMapsSize_ = size; } @@ -171,9 +177,6 @@ public: { return LLVMGetPointerToGlobal(engine_, function); } - const char *AMD64_TRIPLE = "x86_64-unknown-linux-gnu"; - const char *ARM64_TRIPLE = "aarch64-unknown-linux-gnu"; - const char *ARM32_TRIPLE = "arm-unknown-linux-gnu"; private: void UseRoundTripSectionMemoryManager(); bool BuildMCJITEngine(); @@ -182,12 +185,12 @@ private: void Initialize(); void InitMember(); - LLVMMCJITCompilerOptions options_; + LLVMMCJITCompilerOptions options_ {}; LLVMModuleRef module_; - LLVMExecutionEngineRef engine_; - std::string hostTriple_; - char *error_; - struct CodeInfo codeInfo_; + LLVMExecutionEngineRef engine_ {nullptr}; + const char *triple_; + char *error_ {nullptr}; + struct CodeInfo codeInfo_ {}; }; class LLVMCodeGeneratorImpl : public CodeGeneratorImpl { @@ -200,6 +203,26 @@ private: LLVMStubModule *module_; }; +class LLVMAarch64CodeGeneratorImpl : public CodeGeneratorImpl { +public: + explicit LLVMAarch64CodeGeneratorImpl(LLVMStubModule *module) : module_(module) {} + ~LLVMAarch64CodeGeneratorImpl() = default; + void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) override; + +private: + LLVMStubModule *module_; +}; + +class LLVMArm32CodeGeneratorImpl : public CodeGeneratorImpl { +public: + explicit LLVMArm32CodeGeneratorImpl(LLVMStubModule *module) : module_(module) {} + ~LLVMArm32CodeGeneratorImpl() = default; + void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) override; + +private: + LLVMStubModule *module_; +}; + class LLVMModuleAssembler { public: explicit LLVMModuleAssembler(LLVMStubModule *module, const char* triple) diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index d8756c04..a5b65f87 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -14,12 +14,20 @@ */ #include "ecmascript/compiler/llvm_ir_builder.h" + +#include #include #include +#include + #include "ecmascript/compiler/circuit.h" +#include "ecmascript/compiler/compiler_macros.h" #include "ecmascript/compiler/fast_stub.h" #include "ecmascript/compiler/gate.h" +#include "ecmascript/compiler/js_thread_offset_table.h" #include "ecmascript/compiler/stub_descriptor.h" +#include "ecmascript/compiler/triple.h" +#include "ecmascript/frames.h" #include "ecmascript/js_array.h" #include "ecmascript/js_thread.h" #include "llvm/IR/Instructions.h" @@ -30,10 +38,10 @@ namespace kungfu { std::unordered_map g_values = {}; -LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, - LLVMStubModule *module, LLVMValueRef function) +LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, + LLVMStubModule *module, LLVMValueRef function, const char *triple) : schedule_(schedule), circuit_(circuit), module_(module->GetModule()), - function_(function), stubModule_(module) + function_(function), stubModule_(module), triple_(triple) { builder_ = LLVMCreateBuilder(); context_ = LLVMGetGlobalContext(); @@ -48,11 +56,11 @@ LLVMIRBuilder::~LLVMIRBuilder() } } -int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const +int LLVMIRBuilder::FindBasicBlock(GateRef gate) const { for (size_t bbIdx = 0; bbIdx < schedule_->size(); bbIdx++) { for (size_t instIdx = (*schedule_)[bbIdx].size(); instIdx > 0; instIdx--) { - AddrShift tmp = (*schedule_)[bbIdx][instIdx - 1]; + GateRef tmp = (*schedule_)[bbIdx][instIdx - 1]; if (tmp == gate) { return bbIdx; } @@ -63,8 +71,10 @@ int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const void LLVMIRBuilder::AssignHandleMap() { - opCodeHandleMap_ = {{OpCode::STATE_ENTRY, &LLVMIRBuilder::HandleGoto}, + opCodeHandleMap_ = { + {OpCode::STATE_ENTRY, &LLVMIRBuilder::HandleGoto}, {OpCode::RETURN, &LLVMIRBuilder::HandleReturn}, + {OpCode::RETURN_VOID, &LLVMIRBuilder::HandleReturnVoid}, {OpCode::IF_BRANCH, &LLVMIRBuilder::HandleBranch}, {OpCode::SWITCH_BRANCH, &LLVMIRBuilder::HandleSwitch}, {OpCode::ORDINARY_BLOCK, &LLVMIRBuilder::HandleGoto}, {OpCode::IF_TRUE, &LLVMIRBuilder::HandleGoto}, {OpCode::IF_FALSE, &LLVMIRBuilder::HandleGoto}, {OpCode::SWITCH_CASE, &LLVMIRBuilder::HandleGoto}, @@ -77,6 +87,7 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::CALL, &LLVMIRBuilder::HandleCall}, {OpCode::INT1_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::INT32_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::FLOAT64_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::INT64_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::ALLOCA, &LLVMIRBuilder::HandleAlloca}, + {OpCode::ANYVALUE_CALL, &LLVMIRBuilder::HandleCall}, {OpCode::INT1_ARG, &LLVMIRBuilder::HandleParameter}, {OpCode::INT32_ARG, &LLVMIRBuilder::HandleParameter}, {OpCode::INT64_ARG, &LLVMIRBuilder::HandleParameter}, {OpCode::INT32_CONSTANT, &LLVMIRBuilder::HandleInt32Constant}, @@ -136,6 +147,7 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::INT64_STORE, &LLVMIRBuilder::HandleStore}, {OpCode::INT32_TO_FLOAT64, &LLVMIRBuilder::HandleChangeInt32ToDouble}, {OpCode::FLOAT64_TO_INT32, &LLVMIRBuilder::HandleChangeDoubleToInt32}, + {OpCode::TAGGED_POINTER_TO_INT64, &LLVMIRBuilder::HandleChangeTaggedPointerToInt64}, {OpCode::BITCAST_INT64_TO_FLOAT64, &LLVMIRBuilder::HandleCastInt64ToDouble}, {OpCode::BITCAST_FLOAT64_TO_INT64, &LLVMIRBuilder::HandleCastDoubleToInt}, {OpCode::INT32_LSL, &LLVMIRBuilder::HandleIntLsl}, @@ -143,12 +155,13 @@ void LLVMIRBuilder::AssignHandleMap() {OpCode::FLOAT64_SMOD, &LLVMIRBuilder::HandleFloatMod}, {OpCode::INT32_SMOD, &LLVMIRBuilder::HandleIntMod}, {OpCode::TAGGED_POINTER_CALL, &LLVMIRBuilder::HandleCall}, - }; - opCodeHandleIgnore= {OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, - OpCode::FRAMESTATE_ENTRY, OpCode::RETURN_LIST, OpCode::THROW_LIST, - OpCode::CONSTANT_LIST, OpCode::ARG_LIST, OpCode::THROW, - OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND}; + opCodeHandleIgnore= { + OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, + OpCode::FRAMESTATE_ENTRY, OpCode::RETURN_LIST, OpCode::THROW_LIST, + OpCode::CONSTANT_LIST, OpCode::ARG_LIST, OpCode::THROW, + OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND + }; } std::string LLVMIRBuilder::LLVMValueToString(LLVMValueRef val) const @@ -161,14 +174,15 @@ std::string LLVMIRBuilder::LLVMValueToString(LLVMValueRef val) const void LLVMIRBuilder::Build() { - LOG_ECMA(INFO) << "LLVM IR Builder Create Id Map of Blocks..."; + COMPILER_LOG(INFO) << "LLVM IR Builder Create Id Map of Blocks..."; for (size_t bbIdx = 0; bbIdx < schedule_->size(); bbIdx++) { for (size_t instIdx = (*schedule_)[bbIdx].size(); instIdx > 0; instIdx--) { GateId gateId = circuit_->GetId((*schedule_)[bbIdx][instIdx - 1]); instIdMapBbId_[gateId] = bbIdx; } } - LOG_ECMA(INFO) << "LLVM IR Builder Visit Gate..."; + COMPILER_LOG(INFO) << "LLVM IR Builder Visit Gate..."; + AssignHandleMap(); for (size_t bbIdx = 0; bbIdx < (*schedule_).size(); bbIdx++) { OperandsVector predecessors; @@ -181,10 +195,12 @@ void LLVMIRBuilder::Build() VisitBlock(bbIdx, predecessors); for (size_t instIdx = (*schedule_)[bbIdx].size(); instIdx > 0; instIdx--) { - AddrShift gate = (*schedule_)[bbIdx][instIdx - 1]; - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + GateRef gate = (*schedule_)[bbIdx][instIdx - 1]; + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); +#if ECMASCRIPT_ENABLE_COMPILER_LOG circuit_->Print(gate); +#endif auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate)); if (found != opCodeHandleMap_.end()) { (this->*(found->second))(gate); @@ -218,12 +234,12 @@ void LLVMIRBuilder::StartLLVMBuilder(BasicBlock *bb) const EnsureLLVMBB(bb); LLVMTFBuilderBasicBlockImpl *impl = bb->GetImpl(); if ((impl == nullptr) || (impl->llvm_bb_ == nullptr)) { - LOG_ECMA(ERROR) << "StartLLVMBuilder failed "; + COMPILER_LOG(ERROR) << "StartLLVMBuilder failed "; return; } impl->started = true; bb->SetImpl(impl); - LOG_ECMA(DEBUG) << "Basicblock id :" << bb->GetId() << "impl:" << bb->GetImpl(); + COMPILER_LOG(DEBUG) << "Basicblock id :" << bb->GetId() << "impl:" << bb->GetImpl(); LLVMPositionBuilderAtEnd(builder_, impl->llvm_bb_); } @@ -234,12 +250,12 @@ void LLVMIRBuilder::ProcessPhiWorkList() for (auto &e : impl->not_merged_phis) { BasicBlock *pred = e.pred; if (impl->started == 0) { - LOG_ECMA(ERROR) << " ProcessPhiWorkList error hav't start "; + COMPILER_LOG(ERROR) << " ProcessPhiWorkList error hav't start "; return; } LLVMValueRef value = g_values[e.operand]; if (LLVMTypeOf(value) != LLVMTypeOf(e.phi)) { - LOG_ECMA(ERROR) << " ProcessPhiWorkList LLVMTypeOf don't match error "; + COMPILER_LOG(ERROR) << " ProcessPhiWorkList LLVMTypeOf don't match error "; } LLVMBasicBlockRef llvmBB = EnsureLLVMBB(pred); LLVMAddIncoming(e.phi, &value, &llvmBB, 1); @@ -277,45 +293,79 @@ LLVMTFBuilderBasicBlockImpl *LLVMIRBuilder::EnsureLLVMBBImpl(BasicBlock *bb) con void LLVMIRBuilder::PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builder) { + /* current frame for x86_64 system: + 0 pre rbp <-- rbp + -8 type + -16 pre frame thread fp + for 32 arm bit system: + 0 pre fp <-- fp + -4 type + -8 pre frame thread fp + for arm64 system + 0 pre fp/ other regs <-- fp + -8 type + -16 pre frame thread fp + -24 current sp before call other function + */ auto frameType = circuit_->GetFrameType(); LLVMAddTargetDependentFunctionAttr(function_, "frame-pointer", "all"); + LLVMAddTargetDependentFunctionAttr(function_, "target-features", "+vfp2"); + LLVMValueRef llvmFpAddr = LLVMCallingFp(module_, builder_, false); + int slotSize = 0; + LLVMTypeRef llvmSlotType = nullptr; + if ((triple_ == TripleConst::GetLLVMAmd64Triple()) || + (triple_ == TripleConst::GetLLVMArm64Triple())) { + slotSize = panda::ecmascript::FrameConst::AARCH64_SLOT_SIZE; // 64bit slot size + llvmSlotType = LLVMInt64Type(); + } else if (triple_ == TripleConst::GetLLVMArm32Triple()) { + slotSize = panda::ecmascript::FrameConst::ARM32_SLOT_SIZE; // 32bit slot size + llvmSlotType = LLVMInt32Type(); + return; + } else { + ASSERT_PRINT(llvmSlotType == nullptr, " triple is not supported !"); + } + + LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, llvmFpAddr, llvmSlotType, "cast_int_t"); + LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(llvmSlotType, + slotSize, false), ""); + LLVMValueRef addr = LLVMBuildIntToPtr(builder, frameTypeSlotAddr, + LLVMPointerType(llvmSlotType, 0), "frameType.Addr"); if (frameType == panda::ecmascript::FrameType::OPTIMIZED_FRAME) { LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "0"); } else if (frameType == panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME) { LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "1"); } else { - LOG_ECMA(DEBUG) << "frameType interpret type error !"; + LOG_ECMA(FATAL) << "frameType interpret type error !"; + ASSERT_PRINT(static_cast(frameType), "is not support !"); } + LLVMValueRef llvmFrameType = LLVMConstInt(llvmSlotType, static_cast(frameType), 0); + (void)llvmFrameType; + LLVMValueRef value = LLVMBuildStore(builder_, llvmFrameType, addr); + if (frameType != panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME) { return; } - LLVMValueRef llvmFpAddr = LLVMCallingFp(module_, builder_); - /* current frame - 0 pre rbp <-- rbp - -8 type - -16 pre frame thread fp - */ - LLVMValueRef thread = LLVMGetParam(function_, 0); - LLVMValueRef rtoffset = LLVMConstInt(LLVMInt64Type(), - panda::ecmascript::JSThread::GetCurrentFrameOffset(), - 0); - LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, thread, rtoffset, ""); - - LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); + LLVMValueRef glue = LLVMGetParam(function_, 0); + LLVMTypeRef glue_type = LLVMTypeOf(glue); + LLVMValueRef rtoffset = LLVMConstInt(glue_type, OffsetTable::GetOffset(JSThread::GlueID::CURRENT_FRAME), 0); + LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); + LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(llvmSlotType, 0), ""); LLVMValueRef threadFpValue = LLVMBuildLoad(builder_, rtbaseAddr, ""); - LLVMValueRef value = LLVMBuildStore(builder_, threadFpValue, - LLVMBuildIntToPtr(builder_, llvmFpAddr, LLVMPointerType(LLVMInt64Type(), 0), "cast")); - LOG_ECMA(INFO) << "store value:" << value << " " + static constexpr int g_LLVMFrameOffset = 2; + addr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(llvmSlotType, g_LLVMFrameOffset * slotSize, false), ""); + value = LLVMBuildStore(builder_, threadFpValue, + LLVMBuildIntToPtr(builder_, addr, LLVMPointerType(llvmSlotType, 0), "cast")); + LOG_ECMA(DEBUG) << "store value:" << value << " " << "value type" << LLVMTypeOf(value); } -LLVMValueRef LLVMIRBuilder::LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder) +LLVMValueRef LLVMIRBuilder::LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller) { /* 0:calling 1:its caller */ - std::vector args = {LLVMConstInt(LLVMInt32Type(), 0, false)}; + std::vector args = {LLVMConstInt(LLVMInt32Type(), 0, isCaller)}; auto fn = LLVMGetNamedFunction(module, "llvm.frameaddress.p0i8"); if (!fn) { /* init instrinsic function declare */ @@ -326,11 +376,25 @@ LLVMValueRef LLVMIRBuilder::LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef fn = LLVMAddFunction(module, "llvm.frameaddress.p0i8", fnTy); } LLVMValueRef fAddrRet = LLVMBuildCall(builder, fn, args.data(), 1, ""); - LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, fAddrRet, LLVMInt64Type(), "cast_int64_t"); - LLVMValueRef addr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(LLVMInt64Type(), - 16, false), ""); // 16:thread fp offset - LLVMValueRef preFpAddr = LLVMBuildIntToPtr(builder, addr, LLVMPointerType(LLVMInt64Type(), 0), "thread.fp.Addr"); - return preFpAddr; + return fAddrRet; +} + +LLVMValueRef LLVMIRBuilder::LLVMCallerSp(LLVMModuleRef &module, LLVMBuilderRef &builder, + LLVMMetadataRef meta) +{ + std::vector args = {LLVMMetadataAsValue(context_, meta)}; + auto fn = LLVMGetNamedFunction(module, "llvm.read_register.i64"); + if (!fn) { + /* init instrinsic function declare */ + LLVMTypeRef paramTys1[] = { + GetMachineRepType(MachineRep::K_META), + }; + auto fnTy = LLVMFunctionType(LLVMInt64Type(), paramTys1, 1, 0); + fn = LLVMAddFunction(module, "llvm.read_register.i64", fnTy); + } + LLVMDumpValue(fn); + LLVMValueRef fAddrRet = LLVMBuildCall(builder_, fn, args.data(), 1, ""); + return fAddrRet; } LLVMBasicBlockRef LLVMIRBuilder::EnsureLLVMBB(BasicBlock *bb) const @@ -345,7 +409,7 @@ LLVMBasicBlockRef LLVMIRBuilder::EnsureLLVMBB(BasicBlock *bb) const impl->llvm_bb_ = llvmBB; impl->continuation = llvmBB; bb->SetImpl(impl); - LOG_ECMA(DEBUG) << "create LLVMBB = " << buf << " impl:" << bb->GetImpl(); + COMPILER_LOG(DEBUG) << "create LLVMBB = " << buf << " impl:" << bb->GetImpl(); return llvmBB; } @@ -368,18 +432,32 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const case MachineRep::K_FLOAT64: dstType = LLVMDoubleTypeInContext(context_); break; - default: // 64bit int goes to default scenario + case MachineRep::K_WORD64: dstType = LLVMInt64TypeInContext(context_); break; + case MachineRep::K_PTR_1: + if (triple_ == TripleConst::GetLLVMArm32Triple()) { + dstType = LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2); // 2: packed vector type + } else { + dstType = LLVMPointerType(LLVMInt64TypeInContext(context_), 1); + } + break; + case MachineRep::K_META: + dstType = LLVMMetadataTypeInContext(context_); + break; + default: + UNREACHABLE(); + break; } return dstType; } -void LLVMIRBuilder::HandleCall(AddrShift gate) +void LLVMIRBuilder::HandleCall(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); switch (circuit_->GetOpCode(gate)) { case OpCode::CALL: + case OpCode::ANYVALUE_CALL: case OpCode::INT1_CALL: case OpCode::INT32_CALL: case OpCode::FLOAT64_CALL: @@ -393,7 +471,26 @@ void LLVMIRBuilder::HandleCall(AddrShift gate) } } -void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inList) +void LLVMIRBuilder::SaveCallerSp() +{ + if (triple_ == TripleConst::GetLLVMArm64Triple()) { + int slotSize = 8; + LLVMTypeRef llvmSlotType = LLVMInt64Type(); + LLVMValueRef llvmFpAddr = LLVMCallingFp(module_, builder_, false); + LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, llvmSlotType, "cast_int_t"); + LLVMValueRef frameSpSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(llvmSlotType, + 3 * slotSize, false), ""); // 3: type + threadsp + current sp + LLVMValueRef addr = LLVMBuildIntToPtr(builder_, frameSpSlotAddr, + LLVMPointerType(llvmSlotType, 0), "frameType.Addr"); + LLVMMetadataRef meta = LLVMMDStringInContext2(context_, "sp", 3); // 3 : 3 means len of "sp" + LLVMMetadataRef metadataNode = LLVMMDNodeInContext2(context_, &meta, 1); + LLVMValueRef spValue = LLVMCallerSp(module_, builder_, metadataNode); + LLVMBuildStore(builder_, spValue, addr); + } +} + + +void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector &inList) { int paraStartIndex = 2; int index = circuit_->GetBitField(inList[1]); @@ -403,106 +500,89 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi StubDescriptor *callee_descriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(index); LLVMTypeRef rtfuncType = stubModule_->GetStubFunctionType(index); LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); - LLVMValueRef thread = g_values[inList[2]]; // 2 : 2 means skip two input gates (target thread) + LLVMValueRef glue = g_values[inList[2]]; // 2 : 2 means skip two input gates (target glue) + LLVMTypeRef glue_type = LLVMTypeOf(glue); // runtime case if (callee_descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB) { - rtoffset = LLVMConstInt(LLVMInt64Type(), - panda::ecmascript::JSThread::GetRuntimeFunctionsOffset() + + rtoffset = LLVMConstInt(glue_type, OffsetTable::GetOffset(JSThread::GlueID::RUNTIME_FUNCTIONS) + (index - FAST_STUB_MAXCOUNT) * sizeof(uintptr_t), 0); } else { - rtoffset = LLVMConstInt(LLVMInt64Type(), - panda::ecmascript::JSThread::GetFastStubEntryOffset() + - (index) * sizeof(uintptr_t), 0); + rtoffset = LLVMConstInt(glue_type, OffsetTable::GetOffset(JSThread::GlueID::FAST_STUB_ENTIRES) + + index * sizeof(uintptr_t), 0); } - LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, thread, rtoffset, ""); - LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(LLVMInt64Type(), 0), ""); + LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); + LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(glue_type, 0), ""); LLVMValueRef llvmAddr = LLVMBuildLoad(builder_, rtbaseAddr, ""); callee = LLVMBuildIntToPtr(builder_, llvmAddr, rtfuncTypePtr, "cast"); paraStartIndex += 1; // 16 : params limit LLVMValueRef params[16]; for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) { - AddrShift gateTmp = inList[paraIdx]; + GateRef gateTmp = inList[paraIdx]; params[paraIdx - paraStartIndex] = g_values[gateTmp]; - circuit_->Print(gateTmp); - LOG_ECMA(INFO) << "arg" << paraIdx - paraStartIndex << ": " << - LLVMValueToString(params[paraIdx - paraStartIndex]); } if (callee == nullptr) { - LOG_ECMA(ERROR) << "callee nullptr"; + COMPILER_LOG(ERROR) << "callee nullptr"; return; } + SaveCallerSp(); g_values[gate] = LLVMBuildCall(builder_, callee, params, inList.size() - paraStartIndex, ""); return; } -void LLVMIRBuilder::HandleAlloca(AddrShift gate) +void LLVMIRBuilder::HandleAlloca(GateRef gate) { return VisitAlloca(gate); } -void LLVMIRBuilder::VisitAlloca(AddrShift gate) +void LLVMIRBuilder::VisitAlloca(GateRef gate) { uint64_t sizeEnum = circuit_->GetBitField(gate); LLVMTypeRef sizeType = GetMachineRepType(static_cast(sizeEnum)); - LOG_ECMA(INFO) << LLVMGetTypeKind(sizeType); - g_values[gate] = LLVMBuildPtrToInt(builder_, LLVMBuildAlloca(builder_, sizeType, ""), LLVMInt64Type(), + COMPILER_LOG(DEBUG) << LLVMGetTypeKind(sizeType); + g_values[gate] = LLVMBuildPtrToInt(builder_, LLVMBuildAlloca(builder_, sizeType, ""), ConvertLLVMTypeFromGate(gate), ""); // NOTE: pointer val is currently viewed as 64bits return; } -void LLVMIRBuilder::HandlePhi(AddrShift gate) +void LLVMIRBuilder::HandlePhi(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::VALUE_SELECTOR_INT1: { - VisitPhi(gate, ins, MachineRep::K_BIT); - break; - } - case OpCode::VALUE_SELECTOR_INT32: { - VisitPhi(gate, ins, MachineRep::K_WORD32); - break; - } - case OpCode::VALUE_SELECTOR_INT64: { - VisitPhi(gate, ins, MachineRep::K_WORD64); - break; - } - case OpCode::VALUE_SELECTOR_FLOAT64: { - VisitPhi(gate, ins, MachineRep::K_FLOAT64); - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + VisitPhi(gate, ins); } -void LLVMIRBuilder::VisitPhi(AddrShift gate, const std::vector &srcGates, MachineRep rep) +void LLVMIRBuilder::VisitPhi(GateRef gate, const std::vector &srcGates) { - LLVMTypeRef type = GetMachineRepType(rep); + LLVMTypeRef type = ConvertLLVMTypeFromGate(gate); LLVMValueRef phi = LLVMBuildPhi(builder_, type, ""); - std::vector relMergeIns = circuit_->GetInVector(srcGates[0]); + std::vector relMergeIns = circuit_->GetInVector(srcGates[0]); bool addToPhiRebuildList = false; + for (int j = 1; j < static_cast(srcGates.size()); j++) { + circuit_->Print(srcGates[j]); + } + circuit_->Print(gate); for (int i = 1; i < static_cast(srcGates.size()); i++) { GateId gateId = circuit_->GetId(relMergeIns[i - 1]); int bbIdx = instIdMapBbId_[gateId]; - LOG_ECMA(INFO) << "srcGate: " << srcGates[i] << " dominated gateId:" << gateId << "dominated bbIdx: " << bbIdx; + COMPILER_LOG(DEBUG) << "srcGate: " << srcGates[i] << " dominated gateId:" << gateId << "dominated bbIdx: " << + bbIdx; int cnt = bbIdMapBb_.count(bbIdx); // if cnt = 0 means bb with current bbIdx hasn't been created if (cnt > 0) { BasicBlock *bb = bbIdMapBb_[bbIdx].get(); - LOG_ECMA(INFO) << "bb : " << bb; + COMPILER_LOG(DEBUG) << "bb : " << bb; if (bb == nullptr) { - LOG_ECMA(ERROR) << "VisitPhi failed BasicBlock nullptr"; + COMPILER_LOG(ERROR) << "VisitPhi failed BasicBlock nullptr"; return; } LLVMTFBuilderBasicBlockImpl *impl = bb->GetImpl(); if (impl == nullptr) { - LOG_ECMA(ERROR) << "VisitPhi failed impl nullptr"; + COMPILER_LOG(ERROR) << "VisitPhi failed impl nullptr"; return; } LLVMBasicBlockRef llvmBB = EnsureLLVMBB(bb); // The llvm bb LLVMValueRef value = g_values[srcGates[i]]; + if (impl->started) { LLVMAddIncoming(phi, &value, &llvmBB, 1); } else { @@ -524,43 +604,55 @@ void LLVMIRBuilder::VisitPhi(AddrShift gate, const std::vector &srcGa } } -void LLVMIRBuilder::VisitReturn(AddrShift gate, AddrShift popCount, const std::vector &operands) const +void LLVMIRBuilder::VisitReturn(GateRef gate, GateRef popCount, const std::vector &operands) const { // [STATE] [DEPEND] [VALUE] [RETURN_LIST] - AddrShift operand = operands[2]; // 2: skip 2 in gate that are not data gate - LOG_ECMA(INFO) << " gate: " << gate << " popCount: " << popCount; - LOG_ECMA(INFO) << " return: " << operand << " gateId: " << circuit_->GetId(operand); + GateRef operand = operands[2]; // 2: skip 2 in gate that are not data gate + COMPILER_LOG(DEBUG) << " gate: " << gate << " popCount: " << popCount; + COMPILER_LOG(DEBUG) << " return: " << operand << " gateId: " << circuit_->GetId(operand); LLVMValueRef returnValue = g_values[operand]; - LOG_ECMA(INFO) << LLVMValueToString(returnValue); + COMPILER_LOG(DEBUG) << LLVMValueToString(returnValue); LLVMBuildRet(builder_, returnValue); } -void LLVMIRBuilder::HandleReturn(AddrShift gate) +void LLVMIRBuilder::HandleReturn(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitReturn(gate, 1, ins); } +void LLVMIRBuilder::VisitReturnVoid(GateRef gate) const +{ + // [STATE] [DEPEND] [VALUE] [RETURN_LIST] + COMPILER_LOG(DEBUG) << " gate: " << gate; + LLVMBuildRetVoid(builder_); +} + +void LLVMIRBuilder::HandleReturnVoid(GateRef gate) +{ + VisitReturnVoid(gate); +} + void LLVMIRBuilder::VisitBlock(int gate, const OperandsVector &predecessors) // NOLINTNEXTLINE(misc-unused-parameters) { - LOG_ECMA(INFO) << " BBIdx:" << gate; + COMPILER_LOG(DEBUG) << " BBIdx:" << gate; BasicBlock *bb = EnsurBasicBlock(gate); if (bb == nullptr) { - LOG_ECMA(ERROR) << " block create failed "; + COMPILER_LOG(ERROR) << " block create failed "; return; } currentBb_ = bb; LLVMBasicBlockRef llvmbb = EnsureLLVMBB(bb); StartLLVMBuilder(bb); - LOG_ECMA(INFO) << "predecessors :"; + COMPILER_LOG(DEBUG) << "predecessors :"; for (int predecessor : predecessors) { BasicBlock *pre = EnsurBasicBlock(predecessor); if (pre == nullptr) { - LOG_ECMA(ERROR) << " block setup failed, predecessor:%d nullptr" << predecessor; + COMPILER_LOG(ERROR) << " block setup failed, predecessor:%d nullptr" << predecessor; return; } LLVMBasicBlockRef llvmpre = EnsureLLVMBB(pre); - LOG_ECMA(INFO) << " " << predecessor; + COMPILER_LOG(DEBUG) << " " << predecessor; LLVMMoveBasicBlockBefore(llvmpre, llvmbb); } if (gate == 0) { // insert prologue @@ -568,9 +660,9 @@ void LLVMIRBuilder::VisitBlock(int gate, const OperandsVector &predecessors) // } } -void LLVMIRBuilder::HandleGoto(AddrShift gate) +void LLVMIRBuilder::HandleGoto(GateRef gate) { - std::vector outs = circuit_->GetOutVector(gate); + std::vector outs = circuit_->GetOutVector(gate); int block = instIdMapBbId_[circuit_->GetId(gate)]; int bbOut = instIdMapBbId_[circuit_->GetId(outs[0])]; switch (circuit_->GetOpCode(gate)) { @@ -596,7 +688,7 @@ void LLVMIRBuilder::VisitGoto(int block, int bbOut) } BasicBlock *bb = EnsurBasicBlock(bbOut); if (bb == nullptr) { - LOG_ECMA(ERROR) << " block is nullptr "; + COMPILER_LOG(ERROR) << " block is nullptr "; return; } llvm::BasicBlock *self = llvm::unwrap(EnsureLLVMBB(bbIdMapBb_[block].get())); @@ -605,161 +697,151 @@ void LLVMIRBuilder::VisitGoto(int block, int bbOut) EndCurrentBlock(); } -void LLVMIRBuilder::HandleInt32Constant(AddrShift gate) +void LLVMIRBuilder::HandleInt32Constant(GateRef gate) { int32_t value = circuit_->GetBitField(gate); VisitInt32Constant(gate, value); } -void LLVMIRBuilder::HandleInt64Constant(AddrShift gate) +void LLVMIRBuilder::HandleInt64Constant(GateRef gate) { int64_t value = circuit_->GetBitField(gate); VisitInt64Constant(gate, value); } -void LLVMIRBuilder::HandleFloat64Constant(AddrShift gate) +void LLVMIRBuilder::HandleFloat64Constant(GateRef gate) { int64_t value = circuit_->GetBitField(gate); double doubleValue = bit_cast(value); // actual double value VisitFloat64Constant(gate, doubleValue); } -void LLVMIRBuilder::HandleZExtInt(AddrShift gate) +void LLVMIRBuilder::HandleZExtInt(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::ZEXT_INT8_TO_INT32: // no break, fall through - case OpCode::ZEXT_INT16_TO_INT32: - case OpCode::ZEXT_INT1_TO_INT32: { - VisitZExtInt(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::ZEXT_INT32_TO_INT64: // no break, fall through - case OpCode::ZEXT_INT1_TO_INT64: { - VisitZExtInt(gate, ins[0], MachineRep::K_WORD64); - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + VisitZExtInt(gate, ins[0]); } -void LLVMIRBuilder::HandleSExtInt(AddrShift gate) +void LLVMIRBuilder::HandleSExtInt(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::SEXT_INT1_TO_INT32: { - VisitSExtInt(gate, ins[0], MachineRep::K_WORD32); - break; - } - case OpCode::SEXT_INT1_TO_INT64: // no break, fall through - case OpCode::SEXT_INT32_TO_INT64: { - VisitSExtInt(gate, ins[0], MachineRep::K_WORD64); - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + VisitSExtInt(gate, ins[0]); } -void LLVMIRBuilder::VisitInt32Constant(AddrShift gate, int32_t value) const +void LLVMIRBuilder::VisitInt32Constant(GateRef gate, int32_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt32Type(), value, 0); g_values[gate] = llvmValue; - LOG_ECMA(INFO) << "VisitInt32Constant set gate:" << gate << " value:" << value; - LOG_ECMA(INFO) << "VisitInt32Constant " << LLVMValueToString(llvmValue); + COMPILER_LOG(DEBUG) << "VisitInt32Constant set gate:" << gate << " value:" << value; + COMPILER_LOG(DEBUG) << "VisitInt32Constant " << LLVMValueToString(llvmValue); } -void LLVMIRBuilder::VisitInt64Constant(AddrShift gate, int64_t value) const +void LLVMIRBuilder::VisitInt64Constant(GateRef gate, int64_t value) const { LLVMValueRef llvmValue = LLVMConstInt(LLVMInt64Type(), value, 0); + LLVMTypeRef type = ConvertLLVMTypeFromGate(gate); + if (LLVMGetTypeKind(type) == LLVMPointerTypeKind) { + llvmValue = LLVMBuildIntToPtr(builder_, llvmValue, type, ""); + } else if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) { + LLVMValueRef tmp1Value = + LLVMBuildLShr(builder_, llvmValue, LLVMConstInt(LLVMInt32Type(), 32, 0), ""); // 32: offset + LLVMValueRef tmp2Value = LLVMBuildIntCast(builder_, llvmValue, LLVMInt32Type(), ""); // low + LLVMValueRef emptyValue = LLVMGetUndef(type); + tmp1Value = LLVMBuildIntToPtr(builder_, tmp1Value, LLVMPointerType(LLVMInt8Type(), 1), ""); + tmp2Value = LLVMBuildIntToPtr(builder_, tmp2Value, LLVMPointerType(LLVMInt8Type(), 1), ""); + llvmValue = LLVMBuildInsertElement(builder_, emptyValue, tmp2Value, LLVMConstInt(LLVMInt32Type(), 0, 0), ""); + llvmValue = LLVMBuildInsertElement(builder_, llvmValue, tmp1Value, LLVMConstInt(LLVMInt32Type(), 1, 0), ""); + } else if (LLVMGetTypeKind(type) == LLVMIntegerTypeKind) { + // do nothing + } else { + abort(); + } g_values[gate] = llvmValue; - LOG_ECMA(INFO) << "VisitInt64Constant set gate:" << gate << " value:" << value; - LOG_ECMA(INFO) << "VisitInt64Constant " << LLVMValueToString(llvmValue); + COMPILER_LOG(DEBUG) << "VisitInt64Constant set gate:" << gate << " value:" << value; + COMPILER_LOG(DEBUG) << "VisitInt64Constant " << LLVMValueToString(llvmValue); } -void LLVMIRBuilder::VisitFloat64Constant(AddrShift gate, double value) const +void LLVMIRBuilder::VisitFloat64Constant(GateRef gate, double value) const { LLVMValueRef llvmValue = LLVMConstReal(LLVMDoubleType(), value); g_values[gate] = llvmValue; - LOG_ECMA(INFO) << "VisitFloat64Constant set gate:" << gate << " value:" << value; - LOG_ECMA(INFO) << "VisitFloat64Constant " << LLVMValueToString(llvmValue); + COMPILER_LOG(DEBUG) << "VisitFloat64Constant set gate:" << gate << " value:" << value; + COMPILER_LOG(DEBUG) << "VisitFloat64Constant " << LLVMValueToString(llvmValue); } -void LLVMIRBuilder::HandleParameter(AddrShift gate) +void LLVMIRBuilder::HandleParameter(GateRef gate) { return VisitParameter(gate); } -void LLVMIRBuilder::VisitParameter(AddrShift gate) const +void LLVMIRBuilder::VisitParameter(GateRef gate) const { int argth = circuit_->LoadGatePtrConst(gate)->GetBitField(); - LOG_ECMA(INFO) << " Parameter value" << argth; + COMPILER_LOG(DEBUG) << " Parameter value" << argth; LLVMValueRef value = LLVMGetParam(function_, argth); + g_values[gate] = value; - LOG_ECMA(INFO) << "VisitParameter set gate:" << gate << " value:" << value; + COMPILER_LOG(DEBUG) << "VisitParameter set gate:" << gate << " value:" << value; // NOTE: caller put args, otherwise crash if (value == nullptr) { - LOG_ECMA(ERROR) << "generate LLVM IR for para: " << argth << "fail"; + COMPILER_LOG(FATAL) << "generate LLVM IR for para: " << argth << "fail"; return; } - LOG_ECMA(INFO) << "para arg:" << argth << "value IR:" << LLVMValueToString(value); + COMPILER_LOG(DEBUG) << "para arg:" << argth << "value IR:" << LLVMValueToString(value); } -void LLVMIRBuilder::HandleBranch(AddrShift gate) +void LLVMIRBuilder::HandleBranch(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); - AddrShift bTrue = (circuit_->GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; - AddrShift bFalse = (circuit_->GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + GateRef bTrue = (circuit_->GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; + GateRef bFalse = (circuit_->GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; int bbTrue = instIdMapBbId_[circuit_->GetId(bTrue)]; int bbFalse = instIdMapBbId_[circuit_->GetId(bFalse)]; VisitBranch(gate, ins[1], bbTrue, bbFalse); } -void LLVMIRBuilder::HandleIntMod(AddrShift gate) +void LLVMIRBuilder::HandleIntMod(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitIntMod(gate, ins[0], ins[1]); } -void LLVMIRBuilder::VisitIntMod(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntMod(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int mod gate:" << gate; + COMPILER_LOG(DEBUG) << "int mod gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleFloatMod(AddrShift gate) +void LLVMIRBuilder::HandleFloatMod(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitFloatMod(gate, ins[0], ins[1]); } -void LLVMIRBuilder::VisitFloatMod(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitFloatMod(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "float mod gate:" << gate; + COMPILER_LOG(DEBUG) << "float mod gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bfalse) +void LLVMIRBuilder::VisitBranch(GateRef gate, GateRef cmp, int btrue, int bfalse) { - LOG_ECMA(INFO) << "cmp gate:" << cmp; + COMPILER_LOG(DEBUG) << "cmp gate:" << cmp; if (g_values.count(cmp) == 0) { - LOG_ECMA(ERROR) << "Branch condition gate is nullptr!"; + COMPILER_LOG(ERROR) << "Branch condition gate is nullptr!"; return; } LLVMValueRef cond = g_values[cmp]; @@ -776,14 +858,14 @@ void LLVMIRBuilder::VisitBranch(AddrShift gate, AddrShift cmp, int btrue, int bf g_values[gate] = result; } -void LLVMIRBuilder::HandleSwitch(AddrShift gate) +void LLVMIRBuilder::HandleSwitch(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitSwitch(gate, ins[1], outs); } -void LLVMIRBuilder::VisitSwitch(AddrShift gate, AddrShift input, const std::vector &outList) +void LLVMIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector &outList) { LLVMValueRef cond = g_values[input]; unsigned caseNum = outList.size(); @@ -810,187 +892,289 @@ void LLVMIRBuilder::VisitSwitch(AddrShift gate, AddrShift input, const std::vect g_values[gate] = result; } -void LLVMIRBuilder::VisitLoad(AddrShift gate, MachineRep rep, AddrShift base) const +void LLVMIRBuilder::VisitLoad(GateRef gate, GateRef base) const { - LOG_ECMA(INFO) << "Load base gate:" << base; + COMPILER_LOG(DEBUG) << "Load base gate:" << base; LLVMValueRef baseAddr = g_values[base]; - if (LLVMGetTypeKind(LLVMTypeOf(baseAddr)) == LLVMIntegerTypeKind) { - baseAddr = LLVMBuildIntToPtr(builder_, baseAddr, LLVMPointerType(GetMachineRepType(rep), 0), ""); - } - baseAddr = LLVMBuildPointerCast(builder_, baseAddr, LLVMPointerType(GetMachineRepType(rep), 0), ""); - LLVMValueRef value = LLVMBuildLoad(builder_, baseAddr, ""); - g_values[gate] = value; - LOG_ECMA(INFO) << "Load value:" << value << " " - << "value type" << LLVMTypeOf(value); + LLVMTypeRef pointerType = ConvertLLVMTypeFromGate(gate); + LLVMDumpType(pointerType); + LLVMTypeRef returnType; + baseAddr = CanonicalizeToPtr(baseAddr); + returnType = ConvertLLVMTypeFromGate(gate); + baseAddr = LLVMBuildPointerCast(builder_, baseAddr, + LLVMPointerType(returnType, LLVMGetPointerAddressSpace(ConvertLLVMTypeFromGate(base))), ""); + LLVMValueRef result = LLVMBuildLoad(builder_, baseAddr, ""); + g_values[gate] = result; } -void LLVMIRBuilder::VisitStore(AddrShift gate, MachineRep rep, AddrShift base, AddrShift dataToStore) const +void LLVMIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef dataToStore) const { - LOG_ECMA(INFO) << "store base gate:" << base; + COMPILER_LOG(DEBUG) << "store base gate:" << base; LLVMValueRef baseAddr = g_values[base]; - if (LLVMGetTypeKind(LLVMTypeOf(baseAddr)) == LLVMIntegerTypeKind) { - baseAddr = LLVMBuildIntToPtr(builder_, baseAddr, LLVMPointerType(GetMachineRepType(rep), 0), ""); - } - baseAddr = LLVMBuildPointerCast(builder_, baseAddr, LLVMPointerType(GetMachineRepType(rep), 0), ""); - LLVMValueRef value = LLVMBuildStore(builder_, g_values[dataToStore], baseAddr); + LLVMDumpValue(baseAddr); + std::cout << std::endl; + baseAddr = CanonicalizeToPtr(baseAddr); + LLVMValueRef data = g_values[dataToStore]; + baseAddr = LLVMBuildPointerCast(builder_, baseAddr, + LLVMPointerType(ConvertLLVMTypeFromGate(dataToStore), + LLVMGetPointerAddressSpace(ConvertLLVMTypeFromGate(base))), ""); + LLVMValueRef value = LLVMBuildStore(builder_, data, baseAddr); g_values[gate] = value; - LOG_ECMA(INFO) << "store value:" << value << " " - << "value type" << LLVMTypeOf(value); + COMPILER_LOG(DEBUG) << "store value:" << value << " " << "value type" << LLVMTypeOf(value); } -void LLVMIRBuilder::VisitIntOrUintCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMIntPredicate opcode) const +void LLVMIRBuilder::VisitIntOrUintCmp(GateRef gate, GateRef e1, GateRef e2, LLVMIntPredicate opcode) const { - LOG_ECMA(INFO) << "cmp gate:" << gate; + COMPILER_LOG(DEBUG) << "cmp gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + e1Value = CanonicalizeToInt(e1Value); + e2Value = CanonicalizeToInt(e2Value); LLVMValueRef result = LLVMBuildICmp(builder_, opcode, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitFloatOrDoubleCmp(AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const +LLVMValueRef LLVMIRBuilder::CanonicalizeToInt(LLVMValueRef value) const { - LOG_ECMA(INFO) << "cmp gate:" << gate; + if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) { + LLVMValueRef e1Value0 = LLVMBuildExtractElement(builder_, value, LLVMConstInt(LLVMInt32Type(), 0, 1), ""); + LLVMValueRef e1Value1 = LLVMBuildExtractElement(builder_, value, LLVMConstInt(LLVMInt32Type(), 1, 1), ""); + LLVMValueRef tmp1 = LLVMBuildPtrToInt(builder_, e1Value1, LLVMInt64Type(), ""); + LLVMValueRef constValue = LLVMConstInt(LLVMInt64Type(), 32, 0); // 32: offset + LLVMValueRef tmp1Value = LLVMBuildShl(builder_, tmp1, constValue, ""); + LLVMValueRef tmp2Value = LLVMBuildPtrToInt(builder_, e1Value0, LLVMInt64Type(), ""); + LLVMValueRef resultValue = LLVMBuildAdd(builder_, tmp1Value, tmp2Value, ""); + return resultValue; + } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) { + return LLVMBuildPtrToInt(builder_, value, LLVMInt64Type(), ""); + } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) { + return value; + } else { + COMPILER_LOG(DEBUG) << "can't Canonicalize to Int64: "; + abort(); + } +} + +LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value) const +{ + if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) { + LLVMValueRef tmp = LLVMBuildExtractElement(builder_, value, LLVMConstInt(LLVMInt32Type(), 0, 1), ""); + return LLVMBuildPointerCast(builder_, tmp, LLVMPointerType(LLVMInt8Type(), 1), ""); + } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) { + return LLVMBuildPointerCast(builder_, value, + LLVMPointerType(LLVMInt8Type(), LLVMGetPointerAddressSpace(LLVMTypeOf(value))), ""); + } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) { + LLVMValueRef tmp = LLVMBuildIntToPtr(builder_, value, LLVMPointerType(LLVMInt64Type(), 0), ""); + return LLVMBuildPointerCast(builder_, tmp, + LLVMPointerType(LLVMInt8Type(), LLVMGetPointerAddressSpace(LLVMTypeOf(value))), ""); + } else { + COMPILER_LOG(DEBUG) << "can't Canonicalize to Ptr: "; + abort(); + } +} + +void LLVMIRBuilder::VisitFloatOrDoubleCmp(GateRef gate, GateRef e1, GateRef e2, LLVMRealPredicate opcode) const +{ + COMPILER_LOG(DEBUG) << "cmp gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFCmp(builder_, opcode, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleIntRev(AddrShift gate) +void LLVMIRBuilder::HandleIntRev(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitIntRev(gate, ins[0]); } -void LLVMIRBuilder::VisitIntRev(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitIntRev(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "int sign invert gate:" << gate; + COMPILER_LOG(DEBUG) << "int sign invert gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildNot(builder_, e1Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleIntAdd(AddrShift gate) +void LLVMIRBuilder::HandleIntAdd(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::INT32_ADD: { - VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD32); - break; - } - case OpCode::INT64_ADD: { - VisitIntAdd(gate, ins[0], ins[1], MachineRep::K_WORD64); - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitIntAdd(gate, ins[0], ins[1]); } -void LLVMIRBuilder::VisitIntAdd(AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const +LLVMValueRef LLVMIRBuilder::PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep) const { - LOG_ECMA(INFO) << "int add gate:" << gate; + LLVMValueRef ptr = CanonicalizeToPtr(baseAddr); + LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offset, 1, ""); + LLVMValueRef result = LLVMBuildPointerCast(builder_, dstRef8, rep, ""); + return result; +} + +LLVMValueRef LLVMIRBuilder::VectorAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep) const +{ + LLVMValueRef ptr = CanonicalizeToPtr(baseAddr); + LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offset, 1, ""); + LLVMValueRef result = LLVMBuildInsertElement(builder_, baseAddr, dstRef8, LLVMConstInt(LLVMInt32Type(), 0, 0), ""); + return result; +} + +void LLVMIRBuilder::VisitIntAdd(GateRef gate, GateRef e1, GateRef e2) const +{ + COMPILER_LOG(DEBUG) << "int add gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); - if (LLVMGetTypeKind(LLVMTypeOf(e1Value)) == LLVMPointerTypeKind) { // for scenario: pointer + offset - e1Value = LLVMBuildPtrToInt(builder_, e1Value, GetMachineRepType(rep), ""); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + LLVMTypeRef e1Type = ConvertLLVMTypeFromGate(e1); + LLVMValueRef result; + LLVMValueRef offset = e2Value; + /* pointer int + vector{i8 * x 2} int + */ + LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate); + if (LLVMGetTypeKind(e1Type) == LLVMPointerTypeKind) { // for scenario: pointer + offset + result = PointerAdd(e1Value, offset, returnType); + } else if (LLVMGetTypeKind(e1Type) == LLVMVectorTypeKind) { + result = VectorAdd(e1Value, offset, returnType); + } else { + LLVMValueRef tmp1Value = LLVMBuildIntCast2(builder_, e1Value, returnType, 0, ""); + LLVMValueRef tmp2Value = LLVMBuildIntCast2(builder_, e2Value, returnType, 0, ""); + result = LLVMBuildAdd(builder_, tmp1Value, tmp2Value, ""); + if (LLVMTypeOf(tmp1Value) != LLVMTypeOf(tmp2Value)) { + ASSERT(LLVMTypeOf(tmp1Value) == LLVMTypeOf(tmp2Value)); + } } - LLVMValueRef result = LLVMBuildAdd(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleFloatAdd(AddrShift gate) +LLVMTypeRef LLVMIRBuilder::ConvertLLVMTypeFromGate(GateRef gate) const { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + if (circuit_->GetTypeCode(gate) >= TypeCode::JS_TYPE_OBJECT_START) { + if (triple_ == TripleConst::GetLLVMArm32Triple()) { + return LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2); + } else { + return LLVMPointerType(LLVMInt64Type(), 1); + } + } + switch (circuit_->GetOpCode(gate).GetValueCode()) { + case ValueCode::NOVALUE: + return LLVMVoidType(); + case ValueCode::ANYVALUE: + { + if (triple_ == TripleConst::GetLLVMArm32Triple()) { + return LLVMInt32Type(); + } else { + return LLVMInt64Type(); + } + } + case ValueCode::INT1: + return LLVMInt1Type(); + case ValueCode::INT8: + return LLVMInt8Type(); + case ValueCode::INT16: + return LLVMInt16Type(); + case ValueCode::INT32: + return LLVMInt32Type(); + case ValueCode::INT64: + return LLVMInt64Type(); + case ValueCode::FLOAT32: + return LLVMFloatType(); + case ValueCode::FLOAT64: + return LLVMDoubleType(); + default: + abort(); + } +} + +void LLVMIRBuilder::HandleFloatAdd(GateRef gate) +{ + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitFloatAdd(gate, ins[0], ins[1]); } -void LLVMIRBuilder::VisitFloatAdd(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitFloatAdd(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "float add gate:" << gate; + COMPILER_LOG(DEBUG) << "float add gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFAdd(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleFloatSub(AddrShift gate) +void LLVMIRBuilder::HandleFloatSub(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitFloatSub(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleFloatMul(AddrShift gate) +void LLVMIRBuilder::HandleFloatMul(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitFloatMul(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleFloatDiv(AddrShift gate) +void LLVMIRBuilder::HandleFloatDiv(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitFloatDiv(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleIntSub(AddrShift gate) +void LLVMIRBuilder::HandleIntSub(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitIntSub(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleIntMul(AddrShift gate) +void LLVMIRBuilder::HandleIntMul(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitIntMul(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleIntOr(AddrShift gate) +void LLVMIRBuilder::HandleIntOr(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitIntOr(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleIntXor(AddrShift gate) +void LLVMIRBuilder::HandleIntXor(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitIntXor(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleIntLsr(AddrShift gate) +void LLVMIRBuilder::HandleIntLsr(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitIntLsr(gate, ins[0], ins[1]); } -void LLVMIRBuilder::HandleIntOrUintCmp(AddrShift gate) +void LLVMIRBuilder::HandleIntOrUintCmp(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); switch (circuit_->GetOpCode(gate)) { case OpCode::INT32_SLT: // no break, fall through case OpCode::INT64_SLT: { @@ -1033,314 +1217,315 @@ void LLVMIRBuilder::HandleIntOrUintCmp(AddrShift gate) } } -void LLVMIRBuilder::HandleFloatOrDoubleCmp(AddrShift gate) +void LLVMIRBuilder::HandleFloatOrDoubleCmp(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); VisitFloatOrDoubleCmp(gate, ins[0], ins[1], LLVMRealOEQ); } -void LLVMIRBuilder::HandleLoad(AddrShift gate) +void LLVMIRBuilder::HandleLoad(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::INT8_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD8, base); - break; - } - case OpCode::INT16_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD16, base); - break; - } - case OpCode::INT32_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD32, base); - break; - } - case OpCode::INT64_LOAD: { - AddrShift base = ins[1]; - VisitLoad(gate, MachineRep::K_WORD64, base); - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + GateRef base = ins[1]; + VisitLoad(gate, base); } -void LLVMIRBuilder::HandleStore(AddrShift gate) +void LLVMIRBuilder::HandleStore(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - std::vector outs = circuit_->GetOutVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::INT32_STORE: { - VisitStore(gate, MachineRep::K_WORD32, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate - break; - } - case OpCode::INT64_STORE: { - VisitStore(gate, MachineRep::K_WORD64, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + std::vector outs = circuit_->GetOutVector(gate); + VisitStore(gate, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate } -void LLVMIRBuilder::HandleChangeInt32ToDouble(AddrShift gate) +void LLVMIRBuilder::HandleChangeInt32ToDouble(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitChangeInt32ToDouble(gate, ins[0]); } -void LLVMIRBuilder::HandleChangeDoubleToInt32(AddrShift gate) +void LLVMIRBuilder::HandleChangeDoubleToInt32(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitChangeDoubleToInt32(gate, ins[0]); } -void LLVMIRBuilder::VisitFloatSub(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::HandleChangeTaggedPointerToInt64(GateRef gate) { - LOG_ECMA(INFO) << "float sub gate:" << gate; + std::vector ins = circuit_->GetInVector(gate); + VisitChangeTaggedPointerToInt64(gate, ins[0]); +} + +void LLVMIRBuilder::VisitFloatSub(GateRef gate, GateRef e1, GateRef e2) const +{ + COMPILER_LOG(DEBUG) << "float sub gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFSub(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitFloatMul(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitFloatMul(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "float mul gate:" << gate; + COMPILER_LOG(DEBUG) << "float mul gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFMul(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitFloatDiv(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitFloatDiv(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "float div gate:" << gate; + COMPILER_LOG(DEBUG) << "float div gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildFDiv(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitIntSub(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntSub(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int sub gate:" << gate; + COMPILER_LOG(DEBUG) << "int sub gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildSub(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitIntMul(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntMul(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int mul gate:" << gate; + COMPILER_LOG(DEBUG) << "int mul gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); LLVMValueRef result = LLVMBuildMul(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitIntOr(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntOr(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int or gate:" << gate; + COMPILER_LOG(DEBUG) << "int or gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + + e1Value = CanonicalizeToInt(e1Value); + e2Value = CanonicalizeToInt(e2Value); LLVMValueRef result = LLVMBuildOr(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleIntAnd(AddrShift gate) +void LLVMIRBuilder::HandleIntAnd(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitIntAnd(gate, ins[0], ins[1]); } -void LLVMIRBuilder::VisitIntAnd(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntAnd(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int and gate:" << gate; + COMPILER_LOG(DEBUG) << "int and gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + e1Value = CanonicalizeToInt(e1Value); + e2Value = CanonicalizeToInt(e2Value); LLVMValueRef result = LLVMBuildAnd(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitIntXor(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntXor(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int xor gate:" << gate; + COMPILER_LOG(DEBUG) << "int xor gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + e1Value = CanonicalizeToInt(e1Value); + e2Value = CanonicalizeToInt(e2Value); LLVMValueRef result = LLVMBuildXor(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitIntLsr(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntLsr(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int lsr gate:" << gate; + COMPILER_LOG(DEBUG) << "int lsr gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + e1Value = CanonicalizeToInt(e1Value); + e2Value = CanonicalizeToInt(e2Value); LLVMValueRef result = LLVMBuildLShr(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleIntLsl(AddrShift gate) +void LLVMIRBuilder::HandleIntLsl(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitIntLsl(gate, ins[0], ins[1]); } -void LLVMIRBuilder::VisitIntLsl(AddrShift gate, AddrShift e1, AddrShift e2) const +void LLVMIRBuilder::VisitIntLsl(GateRef gate, GateRef e1, GateRef e2) const { - LOG_ECMA(INFO) << "int lsl gate:" << gate; + COMPILER_LOG(DEBUG) << "int lsl gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef e2Value = g_values[e2]; - LOG_ECMA(INFO) << "operand 1: " << LLVMValueToString(e2Value); + COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value); + e1Value = CanonicalizeToInt(e1Value); + e2Value = CanonicalizeToInt(e2Value); LLVMValueRef result = LLVMBuildShl(builder_, e1Value, e2Value, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitZExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const +void LLVMIRBuilder::VisitZExtInt(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "int zero extension gate:" << gate; + COMPILER_LOG(DEBUG) << "int zero extension gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); - LLVMValueRef result = LLVMBuildZExt(builder_, e1Value, GetMachineRepType(rep), ""); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); + LLVMValueRef result = LLVMBuildZExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitSExtInt(AddrShift gate, AddrShift e1, MachineRep rep) const +void LLVMIRBuilder::VisitSExtInt(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "int sign extension gate:" << gate; + COMPILER_LOG(DEBUG) << "int sign extension gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); - LLVMValueRef result = LLVMBuildSExt(builder_, e1Value, GetMachineRepType(rep), ""); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); + LLVMValueRef result = LLVMBuildSExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleCastIntXToIntY(AddrShift gate) +void LLVMIRBuilder::HandleCastIntXToIntY(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); - switch (circuit_->GetOpCode(gate)) { - case OpCode::TRUNC_INT64_TO_INT1: - case OpCode::TRUNC_INT32_TO_INT1: { - VisitCastIntXToIntY(gate, ins[0], MachineRep::K_BIT); - break; - } - case OpCode::TRUNC_INT64_TO_INT32: { - VisitCastIntXToIntY(gate, ins[0], MachineRep::K_WORD32); - break; - } - default: { - break; - } - } + std::vector ins = circuit_->GetInVector(gate); + VisitCastIntXToIntY(gate, ins[0]); } -void LLVMIRBuilder::VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep rep) const +void LLVMIRBuilder::VisitCastIntXToIntY(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "int cast2 int gate:" << gate; + COMPILER_LOG(DEBUG) << "int cast2 int gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); - LLVMValueRef result = LLVMBuildIntCast2(builder_, e1Value, GetMachineRepType(rep), 1, ""); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); + LLVMValueRef result = LLVMBuildIntCast2(builder_, e1Value, ConvertLLVMTypeFromGate(gate), 1, ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitChangeInt32ToDouble(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "int cast2 double gate:" << gate; + COMPILER_LOG(DEBUG) << "int cast2 double gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildSIToFP(builder_, e1Value, LLVMDoubleType(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::VisitChangeDoubleToInt32(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "double cast2 int32 gate:" << gate; + COMPILER_LOG(DEBUG) << "double cast2 int32 gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, LLVMInt32Type(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleCastInt64ToDouble(AddrShift gate) +void LLVMIRBuilder::VisitChangeTaggedPointerToInt64(GateRef gate, GateRef e1) const { - std::vector ins = circuit_->GetInVector(gate); + COMPILER_LOG(DEBUG) << "double cast2 int32 gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); + LLVMValueRef result = CanonicalizeToInt(e1Value); + g_values[gate] = result; + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); +} + +void LLVMIRBuilder::HandleCastInt64ToDouble(GateRef gate) +{ + std::vector ins = circuit_->GetInVector(gate); VisitCastInt64ToDouble(gate, ins[0]); } -void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitCastInt64ToDouble(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "int cast2 double gate:" << gate; + COMPILER_LOG(DEBUG) << "int cast2 double gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, LLVMDoubleType(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); } -void LLVMIRBuilder::HandleCastDoubleToInt(AddrShift gate) +void LLVMIRBuilder::HandleCastDoubleToInt(GateRef gate) { - std::vector ins = circuit_->GetInVector(gate); + std::vector ins = circuit_->GetInVector(gate); VisitCastDoubleToInt(gate, ins[0]); } -void LLVMIRBuilder::VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitCastDoubleToInt(GateRef gate, GateRef e1) const { - LOG_ECMA(INFO) << "double cast2 int gate:" << gate; + COMPILER_LOG(DEBUG) << "double cast2 int gate:" << gate; LLVMValueRef e1Value = g_values[e1]; - LOG_ECMA(INFO) << "operand 0: " << LLVMValueToString(e1Value); + COMPILER_LOG(DEBUG) << "operand 0: " << LLVMValueToString(e1Value); LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, LLVMInt64Type(), ""); g_values[gate] = result; - LOG_ECMA(INFO) << "result: " << LLVMValueToString(result); + COMPILER_LOG(DEBUG) << "result: " << LLVMValueToString(result); +} + +LLVMTypeRef LLVMIRBuilder::ConvertLLVMTypeFromTypeCode(TypeCode type) const +{ + if (UNLIKELY(type == TypeCode::NOTYPE)) { + UNREACHABLE(); + } + if (type <= TypeCode::JS_TYPE_SPECIAL_STOP) { + return LLVMInt64Type(); + } + // type >= TypeCode::JS_TYPE_OBJECT_START + return LLVMPointerType(LLVMInt64Type(), 1); } LLVMStubModule::LLVMStubModule(const char *name, const char *triple) + : triple_(triple) { module_ = LLVMModuleCreateWithName(name); + triple_ = triple; LLVMSetTarget(module_, triple); } +LLVMStubModule::~LLVMStubModule() +{ + if (module_ != nullptr) { + LLVMDisposeModule(module_); + module_ = nullptr; + } +} + void LLVMStubModule::Initialize() { uint32_t i; @@ -1356,12 +1541,14 @@ void LLVMStubModule::Initialize() stubFunctionType_[i] = GetLLVMFunctionTypeStubDescriptor(stubDescriptor); } } +#ifndef ECMASCRIPT_ENABLE_SPECIFIC_STUBS for (i = 0; i < MAX_TEST_FUNCTION_COUNT; i++) { auto testFuncDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + TEST_FUNCTION_OFFSET); if (!testFuncDescriptor->GetName().empty()) { testFunctions_[i] = GetLLVMFunctionByStubDescriptor(testFuncDescriptor); } } +#endif } LLVMValueRef LLVMStubModule::GetLLVMFunctionByStubDescriptor(StubDescriptor *stubDescriptor) @@ -1379,28 +1566,35 @@ LLVMTypeRef LLVMStubModule::GetLLVMFunctionTypeStubDescriptor(StubDescriptor *st auto paramsType = stubDescriptor->GetParametersType(); paramTys.push_back(ConvertLLVMTypeFromMachineType(paramsType[i])); } - auto functype = LLVMFunctionType(returnType, paramTys.data(), paramCount, 0); + auto functype = LLVMFunctionType(returnType, paramTys.data(), paramCount, stubDescriptor->GetVariableArgs()); return functype; } LLVMTypeRef LLVMStubModule::ConvertLLVMTypeFromMachineType(MachineType type) { static std::map machineTypeMap = { - {MachineType::NONE_TYPE, LLVMVoidType()}, - {MachineType::BOOL_TYPE, LLVMInt1Type()}, - {MachineType::INT8_TYPE, LLVMInt8Type()}, - {MachineType::INT16_TYPE, LLVMInt16Type()}, - {MachineType::INT32_TYPE, LLVMInt32Type()}, - {MachineType::INT64_TYPE, LLVMInt64Type()}, - {MachineType::UINT8_TYPE, LLVMInt8Type()}, - {MachineType::UINT16_TYPE, LLVMInt16Type()}, - {MachineType::UINT32_TYPE, LLVMInt32Type()}, - {MachineType::UINT64_TYPE, LLVMInt64Type()}, - {MachineType::FLOAT32_TYPE, LLVMFloatType()}, - {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, - {MachineType::TAGGED_POINTER_TYPE, LLVMPointerType(LLVMInt64Type(), 1)}, - {MachineType::TAGGED_TYPE, LLVMInt64Type()}, + {MachineType::NONE, LLVMVoidType()}, + {MachineType::BOOL, LLVMInt1Type()}, + {MachineType::INT8, LLVMInt8Type()}, + {MachineType::INT16, LLVMInt16Type()}, + {MachineType::INT32, LLVMInt32Type()}, + {MachineType::INT64, LLVMInt64Type()}, + {MachineType::UINT8, LLVMInt8Type()}, + {MachineType::UINT16, LLVMInt16Type()}, + {MachineType::UINT32, LLVMInt32Type()}, + {MachineType::UINT64, LLVMInt64Type()}, + {MachineType::FLOAT32, LLVMFloatType()}, + {MachineType::FLOAT64, LLVMDoubleType()}, + {MachineType::NATIVE_POINTER, LLVMInt64Type()}, + {MachineType::TAGGED_POINTER, LLVMPointerType(LLVMInt64Type(), 1)}, + {MachineType::TAGGED, LLVMPointerType(LLVMInt64Type(), 1)}, }; + if (triple_ == TripleConst::GetLLVMArm32Triple()) { + machineTypeMap[MachineType::NATIVE_POINTER] = LLVMInt32Type(); + LLVMTypeRef vectorType = LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2); // 2: packed vector type + machineTypeMap[MachineType::TAGGED_POINTER] = vectorType; + machineTypeMap[MachineType::TAGGED] = vectorType; + } return machineTypeMap[type]; } } // namespace kungfu diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index 9191be54..ea859be2 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -22,8 +22,9 @@ #include #include "ecmascript/compiler/circuit.h" -#include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/compiler/gate.h" +#include "ecmascript/compiler/stub_descriptor.h" +#include "ecmascript/compiler/triple.h" #include "llvm-c/Core.h" #include "llvm-c/Types.h" @@ -32,7 +33,7 @@ using OperandsVector = std::set; class BasicBlock; using BasicBlockMap = std::map>; class LLVMIRBuilder; -typedef void (LLVMIRBuilder::*HandleType)(AddrShift gate); +using HandleType = void(LLVMIRBuilder::*)(GateRef gate); enum class MachineRep { K_NONE, @@ -44,7 +45,9 @@ enum class MachineRep { // FP representations must be last, and in order of increasing size. K_FLOAT32, K_FLOAT64, - K_SIMD128 + K_SIMD128, + K_PTR_1, // Tagged Pointer + K_META, }; class BasicBlock { @@ -91,7 +94,7 @@ private: struct NotMergedPhiDesc { BasicBlock *pred; - AddrShift operand; + GateRef operand; LLVMValueRef phi; }; @@ -105,8 +108,8 @@ struct LLVMTFBuilderBasicBlockImpl { class LLVMStubModule { public: - explicit LLVMStubModule(const char *name, const char *triple); - ~LLVMStubModule() = default; + LLVMStubModule(const char *name, const char *hostTriple); + ~LLVMStubModule(); void Initialize(); @@ -129,8 +132,17 @@ public: LLVMValueRef GetTestFunction(uint32_t index) { - ASSERT(index - TEST_FUNCTION_OFFSET < MAX_TEST_FUNCTION_COUNT); - return testFunctions_[index - TEST_FUNCTION_OFFSET]; +#ifndef ECMASCRIPT_ENABLE_SPECIFIC_STUBS + ASSERT(index - TEST_FUNCTION_OFFSET < MAX_TEST_FUNCTION_COUNT); + return testFunctions_[index - TEST_FUNCTION_OFFSET]; +#else + return nullptr; +#endif + } + + const char *GetTargetTriple() const + { + return triple_; } private: @@ -142,58 +154,63 @@ private: static constexpr uint32_t TEST_FUNCTION_OFFSET = kungfu::TEST_FUNC_BEGIN + 1; std::array stubFunctions_ {nullptr}; std::array stubFunctionType_ {nullptr}; +#ifndef ECMASCRIPT_ENABLE_SPECIFIC_STUBS std::array testFunctions_ {nullptr}; +#endif LLVMModuleRef module_; + const char *triple_; }; #define OPCODES(V) \ - V(Call, (AddrShift gate, const std::vector &inList)) \ - V(Alloca, (AddrShift gate)) \ + V(Call, (GateRef gate, const std::vector &inList)) \ + V(Alloca, (GateRef gate)) \ V(Block, (int id, const OperandsVector &predecessors)) \ V(Goto, (int block, int bbout)) \ - V(Parameter, (AddrShift gate) const ) \ - V(Int32Constant, (AddrShift gate, int32_t value) const ) \ - V(Int64Constant, (AddrShift gate, int64_t value) const ) \ - V(Float64Constant, (AddrShift gate, double value) const ) \ - V(ZExtInt, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ - V(SExtInt, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ - V(Load, (AddrShift gate, MachineRep rep, AddrShift base) const ) \ - V(Store, (AddrShift gate, MachineRep rep, AddrShift base, AddrShift value) const ) \ - V(IntRev, (AddrShift gate, AddrShift e1) const ) \ - V(IntAdd, (AddrShift gate, AddrShift e1, AddrShift e2, MachineRep rep) const ) \ - V(FloatAdd, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(FloatSub, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(FloatMul, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(FloatDiv, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntSub, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntMul, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntOr, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntAnd, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntXor, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntLsr, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(Int32LessThanOrEqual, (AddrShift gate, AddrShift e1, AddrShift e2) const ) \ - V(IntOrUintCmp, (AddrShift gate, AddrShift e1, AddrShift e2, LLVMIntPredicate opcode) const ) \ - V(FloatOrDoubleCmp, (AddrShift gate, AddrShift e1, AddrShift e2, LLVMRealPredicate opcode) const ) \ - V(Branch, (AddrShift gate, AddrShift cmp, AddrShift btrue, AddrShift bfalse)) \ - V(Switch, (AddrShift gate, AddrShift input, const std::vector &outList)) \ - V(SwitchCase, (AddrShift gate, AddrShift switchBranch, AddrShift out)) \ - V(Phi, (AddrShift gate, const std::vector &srcGates, MachineRep rep)) \ - V(Return, (AddrShift gate, AddrShift popCount, const std::vector &operands) const ) \ - V(CastIntXToIntY, (AddrShift gate, AddrShift e1, MachineRep rep) const ) \ - V(ChangeInt32ToDouble, (AddrShift gate, AddrShift e1) const ) \ - V(ChangeDoubleToInt32, (AddrShift gate, AddrShift e1) const ) \ - V(CastInt64ToDouble, (AddrShift gate, AddrShift e1) const ) \ - V(CastDoubleToInt, (AddrShift gate, AddrShift e1) const ) \ - V(CastInt64ToPointer, (AddrShift gate, AddrShift e1) const ) \ - V(IntLsl, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ - V(IntMod, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ - V(FloatMod, (AddrShift gate, AddrShift e1, AddrShift e2) const) \ - + V(Parameter, (GateRef gate) const) \ + V(Int32Constant, (GateRef gate, int32_t value) const) \ + V(Int64Constant, (GateRef gate, int64_t value) const) \ + V(Float64Constant, (GateRef gate, double value) const) \ + V(ZExtInt, (GateRef gate, GateRef e1) const) \ + V(SExtInt, (GateRef gate, GateRef e1) const) \ + V(Load, (GateRef gate, GateRef base) const) \ + V(Store, (GateRef gate, GateRef base, GateRef value) const) \ + V(IntRev, (GateRef gate, GateRef e1) const) \ + V(IntAdd, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(FloatAdd, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(FloatSub, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(FloatMul, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(FloatDiv, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntSub, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntMul, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntOr, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntAnd, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntXor, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntLsr, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(Int32LessThanOrEqual, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntOrUintCmp, (GateRef gate, GateRef e1, GateRef e2, LLVMIntPredicate opcode) const) \ + V(FloatOrDoubleCmp, (GateRef gate, GateRef e1, GateRef e2, LLVMRealPredicate opcode) const) \ + V(Branch, (GateRef gate, GateRef cmp, GateRef btrue, GateRef bfalse)) \ + V(Switch, (GateRef gate, GateRef input, const std::vector &outList)) \ + V(SwitchCase, (GateRef gate, GateRef switchBranch, GateRef out)) \ + V(Phi, (GateRef gate, const std::vector &srcGates)) \ + V(Return, (GateRef gate, GateRef popCount, const std::vector &operands) const) \ + V(ReturnVoid, (GateRef gate) const) \ + V(CastIntXToIntY, (GateRef gate, GateRef e1) const) \ + V(ChangeInt32ToDouble, (GateRef gate, GateRef e1) const) \ + V(ChangeDoubleToInt32, (GateRef gate, GateRef e1) const) \ + V(CastInt64ToDouble, (GateRef gate, GateRef e1) const) \ + V(CastDoubleToInt, (GateRef gate, GateRef e1) const) \ + V(CastInt64ToPointer, (GateRef gate, GateRef e1) const) \ + V(IntLsl, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(IntMod, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(FloatMod, (GateRef gate, GateRef e1, GateRef e2) const) \ + V(ChangeTaggedPointerToInt64, (GateRef gate, GateRef e1) const) class LLVMIRBuilder { public: - explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, - LLVMStubModule *module, LLVMValueRef function); + explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, + LLVMStubModule *module, LLVMValueRef function, + const char *hostTriple = TripleConst::GetLLVMAmd64Triple()); ~LLVMIRBuilder(); void Build(); @@ -201,28 +218,47 @@ private: #define DECLAREVISITOPCODE(name, signature) void Visit##name signature; OPCODES(DECLAREVISITOPCODE) #undef DECLAREVISITOPCODE - #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(AddrShift gate); + #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(GateRef gate); OPCODES(DECLAREHANDLEOPCODE) #undef DECLAREHANDLEOPCODE BasicBlock *EnsurBasicBlock(int id); - LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder); + LLVMValueRef LLVMCallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller); + void SaveCallerSp(); + LLVMValueRef LLVMCallerSp(LLVMModuleRef &module, LLVMBuilderRef &builder, + LLVMMetadataRef meta); void PrologueHandle(LLVMModuleRef &module, LLVMBuilderRef &builder); LLVMBasicBlockRef EnsureLLVMBB(BasicBlock *bb) const; LLVMTFBuilderBasicBlockImpl *EnsureLLVMBBImpl(BasicBlock *bb) const; void StartLLVMBuilder(BasicBlock *bb) const; LLVMTypeRef GetMachineRepType(MachineRep rep) const; - int FindBasicBlock(AddrShift gate) const; + int FindBasicBlock(GateRef gate) const; void EndCurrentBlock() const; void End(); void ProcessPhiWorkList(); void AssignHandleMap(); std::string LLVMValueToString(LLVMValueRef val) const; + LLVMTypeRef ConvertLLVMTypeFromTypeCode(TypeCode type) const; + + LLVMTypeRef GetArchRelate() const + { + if (triple_ == TripleConst::GetLLVMArm32Triple()) { + return LLVMInt32Type(); + } + return LLVMInt64Type(); + } + LLVMTypeRef ConvertLLVMTypeFromGate(GateRef gate) const; + LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep) const; + LLVMValueRef VectorAdd(LLVMValueRef e1Value, LLVMValueRef e2Value, LLVMTypeRef rep) const; + LLVMValueRef CanonicalizeToInt(LLVMValueRef value) const; + + LLVMValueRef CanonicalizeToPtr(LLVMValueRef value) const; private: - const std::vector> *schedule_ {nullptr}; + + const std::vector> *schedule_ {nullptr}; const Circuit *circuit_ {nullptr}; BasicBlock *currentBb_ {nullptr}; int lineNumber_ {0}; @@ -238,6 +274,7 @@ private: LLVMStubModule *stubModule_ {nullptr}; std::unordered_map opCodeHandleMap_; std::set opCodeHandleIgnore; + const char *triple_; }; } // namespace kungfu -#endif // PANDA_RUNTIME_ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H \ No newline at end of file +#endif // PANDA_RUNTIME_ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H diff --git a/ecmascript/compiler/machine_type.h b/ecmascript/compiler/machine_type.h index f17f6080..f9b9eb35 100644 --- a/ecmascript/compiler/machine_type.h +++ b/ecmascript/compiler/machine_type.h @@ -18,21 +18,21 @@ namespace kungfu { enum class MachineType { - NONE_TYPE, - BOOL_TYPE, - INT8_TYPE, - INT16_TYPE, - INT32_TYPE, - INT64_TYPE, - UINT8_TYPE, - UINT16_TYPE, - UINT32_TYPE, - UINT64_TYPE, - POINTER_TYPE, - TAGGED_TYPE, - TAGGED_POINTER_TYPE, - FLOAT32_TYPE, - FLOAT64_TYPE, + NONE, + BOOL, + INT8, + INT16, + INT32, + INT64, + UINT8, + UINT16, + UINT32, + UINT64, + FLOAT32, + FLOAT64, + NATIVE_POINTER, // GC will not visit NATIVE_POINTER. + TAGGED, // GC cares + TAGGED_POINTER, }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_MACHINE_TYPE_H \ No newline at end of file diff --git a/ecmascript/compiler/scheduler.cpp b/ecmascript/compiler/scheduler.cpp index a89fbc57..9d75e274 100644 --- a/ecmascript/compiler/scheduler.cpp +++ b/ecmascript/compiler/scheduler.cpp @@ -20,17 +20,17 @@ #include "ecmascript/compiler/verifier.h" namespace kungfu { -using DominatorTreeInfo = std::tuple, std::unordered_map, +using DominatorTreeInfo = std::tuple, std::unordered_map, std::vector>; DominatorTreeInfo Scheduler::CalculateDominatorTree(const Circuit *circuit) { - std::vector bbGatesList; - std::unordered_map bbGatesAddrToIdx; - std::unordered_map dfsTimestamp; + std::vector bbGatesList; + std::unordered_map bbGatesAddrToIdx; + std::unordered_map dfsTimestamp; circuit->AdvanceTime(); { size_t timestamp = 0; - std::deque pendingList; + std::deque pendingList; auto startGate = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY)); circuit->SetMark(startGate, MarkCode::VISITED); pendingList.push_back(startGate); @@ -101,18 +101,18 @@ DominatorTreeInfo Scheduler::CalculateDominatorTree(const Circuit *circuit) return {bbGatesList, bbGatesAddrToIdx, immDom}; } -std::vector> Scheduler::Run(const Circuit *circuit) +std::vector> Scheduler::Run(const Circuit *circuit) { #ifndef NDEBUG if (!Verifier::Run(circuit)) { UNREACHABLE(); } #endif - std::vector bbGatesList; - std::unordered_map bbGatesAddrToIdx; + std::vector bbGatesList; + std::unordered_map bbGatesAddrToIdx; std::vector immDom; std::tie(bbGatesList, bbGatesAddrToIdx, immDom) = Scheduler::CalculateDominatorTree(circuit); - std::vector> result(bbGatesList.size()); + std::vector> result(bbGatesList.size()); for (size_t idx = 0; idx < bbGatesList.size(); idx++) { result[idx].push_back(bbGatesList[idx]); } @@ -162,14 +162,14 @@ std::vector> Scheduler::Run(const Circuit *circuit) return jumpUp[nodeA][0]; }; { - std::vector order; + std::vector order; auto lowerBound = Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, &order).value(); for (const auto &schedulableGate : order) { result[lowerBound.at(schedulableGate)].push_back(schedulableGate); } auto argList = circuit->GetOutVector(Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))); - std::sort(argList.begin(), argList.end(), [&](const AddrShift &lhs, const AddrShift &rhs) -> bool { + std::sort(argList.begin(), argList.end(), [&](const GateRef &lhs, const GateRef &rhs) -> bool { return circuit->GetBitField(lhs) > circuit->GetBitField(rhs); }); for (const auto &arg : argList) { @@ -186,12 +186,12 @@ std::vector> Scheduler::Run(const Circuit *circuit) return result; } -std::optional> Scheduler::CalculateSchedulingUpperBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor, const std::vector &schedulableGatesList) +std::optional> Scheduler::CalculateSchedulingUpperBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor, const std::vector &schedulableGatesList) { - std::unordered_map upperBound; - std::function(AddrShift)> dfs = [&](AddrShift curGate) -> std::optional { + std::unordered_map upperBound; + std::function(GateRef)> dfs = [&](GateRef curGate) -> std::optional { if (upperBound.count(curGate) > 0) { return upperBound[curGate]; } @@ -230,14 +230,14 @@ std::optional> Scheduler::CalculateSchedul return upperBound; } -std::optional> Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &lowestCommonAncestor, std::vector *order) +std::optional> Scheduler::CalculateSchedulingLowerBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &lowestCommonAncestor, std::vector *order) { - std::unordered_map lowerBound; - std::unordered_map useCount; - std::deque pendingList; - std::vector bbAndFixedGatesList; + std::unordered_map lowerBound; + std::unordered_map useCount; + std::deque pendingList; + std::vector bbAndFixedGatesList; for (const auto &item : bbGatesAddrToIdx) { bbAndFixedGatesList.push_back(item.first); for (const auto &succGate : circuit->GetOutVector(item.first)) { @@ -246,7 +246,7 @@ std::optional> Scheduler::CalculateSchedul } } } - std::function dfsVisit = [&](AddrShift curGate) { + std::function dfsVisit = [&](GateRef curGate) { for (const auto &prevGate : circuit->GetInVector(curGate)) { if (circuit->GetOpCode(prevGate).IsSchedulable()) { useCount[prevGate]++; @@ -259,7 +259,7 @@ std::optional> Scheduler::CalculateSchedul for (const auto &gate : bbAndFixedGatesList) { dfsVisit(gate); } - std::function dfsFinish = [&](AddrShift curGate) { + std::function dfsFinish = [&](GateRef curGate) { size_t cnt = 0; for (const auto &prevGate : circuit->GetInVector(curGate)) { if (circuit->GetOpCode(prevGate).IsSchedulable()) { @@ -294,10 +294,10 @@ std::optional> Scheduler::CalculateSchedul return lowerBound; } -void Scheduler::Print(const std::vector> *cfg, const Circuit *circuit) +void Scheduler::Print(const std::vector> *cfg, const Circuit *circuit) { - std::vector bbGatesList; - std::unordered_map bbGatesAddrToIdx; + std::vector bbGatesList; + std::unordered_map bbGatesAddrToIdx; std::vector immDom; std::tie(bbGatesList, bbGatesAddrToIdx, immDom) = Scheduler::CalculateDominatorTree(circuit); std::cout << "==========================================================================" << std::endl; diff --git a/ecmascript/compiler/scheduler.h b/ecmascript/compiler/scheduler.h index 69f569b9..94d8a574 100644 --- a/ecmascript/compiler/scheduler.h +++ b/ecmascript/compiler/scheduler.h @@ -25,18 +25,18 @@ #include "ecmascript/compiler/circuit.h" namespace kungfu { -using ControlFlowGraph = std::vector>; +using ControlFlowGraph = std::vector>; class Scheduler { public: - static std::tuple, std::unordered_map, std::vector> + static std::tuple, std::unordered_map, std::vector> CalculateDominatorTree(const Circuit *circuit); static ControlFlowGraph Run(const Circuit *circuit); - static std::optional> CalculateSchedulingUpperBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor, const std::vector &schedulableGatesList); - static std::optional> CalculateSchedulingLowerBound(const Circuit *circuit, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &lowestCommonAncestor, std::vector *order = nullptr); + static std::optional> CalculateSchedulingUpperBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor, const std::vector &schedulableGatesList); + static std::optional> CalculateSchedulingLowerBound(const Circuit *circuit, + const std::unordered_map &bbGatesAddrToIdx, + const std::function &lowestCommonAncestor, std::vector *order = nullptr); static void Print(const ControlFlowGraph *cfg, const Circuit *circuit); }; }; // namespace kungfu diff --git a/ecmascript/compiler/stub-inl.h b/ecmascript/compiler/stub-inl.h new file mode 100644 index 00000000..549fa8eb --- /dev/null +++ b/ecmascript/compiler/stub-inl.h @@ -0,0 +1,1669 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef ECMASCRIPT_COMPILER_STUB_INL_H +#define ECMASCRIPT_COMPILER_STUB_INL_H + +#include "ecmascript/compiler/stub.h" + +namespace kungfu { +using LabelImpl = Stub::Label::LabelImpl; +using JSTaggedValue = JSTaggedValue; +using JSFunction = panda::ecmascript::JSFunction; +using PropertyBox = panda::ecmascript::PropertyBox; + +void Stub::Label::Seal() +{ + return impl_->Seal(); +} +void Stub::Label::WriteVariable(Stub::Variable *var, GateRef value) +{ + impl_->WriteVariable(var, value); +} +GateRef Stub::Label::ReadVariable(Stub::Variable *var) +{ + return impl_->ReadVariable(var); +} +void Stub::Label::Bind() +{ + impl_->Bind(); +} +void Stub::Label::MergeAllControl() +{ + impl_->MergeAllControl(); +} +void Stub::Label::MergeAllDepend() +{ + impl_->MergeAllDepend(); +} +void Stub::Label::AppendPredecessor(const Stub::Label *predecessor) +{ + impl_->AppendPredecessor(predecessor->GetRawLabel()); +} +std::vector Stub::Label::GetPredecessors() const +{ + std::vector