From 9ba6f3970c6fa4ba42a3d763168dbdcf4a0ddadc Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 17 Nov 2014 18:42:44 -0500 Subject: [PATCH] finish implementation of transferPointer --- .../main/java/org/capnproto/WireHelpers.java | 34 ++++++++++++++++++- .../main/java/org/capnproto/WirePointer.java | 4 +++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/runtime/src/main/java/org/capnproto/WireHelpers.java b/runtime/src/main/java/org/capnproto/WireHelpers.java index eb58a14..302d78e 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -343,7 +343,39 @@ final class WireHelpers { //# Need to create a far pointer. Try to allocate it in the same segment as the source, //# so that it doesn't need to be a double-far. - throw new Error("unimplemented"); + int landingPadOffset = srcSegment.allocate(1); + if (landingPadOffset == SegmentBuilder.FAILED_ALLOCATION) { + //# Darn, need a double-far. + + BuilderArena.AllocateResult allocation = srcSegment.getArena().allocate(2); + SegmentBuilder farSegment = allocation.segment; + landingPadOffset = allocation.offset; + + FarPointer.set(farSegment.buffer, landingPadOffset, false, srcTargetOffset); + FarPointer.setSegmentId(farSegment.buffer, landingPadOffset, srcSegment.id); + + WirePointer.setKindWithZeroOffset(farSegment.buffer, landingPadOffset + 1, + WirePointer.kind(srcTarget)); + + farSegment.buffer.putInt((landingPadOffset + 1) * Constants.BYTES_PER_WORD + 4, + srcSegment.buffer.getInt(srcOffset * Constants.BYTES_PER_WORD + 4)); + + FarPointer.set(dstSegment.buffer, dstOffset, + true, landingPadOffset); + FarPointer.setSegmentId(dstSegment.buffer, dstOffset, + farSegment.id); + } else { + //# Simple landing pad is just a pointer. + WirePointer.setKindAndTarget(srcSegment.buffer, landingPadOffset, + WirePointer.kind(srcTarget), srcTargetOffset); + srcSegment.buffer.putInt(landingPadOffset * Constants.BYTES_PER_WORD + 4, + srcSegment.buffer.getInt(srcOffset * Constants.BYTES_PER_WORD + 4)); + + FarPointer.set(dstSegment.buffer, dstOffset, + false, landingPadOffset); + FarPointer.setSegmentId(dstSegment.buffer, dstOffset, + srcSegment.id); + } } } diff --git a/runtime/src/main/java/org/capnproto/WirePointer.java b/runtime/src/main/java/org/capnproto/WirePointer.java index b9f6e2e..9b6f653 100644 --- a/runtime/src/main/java/org/capnproto/WirePointer.java +++ b/runtime/src/main/java/org/capnproto/WirePointer.java @@ -50,6 +50,10 @@ final class WirePointer { (((targetOffset - offset) - 1) << 2) | kind); } + public static void setKindWithZeroOffset(ByteBuffer buffer, int offset, byte kind) { + buffer.putInt(offset * Constants.BYTES_PER_WORD, kind); + } + public static void setKindAndTargetForEmptyStruct(ByteBuffer buffer, int offset) { //# This pointer points at an empty struct. Assuming the //# WirePointer itself is in-bounds, we can set the target to