Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewind() called early in TransferContext #512

Merged
merged 6 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions kt/godot-library/src/main/kotlin/godot/core/Constructors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,7 @@ abstract class KtConstructor<T : KtObject>(
abstract operator fun invoke(): T

fun construct(rawPtr: VoidPtr, instanceId: Long) = KtObject.instantiateWith(rawPtr, instanceId) {
val argsSize = TransferContext.buffer.int
require(argsSize == parameterCount) {
"Expecting $parameterCount parameter(s) for constructor, but got $argsSize instead."
}
for (i in 0 until parameterCount) {
paramsArray[i] = TransferContext.readSingleArgument(parameterTypes[i], parameterNullables[i])
}
TransferContext.buffer.rewind()
TransferContext.readArguments(parameterTypes, parameterNullables, paramsArray)
val instance = invoke()
resetParamsArray()
instance
Expand Down
11 changes: 2 additions & 9 deletions kt/godot-library/src/main/kotlin/godot/core/KtObject.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,12 @@ abstract class KtObject {

internal inline fun callConstructor(classIndex: Int, scriptIndex: Int): Unit {
TransferContext.createNativeObject(classIndex, this, scriptIndex)
readPtrAndIdFromBuffer()
TransferContext.initializeKtObject(this)
}

internal inline fun getSingleton(classIndex: Int) {
TransferContext.getSingleton(classIndex)
readPtrAndIdFromBuffer()
}

private inline fun readPtrAndIdFromBuffer() {
val buffer = TransferContext.buffer
rawPtr = buffer.long
id = ObjectID(buffer.long)
buffer.rewind()
TransferContext.initializeKtObject(this)
}

open fun _onDestroy() = Unit
Expand Down
3 changes: 0 additions & 3 deletions kt/godot-library/src/main/kotlin/godot/core/Properties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,8 @@ open class KtProperty<T : KtObject, P : Any?>(
}

protected fun <P> extractSetterArgument(): P {
val argsSize = TransferContext.buffer.int
require(argsSize == 1) { "Setter should be called with only one argument." }
//TODO: manage nullable argument of enum setter (only for objects)
val arg = TransferContext.readSingleArgument(variantType)
TransferContext.buffer.rewind()
@Suppress("UNCHECKED_CAST")
return arg as P
}
Expand Down
15 changes: 3 additions & 12 deletions kt/godot-library/src/main/kotlin/godot/core/callable/KtCallable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,17 @@ abstract class KtCallable<T : KtObject, R : Any?>(
val variantType: VariantType,
vararg parameterTypes: Pair<VariantType, Boolean>
) {
private val types: List<VariantType> = parameterTypes.map { it.first }
private val isNullables: List<Boolean> = parameterTypes.map { it.second }
private val types: Array<VariantType> = parameterTypes.map { it.first }.toTypedArray()
private val isNullables: Array<Boolean> = parameterTypes.map { it.second }.toTypedArray()

fun invoke(instance: T) {
val argsSize = TransferContext.buffer.int
require(argsSize == parameterCount) { "Expecting $parameterCount parameter(s) for function $name, but got $argsSize instead." }
readArguments(argsSize)
TransferContext.readArguments(types, isNullables, paramsArray)
val ret = invokeKt(instance)
resetParamsArray()

TransferContext.writeReturnValue(ret, variantType)
}

private fun readArguments(argsSize: Int) {
for (i in 0 until argsSize) {
paramsArray[i] = TransferContext.readSingleArgument(types[i], isNullables[i])
}
TransferContext.buffer.rewind()
}

companion object {
val paramsArray by threadLocal {
Array<Any?>(Constraints.MAX_FUNCTION_ARG_COUNT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package godot.core.memory

import godot.core.KtObject
import godot.core.LongStringQueue
import godot.core.ObjectID
import godot.core.VariantType
import godot.tools.common.constants.Constraints
import godot.util.VoidPtr
Expand All @@ -22,32 +23,51 @@ internal object TransferContext {
return (LongStringQueue.stringMaxSize + 12).coerceAtLeast(68) * Constraints.MAX_FUNCTION_ARG_COUNT + 4
}

val buffer by threadLocalLazy<ByteBuffer> {
private val buffer by threadLocalLazy<ByteBuffer> {
val buf = ByteBuffer.allocateDirect(bufferSize)
buf.order(ByteOrder.LITTLE_ENDIAN)
buf
}

fun writeArguments(vararg values: Pair<VariantType, Any?>) {
buffer.rewind()
buffer.putInt(values.size)
for (value in values) {
value.first.toGodot(buffer, value.second)
}
}

fun readSingleArgument(variantType: VariantType, isNullable: Boolean = false): Any? {
buffer.rewind()
val argsSize = buffer.int
require(argsSize == 1) {
"Expecting 1 parameter, but got $argsSize instead."
}
return variantType.toKotlin(buffer, isNullable)
}

fun readSingleArgument(variantType: VariantType, isNullable: Boolean = false) =
variantType.toKotlin(buffer, isNullable)
fun readArguments(variantTypes: Array<VariantType>, areNullable: Array<Boolean>, returnArray: Array<Any?>) {
buffer.rewind()
val argsSize = buffer.int
val argumentCount = variantTypes.size
require(argsSize == argumentCount) {
"Expecting $argumentCount parameter(s), but got $argsSize instead."
}

// Assume that variantTypes and areNullable have the same size and that returnArray is big enough
for (i in 0 until argsSize) {
returnArray[i] = variantTypes[i].toKotlin(buffer, areNullable[i])
}
}

fun writeReturnValue(value: Any?, type: VariantType) {
type.toGodot(buffer, value)
buffer.rewind()
type.toGodot(buffer, value)
}

fun readReturnValue(type: VariantType, isNullable: Boolean = false): Any? {
val ret = type.toKotlin(buffer, isNullable)
buffer.rewind()
return ret
return type.toKotlin(buffer, isNullable)
}

fun callMethod(ptr: VoidPtr, methodIndex: Int, expectedReturnType: VariantType) {
Expand All @@ -58,6 +78,12 @@ internal object TransferContext {
)
}

fun initializeKtObject(obj: KtObject) {
buffer.rewind()
obj.rawPtr = buffer.long
obj.id = ObjectID(buffer.long)
}

fun removeScriptInstance(id: Long) {
MemoryManager.unregisterScriptInstance(id)
}
Expand Down
37 changes: 18 additions & 19 deletions src/memory/transfer_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ TransferContext::~TransferContext() {
}
}

SharedBuffer* TransferContext::get_buffer(jni::Env& p_env) {
SharedBuffer* TransferContext::get_and_rewind_buffer(jni::Env& p_env) {
thread_local static SharedBuffer shared_buffer;

if (unlikely(!shared_buffer.is_init())) {
Expand All @@ -43,7 +43,7 @@ SharedBuffer* TransferContext::get_buffer(jni::Env& p_env) {
shared_buffer = SharedBuffer {address, 0};
#endif
}

shared_buffer.rewind();
CedNaru marked this conversation as resolved.
Show resolved Hide resolved
return &shared_buffer;
}

Expand All @@ -55,30 +55,31 @@ void TransferContext::remove_script_instance(uint64_t id) {
}

void TransferContext::read_return_value(jni::Env& p_env, Variant& r_ret) {
SharedBuffer* buffer {get_buffer(p_env)};
SharedBuffer* buffer {get_and_rewind_buffer(p_env)};
ktvariant::get_variant_from_buffer(buffer, r_ret);
buffer->rewind();
}

void TransferContext::write_args(jni::Env& p_env, const Variant** p_args, int args_size) {
SharedBuffer* buffer {get_buffer(p_env)};
SharedBuffer* buffer {get_and_rewind_buffer(p_env)};
buffer->increment_position(encode_uint32(args_size, buffer->get_cursor()));
for (auto i = 0; i < args_size; ++i) {
ktvariant::send_variant_to_buffer(*p_args[i], buffer);
}
buffer->rewind();
}

uint32_t TransferContext::read_args(jni::Env& p_env, Variant* args) {
SharedBuffer* buffer {get_buffer(p_env)};
SharedBuffer* buffer {get_and_rewind_buffer(p_env)};
uint32_t size {read_args_size(buffer)};
for (uint32_t i = 0; i < size; ++i) {
ktvariant::get_variant_from_buffer(buffer, args[i]);
}
buffer->rewind();
return size;
}

void TransferContext::write_return_value(jni::Env& p_env, Variant& variant) {
ktvariant::send_variant_to_buffer(variant, get_and_rewind_buffer(p_env));
}

void TransferContext::icall(JNIEnv* rawEnv, jobject instance, jlong j_ptr, jint p_method_index, jint expectedReturnType) {
if (unlikely(stack_offset == -1)) {
for (int i = 0; i < MAX_STACK_SIZE; i++) {
Expand All @@ -90,7 +91,7 @@ void TransferContext::icall(JNIEnv* rawEnv, jobject instance, jlong j_ptr, jint
TransferContext* transfer_context {GDKotlin::get_instance().transfer_context};
jni::Env env {rawEnv};

SharedBuffer* buffer {transfer_context->get_buffer(env)};
SharedBuffer* buffer {transfer_context->get_and_rewind_buffer(env)};
uint32_t args_size {read_args_size(buffer)};

auto* ptr {reinterpret_cast<Object*>(static_cast<uintptr_t>(j_ptr))};
Expand Down Expand Up @@ -118,18 +119,22 @@ void TransferContext::icall(JNIEnv* rawEnv, jobject instance, jlong j_ptr, jint
}

const Variant& ret_value {methodBind->call(ptr, args_ptr, args_size, r_error)};
write_return_value(buffer, ret_value);

buffer->rewind();
ktvariant::send_variant_to_buffer(ret_value, buffer);
} else {
Variant* args {variant_args + stack_offset};
read_args_to_array(buffer, args, args_size);


const Variant** args_ptr {variant_args_ptr + stack_offset};

stack_offset += args_size;
const Variant& ret_value {methodBind->call(ptr, args_ptr, args_size, r_error)};
stack_offset -= args_size;

write_return_value(buffer, ret_value);
buffer->rewind();
ktvariant::send_variant_to_buffer(ret_value, buffer);
}

#ifdef DEBUG_ENABLED
Expand Down Expand Up @@ -161,11 +166,10 @@ void TransferContext::create_native_object(JNIEnv* p_raw_env, jobject p_instance

jni::Env env {p_raw_env};
TransferContext* transfer_context {GDKotlin::get_instance().transfer_context};
SharedBuffer* buffer {transfer_context->get_buffer(env)};

SharedBuffer* buffer {transfer_context->get_and_rewind_buffer(env)};
buffer->increment_position(encode_uint64(raw_ptr, buffer->get_cursor()));
buffer->increment_position(encode_uint64(id, buffer->get_cursor()));
buffer->rewind();
}

void TransferContext::get_singleton(JNIEnv* p_raw_env, jobject p_instance, jint p_class_index) {
Expand All @@ -174,10 +178,9 @@ void TransferContext::get_singleton(JNIEnv* p_raw_env, jobject p_instance, jint
)};
jni::Env env {p_raw_env};

SharedBuffer* buffer {GDKotlin::get_instance().transfer_context->get_buffer(env)};
SharedBuffer* buffer {GDKotlin::get_instance().transfer_context->get_and_rewind_buffer(env)};
buffer->increment_position(encode_uint64(reinterpret_cast<uintptr_t>(singleton), buffer->get_cursor()));
buffer->increment_position(encode_uint64(singleton->get_instance_id(), buffer->get_cursor()));
buffer->rewind();
}

void TransferContext::free_object(JNIEnv* p_raw_env, jobject p_instance, jlong p_raw_ptr) {
Expand All @@ -189,7 +192,3 @@ void TransferContext::free_object(JNIEnv* p_raw_env, jobject p_instance, jlong p

memdelete(owner);
}

void TransferContext::write_return_value(jni::Env& p_env, Variant& variant) {
write_return_value(get_buffer(p_env), variant);
}
9 changes: 1 addition & 8 deletions src/memory/transfer_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class TransferContext : public JavaInstanceWrapper {
static void free_object(JNIEnv* p_raw_env, jobject p_instance, jlong p_raw_ptr);

private:
SharedBuffer* get_buffer(jni::Env& p_env);
SharedBuffer* get_and_rewind_buffer(jni::Env& p_env);

_FORCE_INLINE_ static uint32_t read_args_size(SharedBuffer* buffer) {
uint32_t args_size {decode_uint32(buffer->get_cursor())};
Expand All @@ -46,13 +46,6 @@ class TransferContext : public JavaInstanceWrapper {
for (uint32_t i = 0; i < args_size; ++i) {
ktvariant::get_variant_from_buffer(buffer, p_args[i]);
}

buffer->rewind();
}

_FORCE_INLINE_ static void write_return_value(SharedBuffer* buffer, const Variant& r_ret) {
ktvariant::send_variant_to_buffer(r_ret, buffer);
buffer->rewind();
CedNaru marked this conversation as resolved.
Show resolved Hide resolved
}

// clang-format off
Expand Down