Skip to content

Commit ca2493f

Browse files
fix(storage): do not inhibit the dead code elimination. (#8543)
When the go compiler encounters a call to MethodByName(), it assumes that every method of every reachable type can be accessed, and nothing may be eliminated. Go 1.22 has gained support for calls like MethodByName("Foobar"). If the argument to MethodByName() is a compile-time constant, then the compiler no longer disables the DCE, and only keeps methods named Foobar. Rewrite setConditionField() so that MethodByName() is only called with compile-time constants. This way importing cloud.google.com/go/storage will not inhibit the DCE. Co-authored-by: Brenna N Epp <[email protected]>
1 parent 19414ae commit ca2493f

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

storage/bucket.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,11 +1360,11 @@ func applyBucketConds(method string, conds *BucketConditions, call interface{})
13601360
cval := reflect.ValueOf(call)
13611361
switch {
13621362
case conds.MetagenerationMatch != 0:
1363-
if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
1363+
if !setIfMetagenerationMatch(cval, conds.MetagenerationMatch) {
13641364
return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
13651365
}
13661366
case conds.MetagenerationNotMatch != 0:
1367-
if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
1367+
if !setIfMetagenerationNotMatch(cval, conds.MetagenerationNotMatch) {
13681368
return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
13691369
}
13701370
}

storage/storage.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,7 @@ func (c *Conditions) isMetagenerationValid() bool {
18061806
func applyConds(method string, gen int64, conds *Conditions, call interface{}) error {
18071807
cval := reflect.ValueOf(call)
18081808
if gen >= 0 {
1809-
if !setConditionField(cval, "Generation", gen) {
1809+
if !setGeneration(cval, gen) {
18101810
return fmt.Errorf("storage: %s: generation not supported", method)
18111811
}
18121812
}
@@ -1818,25 +1818,25 @@ func applyConds(method string, gen int64, conds *Conditions, call interface{}) e
18181818
}
18191819
switch {
18201820
case conds.GenerationMatch != 0:
1821-
if !setConditionField(cval, "IfGenerationMatch", conds.GenerationMatch) {
1821+
if !setIfGenerationMatch(cval, conds.GenerationMatch) {
18221822
return fmt.Errorf("storage: %s: ifGenerationMatch not supported", method)
18231823
}
18241824
case conds.GenerationNotMatch != 0:
1825-
if !setConditionField(cval, "IfGenerationNotMatch", conds.GenerationNotMatch) {
1825+
if !setIfGenerationNotMatch(cval, conds.GenerationNotMatch) {
18261826
return fmt.Errorf("storage: %s: ifGenerationNotMatch not supported", method)
18271827
}
18281828
case conds.DoesNotExist:
1829-
if !setConditionField(cval, "IfGenerationMatch", int64(0)) {
1829+
if !setIfGenerationMatch(cval, int64(0)) {
18301830
return fmt.Errorf("storage: %s: DoesNotExist not supported", method)
18311831
}
18321832
}
18331833
switch {
18341834
case conds.MetagenerationMatch != 0:
1835-
if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
1835+
if !setIfMetagenerationMatch(cval, conds.MetagenerationMatch) {
18361836
return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
18371837
}
18381838
case conds.MetagenerationNotMatch != 0:
1839-
if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
1839+
if !setIfMetagenerationNotMatch(cval, conds.MetagenerationNotMatch) {
18401840
return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
18411841
}
18421842
}
@@ -1897,16 +1897,45 @@ func applySourceCondsProto(gen int64, conds *Conditions, call *storagepb.Rewrite
18971897
return nil
18981898
}
18991899

1900-
// setConditionField sets a field on a *raw.WhateverCall.
1900+
// setGeneration sets Generation on a *raw.WhateverCall.
19011901
// We can't use anonymous interfaces because the return type is
19021902
// different, since the field setters are builders.
1903-
func setConditionField(call reflect.Value, name string, value interface{}) bool {
1904-
m := call.MethodByName(name)
1905-
if !m.IsValid() {
1906-
return false
1903+
// We also make sure to supply a compile-time constant to MethodByName;
1904+
// otherwise, the Go Linker will disable dead code elimination, leading
1905+
// to larger binaries for all packages that import storage.
1906+
func setGeneration(cval reflect.Value, value interface{}) bool {
1907+
return setCondition(cval.MethodByName("Generation"), value)
1908+
}
1909+
1910+
// setIfGenerationMatch sets IfGenerationMatch on a *raw.WhateverCall.
1911+
// See also setGeneration.
1912+
func setIfGenerationMatch(cval reflect.Value, value interface{}) bool {
1913+
return setCondition(cval.MethodByName("IfGenerationMatch"), value)
1914+
}
1915+
1916+
// setIfGenerationNotMatch sets IfGenerationNotMatch on a *raw.WhateverCall.
1917+
// See also setGeneration.
1918+
func setIfGenerationNotMatch(cval reflect.Value, value interface{}) bool {
1919+
return setCondition(cval.MethodByName("IfGenerationNotMatch"), value)
1920+
}
1921+
1922+
// setIfMetagenerationMatch sets IfMetagenerationMatch on a *raw.WhateverCall.
1923+
// See also setGeneration.
1924+
func setIfMetagenerationMatch(cval reflect.Value, value interface{}) bool {
1925+
return setCondition(cval.MethodByName("IfMetagenerationMatch"), value)
1926+
}
1927+
1928+
// setIfMetagenerationNotMatch sets IfMetagenerationNotMatch on a *raw.WhateverCall.
1929+
// See also setGeneration.
1930+
func setIfMetagenerationNotMatch(cval reflect.Value, value interface{}) bool {
1931+
return setCondition(cval.MethodByName("IfMetagenerationNotMatch"), value)
1932+
}
1933+
1934+
func setCondition(setter reflect.Value, value interface{}) bool {
1935+
if setter.IsValid() {
1936+
setter.Call([]reflect.Value{reflect.ValueOf(value)})
19071937
}
1908-
m.Call([]reflect.Value{reflect.ValueOf(value)})
1909-
return true
1938+
return setter.IsValid()
19101939
}
19111940

19121941
// Retryer returns an object handle that is configured with custom retry

0 commit comments

Comments
 (0)