func (self *Thread) NewFrame(method *rtc.Method) *Frame { if method.IsNative() { return newNativeFrame(self, method) } else { return self.frameCache.borrowFrame(method) //return newFrame(self, method) } }
func (self *Thread) InvokeMethod(method *rtc.Method) { //self._logInvoke(self.stack.size, method) currentFrame := self.CurrentFrame() newFrame := self.NewFrame(method) self.PushFrame(newFrame) argSlotsCount := method.ArgSlotCount() if argSlotsCount > 0 { _passArgs(currentFrame.operandStack, newFrame.localVars, argSlotsCount) } if method.IsSynchronized() { var monitor *rtc.Monitor if method.IsStatic() { classObj := method.Class().JClass() monitor = classObj.Monitor() } else { thisObj := newFrame.LocalVars().GetThis() monitor = thisObj.Monitor() } monitor.Enter(self) newFrame.SetOnPopAction(func() { monitor.Exit(self) }) } }
func (self *FrameCache) borrowFrame(method *rtc.Method) *Frame { if self.frameCount > 0 { for i, frame := range self.cachedFrames { if frame != nil && frame.maxLocals >= method.MaxLocals() && frame.maxStack >= method.MaxStack() { self.frameCount-- self.cachedFrames[i] = nil frame.reset(method) return frame } } } return newFrame(self.thread, method) }
func getParameterTypeArr(method *rtc.Method) *rtc.Obj { paramTypes := method.ParameterTypes() paramCount := len(paramTypes) classClass := rtc.BootLoader().JLClassClass() classArr := classClass.NewArray(uint(paramCount)) if paramCount > 0 { classObjs := classArr.Refs() for i, paramType := range paramTypes { classObjs[i] = paramType.JClass() } } return classArr }
func getExceptionTypeArr(method *rtc.Method) *rtc.Obj { exTypes := method.ExceptionTypes() exCount := len(exTypes) classClass := rtc.BootLoader().JLClassClass() classArr := classClass.NewArray(uint(exCount)) if exCount > 0 { classObjs := classArr.Refs() for i, exType := range exTypes { classObjs[i] = exType.JClass() } } return classArr }
func newFrame(thread *Thread, method *rtc.Method) *Frame { return &Frame{ thread: thread, method: method, maxLocals: method.MaxLocals(), maxStack: method.MaxStack(), localVars: newLocalVars(method.MaxLocals()), operandStack: newOperandStack(method.MaxStack()), } }
func newNativeFrame(thread *Thread, method *rtc.Method) *Frame { frame := &Frame{} frame.thread = thread frame.method = method frame.localVars = newLocalVars(method.ArgSlotCount()) // todo frame.operandStack = newOperandStack(4) // todo code := method.Code() if code == nil { code = getHackCode(method.Descriptor()) method.HackSetCode(code) } return frame }
func (self *Thread) _logInvoke(stackSize uint, method *rtc.Method) { space := strings.Repeat(" ", int(stackSize)) className := method.Class().Name() methodName := method.Name() if method.IsStatic() { fmt.Printf("[method]%v thread:%p %v.%v()\n", space, self, className, methodName) } else { fmt.Printf("[method]%v thread:%p %v#%v()\n", space, self, className, methodName) } }
// Object[] -> []interface{} func convertArgs(this, argArr *rtc.Obj, method *rtc.Method) []interface{} { if method.ArgSlotCount() == 0 { return nil } if method.ArgSlotCount() == 1 && !method.IsStatic() { return []interface{}{this} } argObjs := argArr.Refs() argTypes := method.ParsedDescriptor().ParameterTypes() args := make([]interface{}, method.ArgSlotCount()) j := 0 if !method.IsStatic() { args[0] = this j = 1 } for i, argType := range argTypes { argObj := argObjs[i] if argType.IsBaseType() { // todo unboxed := box.Unbox(argObj, argType.Descriptor()) args[i+j] = unboxed if argType.IsLongOrDouble() { j++ } } else { args[i+j] = argObj } } return args }
func getReturnType(method *rtc.Method) *rtc.Obj { goReturnType := method.ReturnType() return goReturnType.JClass() }