blob: 9b6d7e68c6296fd65e54c55763ffba15f05e0d41 [file]
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* 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 <cinttypes>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <type_traits>
#include "Alignment.hpp"
#include "KAssert.h"
#include "KString.h"
#include "StackTrace.hpp"
#include "Memory.h"
#include "Porting.h"
#include "Natives.h"
#include "Types.h"
#include "std_support/CStdlib.hpp"
using namespace kotlin;
extern "C" {
KInt Kotlin_Any_hashCode(KConstRef thiz) {
// NOTE: `Any?.identityHashCode()` is used in Blackhole implementations of both kotlinx-benchmark and
// K/N's own benchmarks. These usages rely on this being an intrinsic property of the object.
// So, calling `obj.identityHashCode()` should be seen by the optimizer as reading the entire
// `obj` memory, and any changes to `obj` beforehand couldn't be optimized away. Additionally,
// it should be very cheap to call in order not to pollute the time measurements.
// Here we will use different mechanism for stable hashcode, using meta-objects
// if moving collector will be used.
return reinterpret_cast<uintptr_t>(thiz);
}
NO_INLINE OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
kotlin::StackTrace stackTrace;
{
// Don't use `kotlin::CallWithThreadState` to avoid messing up callstack.
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
// Skip this function and primary `Throwable` constructor.
stackTrace = kotlin::StackTrace<>::current(2);
}
ObjHolder resultHolder;
ObjHeader* result = AllocArrayInstance(theNativePtrArrayTypeInfo, stackTrace.size(), resultHolder.slot());
for (size_t index = 0; index < stackTrace.size(); ++index) {
Kotlin_NativePtrArray_set(result, index, stackTrace[index]);
}
RETURN_OBJ(result);
}
OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) {
const KNativePtr* array = PrimitiveArrayAddressOfElementAt<KNativePtr>(stackTrace->array(), 0);
size_t size = stackTrace->array()->count_;
auto stackTraceStrings = kotlin::CallWithThreadState<kotlin::ThreadState::kNative>(kotlin::GetStackTraceStrings, kotlin::std_support::span<void* const>(array, size));
ObjHolder resultHolder;
ObjHeader* strings = AllocArrayInstance(theArrayTypeInfo, stackTraceStrings.size(), resultHolder.slot());
for (size_t index = 0; index < stackTraceStrings.size(); ++index) {
ObjHolder holder;
CreateStringFromCString(stackTraceStrings[index].c_str(), holder.slot());
UpdateHeapRef(ArrayAddressOfElementAt(strings->array(), index), holder.obj());
}
RETURN_OBJ(strings);
}
// TODO: consider handling it with compiler magic instead.
OBJ_GETTER0(Kotlin_native_internal_undefined) {
RETURN_OBJ(nullptr);
}
void* Kotlin_interop_malloc(KLong size, KInt align) {
if (size < 0 || static_cast<std::make_unsigned_t<decltype(size)>>(size) > std::numeric_limits<size_t>::max()) {
return nullptr;
}
RuntimeAssert(align > 0, "Invalid alignment %d", align);
size_t actualAlign = static_cast<size_t>(align);
size_t actualSize = AlignUp(static_cast<size_t>(size), actualAlign);
void* result = std::memset(std_support::aligned_malloc(actualAlign, actualSize), 0, actualSize);
RuntimeAssert(IsAligned(result, actualAlign), "aligned_malloc result %p is not aligned to %zu", result, actualAlign);
return result;
}
void Kotlin_interop_free(void* ptr) {
std_support::aligned_free(ptr);
}
void Kotlin_system_exitProcess(KInt status) {
std::exit(status);
}
const void* Kotlin_Any_getTypeInfo(KConstRef obj) {
return obj->type_info();
}
void Kotlin_CPointer_CopyMemory(KNativePtr to, KNativePtr from, KInt count) {
memcpy(to, from, count);
}
RUNTIME_NOTHROW RUNTIME_PURE KRef* Kotlin_arrayGetElementAddress(KRef array, KInt index) {
ArrayHeader* arr = array->array();
RuntimeAssert(index >= 0 && static_cast<uint32_t>(index) < arr->count_, "Index %" PRId32 " must be in [0, %" PRIu32 ")", index, arr->count_);
return ArrayAddressOfElementAt(arr, index);
}
RUNTIME_NOTHROW RUNTIME_PURE KInt* Kotlin_intArrayGetElementAddress(KRef array, KInt index) {
ArrayHeader* arr = array->array();
RuntimeAssert(index >= 0 && static_cast<uint32_t>(index) < arr->count_, "Index %" PRId32 " must be in [0, %" PRIu32 ")", index, arr->count_);
return IntArrayAddressOfElementAt(arr, index);
}
RUNTIME_NOTHROW RUNTIME_PURE KLong* Kotlin_longArrayGetElementAddress(KRef array, KInt index) {
ArrayHeader* arr = array->array();
RuntimeAssert(index >= 0 && static_cast<uint32_t>(index) < arr->count_, "Index %" PRId32 " must be in [0, %" PRIu32 ")", index, arr->count_);
return LongArrayAddressOfElementAt(arr, index);
}
} // extern "C"