-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #382 from xushiwei/q
patch reflect: Append/Index; Int fix
- Loading branch information
Showing
9 changed files
with
969 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package main | ||
|
||
import "reflect" | ||
|
||
func main() { | ||
tyIntSlice := reflect.SliceOf(reflect.TypeOf(0)) | ||
v := reflect.Zero(tyIntSlice) | ||
v = reflect.Append(v, reflect.ValueOf(1), reflect.ValueOf(2), reflect.ValueOf(3)) | ||
for i, n := 0, v.Len(); i < n; i++ { | ||
item := v.Index(i) | ||
println(item.Int()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
// 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 reflect | ||
|
||
/* | ||
import ( | ||
"unsafe" | ||
) | ||
// 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 { | ||
makeFuncCtxt | ||
ftyp *funcType | ||
fn 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 MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { | ||
if typ.Kind() != Func { | ||
panic("reflect: call of MakeFunc with non-Func type") | ||
} | ||
t := typ.common() | ||
ftyp := (*funcType)(unsafe.Pointer(t)) | ||
code := abi.FuncPCABI0(makeFuncStub) | ||
// makeFuncImpl contains a stack map for use by the runtime | ||
_, _, abid := funcLayout(ftyp, nil) | ||
impl := &makeFuncImpl{ | ||
makeFuncCtxt: makeFuncCtxt{ | ||
fn: code, | ||
stack: abid.stackPtrs, | ||
argLen: abid.stackCallArgsSize, | ||
regPtrs: abid.inRegPtrs, | ||
}, | ||
ftyp: ftyp, | ||
fn: fn, | ||
} | ||
return Value{t, unsafe.Pointer(impl), 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 makeFuncStub() | ||
// 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 { | ||
makeFuncCtxt | ||
method int | ||
rcvr 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 makeMethodValue(op string, v Value) Value { | ||
/* | ||
if v.flag&flagMethod == 0 { | ||
panic("reflect: internal error: invalid use of makeMethodValue") | ||
} | ||
// Ignoring the flagMethod bit, v describes the receiver, not the method type. | ||
fl := v.flag & (flagRO | flagAddr | flagIndir) | ||
fl |= flag(v.typ().Kind()) | ||
rcvr := Value{v.typ(), v.ptr, fl} | ||
// v.Type returns the actual type of the method value. | ||
ftyp := (*funcType)(unsafe.Pointer(v.Type().(*rtype))) | ||
code := methodValueCallCodePtr() | ||
// methodValue contains a stack map for use by the runtime | ||
_, _, abid := funcLayout(ftyp, nil) | ||
fv := &methodValue{ | ||
makeFuncCtxt: makeFuncCtxt{ | ||
fn: code, | ||
stack: abid.stackPtrs, | ||
argLen: abid.stackCallArgsSize, | ||
regPtrs: abid.inRegPtrs, | ||
}, | ||
method: int(v.flag) >> flagMethodShift, | ||
rcvr: 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(op, fv.rcvr, fv.method) | ||
return Value{ftyp.Common(), unsafe.Pointer(fv), v.flag&flagRO | flag(Func)} | ||
*/ | ||
panic("todo") | ||
} | ||
|
||
/* | ||
func methodValueCallCodePtr() 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 methodValueCall() | ||
// This structure must be kept in sync with runtime.reflectMethodValue. | ||
// Any changes should be reflected in all both. | ||
type makeFuncCtxt struct { | ||
fn uintptr | ||
stack *bitVector // ptrmap for both stack args and results | ||
argLen uintptr // just args | ||
regPtrs 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:nosplit | ||
func moveMakeFuncArgPtrs(ctxt *makeFuncCtxt, args *abi.RegArgs) { | ||
for i, arg := range args.Ints { | ||
// Avoid write barriers! Because our write barrier enqueues what | ||
// was there before, we might enqueue garbage. | ||
if ctxt.regPtrs.Get(i) { | ||
*(*uintptr)(unsafe.Pointer(&args.Ptrs[i])) = arg | ||
} 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(&args.Ptrs[i])) = 0 | ||
} | ||
} | ||
} | ||
*/ |
Oops, something went wrong.