// public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) // (Ljava/lang/Object;ILjava/lang/Object;II)V func arraycopy(frame *rtda.Frame) { vars := frame.LocalVars() src := vars.GetRef(0) srcPos := vars.GetInt(1) dest := vars.GetRef(2) destPos := vars.GetInt(3) length := vars.GetInt(4) // NullPointerException if src == nil || dest == nil { panic("NPE") // todo } // ArrayStoreException if !checkArrayCopy(src, dest) { panic("ArrayStoreException") } // IndexOutOfBoundsException if srcPos < 0 || destPos < 0 || length < 0 || srcPos+length > heap.ArrayLength(src) || destPos+length > heap.ArrayLength(dest) { panic("IndexOutOfBoundsException") // todo } heap.ArrayCopy(src, dest, srcPos, destPos, length) }
// public static native void set(Object array, int index, Object value) // throws IllegalArgumentException, ArrayIndexOutOfBoundsException; // (Ljava/lang/Object;ILjava/lang/Object;)V func set(frame *rtda.Frame) { vars := frame.LocalVars() arr := vars.GetRef(0) index := vars.GetInt(1) value := vars.GetRef(2) if arr == nil { frame.Thread().ThrowNPE() return } if !arr.IsArray() { frame.Thread().ThrowIllegalArgumentException("Argument is not an array") return } if index < 0 || index >= heap.ArrayLength(arr) { frame.Thread().ThrowArrayIndexOutOfBoundsExceptionNoMsg() return } if !arr.IsPrimitiveArray() { arr.Refs()[index] = value return } //TODO Consistent with the current need to determine whether the type and source type // Such as: // [I // java/lang/Integer // frame.Thread().ThrowIllegalArgumentException("argument type mismatch") // primitive array primitiveDescriptorStr := arr.Class().Name()[1:] if primitiveDescriptorStr != value.GetPrimitiveDescriptor() { frame.Thread().ThrowIllegalArgumentException("argument type mismatch") return } unboxed := box.Unbox(value, primitiveDescriptorStr) primitiveDescriptor := arr.Class().Name()[1] switch primitiveDescriptor { case 'Z': arr.Booleans()[index] = int8(unboxed.(int32)) case 'B': arr.Bytes()[index] = int8(unboxed.(int32)) case 'C': arr.Chars()[index] = uint16(unboxed.(int32)) case 'S': arr.Shorts()[index] = int16(unboxed.(int32)) case 'I': arr.Ints()[index] = unboxed.(int32) case 'J': arr.Longs()[index] = unboxed.(int64) case 'F': arr.Floats()[index] = unboxed.(float32) case 'D': arr.Doubles()[index] = unboxed.(float64) } }
// public static native int getLength(Object array) throws IllegalArgumentException; // (Ljava/lang/Object;)I func getLength(frame *rtda.Frame) { vars := frame.LocalVars() arr := vars.GetRef(0) // todo IllegalArgumentException _len := heap.ArrayLength(arr) stack := frame.OperandStack() stack.PushInt(_len) }
func _checkArrayAndIndex(frame *rtda.Frame, arrRef *heap.Object, index int32) bool { if arrRef == nil { frame.Thread().ThrowNPE() return false } if index < 0 || index >= heap.ArrayLength(arrRef) { frame.Thread().ThrowArrayIndexOutOfBoundsException(index) return false } return true }
func (self *ARRAY_LENGTH) Execute(frame *rtda.Frame) { stack := frame.OperandStack() arrRef := stack.PopRef() if arrRef == nil { frame.Thread().ThrowNPE() return } arrLen := heap.ArrayLength(arrRef) stack.PushInt(arrLen) }
// private native Object[] getEnclosingMethod0(); // ()[Ljava/lang/Object; func getEnclosingMethod0(frame *rtda.Frame) { class := _popClass(frame) if class.IsPrimitive() { frame.OperandStack().PushNull() } else { emInfo := class.EnclosingMethod() emInfoObj := _createEnclosintMethodInfo(frame.ClassLoader(), emInfo) if emInfoObj == nil || heap.ArrayLength(emInfoObj) == 0 { frame.OperandStack().PushNull() } else { frame.OperandStack().PushRef(emInfoObj) } } }
// public static native Object get(Object array, int index) // throws IllegalArgumentException, ArrayIndexOutOfBoundsException; // (Ljava/lang/Object;I)Ljava/lang/Object; func get(frame *rtda.Frame) { vars := frame.LocalVars() arr := vars.GetRef(0) index := vars.GetInt(1) if arr == nil { frame.Thread().ThrowNPE() return } if !arr.IsArray() { frame.Thread().ThrowIllegalArgumentException("Argument is not an array") return } if index < 0 || index >= heap.ArrayLength(arr) { frame.Thread().ThrowArrayIndexOutOfBoundsExceptionNoMsg() return } if !arr.IsPrimitiveArray() { obj := arr.Refs()[index] frame.OperandStack().PushRef(obj) return } // primitive array stack := frame.OperandStack() primitiveDescriptor := arr.Class().Name()[1] switch primitiveDescriptor { case 'Z': stack.PushBoolean(arr.Booleans()[index] == 1) case 'B': stack.PushInt(int32(arr.Bytes()[index])) case 'C': stack.PushInt(int32(arr.Chars()[index])) case 'S': stack.PushInt(int32(arr.Shorts()[index])) case 'I': stack.PushInt(arr.Ints()[index]) case 'J': stack.PushLong(arr.Longs()[index]) case 'F': stack.PushFloat(arr.Floats()[index]) case 'D': stack.PushDouble(arr.Doubles()[index]) } // boxing box.Box(frame, primitiveDescriptor) }
func _aloadPop(frame *rtda.Frame) (*rtda.OperandStack, *heap.Object, int, bool) { stack := frame.OperandStack() index := stack.PopInt() arrRef := stack.PopRef() if arrRef == nil { frame.Thread().ThrowNPE() return nil, nil, 0, false } if index < 0 || index >= heap.ArrayLength(arrRef) { frame.Thread().ThrowArrayIndexOutOfBoundsException(index) return nil, nil, 0, false } return stack, arrRef, int(index), true }