1 /* 2 * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.internal.foreign.abi; 24 25 import jdk.incubator.foreign.MemoryAddress; 26 import jdk.incubator.foreign.MemorySegment; 27 import jdk.internal.foreign.MemoryAddressImpl; 28 import jdk.internal.foreign.Utils; 29 30 import java.util.ArrayDeque; 31 import java.util.Deque; 32 import java.util.List; 33 34 public class BindingInterpreter { 35 36 static void unbox(Object arg, List<Binding> bindings, StoreFunc storeFunc, List<? super MemorySegment> buffers) { 37 Deque<Object> stack = new ArrayDeque<>(); 38 stack.push(arg); 39 for (Binding b : bindings) { 40 switch (b.tag()) { 41 case MOVE -> { 42 Binding.Move binding = (Binding.Move) b; 43 storeFunc.store(binding.storage(), binding.type(), stack.pop()); 44 } 45 case DEREFERENCE -> { 46 Binding.Dereference deref = (Binding.Dereference) b; 47 MemorySegment operand = (MemorySegment) stack.pop(); 48 MemoryAddress baseAddress = operand.baseAddress(); 49 MemoryAddress readAddress = baseAddress.addOffset(deref.offset()); 50 stack.push(SharedUtils.read(readAddress, deref.type())); 51 } 52 case COPY_BUFFER -> { 53 Binding.Copy binding = (Binding.Copy) b; 54 MemorySegment operand = (MemorySegment) stack.pop(); 55 assert operand.byteSize() == binding.size() : "operand size mismatch"; 56 MemorySegment copy = MemorySegment.allocateNative(binding.size(), binding.alignment()); 57 copy.copyFrom(operand.asSlice(0, binding.size())); 58 buffers.add(copy); 59 stack.push(copy); 60 } 61 case ALLOC_BUFFER -> 62 throw new UnsupportedOperationException(); 63 case CONVERT_ADDRESS -> 64 stack.push(((MemoryAddress) stack.pop()).toRawLongValue()); 65 case BASE_ADDRESS -> 66 stack.push(((MemorySegment) stack.pop()).baseAddress()); 67 case DUP -> 68 stack.push(stack.peekLast()); 69 default -> throw new IllegalArgumentException("Unsupported tag: " + b); 70 } 71 } 72 } 73 74 static Object box(List<Binding> bindings, LoadFunc loadFunc) { 75 Deque<Object> stack = new ArrayDeque<>(); 76 for (Binding b : bindings) { 77 switch (b.tag()) { 78 case MOVE -> { 79 Binding.Move binding = (Binding.Move) b; 80 stack.push(loadFunc.load(binding.storage(), binding.type())); 81 } 82 case DEREFERENCE -> { 83 Binding.Dereference binding = (Binding.Dereference) b; 84 Object value = stack.pop(); 85 MemorySegment operand = (MemorySegment) stack.pop(); 86 MemoryAddress baseAddress = operand.baseAddress(); 87 MemoryAddress writeAddress = baseAddress.addOffset(binding.offset()); 88 SharedUtils.write(writeAddress, binding.type(), value); 89 } 90 case COPY_BUFFER -> { 91 Binding.Copy binding = (Binding.Copy) b; 92 MemoryAddress operand = (MemoryAddress) stack.pop(); 93 operand = MemoryAddressImpl.ofLongUnchecked(operand.toRawLongValue(), binding.size()); 94 MemorySegment copy = MemorySegment.allocateNative(binding.size(), binding.alignment()); 95 copy.copyFrom(operand.segment().asSlice(0, binding.size())); 96 stack.push(copy); // leaked 97 } 98 case ALLOC_BUFFER -> { 99 Binding.Allocate binding = (Binding.Allocate) b; 100 stack.push(MemorySegment.allocateNative(binding.size(), binding.alignment())); 101 } 102 case CONVERT_ADDRESS -> 103 stack.push(MemoryAddress.ofLong((long) stack.pop())); 104 case BASE_ADDRESS -> 105 stack.push(((MemorySegment) stack.pop()).baseAddress()); 106 case DUP -> 107 stack.push(stack.peekLast()); 108 default -> throw new IllegalArgumentException("Unsupported tag: " + b); 109 } 110 } 111 112 return stack.pop(); 113 } 114 115 interface StoreFunc { 116 void store(VMStorage storage, Class<?> type, Object o); 117 } 118 119 interface LoadFunc { 120 Object load(VMStorage storage, Class<?> type); 121 } 122 }