Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 98d55ab

Browse filesBrowse files
committed
compiler, runtime: make slice lookup panics recoverable
1 parent 88d273d commit 98d55ab
Copy full SHA for 98d55ab

File tree

5 files changed

+19
-11
lines changed
Filter options

5 files changed

+19
-11
lines changed

‎GNUmakefile

Copy file name to clipboardExpand all lines: GNUmakefile
+2
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ TEST_PACKAGES_LINUX := \
383383
crypto/hmac \
384384
debug/dwarf \
385385
debug/plan9obj \
386+
encoding/binary \
386387
go/constant \
387388
image \
388389
io/ioutil \
@@ -406,6 +407,7 @@ TEST_PACKAGES_WINDOWS := \
406407
compress/flate \
407408
crypto/des \
408409
crypto/hmac \
410+
encoding/binary \
409411
go/constant \
410412
math/bits \
411413
strconv \

‎compiler/asserts.go

Copy file name to clipboardExpand all lines: compiler/asserts.go
+4-10
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (b *builder) createLookupBoundsCheck(arrayLen, index llvm.Value) {
3131

3232
// Now do the bounds check: index >= arrayLen
3333
outOfBounds := b.CreateICmp(llvm.IntUGE, index, arrayLen, "")
34-
b.createRuntimeAssert(outOfBounds, "lookup", "lookupPanic", false)
34+
b.createRuntimeAssert(outOfBounds, "lookup", "lookupPanic", true)
3535
}
3636

3737
// createSliceBoundsCheck emits a bounds check before a slicing operation to make
@@ -230,7 +230,7 @@ func (b *builder) createDivideByZeroCheck(y llvm.Value) {
230230

231231
// createRuntimeAssert is a common function to create a new branch on an assert
232232
// bool, calling an assert func if the assert value is true (1).
233-
func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc string, invoke bool) {
233+
func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc string, isInvoke bool) {
234234
// Check whether we can resolve this check at compile time.
235235
if !assert.IsAConstantInt().IsNil() {
236236
val := assert.ZExtValue()
@@ -245,23 +245,17 @@ func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc
245245
// current insert position.
246246
faultBlock := b.ctx.AddBasicBlock(b.llvmFn, blockPrefix+".throw")
247247
nextBlock := b.insertBasicBlock(blockPrefix + ".next")
248-
b.blockExits[b.currentBlock] = nextBlock // adjust outgoing block for phi nodes
249248

250249
// Now branch to the out-of-bounds or the regular block.
251250
b.CreateCondBr(assert, faultBlock, nextBlock)
252251

253252
// Fail: the assert triggered so panic.
254253
b.SetInsertPointAtEnd(faultBlock)
255-
if invoke {
256-
// This runtime panic is recoverable.
257-
b.createRuntimeInvoke(assertFunc, nil, "")
258-
} else {
259-
// This runtime panic is not recoverable.
260-
b.createRuntimeCall(assertFunc, nil, "")
261-
}
254+
b.createRuntimeCallCommon(assertFunc, nil, "", isInvoke)
262255
b.CreateUnreachable()
263256

264257
// Ok: assert didn't trigger so continue normally.
258+
b.blockExits[b.currentBlock] = nextBlock // adjust outgoing block for phi nodes
265259
b.SetInsertPointAtEnd(nextBlock)
266260
}
267261

‎src/runtime/error.go

Copy file name to clipboardExpand all lines: src/runtime/error.go
+1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ func (r runtimeError) RuntimeError() {}
2121

2222
var (
2323
divideError error = runtimeError{"runtime error: integer divide by zero"}
24+
lookupError error = runtimeError{"runtime error: index out of range"}
2425
overflowError error = runtimeError{"runtime error: integer overflow"}
2526
)

‎src/runtime/panic.go

Copy file name to clipboardExpand all lines: src/runtime/panic.go
+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func nilMapPanic() {
187187

188188
// Panic when trying to access an array or slice out of bounds.
189189
func lookupPanic() {
190-
runtimePanicAt(returnAddress(0), "index out of range")
190+
_panic(lookupError)
191191
}
192192

193193
// Panic when trying to slice a slice out of bounds.

‎testdata/recover.go

Copy file name to clipboardExpand all lines: testdata/recover.go
+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func main() {
3232

3333
println("\n# runtime panics")
3434
runtimePanicDivByZero(1, 0)
35+
runtimePanicLookup([]int{1, 2, 3}, 10)
3536

3637
println("\n# runtime.Goexit")
3738
runtimeGoexit()
@@ -127,6 +128,16 @@ func runtimePanicDivByZero(a, b int) int {
127128
return a / b
128129
}
129130

131+
func runtimePanicLookup(slice []int, index int) int {
132+
defer func() {
133+
if err := recover(); err != nil {
134+
println("recovered:", err)
135+
}
136+
}()
137+
138+
return slice[index]
139+
}
140+
130141
func runtimeGoexit() {
131142
wg.Add(1)
132143
go func() {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.