Add checks for metadata state (#375)

* Add checks for metadata state

Type metadata actually *is* mutable, is updated by the runtime, and we need to be careful when reading from it.

* Add a precondition for type metadata state

* Replace `precondition` with an `assert`

* Add missing license headers
This commit is contained in:
Max Desiatov 2021-02-01 10:02:49 +00:00 committed by GitHub
parent 9a79548312
commit d75b185553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 0 deletions

View File

@ -0,0 +1,42 @@
// Copyright 2021 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
enum MetadataState: UInt {
case complete = 0x00
case nonTransitiveComplete = 0x01
case layoutComplete = 0x3F
case abstract = 0xFF
}
private let isBlockingMask: UInt = 0x100
struct MetadataRequest {
private let bits: UInt
init(desiredState: MetadataState, isBlocking: Bool) {
if isBlocking {
bits = desiredState.rawValue | isBlockingMask
} else {
bits = desiredState.rawValue & ~isBlockingMask
}
}
}
struct MetadataResponse {
let metadata: UnsafePointer<StructMetadata>
let state: MetadataState
}
@_silgen_name("swift_checkMetadataState")
func _checkMetadataState(_ request: MetadataRequest, _ type: StructMetadata) -> MetadataResponse

View File

@ -129,5 +129,15 @@ struct StructMetadata {
extension StructMetadata {
init(type: Any.Type) {
self = Self(pointer: unsafeBitCast(type, to: UnsafePointer<StructMetadataLayout>.self))
assert(
_checkMetadataState(
.init(desiredState: .layoutComplete, isBlocking: false),
self
).state.rawValue < MetadataState.layoutComplete.rawValue,
"""
Struct metadata for \(type) is in incomplete state, \
proceeding would result in an undefined behavior.
"""
)
}
}

View File

@ -1,8 +1,26 @@
// Copyright 2021 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Benchmark
import TokamakCore
private let bigType = NavigationView<HStack<VStack<Button<Text>>>>.self
benchmark("mangledName Runtime") {
_ = typeInfo(of: bigType)!.mangledName
}
benchmark("typeConstructorName TokamakCore") {
_ = typeConstructorName(bigType)
}

View File

@ -1,3 +1,17 @@
// Copyright 2021 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Benchmark
import TokamakStaticHTML