Source File
makefunc.go
Belonging Package
reflect
// Copyright 2012 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// MakeFunc implementation.package reflectimport ()// makeFuncImpl is the closure value implementing the function// returned by MakeFunc.// The first three words of this type must be kept in sync with// methodValue and runtime.reflectMethodValue.// Any changes should be reflected in all three.type makeFuncImpl struct {makeFuncCtxtftyp *funcTypefn func([]Value) []Value}// MakeFunc returns a new function of the given [Type]// that wraps the function fn. When called, that new function// does the following://// - converts its arguments to a slice of Values.// - runs results := fn(args).// - returns the results as a slice of Values, one per formal result.//// The implementation fn can assume that the argument [Value] slice// has the number and type of arguments given by typ.// If typ describes a variadic function, the final Value is itself// a slice representing the variadic arguments, as in the// body of a variadic function. The result Value slice returned by fn// must have the number and type of results given by typ.//// The [Value.Call] method allows the caller to invoke a typed function// in terms of Values; in contrast, MakeFunc allows the caller to implement// a typed function in terms of Values.//// The Examples section of the documentation includes an illustration// of how to use MakeFunc to build a swap function for different types.func ( Type, func( []Value) ( []Value)) Value {if .Kind() != Func {panic("reflect: call of MakeFunc with non-Func type")}:= .common():= (*funcType)(unsafe.Pointer()):= abi.FuncPCABI0(makeFuncStub)// makeFuncImpl contains a stack map for use by the runtime, , := funcLayout(, nil):= &makeFuncImpl{makeFuncCtxt: makeFuncCtxt{fn: ,stack: .stackPtrs,argLen: .stackCallArgsSize,regPtrs: .inRegPtrs,},ftyp: ,fn: ,}return Value{, unsafe.Pointer(), flag(Func)}}// makeFuncStub is an assembly function that is the code half of// the function returned from MakeFunc. It expects a *callReflectFunc// as its context register, and its job is to invoke callReflect(ctxt, frame)// where ctxt is the context register and frame is a pointer to the first// word in the passed-in argument frame.func ()// The first 3 words of this type must be kept in sync with// makeFuncImpl and runtime.reflectMethodValue.// Any changes should be reflected in all three.type methodValue struct {makeFuncCtxtmethod intrcvr Value}// makeMethodValue converts v from the rcvr+method index representation// of a method value to an actual method func value, which is// basically the receiver value with a special bit set, into a true// func value - a value holding an actual func. The output is// semantically equivalent to the input as far as the user of package// reflect can tell, but the true func representation can be handled// by code like Convert and Interface and Assign.func ( string, Value) Value {if .flag&flagMethod == 0 {panic("reflect: internal error: invalid use of makeMethodValue")}// Ignoring the flagMethod bit, v describes the receiver, not the method type.:= .flag & (flagRO | flagAddr | flagIndir)|= flag(.typ().Kind()):= Value{.typ(), .ptr, }// v.Type returns the actual type of the method value.:= (*funcType)(unsafe.Pointer(.Type().(*rtype))):= methodValueCallCodePtr()// methodValue contains a stack map for use by the runtime, , := funcLayout(, nil):= &methodValue{makeFuncCtxt: makeFuncCtxt{fn: ,stack: .stackPtrs,argLen: .stackCallArgsSize,regPtrs: .inRegPtrs,},method: int(.flag) >> flagMethodShift,rcvr: ,}// Cause panic if method is not appropriate.// The panic would still happen during the call if we omit this,// but we want Interface() and other operations to fail early.methodReceiver(, .rcvr, .method)return Value{.Common(), unsafe.Pointer(), .flag&flagRO | flag(Func)}}func () uintptr {return abi.FuncPCABI0(methodValueCall)}// methodValueCall is an assembly function that is the code half of// the function returned from makeMethodValue. It expects a *methodValue// as its context register, and its job is to invoke callMethod(ctxt, frame)// where ctxt is the context register and frame is a pointer to the first// word in the passed-in argument frame.func ()// This structure must be kept in sync with runtime.reflectMethodValue.// Any changes should be reflected in all both.type makeFuncCtxt struct {fn uintptrstack *bitVector // ptrmap for both stack args and resultsargLen uintptr // just argsregPtrs abi.IntArgRegBitmap}// moveMakeFuncArgPtrs uses ctxt.regPtrs to copy integer pointer arguments// in args.Ints to args.Ptrs where the GC can see them.//// This is similar to what reflectcallmove does in the runtime, except// that happens on the return path, whereas this happens on the call path.//// nosplit because pointers are being held in uintptr slots in args, so// having our stack scanned now could lead to accidentally freeing// memory.////go:nosplitfunc ( *makeFuncCtxt, *abi.RegArgs) {for , := range .Ints {// Avoid write barriers! Because our write barrier enqueues what// was there before, we might enqueue garbage.if .regPtrs.Get() {*(*uintptr)(unsafe.Pointer(&.Ptrs[])) =} else {// We *must* zero this space ourselves because it's defined in// assembly code and the GC will scan these pointers. Otherwise,// there will be garbage here.*(*uintptr)(unsafe.Pointer(&.Ptrs[])) = 0}}}
![]() |
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |