diff --git a/.github/actions/build_and_test_ya/action.yml b/.github/actions/build_and_test_ya/action.yml
index 9dd86a4820ea..e142a282b8bd 100644
--- a/.github/actions/build_and_test_ya/action.yml
+++ b/.github/actions/build_and_test_ya/action.yml
@@ -51,12 +51,37 @@ inputs:
vars:
type: string
default: ""
+ custom_branch_name:
+ description: "Custom branch name required when workflow branch != checkout branch"
+ type: string
+ required: false
defaults:
run:
shell: bash
runs:
using: "composite"
steps:
+ - name: Prepare folder prefix
+ id: prepare_prefix
+ shell: bash
+ run: |
+ # Check if custom_branch_name is set and not empty
+ if [ -n "${{ inputs.custom_branch_name }}" ]; then
+ # Extract and sanitize custom_branch_name
+ CUSTOM_BRANCH_NAME="${{ inputs.custom_branch_name }}"
+ # Replace all unsupported characters with hyphens
+ SANITIZED_NAME="${CUSTOM_BRANCH_NAME//[^a-zA-Z0-9-]/-}"
+ # Optionally limit the length to, say, 50 characters
+ SANITIZED_NAME="${SANITIZED_NAME:0:50}"
+ # Assign the sanitized name to the folder_prefix
+ FOLDER_PREFIX="ya-${SANITIZED_NAME}-"
+ else
+ # If the branch name is not provided, use a default prefix
+ FOLDER_PREFIX='ya-'
+ fi
+ # Output the folder_prefix for use in subsequent steps
+ echo "folder_prefix=${FOLDER_PREFIX}" >> $GITHUB_ENV
+
- name: Prepare s3cmd
uses: ./.github/actions/s3cmd
with:
@@ -64,7 +89,7 @@ runs:
s3_endpoint: ${{ fromJSON( inputs.vars ).AWS_ENDPOINT }}
s3_key_id: ${{ fromJSON( inputs.secs ).AWS_KEY_ID }}
s3_key_secret: ${{ fromJSON( inputs.secs ).AWS_KEY_VALUE }}
- folder_prefix: ya-
+ folder_prefix: ${{ env.folder_prefix }}
build_preset: ${{ inputs.build_preset }}
- name: Run build and tests
@@ -88,3 +113,4 @@ runs:
bazel_remote_password: ${{ fromJSON( inputs.secs ).REMOTE_CACHE_PASSWORD || '' }}
put_build_results_to_cache: ${{ inputs.put_build_results_to_cache }}
test_retry_count: ${{ inputs.test_retry_count }}
+ custom_branch_name: ${{ inputs.custom_branch_name }}
diff --git a/.github/actions/test_ya/action.yml b/.github/actions/test_ya/action.yml
index 97b574459858..c41fdbbc01be 100644
--- a/.github/actions/test_ya/action.yml
+++ b/.github/actions/test_ya/action.yml
@@ -60,6 +60,11 @@ inputs:
type: string
default: ""
description: "how many times to retry failed tests"
+ custom_branch_name:
+ description: "Custom branch name required when workflow branch != checkout branch"
+ type: string
+ required: false
+
outputs:
success:
value: ${{ steps.build.outputs.status }}
@@ -271,8 +276,18 @@ runs:
--cache-size 2TB --force-build-depends
)
+ echo "inputs.custom_branch_name = ${{ inputs.custom_branch_name }}"
+ echo "GITHUB_REF_NAME = $GITHUB_REF_NAME"
+
+ if [ -z "${{ inputs.custom_branch_name }}" ]; then
+ BRANCH_NAME="${GITHUB_REF_NAME}"
+ else
+ BRANCH_NAME="${{ inputs.custom_branch_name }}"
+ fi
+ echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
+ echo "BRANCH_NAME is set to $BRANCH_NAME"
- TESTMO_BRANCH_TAG="$GITHUB_REF_NAME"
+ TESTMO_BRANCH_TAG="$BRANCH_NAME"
TESTMO_ARCH="${{ runner.arch == 'X64' && 'x86-64' || runner.arch == 'ARM64' && 'arm64' || 'unknown' }}"
TESTMO_PR_NUMBER=${{ github.event.number }}
@@ -453,6 +468,7 @@ runs:
--public_dir "$PUBLIC_DIR" \
--public_dir_url "$PUBLIC_DIR_URL" \
--build_preset "$BUILD_PRESET" \
+ --branch "$BRANCH_NAME" \
--status_report_file statusrep.txt \
--is_retry $IS_RETRY \
--is_last_retry $IS_LAST_RETRY \
@@ -470,7 +486,7 @@ runs:
# upload tests results to YDB
ydb_upload_run_name="${TESTMO_RUN_NAME// /"_"}"
- result=`.github/scripts/analytics/upload_tests_results.py --test-results-file ${CURRENT_JUNIT_XML_PATH} --run-timestamp $(date +%s) --commit $(git rev-parse HEAD) --build-type ${BUILD_PRESET} --pull $ydb_upload_run_name --job-name "${{ github.workflow }}" --job-id "${{ github.run_id }}" --branch ${GITHUB_REF_NAME}`
+ result=`.github/scripts/analytics/upload_tests_results.py --test-results-file ${CURRENT_JUNIT_XML_PATH} --run-timestamp $(date +%s) --commit $(git rev-parse HEAD) --build-type ${BUILD_PRESET} --pull $ydb_upload_run_name --job-name "${{ github.workflow }}" --job-id "${{ github.run_id }}" --branch "${BRANCH_NAME}"`
if [ ${{ inputs.testman_token }} ]; then
# finish testme session
@@ -573,7 +589,7 @@ runs:
echo file ${file_to_check} NOT changed
else
echo file ${file_to_check} changed
- .github/scripts/tests/get_muted_tests.py --output_folder "$PUBLIC_DIR/mute_info/" get_mute_diff --base_sha $ORIGINAL_HEAD~1 --head_sha $ORIGINAL_HEAD --job-id "${{ github.run_id }}" --branch "${GITHUB_REF_NAME}"
+ .github/scripts/tests/get_muted_tests.py --output_folder "$PUBLIC_DIR/mute_info/" get_mute_diff --base_sha $ORIGINAL_HEAD~1 --head_sha $ORIGINAL_HEAD --job-id "${{ github.run_id }}" --branch "${BRANCH_NAME}"
FILE_PATH=$PUBLIC_DIR/mute_info/2_new_muted_tests.txt
SEPARATOR=""
if [ -f "$FILE_PATH" ]; then
@@ -633,7 +649,7 @@ runs:
run: |
set -x
export build_preset="${{ inputs.build_preset }}"
- export branch_to_compare="$GITHUB_REF_NAME"
+ export branch_to_compare="$BRANCH_NAME"
export yellow_treshold=102400
export red_treshold=2097152
export commit_git_sha="$(git rev-parse HEAD)"
diff --git a/.github/actions/update_changelog/update_changelog.py b/.github/actions/update_changelog/update_changelog.py
index bdfeb69ad5c0..7ae60214c4e9 100644
--- a/.github/actions/update_changelog/update_changelog.py
+++ b/.github/actions/update_changelog/update_changelog.py
@@ -57,7 +57,7 @@ def to_file(changelog_path, changelog):
for category, items in changelog[UNRELEASED].items():
if(len(changelog[UNRELEASED][category]) == 0):
continue
- file.write(f"{CATEGORY_PREFIX}{category}\n")
+ file.write(f"{CATEGORY_PREFIX}{category}\n\n")
for id, body in items.items():
file.write(f"{ITEM_PREFIX}{id}:{body.strip()}\n")
file.write("\n")
@@ -69,7 +69,7 @@ def to_file(changelog_path, changelog):
for category, items in categories.items():
if(len(changelog[version][category]) == 0):
continue
- file.write(f"{CATEGORY_PREFIX}{category}\n")
+ file.write(f"{CATEGORY_PREFIX}{category}\n\n")
for id, body in items.items():
file.write(f"{ITEM_PREFIX}{id}:{body.strip()}\n")
file.write("\n")
@@ -83,7 +83,7 @@ def extract_changelog_category(description):
return None
def extract_pr_number(changelog_entry):
- match = re.search(r"#(\d+)", changelog_entry)
+ match = re.search(r"\* (\d+)", changelog_entry)
if match:
return int(match.group(1))
return None
@@ -136,14 +136,17 @@ def update_changelog(changelog_path, pr_data):
to_file(changelog_path, changelog)
def run_command(command):
+ print(f"Executing command: {command}")
try:
result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ output = result.stdout.decode().strip()
+ print(f"Command output: {output}")
+ return output
except subprocess.CalledProcessError as e:
print(f"::error::Command failed with exit code {e.returncode}: {e.stderr.decode()}")
print(f"::error::Command: {e.cmd}")
print(f"::error::Output: {e.stdout.decode()}")
sys.exit(1)
- return result.stdout.decode().strip()
def branch_exists(branch_name):
result = subprocess.run(["git", "ls-remote", "--heads", "origin", branch_name], capture_output=True, text=True)
@@ -169,7 +172,7 @@ def fetch_user_details(username):
response.raise_for_status()
return response.json()
-if __name__ == "__main__":
+def main():
if len(sys.argv) != 5:
print("Usage: update_changelog.py ")
sys.exit(1)
@@ -178,6 +181,13 @@ def fetch_user_details(username):
changelog_path = sys.argv[2]
base_branch = sys.argv[3]
suffix = sys.argv[4]
+
+ # Fetch latest changes
+ run_command("git fetch origin")
+ # Check out existing branch
+ run_command(f"git checkout {base_branch}")
+ # Make sure it's up to date
+ run_command(f"git pull origin {base_branch}")
try:
with open(pr_data_file, 'r') as file:
@@ -187,6 +197,10 @@ def fetch_user_details(username):
sys.exit(1)
pr_data = []
+ if not pr_ids:
+ print("::notice::No PR IDs found in the provided file.")
+ return
+
for pr in pr_ids:
try:
pr_details = fetch_pr_details(pr["id"])
@@ -203,7 +217,7 @@ def fetch_user_details(username):
except Exception as e:
print(f"::error::Failed to fetch PR details for PR #{pr['id']}: {e}")
sys.exit(1)
-
+
update_changelog(changelog_path, pr_data)
base_branch_name = f"changelog/{base_branch}-{suffix}"
@@ -212,13 +226,18 @@ def fetch_user_details(username):
while branch_exists(branch_name):
branch_name = f"{base_branch_name}-{index}"
index += 1
+
run_command(f"git checkout -b {branch_name}")
run_command(f"git add {changelog_path}")
run_command(f"git commit -m \"Update CHANGELOG.md for {suffix}\"")
run_command(f"git push origin {branch_name}")
- pr_title = f"Update CHANGELOG.md for {suffix}"
+ pr_title = f"Update CHANGELOG.md for {base_branch}:{suffix}"
pr_body = f"This PR updates the CHANGELOG.md file for {suffix}."
pr_create_command = f"gh pr create --title \"{pr_title}\" --body \"{pr_body}\" --base {base_branch} --head {branch_name}"
pr_url = run_command(pr_create_command)
# run_command(f"gh pr edit {pr_url} --add-assignee galnat") # TODO: Make assignee customizable
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.github/config/muted_ya.txt b/.github/config/muted_ya.txt
index 4a86e11680b7..f43771c43956 100644
--- a/.github/config/muted_ya.txt
+++ b/.github/config/muted_ya.txt
@@ -16,7 +16,12 @@ ydb/core/keyvalue/ut_trace TKeyValueTracingTest.ReadHuge
ydb/core/keyvalue/ut_trace TKeyValueTracingTest.ReadSmall
ydb/core/keyvalue/ut_trace TKeyValueTracingTest.WriteHuge
ydb/core/keyvalue/ut_trace TKeyValueTracingTest.WriteSmall
+ydb/core/kqp/ut/batch_operations KqpBatchUpdate.Large_3
+ydb/core/kqp/ut/batch_operations [*/*] chunk chunk
ydb/core/kqp/ut/cost KqpCost.OlapWriteRow
+ydb/core/kqp/ut/federated_query/s3 KqpFederatedQuery.ExecuteScriptWithLargeFile
+ydb/core/kqp/ut/federated_query/s3 KqpFederatedQuery.ExecuteScriptWithThinFile
+ydb/core/kqp/ut/federated_query/s3 sole chunk chunk
ydb/core/kqp/ut/olap KqpDecimalColumnShard.TestAggregation
ydb/core/kqp/ut/olap KqpDecimalColumnShard.TestFilterCompare
ydb/core/kqp/ut/olap KqpOlapIndexes.IndexesInBS
@@ -30,29 +35,21 @@ ydb/core/kqp/ut/olap KqpOlapWrite.TierDraftsGCWithRestart
ydb/core/kqp/ut/olap [*/*] chunk chunk
ydb/core/kqp/ut/query KqpAnalyze.AnalyzeTable+ColumnStore
ydb/core/kqp/ut/query KqpAnalyze.AnalyzeTable-ColumnStore
-ydb/core/kqp/ut/query KqpLimits.TooBigColumn+useSink
ydb/core/kqp/ut/query KqpStats.SysViewClientLost
ydb/core/kqp/ut/scheme KqpOlapScheme.TenThousandColumns
ydb/core/kqp/ut/scheme KqpScheme.AlterAsyncReplication
ydb/core/kqp/ut/scheme [*/*] chunk chunk
ydb/core/kqp/ut/service [*/*] chunk chunk
ydb/core/kqp/ut/tx KqpSinkTx.OlapInvalidateOnError
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TConflictReadWriteOlap
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TConflictReadWriteOltp
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TConflictReadWriteOltpNoSink
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TConflictWriteOlap
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TConflictWriteOltp
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TConflictWriteOltpNoSink
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TReadOnlyOltp
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TReadOnlyOltpNoSink
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TSimpleOltp
-ydb/core/kqp/ut/tx KqpSnapshotIsolation.TSimpleOltpNoSink
ydb/core/kqp/ut/yql KqpScripting.StreamExecuteYqlScriptScanOperationTmeoutBruteForce
ydb/core/mind/hive/ut TStorageBalanceTest.TestScenario2
+ydb/core/persqueue/ut/ut_with_sdk TopicAutoscaling.PartitionSplit_DistributedTxCommit_CheckOffsetCommitForDifferentCases_SplitedTopic
+ydb/core/quoter/ut QuoterWithKesusTest.KesusRecreation
ydb/core/quoter/ut QuoterWithKesusTest.PrefetchCoefficient
ydb/core/statistics/aggregator/ut AnalyzeColumnshard.AnalyzeRebootColumnShard
-ydb/core/tablet_flat/ut DataCleanup.CleanupDataWithFollowers
ydb/core/tx/datashard/ut_incremental_backup IncrementalBackup.ComplexRestoreBackupCollection+WithIncremental
+ydb/core/tx/schemeshard/ut_export_reboots_s3 TExportToS3WithRebootsTests.CancelShouldSucceedOnManyTables
+ydb/core/tx/schemeshard/ut_export_reboots_s3 TExportToS3WithRebootsTests.ShouldSucceedOnManyTables
ydb/core/tx/schemeshard/ut_login_large TSchemeShardLoginLargeTest.RemoveLogin_Many
ydb/core/tx/schemeshard/ut_move_reboots TSchemeShardMoveRebootsTest.WithData
ydb/core/tx/schemeshard/ut_move_reboots TSchemeShardMoveRebootsTest.WithDataAndPersistentPartitionStats
@@ -62,7 +59,6 @@ ydb/library/actors/interconnect/ut_huge_cluster HugeCluster.AllToAll
ydb/library/actors/interconnect/ut_huge_cluster sole chunk chunk
ydb/library/yaml_config/ut_transform test_transform.py.TestYamlConfigTransformations.test_basic[args1-dump_ds_init]
ydb/library/yql/dq/opt/ut sole chunk chunk
-ydb/public/sdk/cpp/src/client/topic/ut [*/*] chunk chunk
ydb/services/ydb/sdk_sessions_pool_ut YdbSdkSessionsPool.StressTestSync1
ydb/services/ydb/sdk_sessions_pool_ut YdbSdkSessionsPool.StressTestSync10
ydb/services/ydb/sdk_sessions_ut YdbSdkSessions.TestSdkFreeSessionAfterBadSessionQueryService
@@ -84,8 +80,6 @@ ydb/tests/fq/yds test_select_limit_db_id.py.TestSelectLimitWithDbId.test_select_
ydb/tests/fq/yds test_yds_bindings.py.TestBindings.test_yds_insert[v1]
ydb/tests/functional/compatibility test_compatibility.py.TestCompatibility.test_simple
ydb/tests/functional/compatibility test_followers.py.TestFollowersCompatibility.test_followers_compatability
-ydb/tests/functional/compatibility test_stress.py.TestStress.test_kv[last_stable-row]
-ydb/tests/functional/compatibility test_stress.py.TestStress.test_kv[mixed-row]
ydb/tests/functional/compatibility test_stress.py.TestStress.test_log[last_stable-row]
ydb/tests/functional/compatibility test_stress.py.TestStress.test_log[mixed-row]
ydb/tests/functional/compatibility test_stress.py.TestStress.test_tpch1[current-row]
@@ -94,18 +88,11 @@ ydb/tests/functional/compatibility test_stress.py.TestStress.test_tpch1[mixed-ro
ydb/tests/functional/hive test_drain.py.TestHive.test_drain_on_stop
ydb/tests/functional/rename [test_rename.py */*] chunk chunk
ydb/tests/functional/serializable sole chunk chunk
-ydb/tests/functional/serializable test.py.test_local
ydb/tests/functional/serverless test_serverless.py.test_database_with_disk_quotas[enable_alter_database_create_hive_first--false]
ydb/tests/functional/serverless test_serverless.py.test_database_with_disk_quotas[enable_alter_database_create_hive_first--true]
ydb/tests/functional/suite_tests [test_sql_logic.py */*] chunk chunk
ydb/tests/functional/suite_tests test_postgres.py.TestPGSQL.test_sql_suite[plan-jointest/join2.test]
-ydb/tests/functional/suite_tests test_postgres.py.TestPGSQL.test_sql_suite[plan-select.test]
-ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[plan-select1-1.test]
-ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[plan-select2-1.test]
-ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[plan-select2-3.test]
-ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[plan-select2-4.test]
-ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[plan-select3-9.test]
-ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[results-select3-13.test]
+ydb/tests/functional/suite_tests test_sql_logic.py.TestSQLLogic.test_sql_suite[results-select2-1.test]
ydb/tests/functional/tenants test_dynamic_tenants.py.test_create_and_drop_the_same_tenant2[enable_alter_database_create_hive_first--false]
ydb/tests/functional/tenants test_dynamic_tenants.py.test_create_and_drop_the_same_tenant2[enable_alter_database_create_hive_first--true]
ydb/tests/functional/tenants test_tenants.py.TestTenants.test_create_drop_create_table3[enable_alter_database_create_hive_first--false]
@@ -119,16 +106,17 @@ ydb/tests/functional/tpc/large sole chunk chunk
ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[10]
ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[11]
ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[12]
-ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[36]
-ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[67]
-ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[86]
ydb/tests/functional/tpc/large test_tpcds.py.TestTpcdsS1.test_tpcds[9]
-ydb/tests/functional/tpc/large test_tpch_spilling.py.TestTpchSpillingS10.test_tpch[7]
ydb/tests/olap sole chunk chunk
+ydb/tests/olap test_log_scenario.py.TestLogScenario.test
+ydb/tests/olap test_log_scenario.py.TestLogScenario.test[1051200]
+ydb/tests/olap test_log_scenario.py.TestLogScenario.test[180]
ydb/tests/olap test_quota_exhaustion.py.TestYdbWorkload.test_delete
-ydb/tests/olap/data_quotas test_quota_exhaustion.py.TestYdbWorkload.test_duplicates
ydb/tests/olap/column_family/compression alter_compression.py.TestAlterCompression.test_all_supported_compression
ydb/tests/olap/column_family/compression sole chunk chunk
+ydb/tests/olap/data_quotas [*/*] chunk chunk
+ydb/tests/olap/data_quotas test_quota_exhaustion.py.TestYdbWorkload.test
+ydb/tests/olap/data_quotas test_quota_exhaustion.py.TestYdbWorkload.test_duplicates
ydb/tests/olap/oom overlapping_portions.py.TestOverlappingPortions.test
ydb/tests/olap/scenario sole chunk chunk
ydb/tests/olap/scenario test_alter_compression.py.TestAlterCompression.test[alter_compression]
@@ -139,7 +127,6 @@ ydb/tests/olap/ttl_tiering [data_migration_when_alter_ttl.py] chunk chunk
ydb/tests/olap/ttl_tiering [ttl_delete_s3.py] chunk chunk
ydb/tests/olap/ttl_tiering data_migration_when_alter_ttl.py.TestDataMigrationWhenAlterTtl.test
ydb/tests/olap/ttl_tiering sole chunk chunk
-ydb/tests/olap/ttl_tiering ttl_delete_s3.py.TestDeleteS3Ttl.test_data_unchanged_after_ttl_change
ydb/tests/olap/ttl_tiering ttl_delete_s3.py.TestDeleteS3Ttl.test_delete_s3_tiering
ydb/tests/olap/ttl_tiering ttl_delete_s3.py.TestDeleteS3Ttl.test_ttl_delete
ydb/tests/postgres_integrations/go-libpq [docker_wrapper_test.py] chunk chunk
@@ -225,4 +212,5 @@ ydb/tests/sql/large test_workload_manager.py.TestWorkloadManager.test_resource_p
ydb/tests/sql/large test_workload_manager.py.TestWorkloadManager.test_resource_pool_queue_size_limit
ydb/tests/stress/log/tests test_workload.py.TestYdbLogWorkload.test[column]
ydb/tests/stress/log/tests test_workload.py.TestYdbLogWorkload.test[row]
+ydb/tests/stress/mixedpy test_mixed.py.TestYdbMixedWorkload.test[column]
ydb/tools/stress_tool/ut TDeviceTestTool.PDiskTestLogWrite
diff --git a/.github/scripts/analytics/data_mart_delete_table.py b/.github/scripts/analytics/data_mart_delete_table.py
new file mode 100644
index 000000000000..76121b3fc523
--- /dev/null
+++ b/.github/scripts/analytics/data_mart_delete_table.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+
+import argparse
+import ydb
+import configparser
+import os
+
+# Load configuration
+dir = os.path.dirname(__file__)
+config = configparser.ConfigParser()
+config_file_path = f"{dir}/../../config/ydb_qa_db.ini"
+config.read(config_file_path)
+
+DATABASE_ENDPOINT = config["QA_DB"]["DATABASE_ENDPOINT"]
+DATABASE_PATH = config["QA_DB"]["DATABASE_PATH"]
+
+def parse_args():
+ parser = argparse.ArgumentParser(description="Delete a YDB table")
+ parser.add_argument("--table_path", required=True, help="Table path and name to delete")
+
+ return parser.parse_args()
+
+def check_table_exists(session, table_path):
+ """Check if table exists"""
+ try:
+ session.describe_table(table_path)
+ return True
+ except ydb.SchemeError:
+ return False
+
+def delete_table(session, table_path):
+ """Delete the specified table."""
+ try:
+ session.drop_table(table_path)
+ print(f"Table '{table_path}' successfully deleted.")
+ return True
+ except ydb.Error as e:
+ print(f"Error deleting table: {e}")
+ return False
+
+def main():
+ args = parse_args()
+
+ if "CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS" not in os.environ:
+ print("Error: Env variable CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS is missing, skipping")
+ return 1
+ else:
+ os.environ["YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS"] = os.environ[
+ "CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS"
+ ]
+
+ table_path = args.table_path
+ full_table_path = f'{DATABASE_PATH}/{table_path}'
+
+ print(f"Connecting to YDB to delete table {full_table_path}")
+
+ with ydb.Driver(
+ endpoint=DATABASE_ENDPOINT,
+ database=DATABASE_PATH,
+ credentials=ydb.credentials_from_env_variables()
+ ) as driver:
+ # Wait until driver is ready
+ driver.wait(timeout=10, fail_fast=True)
+
+ with ydb.SessionPool(driver) as pool:
+ # Проверяем существование таблицы
+ def check_and_delete(session):
+ exists = check_table_exists(session, full_table_path)
+ if exists:
+ return delete_table(session, full_table_path)
+ else:
+ print(f"Table '{full_table_path}' does not exist.")
+ return False
+
+ result = pool.retry_operation_sync(check_and_delete)
+
+ if result:
+ print(f"Table {full_table_path} has been deleted successfully.")
+ return 0
+ else:
+ print(f"No table was deleted.")
+ return 1
+
+if __name__ == "__main__":
+ exit_code = main()
+ exit(exit_code)
diff --git a/.github/scripts/analytics/data_mart_executor.py b/.github/scripts/analytics/data_mart_executor.py
index 00116e8cff93..2f88ac849cbc 100755
--- a/.github/scripts/analytics/data_mart_executor.py
+++ b/.github/scripts/analytics/data_mart_executor.py
@@ -145,7 +145,7 @@ def main():
]
table_path = args.table_path
- batch_size = 50000
+ batch_size = 1000
# Read SQL query from file
sql_query_path = os.path.join(repo_path, args.query_path)
diff --git a/.github/scripts/analytics/data_mart_queries/perfomance_olap_mart.sql b/.github/scripts/analytics/data_mart_queries/perfomance_olap_mart.sql
index 960cace5add0..12630831db3b 100644
--- a/.github/scripts/analytics/data_mart_queries/perfomance_olap_mart.sql
+++ b/.github/scripts/analytics/data_mart_queries/perfomance_olap_mart.sql
@@ -1,318 +1,178 @@
-select
+$start_timestamp = (CurrentUtcDate() - 30 * Interval("P1D"));
- Db ,
+$all_suites = (
+ SELECT
+ Suite, Test
+ FROM (
+ SELECT
+ Suite,
+ ListSort(AGG_LIST_DISTINCT(Test)) AS Tests
+ FROM `perfomance/olap/tests_results`
+ WHERE Timestamp >= $start_timestamp
+ GROUP BY Suite
+ )
+ FLATTEN LIST BY Tests AS Test
+);
+
+$launch_times = (
+ SELECT
+ launch_times_raw.*,
+ all_suites.*
+ FROM (
+ SELECT
+ Db,
+ Branch,
+ Version,
+ LunchId,
+ CAST(Min(RunId / 1000UL) AS Timestamp) AS Run_start_timestamp,
+ ROW_NUMBER() OVER (PARTITION BY Db, Version ORDER BY Min(RunId) ASC) AS Run_number_in_version,
+ ROW_NUMBER() OVER (PARTITION BY Db, Branch ORDER BY Min(RunId) DESC) AS Run_number_in_branch_desc
+ FROM `perfomance/olap/tests_results`
+ WHERE Timestamp >= $start_timestamp
+ GROUP BY
+ Db,
+ Unicode::SplitToList(JSON_VALUE(Info, "$.cluster.version"), '.')[0] As Branch,
+ JSON_VALUE(Info, "$.cluster.version") AS Version,
+ JSON_VALUE(Info, "$.ci_launch_id") AS LunchId
+ ) AS launch_times_raw
+ CROSS JOIN $all_suites AS all_suites
+);
+
+$all_tests_raw =
+ SELECT
+ tests_results.*,
+ JSON_VALUE(Info, "$.report_url") AS Report,
+ JSON_VALUE(tests_results.Info, "$.cluster.version") AS Version_n,
+ JSON_VALUE(tests_results.Info, "$.ci_launch_id") AS LunchId_n,
+ CAST(JSON_VALUE(Stats, '$.DiffsCount') AS INT) AS diff_response,
+ IF(Success > 0, MeanDuration / 1000) AS YdbSumMeans,
+ IF(Success > 0, MaxDuration / 1000) AS YdbSumMax,
+ IF(Success > 0, MinDuration / 1000) AS YdbSumMin,
+ CAST(RunId / 1000UL AS Timestamp) AS RunTs,
+ IF (JSON_VALUE(Stats, "$.errors.other") = "true",
+ "red",
+ IF (JSON_VALUE(Stats, "$.errors.timeout") = "true",
+ "blue",
+ IF (JSON_VALUE(Stats, "$.errors.warning") = "true",
+ "yellow",
+ "green"
+ )
+ )
+ ) AS Color
+ FROM `perfomance/olap/tests_results` AS tests_results
+ WHERE Timestamp >= $start_timestamp;
+
+SELECT
+ Db,
Suite,
Test,
- Next_Run_start_timestamp ,
Run_start_timestamp,
Run_number_in_version,
Run_number_in_branch_desc,
- MaxDuration ,
- MeanDuration ,
- MedianDuration ,
- MinDuration ,
- YdbSumMax ,
- YdbSumMeans ,
- YdbSumMin ,
+ MaxDuration,
+ MeanDuration,
+ MedianDuration,
+ MinDuration,
+ YdbSumMax,
+ YdbSumMeans,
+ YdbSumMin,
Version,
Branch,
- diff_response ,
+ diff_response,
Timestamp,
- COALESCE(Success ,0) as Success ,
- max(Kind) OVER (PARTITION by Db , Run_start_timestamp, Suite) as Kind,
- max(Report) OVER (PARTITION by Db , Run_start_timestamp, Suite) as Report,
- max(RunId) OVER (PARTITION by Db , Run_start_timestamp, Suite) as RunId,
- max(RunTs) OVER (PARTITION by Db , Run_start_timestamp, Suite) as RunTs,
+ COALESCE(Success,0) AS Success,
+ max(Kind) OVER (PARTITION by Db, Run_start_timestamp, Suite) AS Kind,
+ max(Report) OVER (PARTITION by Db, Run_start_timestamp, Suite) AS Report,
+ max(RunId) OVER (PARTITION by Db, Run_start_timestamp, Suite) AS RunId,
+ max(RunTs) OVER (PARTITION by Db, Run_start_timestamp, Suite) AS RunTs,
YdbSumMeans IS NULL AS errors,
- max(Report) OVER (PARTITION by Db , Run_start_timestamp, Suite) IS NULL AS Suite_not_runned,
+ max(Report) OVER (PARTITION by Db, Run_start_timestamp, Suite) IS NULL AS Suite_not_runned,
Color
- from (
-
-SELECT
- null_template.Db AS Db, --only from null_template
- COALESCE(real_data.Kind, null_template.Kind) AS Kind,
- COALESCE(real_data.MaxDuration, null_template.MaxDuration) AS MaxDuration,
- COALESCE(real_data.MeanDuration, null_template.MeanDuration) AS MeanDuration,
- COALESCE(real_data.MedianDuration, null_template.MedianDuration) AS MedianDuration,
- COALESCE(real_data.MinDuration, null_template.MinDuration) AS MinDuration,
- null_template.Next_Run_start_timestamp AS Next_Run_start_timestamp, --only from null_template
- COALESCE(real_data.Report, null_template.Report) AS Report,
- COALESCE(real_data.Branch, null_template.Branch) AS Branch,
- COALESCE(real_data.RunId, null_template.RunId) AS RunId,
- COALESCE(real_data.RunTs, null_template.RunTs) AS RunTs,
- null_template.Run_number_in_version AS Run_number_in_version, --only from null_template
- null_template.Run_start_timestamp AS Run_start_timestamp, --only from null_template
- COALESCE(real_data.Run_number_in_branch_desc, null_template.Run_number_in_branch_desc) AS Run_number_in_branch_desc,
- COALESCE(real_data.Success, null_template.Success) AS Success,
- null_template.Suite AS Suite, --only from null_template
- null_template.Test AS Test, --only from null_template
- COALESCE(real_data.Timestamp, null_template.Timestamp) AS Timestamp,
- COALESCE(real_data.Version, null_template.Version) AS Version,
- COALESCE(real_data.YdbSumMax, null_template.YdbSumMax) AS YdbSumMax,
- COALESCE(real_data.YdbSumMeans, null_template.YdbSumMeans) AS YdbSumMeans,
- COALESCE(real_data.YdbSumMin, null_template.YdbSumMin) AS YdbSumMin,
- COALESCE(real_data.diff_response, null_template.diff_response) AS diff_response,
- COALESCE(real_data.Color, null_template.Color) AS Color,
-
FROM (
- SELECT
- all_tests.*,
- launch_times.*
- FROM (
- SELECT
- launch_times.*,
- all_suites.*
- FROM (
- SELECT DISTINCT
- Db,
- Version,
- Branch,
- Run_start_timestamp,
- Run_number_in_version,
- Next_Run_start_timestamp,
- ROW_NUMBER() OVER (PARTITION BY Db, Branch ORDER BY Run_start_timestamp DESC) AS Run_number_in_branch_desc
- FROM (
- SELECT
- Db,
- Version,
- Run_start_timestamp,
- Next_Run_start_timestamp,
- ROW_NUMBER() OVER (PARTITION BY t1.Db, t1.Version ORDER BY t1.Run_start_timestamp ASC) AS Run_number_in_version,
- Unicode::SplitToList(Version, '.')[0] AS Branch
- FROM (
- SELECT
- runs.Db AS Db,
- runs.Version AS Version,
- run_start.Run_start_timestamp AS Run_start_timestamp,
- run_start.Next_Run_start_timestamp AS Next_Run_start_timestamp
- FROM (
- SELECT DISTINCT
- Db,
- Timestamp,
- JSON_VALUE(Info, "$.cluster.version") AS Version,
- CAST(RunId / 1000 AS Timestamp) AS RunTs
- FROM `perfomance/olap/tests_results`
- WHere Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- ) AS runs
- LEFT JOIN (
- SELECT
- Db,
- JSON_VALUE(Info, "$.cluster.version") AS Version,
- Timestamp AS Run_start_timestamp,
- LEAD(Timestamp) OVER (PARTITION BY Db, JSON_VALUE(Info, "$.cluster.version") ORDER BY Timestamp) AS Next_Run_start_timestamp
- FROM `perfomance/olap/tests_results`
- WHERE Suite = 'Clickbench' AND Test = '_Verification'
- And Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- ORDER BY Db, Run_start_timestamp DESC, Version
- ) AS run_start
- ON runs.Db = run_start.Db AND runs.Version = run_start.Version
- WHERE (
- (runs.Timestamp >= run_start.Run_start_timestamp AND runs.Timestamp < run_start.Next_Run_start_timestamp) OR
- (runs.Timestamp >= run_start.Run_start_timestamp AND run_start.Next_Run_start_timestamp IS NULL)
- )
- ) AS t1
- GROUP BY Db, Version, Run_start_timestamp, Next_Run_start_timestamp
- ) AS run_start
- GROUP BY Db, Branch, Version, Run_start_timestamp, Run_number_in_version, Next_Run_start_timestamp
- ) AS launch_times
- CROSS JOIN (
- SELECT
- Suite, Test
- FROM (
- SELECT
- Suite,
- ListSort(AGG_LIST_DISTINCT(Test)) AS Tests
- FROM `perfomance/olap/tests_results`
- WHere Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- GROUP BY Suite
- ORDER BY Suite
- )
- FLATTEN LIST BY Tests AS Test
- ORDER BY Suite, Test
- ) AS all_suites
- ) AS launch_times
- LEFT JOIN (
- SELECT
- all_tests.*,
- JSON_VALUE(Info, "$.report_url") AS Report,
- JSON_VALUE(all_tests.Info, "$.cluster.version") AS Version_n,
- CAST(JSON_VALUE(Stats, '$.DiffsCount') AS INT) AS diff_response,
- IF(Success > 0, MeanDuration / 1000) AS YdbSumMeans,
- IF(Success > 0, MaxDuration / 1000) AS YdbSumMax,
- IF(Success > 0, MinDuration / 1000) AS YdbSumMin,
- CAST(RunId / 1000 AS Timestamp) AS RunTs,
- IF (JSON_VALUE(Stats, "$.errors.other") = "true",
- "red",
- IF (JSON_VALUE(Stats, "$.errors.timeout") = "true",
- "blue",
- IF (JSON_VALUE(Stats, "$.errors.warning") = "true",
- "yellow",
- "green"
- )
- )
- ) as Color
- FROM `perfomance/olap/tests_results` AS all_tests
- Where JSON_VALUE(all_tests.Info, "$.cluster.version") is Null --and Test != '_Verification'
- and Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- ) AS all_tests
- ON all_tests.Db = launch_times.Db
- AND all_tests.Suite = launch_times.Suite
- AND all_tests.Test = launch_times.Test
- -- WHERE ( all_tests.Version_n is Null)
-
-
- ORDER BY Run_start_timestamp DESC, Db, launch_times.Version, RunId
-) AS null_template
-Full OUTER join
-(SELECT
- real_data.Db AS Db,
- real_data.Kind AS Kind,
- real_data.MaxDuration AS MaxDuration,
- real_data.MeanDuration AS MeanDuration,
- real_data.MedianDuration AS MedianDuration,
- real_data.MinDuration AS MinDuration,
- real_data.Next_Run_start_timestamp AS Next_Run_start_timestamp,
- real_data.Report AS Report,
- real_data.Branch AS Branch,
- real_data.RunId AS RunId,
- real_data.RunTs AS RunTs,
- real_data.Run_number_in_version AS Run_number_in_version,
- real_data.Run_start_timestamp AS Run_start_timestamp,
- real_data.Run_number_in_branch_desc AS Run_number_in_branch_desc,
- --real_data.Stats AS Stats,
- real_data.Success AS Success,
- real_data.Suite AS Suite,
- real_data.Test AS Test,
- real_data.Timestamp AS Timestamp,
- real_data.Version AS Version,
- real_data.YdbSumMax AS YdbSumMax,
- real_data.YdbSumMeans AS YdbSumMeans,
- real_data.YdbSumMin AS YdbSumMin,
- real_data.diff_response AS diff_response,
- real_data.Color AS Color,
-
+ SELECT
+ null_template.Db AS Db, --only from null_template
+ COALESCE(real_data.Kind, null_template.Kind) AS Kind,
+ COALESCE(real_data.MaxDuration, null_template.MaxDuration) AS MaxDuration,
+ COALESCE(real_data.MeanDuration, null_template.MeanDuration) AS MeanDuration,
+ COALESCE(real_data.MedianDuration, null_template.MedianDuration) AS MedianDuration,
+ COALESCE(real_data.MinDuration, null_template.MinDuration) AS MinDuration,
+ COALESCE(real_data.Report, null_template.Report) AS Report,
+ COALESCE(real_data.Branch, null_template.Branch) AS Branch,
+ COALESCE(real_data.RunId, null_template.RunId) AS RunId,
+ COALESCE(real_data.RunTs, null_template.RunTs) AS RunTs,
+ null_template.Run_number_in_version AS Run_number_in_version, --only from null_template
+ null_template.Run_start_timestamp AS Run_start_timestamp, --only from null_template
+ COALESCE(real_data.Run_number_in_branch_desc, null_template.Run_number_in_branch_desc) AS Run_number_in_branch_desc,
+ COALESCE(real_data.Success, null_template.Success) AS Success,
+ null_template.Suite AS Suite, --only from null_template
+ null_template.Test AS Test, --only from null_template
+ COALESCE(real_data.Timestamp, null_template.Timestamp) AS Timestamp,
+ COALESCE(real_data.Version, null_template.Version) AS Version,
+ COALESCE(real_data.YdbSumMax, null_template.YdbSumMax) AS YdbSumMax,
+ COALESCE(real_data.YdbSumMeans, null_template.YdbSumMeans) AS YdbSumMeans,
+ COALESCE(real_data.YdbSumMin, null_template.YdbSumMin) AS YdbSumMin,
+ COALESCE(real_data.diff_response, null_template.diff_response) AS diff_response,
+ COALESCE(real_data.Color, null_template.Color) AS Color,
FROM (
SELECT
all_tests.*,
- launch_times.*,
-
- FROM (
- SELECT
- launch_times.*,
- all_suites.*
- FROM (
- SELECT DISTINCT
- Db,
- Version,
- Branch,
- Run_start_timestamp,
- Run_number_in_version,
- Next_Run_start_timestamp,
- ROW_NUMBER() OVER (PARTITION BY Db, Branch ORDER BY Run_start_timestamp DESC) AS Run_number_in_branch_desc
- FROM (
- SELECT
- Db,
- Version,
- Run_start_timestamp,
- Next_Run_start_timestamp,
- ROW_NUMBER() OVER (PARTITION BY t1.Db, t1.Version ORDER BY t1.Run_start_timestamp ASC) AS Run_number_in_version,
- Unicode::SplitToList(Version, '.')[0] AS Branch
- FROM (
- SELECT
- runs.Db AS Db,
- runs.Version AS Version,
- run_start.Run_start_timestamp AS Run_start_timestamp,
- run_start.Next_Run_start_timestamp AS Next_Run_start_timestamp
- FROM (
- SELECT DISTINCT
- Db,
- Timestamp,
- JSON_VALUE(Info, "$.cluster.version") AS Version,
- CAST(RunId / 1000 AS Timestamp) AS RunTs
- FROM `perfomance/olap/tests_results`
- WHere Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- ) AS runs
- LEFT JOIN (
- SELECT
- Db,
- JSON_VALUE(Info, "$.cluster.version") AS Version,
- Timestamp AS Run_start_timestamp,
- LEAD(Timestamp) OVER (PARTITION BY Db, JSON_VALUE(Info, "$.cluster.version") ORDER BY Timestamp) AS Next_Run_start_timestamp
- FROM `perfomance/olap/tests_results`
- WHERE Suite = 'Clickbench' AND Test = '_Verification'
- And Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- ORDER BY Db, Run_start_timestamp DESC, Version
- ) AS run_start
- ON runs.Db = run_start.Db AND runs.Version = run_start.Version
- WHERE (
- (runs.Timestamp >= run_start.Run_start_timestamp AND runs.Timestamp < run_start.Next_Run_start_timestamp) OR
- (runs.Timestamp >= run_start.Run_start_timestamp AND run_start.Next_Run_start_timestamp IS NULL)
- )
- ) AS t1
- GROUP BY Db, Version, Run_start_timestamp, Next_Run_start_timestamp
- ) AS run_start
- GROUP BY Db, Branch, Version, Run_start_timestamp, Run_number_in_version, Next_Run_start_timestamp
- ) AS launch_times
- CROSS JOIN (
- SELECT
- Suite, Test
- FROM (
- SELECT
- Suite,
- ListSort(AGG_LIST_DISTINCT(Test)) AS Tests
- FROM `perfomance/olap/tests_results`
- WHere Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
- GROUP BY Suite
- ORDER BY Suite
-
- )
- FLATTEN LIST BY Tests AS Test
- ORDER BY Suite, Test
- ) AS all_suites
- ) AS launch_times
+ launch_times.*
+ FROM $launch_times AS launch_times
LEFT JOIN (
- SELECT
- all_tests.*,
- JSON_VALUE(Info, "$.report_url") AS Report,
- JSON_VALUE(all_tests.Info, "$.cluster.version") AS Version_n,
- CAST(JSON_VALUE(Stats, '$.DiffsCount') AS INT) AS diff_response,
- IF(Success > 0, MeanDuration / 1000) AS YdbSumMeans,
- IF(Success > 0, MaxDuration / 1000) AS YdbSumMax,
- IF(Success > 0, MinDuration / 1000) AS YdbSumMin,
- CAST(RunId / 1000 AS Timestamp) AS RunTs,
- IF (JSON_VALUE(Stats, "$.errors.other") = "true",
- "red",
- IF (JSON_VALUE(Stats, "$.errors.timeout") = "true",
- "blue",
- IF (JSON_VALUE(Stats, "$.errors.warning") = "true",
- "yellow",
- "green"
- )
- )
- ) as Color
- FROM `perfomance/olap/tests_results` AS all_tests
- WHere Timestamp >= CurrentUtcDate() - 30*Interval("P1D")
+ SELECT
+ *
+ FROM $all_tests_raw AS all_tests_raw
+ WHERE JSON_VALUE(all_tests_raw.Info, "$.cluster.version") is NULL
) AS all_tests
ON all_tests.Db = launch_times.Db
AND all_tests.Suite = launch_times.Suite
AND all_tests.Test = launch_times.Test
- AND all_tests.Version_n = launch_times.Version
- WHERE (
- (all_tests.Timestamp >= launch_times.Run_start_timestamp AND all_tests.Timestamp < launch_times.Next_Run_start_timestamp) OR
- (all_tests.Timestamp >= launch_times.Run_start_timestamp AND launch_times.Next_Run_start_timestamp IS NULL)
- OR all_tests.RunId IS NULL
-
- )
-
- ORDER BY Run_start_timestamp DESC, Db, Version, RunId
+ -- WHERE ( all_tests.Version_n is NULL)
+ ) AS null_template
+ FULL OUTER JOIN (
+ SELECT
+ real_data.Db AS Db,
+ real_data.Kind AS Kind,
+ real_data.MaxDuration AS MaxDuration,
+ real_data.MeanDuration AS MeanDuration,
+ real_data.MedianDuration AS MedianDuration,
+ real_data.MinDuration AS MinDuration,
+ real_data.Report AS Report,
+ real_data.Branch AS Branch,
+ real_data.RunId AS RunId,
+ real_data.RunTs AS RunTs,
+ real_data.Run_number_in_version AS Run_number_in_version,
+ real_data.Run_start_timestamp AS Run_start_timestamp,
+ real_data.Run_number_in_branch_desc AS Run_number_in_branch_desc,
+ --real_data.Stats AS Stats,
+ real_data.Success AS Success,
+ real_data.Suite AS Suite,
+ real_data.Test AS Test,
+ real_data.Timestamp AS Timestamp,
+ real_data.Version AS Version,
+ real_data.YdbSumMax AS YdbSumMax,
+ real_data.YdbSumMeans AS YdbSumMeans,
+ real_data.YdbSumMin AS YdbSumMin,
+ real_data.diff_response AS diff_response,
+ real_data.Color AS Color,
+ FROM (
+ SELECT
+ all_tests.*,
+ launch_times.*,
+ FROM $launch_times AS launch_times
+ LEFT JOIN $all_tests_raw AS all_tests
+ ON all_tests.Db = launch_times.Db
+ AND all_tests.Suite = launch_times.Suite
+ AND all_tests.Test = launch_times.Test
+ AND all_tests.Version_n = launch_times.Version
+ WHERE (
+ all_tests.LunchId_n == launch_times.LunchId
+ OR all_tests.RunId IS NULL
+ )
+ ) AS real_data
) AS real_data
-) as real_data
-
-on null_template.Db = real_data.Db
-and null_template.Run_start_timestamp = real_data.Run_start_timestamp
-and null_template.Suite = real_data.Suite
-and null_template.Test = real_data.Test
+ ON null_template.Db = real_data.Db
+ AND null_template.Run_start_timestamp = real_data.Run_start_timestamp
+ AND null_template.Suite = real_data.Suite
+ AND null_template.Test = real_data.Test
)
-
-
-
diff --git a/.github/scripts/analytics/data_mart_queries/test_history_fast_mart.sql b/.github/scripts/analytics/data_mart_queries/test_history_fast_mart.sql
new file mode 100644
index 000000000000..8245527f3368
--- /dev/null
+++ b/.github/scripts/analytics/data_mart_queries/test_history_fast_mart.sql
@@ -0,0 +1,25 @@
+SELECT
+ build_type,
+ job_name,
+ job_id,
+ commit,
+ branch,
+ pull,
+ run_timestamp,
+ test_id,
+ suite_folder,
+ test_name,
+ cast(suite_folder || '/' || test_name as UTF8) as full_name,
+ duration,
+ status,
+ cast(String::ReplaceAll(status_description, ';;', '\n')as Utf8) as status_description ,
+ owners
+ FROM `test_results/test_runs_column` as all_data
+ WHERE
+ run_timestamp >= CurrentUtcDate() - Interval("P1D")
+ and String::Contains(test_name, '.flake8') = FALSE
+ and (CASE
+ WHEN String::Contains(test_name, 'chunk chunk') OR String::Contains(test_name, 'chunk+chunk') THEN TRUE
+ ELSE FALSE
+ END) = FALSE
+ and (branch = 'main' or branch like 'stable-%')
diff --git a/.github/scripts/analytics/data_mart_queries/test_history_mart.sql b/.github/scripts/analytics/data_mart_queries/test_history_mart.sql
new file mode 100644
index 000000000000..83f5e67d8abb
--- /dev/null
+++ b/.github/scripts/analytics/data_mart_queries/test_history_mart.sql
@@ -0,0 +1,34 @@
+SELECT
+ build_type ,
+ job_name,
+ job_id,
+ commit,
+ branch,
+ pull,
+ run_timestamp,
+ test_id,
+ suite_folder,
+ test_name,
+ cast(suite_folder || '/' || test_name as UTF8) as full_name,
+ duration,
+ status,
+ String::ReplaceAll(status_description, ';;', '\n') as status_description,
+ owners,
+ String::ReplaceAll(owners, 'TEAM:@ydb-platform/', '') as owner_team,
+ String::SplitToList(pull,'_A')[0] as pull_raw,
+ cast(COALESCE(String::SplitToList(pull,'_A')[1],"1") as Uint16) as attempt,
+ (cast(pull as String) || '_' || SUBSTRING(cast(commit as String), 1, 8)) as pull_commit,
+ CASE
+ WHEN String::Contains(test_name, 'chunk chunk') OR String::Contains(test_name, 'chunk+chunk') THEN TRUE
+ ELSE FALSE
+ END as with_cunks
+
+FROM `test_results/test_runs_column`
+
+WHERE
+ run_timestamp >= CurrentUtcDate() - 1*Interval("P1D")
+ and String::Contains(test_name, '.flake8') = FALSE
+ and (CASE
+ WHEN String::Contains(test_name, 'chunk chunk') OR String::Contains(test_name, 'chunk+chunk') THEN TRUE
+ ELSE FALSE
+ END) = FALSE
diff --git a/.github/scripts/analytics/data_mart_queries/test_monitor_mart.sql b/.github/scripts/analytics/data_mart_queries/test_monitor_mart.sql
index ebf1793f8364..4383be240345 100644
--- a/.github/scripts/analytics/data_mart_queries/test_monitor_mart.sql
+++ b/.github/scripts/analytics/data_mart_queries/test_monitor_mart.sql
@@ -36,10 +36,9 @@ SELECT
END as is_muted_or_skipped
FROM `test_results/analytics/tests_monitor`
WHERE date_window >= CurrentUtcDate() - 30 * Interval("P1D")
-and branch = 'main'
+and ( branch = 'main' or branch like 'stable-%')
and is_test_chunk = 0
and (CASE
WHEN is_muted = 1 OR (state = 'Skipped' AND days_in_state > 14) THEN TRUE
ELSE FALSE
END ) = TRUE
-
diff --git a/.github/scripts/analytics/data_mart_queries/test_results_mart.sql b/.github/scripts/analytics/data_mart_queries/test_results_mart.sql
deleted file mode 100644
index 3e7c3d31619c..000000000000
--- a/.github/scripts/analytics/data_mart_queries/test_results_mart.sql
+++ /dev/null
@@ -1,35 +0,0 @@
-SELECT
- build_type ,
- job_name,
- job_id,
- commit,
- branch,
- pull,
- run_timestamp,
- test_id,
- suite_folder,
- test_name,
- cast(suite_folder || '/' || test_name as UTF8) as full_name,
- duration,
- status,
- String::ReplaceAll(status_description, ';;', '\n') as status_description,
- owners,
- String::ReplaceAll(owners, 'TEAM:@ydb-platform/', '') as owner_team,
- String::SplitToList(pull,'_A')[0] as pull_raw,
- cast(COALESCE(String::SplitToList(pull,'_A')[1],"1") as Uint16) as attempt,
- (cast(pull as String) || '_' || SUBSTRING(cast(commit as String), 1, 8)) as pull_commit,
- CASE
- WHEN String::Contains(test_name, 'chunk chunk') OR String::Contains(test_name, 'chunk+chunk') THEN TRUE
- ELSE FALSE
- END as with_cunks
-
-FROM `test_results/test_runs_column`
-
-WHERE
- run_timestamp >= CurrentUtcDate() - 6*Interval("P1D")
- and build_type = 'relwithdebinfo'
- and String::Contains(test_name, '.flake8') = FALSE
- and (CASE
- WHEN String::Contains(test_name, 'chunk chunk') OR String::Contains(test_name, 'chunk+chunk') THEN TRUE
- ELSE FALSE
- END) = FALSE
diff --git a/.github/scripts/analytics/data_mart_ttl_analog.py b/.github/scripts/analytics/data_mart_ttl_analog.py
new file mode 100644
index 000000000000..9d80406ca0c2
--- /dev/null
+++ b/.github/scripts/analytics/data_mart_ttl_analog.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+
+import argparse
+import ydb
+import configparser
+import os
+import time
+
+# Load configuration
+dir = os.path.dirname(__file__)
+config = configparser.ConfigParser()
+config_file_path = f"{dir}/../../config/ydb_qa_db.ini"
+config.read(config_file_path)
+
+DATABASE_ENDPOINT = config["QA_DB"]["DATABASE_ENDPOINT"]
+DATABASE_PATH = config["QA_DB"]["DATABASE_PATH"]
+
+def parse_args():
+ parser = argparse.ArgumentParser(description="Delete old records from YDB table")
+ parser.add_argument("--table-path", required=True, help="Table path and name")
+ parser.add_argument("--timestamp-field", required=True, help="Name of the timestamp field")
+ parser.add_argument("--delete-interval", required=True, help="Interval to delete records older than, in ISO 8601 format (https://en.wikipedia.org/wiki/ISO_8601#Durations) without 'P'")
+
+ return parser.parse_args()
+
+def delete_old_records(session, full_table_path, timestamp_field, delete_interval):
+ """Delete records older than the specified interval."""
+ # First, count the number of records that will be deleted
+ count_query = f"""
+ SELECT COUNT(*) as count
+ FROM `{full_table_path}`
+ WHERE `{timestamp_field}` < CurrentUtcDate() - Interval("P{delete_interval}")
+ """
+
+ print(f"Counting records to delete...")
+ result_sets = session.transaction().execute(count_query)
+ row_count = result_sets[0].rows[0].count
+
+ if row_count == 0:
+ print("No records to delete.")
+ return 0
+
+ print(f"Found {row_count} records older than {delete_interval}.")
+
+ # Now perform the delete operation
+ delete_query = f"""
+ DELETE FROM `{full_table_path}`
+ WHERE `{timestamp_field}` < CurrentUtcDate() - Interval("P{delete_interval}")
+ """
+
+ print(f"Executing DELETE query: {delete_query}")
+ start_time = time.time()
+ session.transaction().execute(delete_query, commit_tx=True)
+ end_time = time.time()
+
+ print(f"Deleted {row_count} records in {end_time - start_time:.2f} seconds.")
+ return row_count
+
+def main():
+ args = parse_args()
+
+ if "CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS" not in os.environ:
+ print("Error: Env variable CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS is missing, skipping")
+ return 1
+ else:
+ os.environ["YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS"] = os.environ[
+ "CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS"
+ ]
+
+ table_path = args.table_path
+ full_table_path = f'{DATABASE_PATH}/{table_path}'
+ timestamp_field = args.timestamp_field
+ delete_interval = args.delete_interval
+
+ print(f"Connecting to YDB to delete records from {full_table_path}")
+ print(f"Will delete records where {timestamp_field} < CurrentUtcDate() - Interval(\"P{delete_interval}\")")
+
+ with ydb.Driver(
+ endpoint=DATABASE_ENDPOINT,
+ database=DATABASE_PATH,
+ credentials=ydb.credentials_from_env_variables()
+ ) as driver:
+ # Wait until driver is ready
+ driver.wait(timeout=10, fail_fast=True)
+
+ with ydb.SessionPool(driver) as pool:
+ try:
+ def transaction_delete(session):
+ return delete_old_records(session, full_table_path, timestamp_field, delete_interval)
+
+ deleted_count = pool.retry_operation_sync(transaction_delete)
+
+ print(f"Successfully deleted old records from {full_table_path}")
+ print(f"Total records deleted: {deleted_count}")
+ return 0
+ except ydb.Error as e:
+ print(f"Error deleting records: {e}")
+ return 1
+
+if __name__ == "__main__":
+ exit_code = main()
+ exit(exit_code)
diff --git a/.github/scripts/analytics/flaky_tests_history.py b/.github/scripts/analytics/flaky_tests_history.py
index d1c1c637af45..29b55d1dc11d 100755
--- a/.github/scripts/analytics/flaky_tests_history.py
+++ b/.github/scripts/analytics/flaky_tests_history.py
@@ -78,8 +78,8 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('--days-window', default=1, type=int, help='how many days back we collecting history')
- parser.add_argument('--build_type',choices=['relwithdebinfo', 'release-asan'], default='relwithdebinfo', type=str, help='build : relwithdebinfo or release-asan')
- parser.add_argument('--branch', default='main',choices=['main'], type=str, help='branch')
+ parser.add_argument('--build_type', default='relwithdebinfo', type=str, help='build types')
+ parser.add_argument('--branch', default='main', type=str, help='branch')
args, unknown = parser.parse_known_args()
history_for_n_day = args.days_window
@@ -203,6 +203,9 @@ def main():
and job_name in (
'Nightly-run',
'Regression-run',
+ 'Regression-run_Large',
+ 'Regression-run_Small_and_Medium',
+ 'Regression-run_compatibility',
'Regression-whitelist-run',
'Postcommit_relwithdebinfo',
'Postcommit_asan'
diff --git a/.github/scripts/analytics/flaky_tests_history_n_runs.py b/.github/scripts/analytics/flaky_tests_history_n_runs.py
index 1c4787a45c59..c35046374e25 100755
--- a/.github/scripts/analytics/flaky_tests_history_n_runs.py
+++ b/.github/scripts/analytics/flaky_tests_history_n_runs.py
@@ -203,6 +203,9 @@ def main():
and job_name in (
'Nightly-run',
'Regression-run',
+ 'Regression-run_Large',
+ 'Regression-run_Small_and_Medium',
+ 'Regression-run_compatibility',
'Regression-whitelist-run',
'Postcommit_relwithdebinfo',
'Postcommit_asan'
@@ -227,6 +230,9 @@ def main():
and job_name in (
'Nightly-run',
'Regression-run',
+ 'Regression-run_Large',
+ 'Regression-run_Small_and_Medium',
+ 'Regression-run_compatibility',
'Regression-whitelist-run',
'Postcommit_relwithdebinfo',
'Postcommit_asan'
diff --git a/.github/scripts/analytics/test_history_fast.py b/.github/scripts/analytics/test_history_fast.py
index cf14a3836370..7dc78b484f16 100755
--- a/.github/scripts/analytics/test_history_fast.py
+++ b/.github/scripts/analytics/test_history_fast.py
@@ -19,6 +19,17 @@ def drop_table(session, table_path):
session.execute_scheme(f"DROP TABLE IF EXISTS `{table_path}`;")
+def check_table_exists(session, table_path):
+ """Check if table exists"""
+ try:
+ session.describe_table(table_path)
+ print(f"Table '{table_path}' already exists.")
+ return True
+ except ydb.SchemeError:
+ print(f"Table '{table_path}' does not exist.")
+ return False
+
+
def create_test_history_fast_table(session, table_path):
print(f"> Creating table: '{table_path}'")
session.execute_scheme(f"""
@@ -38,7 +49,7 @@ def create_test_history_fast_table(session, table_path):
`status` Utf8,
`status_description` Utf8,
`owners` Utf8,
- PRIMARY KEY (`full_name`, `run_timestamp`, `job_name`, `branch`, `build_type`, test_id)
+ PRIMARY KEY (`run_timestamp`, `full_name`, `job_name`, `branch`, `build_type`, test_id)
)
PARTITION BY HASH(run_timestamp)
WITH (
@@ -74,7 +85,7 @@ def bulk_upsert(table_client, table_path, rows):
def get_missed_data_for_upload(driver):
results = []
query = f"""
- SELECT
+ SELECT
build_type,
job_name,
job_id,
@@ -96,8 +107,14 @@ def get_missed_data_for_upload(driver):
) as fast_data_missed
ON all_data.run_timestamp = fast_data_missed.run_timestamp
WHERE
- all_data.run_timestamp >= CurrentUtcDate() - 6*Interval("P1D") AND
- fast_data_missed.run_timestamp is NULL
+ all_data.run_timestamp >= CurrentUtcDate() - 6*Interval("P1D")
+ and String::Contains(all_data.test_name, '.flake8') = FALSE
+ and (CASE
+ WHEN String::Contains(all_data.test_name, 'chunk chunk') OR String::Contains(all_data.test_name, 'chunk+chunk') THEN TRUE
+ ELSE FALSE
+ END) = FALSE
+ and (all_data.branch = 'main' or all_data.branch like 'stable-%')
+ and fast_data_missed.run_timestamp is NULL
"""
scan_query = ydb.ScanQuery(query, {})
@@ -127,7 +144,8 @@ def main():
]
table_path = "test_results/analytics/test_history_fast"
- batch_size = 50000
+ full_table_path = f'{DATABASE_PATH}/{table_path}'
+ batch_size = 1000
with ydb.Driver(
endpoint=DATABASE_ENDPOINT,
@@ -136,13 +154,24 @@ def main():
) as driver:
driver.wait(timeout=10, fail_fast=True)
with ydb.SessionPool(driver) as pool:
+ # Проверяем существование таблицы и создаем её если нужно
+ def check_and_create_table(session):
+ exists = check_table_exists(session, full_table_path)
+ if not exists:
+ create_test_history_fast_table(session, full_table_path)
+ return True
+ return exists
+
+ pool.retry_operation_sync(check_and_create_table)
+
+ # Продолжаем с основной логикой скрипта
prepared_for_upload_rows = get_missed_data_for_upload(driver)
print(f'Preparing to upsert: {len(prepared_for_upload_rows)} rows')
if prepared_for_upload_rows:
for start in range(0, len(prepared_for_upload_rows), batch_size):
batch_rows_for_upload = prepared_for_upload_rows[start:start + batch_size]
print(f'upserting: {start}-{start + len(batch_rows_for_upload)}/{len(prepared_for_upload_rows)} rows')
- bulk_upsert(driver.table_client, f'{DATABASE_PATH}/{table_path}', batch_rows_for_upload)
+ bulk_upsert(driver.table_client, full_table_path, batch_rows_for_upload)
print('Tests uploaded')
else:
print('Nothing to upload')
diff --git a/.github/scripts/analytics/tests_monitor.py b/.github/scripts/analytics/tests_monitor.py
index 89c2489ad3ab..fc23a4c0ed6d 100755
--- a/.github/scripts/analytics/tests_monitor.py
+++ b/.github/scripts/analytics/tests_monitor.py
@@ -283,12 +283,12 @@ def main():
parser.add_argument('--days-window', default=1, type=int, help='how many days back we collecting history')
parser.add_argument(
'--build_type',
- choices=['relwithdebinfo', 'release-asan'],
+ choices=['relwithdebinfo', 'release-asan', 'release-tsan', 'release-msan'],
default='relwithdebinfo',
type=str,
- help='build : relwithdebinfo or release-asan',
+ help='build type',
)
- parser.add_argument('--branch', default='main', choices=['main'], type=str, help='branch')
+ parser.add_argument('--branch', default='main', type=str, help='branch')
parser.add_argument(
'--concurent',
@@ -325,7 +325,7 @@ def main():
tc_settings = ydb.TableClientSettings().with_native_date_in_result_sets(enabled=False)
table_client = ydb.TableClient(driver, tc_settings)
base_date = datetime.datetime(1970, 1, 1)
- default_start_date = datetime.date(2024, 11, 1)
+ default_start_date = datetime.date(2025, 2, 1)
today = datetime.date.today()
table_path = f'test_results/analytics/tests_monitor'
diff --git a/.github/scripts/analytics/upload_testowners.py b/.github/scripts/analytics/upload_testowners.py
index 05cae9b04f06..ed20ffcbf03b 100755
--- a/.github/scripts/analytics/upload_testowners.py
+++ b/.github/scripts/analytics/upload_testowners.py
@@ -1,11 +1,8 @@
#!/usr/bin/env python3
-import argparse
import configparser
-import datetime
import os
import posixpath
-import traceback
import time
import ydb
from collections import Counter
@@ -95,6 +92,9 @@ def main():
and job_name in (
'Nightly-run',
'Regression-run',
+ 'Regression-run_Large',
+ 'Regression-run_Small_and_Medium',
+ 'Regression-run_compatibility',
'Regression-whitelist-run',
'Postcommit_relwithdebinfo',
'Postcommit_asan'
diff --git a/.github/scripts/tests/create_new_muted_ya.py b/.github/scripts/tests/create_new_muted_ya.py
index 8642a93398d7..e2aae4931d9f 100755
--- a/.github/scripts/tests/create_new_muted_ya.py
+++ b/.github/scripts/tests/create_new_muted_ya.py
@@ -28,8 +28,8 @@
DATABASE_PATH = config["QA_DB"]["DATABASE_PATH"]
-def execute_query(driver):
- query_string = '''
+def execute_query(driver, branch='main', build_type='relwithdebinfo'):
+ query_string = f'''
SELECT * from (
SELECT data.*,
CASE WHEN new_flaky.full_name IS NOT NULL THEN True ELSE False END AS new_flaky_today,
@@ -101,7 +101,7 @@ def execute_query(driver):
and data.build_type = deleted.build_type
and data.branch = deleted.branch
)
- where date_window = CurrentUtcDate() and branch = 'main'
+ where date_window = CurrentUtcDate() and branch = '{branch}' and build_type = '{build_type}'
'''
@@ -178,8 +178,8 @@ def apply_and_add_mutes(all_tests, output_path, mute_check):
for test in all_tests
if test.get('days_in_state') >= 1
and test.get('flaky_today')
- and (test.get('pass_count') + test.get('fail_count')) >= 3
- and test.get('fail_count') > 2
+ and (test.get('pass_count') + test.get('fail_count')) >= 2
+ and test.get('fail_count') >= 2
and test.get('fail_count')/(test.get('pass_count') + test.get('fail_count')) > 0.2 # <=80% success rate
)
flaky_tests = sorted(flaky_tests)
@@ -191,8 +191,8 @@ def apply_and_add_mutes(all_tests, output_path, mute_check):
for test in all_tests
if test.get('days_in_state') >= 1
and test.get('flaky_today')
- and (test.get('pass_count') + test.get('fail_count')) >= 3
- and test.get('fail_count') > 2
+ and (test.get('pass_count') + test.get('fail_count')) >=2
+ and test.get('fail_count') >= 2
and test.get('fail_count')/(test.get('pass_count') + test.get('fail_count')) > 0.2 # <=80% success rate
)
## тесты может запускаться 1 раз в день. если за последние 7 дней набирается трешход то мьютим
@@ -356,9 +356,9 @@ def create_mute_issues(all_tests, file_path):
print(f"Writing results to {file_path}")
with open(file_path, 'w') as f:
- f.write("```\n")
+ f.write("\n")
f.write("\n".join(results))
- f.write("\n```")
+ f.write("\n")
with open(os.environ['GITHUB_OUTPUT'], 'a') as gh_out:
gh_out.write(f"created_issues_file={file_path}")
@@ -389,7 +389,7 @@ def mute_worker(args):
) as driver:
driver.wait(timeout=10, fail_fast=True)
- all_tests = execute_query(driver)
+ all_tests = execute_query(driver, args.branch)
if args.mode == 'update_muted_ya':
output_path = args.output_folder
os.makedirs(output_path, exist_ok=True)
@@ -407,6 +407,7 @@ def mute_worker(args):
update_muted_ya_parser = subparsers.add_parser('update_muted_ya', help='create new muted_ya')
update_muted_ya_parser.add_argument('--output_folder', default=repo_path, required=False, help='Output folder.')
+ update_muted_ya_parser.add_argument('--branch', default='main', help='Branch to get history')
create_issues_parser = subparsers.add_parser(
'create_issues',
@@ -415,7 +416,8 @@ def mute_worker(args):
create_issues_parser.add_argument(
'--file_path', default=f'{repo_path}/mute_update/flaky.txt', required=False, help='file path'
)
+ create_issues_parser.add_argument('--branch', default='main', help='Branch to get history')
args = parser.parse_args()
- mute_worker(args)
\ No newline at end of file
+ mute_worker(args)
diff --git a/.github/scripts/tests/generate-summary.py b/.github/scripts/tests/generate-summary.py
index 5fd6f20588b8..239f24e4e2eb 100755
--- a/.github/scripts/tests/generate-summary.py
+++ b/.github/scripts/tests/generate-summary.py
@@ -230,7 +230,7 @@ def render_pm(value, url, diff=None):
return text
-def render_testlist_html(rows, fn, build_preset):
+def render_testlist_html(rows, fn, build_preset, branch):
TEMPLATES_PATH = os.path.join(os.path.dirname(__file__), "templates")
env = Environment(loader=FileSystemLoader(TEMPLATES_PATH), undefined=StrictUndefined)
@@ -273,7 +273,7 @@ def render_testlist_html(rows, fn, build_preset):
tests_names_for_history.append(test.full_name)
try:
- history = get_test_history(tests_names_for_history, last_n_runs, build_preset)
+ history = get_test_history(tests_names_for_history, last_n_runs, build_preset, branch)
except Exception:
print(traceback.format_exc())
@@ -308,7 +308,9 @@ def render_testlist_html(rows, fn, build_preset):
tests=status_test,
has_any_log=has_any_log,
history=history,
- build_preset=buid_preset_params
+ build_preset=build_preset,
+ buid_preset_params=buid_preset_params,
+ branch=branch
)
with open(fn, "w") as fp:
@@ -345,7 +347,7 @@ def get_codeowners_for_tests(codeowners_file_path, tests_data):
tests_data_with_owners.append(test)
-def gen_summary(public_dir, public_dir_url, paths, is_retry: bool, build_preset):
+def gen_summary(public_dir, public_dir_url, paths, is_retry: bool, build_preset, branch):
summary = TestSummary(is_retry=is_retry)
for title, html_fn, path in paths:
@@ -359,7 +361,7 @@ def gen_summary(public_dir, public_dir_url, paths, is_retry: bool, build_preset)
html_fn = os.path.relpath(html_fn, public_dir)
report_url = f"{public_dir_url}/{html_fn}"
- render_testlist_html(summary_line.tests, os.path.join(public_dir, html_fn),build_preset)
+ render_testlist_html(summary_line.tests, os.path.join(public_dir, html_fn),build_preset, branch)
summary_line.add_report(html_fn, report_url)
summary.add_line(summary_line)
@@ -418,6 +420,7 @@ def main():
parser.add_argument("--public_dir_url", required=True)
parser.add_argument("--summary_links", required=True)
parser.add_argument('--build_preset', default="default-linux-x86-64-relwithdebinfo", required=False)
+ parser.add_argument('--branch', default="main", required=False)
parser.add_argument('--status_report_file', required=False)
parser.add_argument('--is_retry', required=True, type=int)
parser.add_argument('--is_last_retry', required=True, type=int)
@@ -434,7 +437,13 @@ def main():
paths = iter(args.args)
title_path = list(zip(paths, paths, paths))
- summary = gen_summary(args.public_dir, args.public_dir_url, title_path, is_retry=bool(args.is_retry),build_preset=args.build_preset)
+ summary = gen_summary(args.public_dir,
+ args.public_dir_url,
+ title_path,
+ is_retry=bool(args.is_retry),
+ build_preset=args.build_preset,
+ branch=args.branch
+ )
write_summary(summary)
if summary.is_failed and not args.is_test_result_ignored:
diff --git a/.github/scripts/tests/get_muted_tests.py b/.github/scripts/tests/get_muted_tests.py
index ff28a7f831aa..ce523706d99d 100755
--- a/.github/scripts/tests/get_muted_tests.py
+++ b/.github/scripts/tests/get_muted_tests.py
@@ -187,7 +187,7 @@ def mute_applier(args):
for test in all_tests:
testsuite = to_str(test['suite_folder'])
testcase = to_str(test['test_name'])
- test['branch'] = 'main'
+ test['branch'] = args.branch
test['is_muted'] = int(mute_check(testsuite, testcase))
upload_muted_tests(all_tests)
diff --git a/.github/scripts/tests/get_test_history.py b/.github/scripts/tests/get_test_history.py
index 06d4c323725e..a3b2e32146b8 100644
--- a/.github/scripts/tests/get_test_history.py
+++ b/.github/scripts/tests/get_test_history.py
@@ -16,7 +16,7 @@
DATABASE_PATH = config["QA_DB"]["DATABASE_PATH"]
-def get_test_history(test_names_array, last_n_runs_of_test_amount, build_type):
+def get_test_history(test_names_array, last_n_runs_of_test_amount, build_type, branch):
if "CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS" not in os.environ:
print(
"Error: Env variable CI_YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS is missing, skipping"
@@ -48,33 +48,64 @@ def get_test_history(test_names_array, last_n_runs_of_test_amount, build_type):
DECLARE $test_names AS List;
DECLARE $rn_max AS Int32;
DECLARE $build_type AS Utf8;
-
- $test_names=[{','.join("'{0}'".format(x) for x in test_names_batch)}];
+ DECLARE $branch AS Utf8;
+
+ $test_names = [{','.join("'{0}'".format(x) for x in test_names_batch)}];
$rn_max = {last_n_runs_of_test_amount};
$build_type = '{build_type}';
+ $branch = '{branch}';
- $tests=(
+ -- Оптимизированный запрос с учетом особенностей YDB
+ $filtered_tests = (
SELECT
- suite_folder ||'/' || test_name as full_name,test_name,build_type, commit, branch, run_timestamp, status, status_description,
+ suite_folder || '/' || test_name AS full_name,
+ test_name,
+ build_type,
+ commit,
+ branch,
+ run_timestamp,
+ status,
+ status_description,
+ job_id,
+ job_name,
ROW_NUMBER() OVER (PARTITION BY test_name ORDER BY run_timestamp DESC) AS rn
FROM
- `test_results/test_runs_column`
- where job_name in (
- 'Nightly-run',
- 'Regression-run',
- 'Regression-whitelist-run',
- 'Postcommit_relwithdebinfo',
- 'Postcommit_asan'
- )
- and build_type = $build_type
- and suite_folder ||'/' || test_name in $test_names
- and status != 'skipped'
+ `test_results/test_runs_column` AS t
+ WHERE
+ t.build_type = $build_type
+ AND t.branch = $branch
+ AND t.job_name IN (
+ 'Nightly-run',
+ 'Regression-run',
+ 'Regression-whitelist-run',
+ 'Postcommit_relwithdebinfo',
+ 'Postcommit_asan'
+ )
+ AND t.status != 'skipped'
+ AND suite_folder || '/' || test_name IN $test_names
);
- select full_name,test_name,build_type, commit, branch, run_timestamp, status, status_description,rn
- from $tests
- WHERE rn <= $rn_max
- ORDER BY test_name, run_timestamp;
+ -- Финальный запрос с ограничением по количеству запусков
+ SELECT
+ full_name,
+ test_name,
+ build_type,
+ commit,
+ branch,
+ run_timestamp,
+ status,
+ status_description,
+ job_id,
+ job_name,
+ rn
+ FROM
+ $filtered_tests
+ WHERE
+ rn <= $rn_max
+ ORDER BY
+ test_name,
+ run_timestamp;
+
"""
query = ydb.ScanQuery(history_query, {})
it = driver.table_client.scan_query(query)
@@ -92,10 +123,13 @@ def get_test_history(test_names_array, last_n_runs_of_test_amount, build_type):
results[row["full_name"].decode("utf-8")] = {}
results[row["full_name"].decode("utf-8")][row["run_timestamp"]] = {
+ "branch": row["branch"],
"status": row["status"],
"commit": row["commit"],
"datetime": datetime.datetime.fromtimestamp(int(row["run_timestamp"] / 1000000)).strftime("%H:%m %B %d %Y"),
- "status_description": row["status_description"],
+ "status_description": row["status_description"].replace(';;','\n'),
+ "job_id": row["job_id"],
+ "job_name": row["job_name"]
}
end_time = time.time()
print(
@@ -104,4 +138,4 @@ def get_test_history(test_names_array, last_n_runs_of_test_amount, build_type):
if __name__ == "__main__":
- get_test_history(test_names_array, last_n_runs_of_test_amount, build_type)
+ get_test_history(test_names_array, last_n_runs_of_test_amount, build_type, branch)
diff --git a/.github/scripts/tests/templates/summary.html b/.github/scripts/tests/templates/summary.html
index a595d1b7e233..e21a31e54b65 100644
--- a/.github/scripts/tests/templates/summary.html
+++ b/.github/scripts/tests/templates/summary.html
@@ -321,6 +321,60 @@
overflow: auto;
}
+ /* Стили для модального окна */
+ #errorModal {
+ display: none;
+ position: fixed;
+ z-index: 1000;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ background-color: rgba(0,0,0,0.5);
+ }
+
+ .modal-content {
+ background-color: #fefefe;
+ margin: 5% auto;
+ padding: 20px;
+ border: 1px solid #888;
+ width: 80%;
+ border-radius: 5px;
+ max-height: 80vh;
+ overflow-y: auto;
+ }
+
+ .close-modal {
+ color: #aaa;
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+ cursor: pointer;
+ }
+
+ .modal-header {
+ margin-bottom: 15px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #eee;
+ font-size: smaller;
+ }
+
+ .modal-info {
+ font-size: small;
+ margin-bottom: 15px;
+ line-height: 1.5;
+ }
+
+ .modal-info-item {
+ margin-bottom: 5px;
+ }
+
+ .modal-info-label {
+ font-weight: bold;
+ display: inline-block;
+ width: 80px;
+ }
")
-
-produces
-
- Hello, !
-
-but the contextual autoescaping in html/template
-
- import "html/template"
- ...
- t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
- err = t.ExecuteTemplate(out, "T", "")
-
-produces safe, escaped HTML output
-
- Hello, <script>alert('you have been pwned')</script>!
-
-# Contexts
-
-This package understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
-functions to each simple action pipeline, so given the excerpt
-
- {{.}}
-
-At parse time each {{.}} is overwritten to add escaping functions as necessary.
-In this case it becomes
-
- {{. | htmlescaper}}
-
-where urlescaper, attrescaper, and htmlescaper are aliases for internal escaping
-functions.
-
-For these internal escaping functions, if an action pipeline evaluates to
-a nil interface value, it is treated as though it were an empty string.
-
-# Namespaced and data- attributes
-
-Attributes with a namespace are treated as if they had no namespace.
-Given the excerpt
-
-
-
-At parse time the attribute will be treated as if it were just "href".
-So at parse time the template becomes:
-
-
-
-Similarly to attributes with namespaces, attributes with a "data-" prefix are
-treated as if they had no "data-" prefix. So given
-
-
-
-At parse time this becomes
-
-
-
-If an attribute has both a namespace and a "data-" prefix, only the namespace
-will be removed when determining the context. For example
-
-
-
-This is handled as if "my:data-href" was just "data-href" and not "href" as
-it would be if the "data-" prefix were to be ignored too. Thus at parse
-time this becomes just
-
-
-
-As a special case, attributes with the namespace "xmlns" are always treated
-as containing URLs. Given the excerpts
-
-
-
-
-
-At parse time they become:
-
-
-
-
-
-# Errors
-
-See the documentation of ErrorCode for details.
-
-# A fuller picture
-
-The rest of this package comment may be skipped on first reading; it includes
-details necessary to understand escaping contexts and error messages. Most users
-will not need to understand these details.
-
-# Contexts
-
-Assuming {{.}} is `O'Reilly: How are you?`, the table below shows
-how {{.}} appears when used in the context to the left.
-
- Context {{.}} After
- {{.}} O'Reilly: How are <i>you</i>?
- O'Reilly: How are you?
- O'Reilly: How are %3ci%3eyou%3c/i%3e?
- O'Reilly%3a%20How%20are%3ci%3e...%3f
- O\x27Reilly: How are \x3ci\x3eyou...?
- "O\x27Reilly: How are \x3ci\x3eyou...?"
- O\x27Reilly: How are \x3ci\x3eyou...\x3f
-
-If used in an unsafe context, then the value might be filtered out:
-
- Context {{.}} After
- #ZgotmplZ
-
-since "O'Reilly:" is not an allowed protocol like "http:".
-
-If {{.}} is the innocuous word, `left`, then it can appear more widely,
-
- Context {{.}} After
- {{.}} left
- left
- left
- left
- left
- left
- left
- left
- left
-
-Non-string values can be used in JavaScript contexts.
-If {{.}} is
-
- struct{A,B string}{ "foo", "bar" }
-
-in the escaped template
-
-
-
-then the template output is
-
-
-
-See package json to understand how non-string content is marshaled for
-embedding in JavaScript contexts.
-
-# Typed Strings
-
-By default, this package assumes that all pipelines produce a plain text string.
-It adds escaping pipeline stages necessary to correctly and safely embed that
-plain text string in the appropriate context.
-
-When a data value is not plain text, you can make sure it is not over-escaped
-by marking it with its type.
-
-Types HTML, JS, URL, and others from content.go can carry safe content that is
-exempted from escaping.
-
-The template
-
- Hello, {{.}}!
-
-can be invoked with
-
- tmpl.Execute(out, template.HTML(`World`))
-
-to produce
-
- Hello, World!
-
-instead of the
-
- Hello, <b>World<b>!
-
-that would have been produced if {{.}} was a regular string.
-
-# Security Model
-
-https://rawgit.com/mikesamuel/sanitized-jquery-templates/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
-
-This package assumes that template authors are trusted, that Execute's data
-parameter is not, and seeks to preserve the properties below in the face
-of untrusted data:
-
-Structure Preservation Property:
-"... when a template author writes an HTML tag in a safe templating language,
-the browser will interpret the corresponding portion of the output as a tag
-regardless of the values of untrusted data, and similarly for other structures
-such as attribute boundaries and JS and CSS string boundaries."
-
-Code Effect Property:
-"... only code specified by the template author should run as a result of
-injecting the template output into a page and all code specified by the
-template author should run as a result of the same."
-
-Least Surprise Property:
-"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript, who
-knows that contextual autoescaping happens should be able to look at a {{.}}
-and correctly infer what sanitization happens."
-
-As a consequence of the Least Surprise Property, template actions within an
-ECMAScript 6 template literal are disabled by default.
-Handling string interpolation within these literals is rather complex resulting
-in no clear safe way to support it.
-To re-enable template actions within ECMAScript 6 template literals, use the
-GODEBUG=jstmpllitinterp=1 environment variable.
-*/
-package template
diff --git a/contrib/go/_std_1.22/src/html/template/js.go b/contrib/go/_std_1.22/src/html/template/js.go
deleted file mode 100644
index d911ada26d3d..000000000000
--- a/contrib/go/_std_1.22/src/html/template/js.go
+++ /dev/null
@@ -1,485 +0,0 @@
-// Copyright 2011 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.
-
-package template
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "reflect"
- "strings"
- "unicode/utf8"
-)
-
-// jsWhitespace contains all of the JS whitespace characters, as defined
-// by the \s character class.
-// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Character_classes.
-const jsWhitespace = "\f\n\r\t\v\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff"
-
-// nextJSCtx returns the context that determines whether a slash after the
-// given run of tokens starts a regular expression instead of a division
-// operator: / or /=.
-//
-// This assumes that the token run does not include any string tokens, comment
-// tokens, regular expression literal tokens, or division operators.
-//
-// This fails on some valid but nonsensical JavaScript programs like
-// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
-// fail on any known useful programs. It is based on the draft
-// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
-// https://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
-func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
- // Trim all JS whitespace characters
- s = bytes.TrimRight(s, jsWhitespace)
- if len(s) == 0 {
- return preceding
- }
-
- // All cases below are in the single-byte UTF-8 group.
- switch c, n := s[len(s)-1], len(s); c {
- case '+', '-':
- // ++ and -- are not regexp preceders, but + and - are whether
- // they are used as infix or prefix operators.
- start := n - 1
- // Count the number of adjacent dashes or pluses.
- for start > 0 && s[start-1] == c {
- start--
- }
- if (n-start)&1 == 1 {
- // Reached for trailing minus signs since "---" is the
- // same as "-- -".
- return jsCtxRegexp
- }
- return jsCtxDivOp
- case '.':
- // Handle "42."
- if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
- return jsCtxDivOp
- }
- return jsCtxRegexp
- // Suffixes for all punctuators from section 7.7 of the language spec
- // that only end binary operators not handled above.
- case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
- return jsCtxRegexp
- // Suffixes for all punctuators from section 7.7 of the language spec
- // that are prefix operators not handled above.
- case '!', '~':
- return jsCtxRegexp
- // Matches all the punctuators from section 7.7 of the language spec
- // that are open brackets not handled above.
- case '(', '[':
- return jsCtxRegexp
- // Matches all the punctuators from section 7.7 of the language spec
- // that precede expression starts.
- case ':', ';', '{':
- return jsCtxRegexp
- // CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
- // are handled in the default except for '}' which can precede a
- // division op as in
- // ({ valueOf: function () { return 42 } } / 2
- // which is valid, but, in practice, developers don't divide object
- // literals, so our heuristic works well for code like
- // function () { ... } /foo/.test(x) && sideEffect();
- // The ')' punctuator can precede a regular expression as in
- // if (b) /foo/.test(x) && ...
- // but this is much less likely than
- // (a + b) / c
- case '}':
- return jsCtxRegexp
- default:
- // Look for an IdentifierName and see if it is a keyword that
- // can precede a regular expression.
- j := n
- for j > 0 && isJSIdentPart(rune(s[j-1])) {
- j--
- }
- if regexpPrecederKeywords[string(s[j:])] {
- return jsCtxRegexp
- }
- }
- // Otherwise is a punctuator not listed above, or
- // a string which precedes a div op, or an identifier
- // which precedes a div op.
- return jsCtxDivOp
-}
-
-// regexpPrecederKeywords is a set of reserved JS keywords that can precede a
-// regular expression in JS source.
-var regexpPrecederKeywords = map[string]bool{
- "break": true,
- "case": true,
- "continue": true,
- "delete": true,
- "do": true,
- "else": true,
- "finally": true,
- "in": true,
- "instanceof": true,
- "return": true,
- "throw": true,
- "try": true,
- "typeof": true,
- "void": true,
-}
-
-var jsonMarshalType = reflect.TypeFor[json.Marshaler]()
-
-// indirectToJSONMarshaler returns the value, after dereferencing as many times
-// as necessary to reach the base type (or nil) or an implementation of json.Marshal.
-func indirectToJSONMarshaler(a any) any {
- // text/template now supports passing untyped nil as a func call
- // argument, so we must support it. Otherwise we'd panic below, as one
- // cannot call the Type or Interface methods on an invalid
- // reflect.Value. See golang.org/issue/18716.
- if a == nil {
- return nil
- }
-
- v := reflect.ValueOf(a)
- for !v.Type().Implements(jsonMarshalType) && v.Kind() == reflect.Pointer && !v.IsNil() {
- v = v.Elem()
- }
- return v.Interface()
-}
-
-// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
-// neither side-effects nor free variables outside (NaN, Infinity).
-func jsValEscaper(args ...any) string {
- var a any
- if len(args) == 1 {
- a = indirectToJSONMarshaler(args[0])
- switch t := a.(type) {
- case JS:
- return string(t)
- case JSStr:
- // TODO: normalize quotes.
- return `"` + string(t) + `"`
- case json.Marshaler:
- // Do not treat as a Stringer.
- case fmt.Stringer:
- a = t.String()
- }
- } else {
- for i, arg := range args {
- args[i] = indirectToJSONMarshaler(arg)
- }
- a = fmt.Sprint(args...)
- }
- // TODO: detect cycles before calling Marshal which loops infinitely on
- // cyclic data. This may be an unacceptable DoS risk.
- b, err := json.Marshal(a)
- if err != nil {
- // While the standard JSON marshaller does not include user controlled
- // information in the error message, if a type has a MarshalJSON method,
- // the content of the error message is not guaranteed. Since we insert
- // the error into the template, as part of a comment, we attempt to
- // prevent the error from either terminating the comment, or the script
- // block itself.
- //
- // In particular we:
- // * replace "*/" comment end tokens with "* /", which does not
- // terminate the comment
- // * replace "", "", or " element,
-// or in an HTML5 event handler attribute such as onclick.
-func jsStrEscaper(args ...any) string {
- s, t := stringify(args...)
- if t == contentTypeJSStr {
- return replace(s, jsStrNormReplacementTable)
- }
- return replace(s, jsStrReplacementTable)
-}
-
-func jsTmplLitEscaper(args ...any) string {
- s, _ := stringify(args...)
- return replace(s, jsBqStrReplacementTable)
-}
-
-// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
-// specials so the result is treated literally when included in a regular
-// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
-// the literal text of {{.X}} followed by the string "bar".
-func jsRegexpEscaper(args ...any) string {
- s, _ := stringify(args...)
- s = replace(s, jsRegexpReplacementTable)
- if s == "" {
- // /{{.X}}/ should not produce a line comment when .X == "".
- return "(?:)"
- }
- return s
-}
-
-// replace replaces each rune r of s with replacementTable[r], provided that
-// r < len(replacementTable). If replacementTable[r] is the empty string then
-// no replacement is made.
-// It also replaces runes U+2028 and U+2029 with the raw strings `\u2028` and
-// `\u2029`.
-func replace(s string, replacementTable []string) string {
- var b strings.Builder
- r, w, written := rune(0), 0, 0
- for i := 0; i < len(s); i += w {
- // See comment in htmlEscaper.
- r, w = utf8.DecodeRuneInString(s[i:])
- var repl string
- switch {
- case int(r) < len(lowUnicodeReplacementTable):
- repl = lowUnicodeReplacementTable[r]
- case int(r) < len(replacementTable) && replacementTable[r] != "":
- repl = replacementTable[r]
- case r == '\u2028':
- repl = `\u2028`
- case r == '\u2029':
- repl = `\u2029`
- default:
- continue
- }
- if written == 0 {
- b.Grow(len(s))
- }
- b.WriteString(s[written:i])
- b.WriteString(repl)
- written = i + w
- }
- if written == 0 {
- return s
- }
- b.WriteString(s[written:])
- return b.String()
-}
-
-var lowUnicodeReplacementTable = []string{
- 0: `\u0000`, 1: `\u0001`, 2: `\u0002`, 3: `\u0003`, 4: `\u0004`, 5: `\u0005`, 6: `\u0006`,
- '\a': `\u0007`,
- '\b': `\u0008`,
- '\t': `\t`,
- '\n': `\n`,
- '\v': `\u000b`, // "\v" == "v" on IE 6.
- '\f': `\f`,
- '\r': `\r`,
- 0xe: `\u000e`, 0xf: `\u000f`, 0x10: `\u0010`, 0x11: `\u0011`, 0x12: `\u0012`, 0x13: `\u0013`,
- 0x14: `\u0014`, 0x15: `\u0015`, 0x16: `\u0016`, 0x17: `\u0017`, 0x18: `\u0018`, 0x19: `\u0019`,
- 0x1a: `\u001a`, 0x1b: `\u001b`, 0x1c: `\u001c`, 0x1d: `\u001d`, 0x1e: `\u001e`, 0x1f: `\u001f`,
-}
-
-var jsStrReplacementTable = []string{
- 0: `\u0000`,
- '\t': `\t`,
- '\n': `\n`,
- '\v': `\u000b`, // "\v" == "v" on IE 6.
- '\f': `\f`,
- '\r': `\r`,
- // Encode HTML specials as hex so the output can be embedded
- // in HTML attributes without further encoding.
- '"': `\u0022`,
- '`': `\u0060`,
- '&': `\u0026`,
- '\'': `\u0027`,
- '+': `\u002b`,
- '/': `\/`,
- '<': `\u003c`,
- '>': `\u003e`,
- '\\': `\\`,
-}
-
-// jsBqStrReplacementTable is like jsStrReplacementTable except it also contains
-// the special characters for JS template literals: $, {, and }.
-var jsBqStrReplacementTable = []string{
- 0: `\u0000`,
- '\t': `\t`,
- '\n': `\n`,
- '\v': `\u000b`, // "\v" == "v" on IE 6.
- '\f': `\f`,
- '\r': `\r`,
- // Encode HTML specials as hex so the output can be embedded
- // in HTML attributes without further encoding.
- '"': `\u0022`,
- '`': `\u0060`,
- '&': `\u0026`,
- '\'': `\u0027`,
- '+': `\u002b`,
- '/': `\/`,
- '<': `\u003c`,
- '>': `\u003e`,
- '\\': `\\`,
- '$': `\u0024`,
- '{': `\u007b`,
- '}': `\u007d`,
-}
-
-// jsStrNormReplacementTable is like jsStrReplacementTable but does not
-// overencode existing escapes since this table has no entry for `\`.
-var jsStrNormReplacementTable = []string{
- 0: `\u0000`,
- '\t': `\t`,
- '\n': `\n`,
- '\v': `\u000b`, // "\v" == "v" on IE 6.
- '\f': `\f`,
- '\r': `\r`,
- // Encode HTML specials as hex so the output can be embedded
- // in HTML attributes without further encoding.
- '"': `\u0022`,
- '&': `\u0026`,
- '\'': `\u0027`,
- '`': `\u0060`,
- '+': `\u002b`,
- '/': `\/`,
- '<': `\u003c`,
- '>': `\u003e`,
-}
-var jsRegexpReplacementTable = []string{
- 0: `\u0000`,
- '\t': `\t`,
- '\n': `\n`,
- '\v': `\u000b`, // "\v" == "v" on IE 6.
- '\f': `\f`,
- '\r': `\r`,
- // Encode HTML specials as hex so the output can be embedded
- // in HTML attributes without further encoding.
- '"': `\u0022`,
- '$': `\$`,
- '&': `\u0026`,
- '\'': `\u0027`,
- '(': `\(`,
- ')': `\)`,
- '*': `\*`,
- '+': `\u002b`,
- '-': `\-`,
- '.': `\.`,
- '/': `\/`,
- '<': `\u003c`,
- '>': `\u003e`,
- '?': `\?`,
- '[': `\[`,
- '\\': `\\`,
- ']': `\]`,
- '^': `\^`,
- '{': `\{`,
- '|': `\|`,
- '}': `\}`,
-}
-
-// isJSIdentPart reports whether the given rune is a JS identifier part.
-// It does not handle all the non-Latin letters, joiners, and combining marks,
-// but it does handle every codepoint that can occur in a numeric literal or
-// a keyword.
-func isJSIdentPart(r rune) bool {
- switch {
- case r == '$':
- return true
- case '0' <= r && r <= '9':
- return true
- case 'A' <= r && r <= 'Z':
- return true
- case r == '_':
- return true
- case 'a' <= r && r <= 'z':
- return true
- }
- return false
-}
-
-// isJSType reports whether the given MIME type should be considered JavaScript.
-//
-// It is used to determine whether a script tag with a type attribute is a javascript container.
-func isJSType(mimeType string) bool {
- // per
- // https://www.w3.org/TR/html5/scripting-1.html#attr-script-type
- // https://tools.ietf.org/html/rfc7231#section-3.1.1
- // https://tools.ietf.org/html/rfc4329#section-3
- // https://www.ietf.org/rfc/rfc4627.txt
- // discard parameters
- mimeType, _, _ = strings.Cut(mimeType, ";")
- mimeType = strings.ToLower(mimeType)
- mimeType = strings.TrimSpace(mimeType)
- switch mimeType {
- case
- "application/ecmascript",
- "application/javascript",
- "application/json",
- "application/ld+json",
- "application/x-ecmascript",
- "application/x-javascript",
- "module",
- "text/ecmascript",
- "text/javascript",
- "text/javascript1.0",
- "text/javascript1.1",
- "text/javascript1.2",
- "text/javascript1.3",
- "text/javascript1.4",
- "text/javascript1.5",
- "text/jscript",
- "text/livescript",
- "text/x-ecmascript",
- "text/x-javascript":
- return true
- default:
- return false
- }
-}
diff --git a/contrib/go/_std_1.22/src/html/template/template.go b/contrib/go/_std_1.22/src/html/template/template.go
deleted file mode 100644
index 30b64dff0408..000000000000
--- a/contrib/go/_std_1.22/src/html/template/template.go
+++ /dev/null
@@ -1,530 +0,0 @@
-// Copyright 2011 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.
-
-package template
-
-import (
- "fmt"
- "io"
- "io/fs"
- "os"
- "path"
- "path/filepath"
- "sync"
- "text/template"
- "text/template/parse"
-)
-
-// Template is a specialized Template from "text/template" that produces a safe
-// HTML document fragment.
-type Template struct {
- // Sticky error if escaping fails, or escapeOK if succeeded.
- escapeErr error
- // We could embed the text/template field, but it's safer not to because
- // we need to keep our version of the name space and the underlying
- // template's in sync.
- text *template.Template
- // The underlying template's parse tree, updated to be HTML-safe.
- Tree *parse.Tree
- *nameSpace // common to all associated templates
-}
-
-// escapeOK is a sentinel value used to indicate valid escaping.
-var escapeOK = fmt.Errorf("template escaped correctly")
-
-// nameSpace is the data structure shared by all templates in an association.
-type nameSpace struct {
- mu sync.Mutex
- set map[string]*Template
- escaped bool
- esc escaper
-}
-
-// Templates returns a slice of the templates associated with t, including t
-// itself.
-func (t *Template) Templates() []*Template {
- ns := t.nameSpace
- ns.mu.Lock()
- defer ns.mu.Unlock()
- // Return a slice so we don't expose the map.
- m := make([]*Template, 0, len(ns.set))
- for _, v := range ns.set {
- m = append(m, v)
- }
- return m
-}
-
-// Option sets options for the template. Options are described by
-// strings, either a simple string or "key=value". There can be at
-// most one equals sign in an option string. If the option string
-// is unrecognized or otherwise invalid, Option panics.
-//
-// Known options:
-//
-// missingkey: Control the behavior during execution if a map is
-// indexed with a key that is not present in the map.
-//
-// "missingkey=default" or "missingkey=invalid"
-// The default behavior: Do nothing and continue execution.
-// If printed, the result of the index operation is the string
-// "".
-// "missingkey=zero"
-// The operation returns the zero value for the map type's element.
-// "missingkey=error"
-// Execution stops immediately with an error.
-func (t *Template) Option(opt ...string) *Template {
- t.text.Option(opt...)
- return t
-}
-
-// checkCanParse checks whether it is OK to parse templates.
-// If not, it returns an error.
-func (t *Template) checkCanParse() error {
- if t == nil {
- return nil
- }
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- if t.nameSpace.escaped {
- return fmt.Errorf("html/template: cannot Parse after Execute")
- }
- return nil
-}
-
-// escape escapes all associated templates.
-func (t *Template) escape() error {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- t.nameSpace.escaped = true
- if t.escapeErr == nil {
- if t.Tree == nil {
- return fmt.Errorf("template: %q is an incomplete or empty template", t.Name())
- }
- if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
- return err
- }
- } else if t.escapeErr != escapeOK {
- return t.escapeErr
- }
- return nil
-}
-
-// Execute applies a parsed template to the specified data object,
-// writing the output to wr.
-// If an error occurs executing the template or writing its output,
-// execution stops, but partial results may already have been written to
-// the output writer.
-// A template may be executed safely in parallel, although if parallel
-// executions share a Writer the output may be interleaved.
-func (t *Template) Execute(wr io.Writer, data any) error {
- if err := t.escape(); err != nil {
- return err
- }
- return t.text.Execute(wr, data)
-}
-
-// ExecuteTemplate applies the template associated with t that has the given
-// name to the specified data object and writes the output to wr.
-// If an error occurs executing the template or writing its output,
-// execution stops, but partial results may already have been written to
-// the output writer.
-// A template may be executed safely in parallel, although if parallel
-// executions share a Writer the output may be interleaved.
-func (t *Template) ExecuteTemplate(wr io.Writer, name string, data any) error {
- tmpl, err := t.lookupAndEscapeTemplate(name)
- if err != nil {
- return err
- }
- return tmpl.text.Execute(wr, data)
-}
-
-// lookupAndEscapeTemplate guarantees that the template with the given name
-// is escaped, or returns an error if it cannot be. It returns the named
-// template.
-func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- t.nameSpace.escaped = true
- tmpl = t.set[name]
- if tmpl == nil {
- return nil, fmt.Errorf("html/template: %q is undefined", name)
- }
- if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
- return nil, tmpl.escapeErr
- }
- if tmpl.text.Tree == nil || tmpl.text.Root == nil {
- return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
- }
- if t.text.Lookup(name) == nil {
- panic("html/template internal error: template escaping out of sync")
- }
- if tmpl.escapeErr == nil {
- err = escapeTemplate(tmpl, tmpl.text.Root, name)
- }
- return tmpl, err
-}
-
-// DefinedTemplates returns a string listing the defined templates,
-// prefixed by the string "; defined templates are: ". If there are none,
-// it returns the empty string. Used to generate an error message.
-func (t *Template) DefinedTemplates() string {
- return t.text.DefinedTemplates()
-}
-
-// Parse parses text as a template body for t.
-// Named template definitions ({{define ...}} or {{block ...}} statements) in text
-// define additional templates associated with t and are removed from the
-// definition of t itself.
-//
-// Templates can be redefined in successive calls to Parse,
-// before the first use of Execute on t or any associated template.
-// A template definition with a body containing only white space and comments
-// is considered empty and will not replace an existing template's body.
-// This allows using Parse to add new named template definitions without
-// overwriting the main template body.
-func (t *Template) Parse(text string) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
-
- ret, err := t.text.Parse(text)
- if err != nil {
- return nil, err
- }
-
- // In general, all the named templates might have changed underfoot.
- // Regardless, some new ones may have been defined.
- // The template.Template set has been updated; update ours.
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- for _, v := range ret.Templates() {
- name := v.Name()
- tmpl := t.set[name]
- if tmpl == nil {
- tmpl = t.new(name)
- }
- tmpl.text = v
- tmpl.Tree = v.Tree
- }
- return t, nil
-}
-
-// AddParseTree creates a new template with the name and parse tree
-// and associates it with t.
-//
-// It returns an error if t or any associated template has already been executed.
-func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
-
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- text, err := t.text.AddParseTree(name, tree)
- if err != nil {
- return nil, err
- }
- ret := &Template{
- nil,
- text,
- text.Tree,
- t.nameSpace,
- }
- t.set[name] = ret
- return ret, nil
-}
-
-// Clone returns a duplicate of the template, including all associated
-// templates. The actual representation is not copied, but the name space of
-// associated templates is, so further calls to Parse in the copy will add
-// templates to the copy but not to the original. Clone can be used to prepare
-// common templates and use them with variant definitions for other templates
-// by adding the variants after the clone is made.
-//
-// It returns an error if t has already been executed.
-func (t *Template) Clone() (*Template, error) {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- if t.escapeErr != nil {
- return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
- }
- textClone, err := t.text.Clone()
- if err != nil {
- return nil, err
- }
- ns := &nameSpace{set: make(map[string]*Template)}
- ns.esc = makeEscaper(ns)
- ret := &Template{
- nil,
- textClone,
- textClone.Tree,
- ns,
- }
- ret.set[ret.Name()] = ret
- for _, x := range textClone.Templates() {
- name := x.Name()
- src := t.set[name]
- if src == nil || src.escapeErr != nil {
- return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
- }
- x.Tree = x.Tree.Copy()
- ret.set[name] = &Template{
- nil,
- x,
- x.Tree,
- ret.nameSpace,
- }
- }
- // Return the template associated with the name of this template.
- return ret.set[ret.Name()], nil
-}
-
-// New allocates a new HTML template with the given name.
-func New(name string) *Template {
- ns := &nameSpace{set: make(map[string]*Template)}
- ns.esc = makeEscaper(ns)
- tmpl := &Template{
- nil,
- template.New(name),
- nil,
- ns,
- }
- tmpl.set[name] = tmpl
- return tmpl
-}
-
-// New allocates a new HTML template associated with the given one
-// and with the same delimiters. The association, which is transitive,
-// allows one template to invoke another with a {{template}} action.
-//
-// If a template with the given name already exists, the new HTML template
-// will replace it. The existing template will be reset and disassociated with
-// t.
-func (t *Template) New(name string) *Template {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- return t.new(name)
-}
-
-// new is the implementation of New, without the lock.
-func (t *Template) new(name string) *Template {
- tmpl := &Template{
- nil,
- t.text.New(name),
- nil,
- t.nameSpace,
- }
- if existing, ok := tmpl.set[name]; ok {
- emptyTmpl := New(existing.Name())
- *existing = *emptyTmpl
- }
- tmpl.set[name] = tmpl
- return tmpl
-}
-
-// Name returns the name of the template.
-func (t *Template) Name() string {
- return t.text.Name()
-}
-
-type FuncMap = template.FuncMap
-
-// Funcs adds the elements of the argument map to the template's function map.
-// It must be called before the template is parsed.
-// It panics if a value in the map is not a function with appropriate return
-// type. However, it is legal to overwrite elements of the map. The return
-// value is the template, so calls can be chained.
-func (t *Template) Funcs(funcMap FuncMap) *Template {
- t.text.Funcs(template.FuncMap(funcMap))
- return t
-}
-
-// Delims sets the action delimiters to the specified strings, to be used in
-// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
-// definitions will inherit the settings. An empty delimiter stands for the
-// corresponding default: {{ or }}.
-// The return value is the template, so calls can be chained.
-func (t *Template) Delims(left, right string) *Template {
- t.text.Delims(left, right)
- return t
-}
-
-// Lookup returns the template with the given name that is associated with t,
-// or nil if there is no such template.
-func (t *Template) Lookup(name string) *Template {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- return t.set[name]
-}
-
-// Must is a helper that wraps a call to a function returning (*Template, error)
-// and panics if the error is non-nil. It is intended for use in variable initializations
-// such as
-//
-// var t = template.Must(template.New("name").Parse("html"))
-func Must(t *Template, err error) *Template {
- if err != nil {
- panic(err)
- }
- return t
-}
-
-// ParseFiles creates a new Template and parses the template definitions from
-// the named files. The returned template's name will have the (base) name and
-// (parsed) contents of the first file. There must be at least one file.
-// If an error occurs, parsing stops and the returned *Template is nil.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-// For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
-// named "foo", while "a/foo" is unavailable.
-func ParseFiles(filenames ...string) (*Template, error) {
- return parseFiles(nil, readFileOS, filenames...)
-}
-
-// ParseFiles parses the named files and associates the resulting templates with
-// t. If an error occurs, parsing stops and the returned template is nil;
-// otherwise it is t. There must be at least one file.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-//
-// ParseFiles returns an error if t or any associated template has already been executed.
-func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
- return parseFiles(t, readFileOS, filenames...)
-}
-
-// parseFiles is the helper for the method and function. If the argument
-// template is nil, it is created from the first file.
-func parseFiles(t *Template, readFile func(string) (string, []byte, error), filenames ...string) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
-
- if len(filenames) == 0 {
- // Not really a problem, but be consistent.
- return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
- }
- for _, filename := range filenames {
- name, b, err := readFile(filename)
- if err != nil {
- return nil, err
- }
- s := string(b)
- // First template becomes return value if not already defined,
- // and we use that one for subsequent New calls to associate
- // all the templates together. Also, if this file has the same name
- // as t, this file becomes the contents of t, so
- // t, err := New(name).Funcs(xxx).ParseFiles(name)
- // works. Otherwise we create a new template associated with t.
- var tmpl *Template
- if t == nil {
- t = New(name)
- }
- if name == t.Name() {
- tmpl = t
- } else {
- tmpl = t.New(name)
- }
- _, err = tmpl.Parse(s)
- if err != nil {
- return nil, err
- }
- }
- return t, nil
-}
-
-// ParseGlob creates a new Template and parses the template definitions from
-// the files identified by the pattern. The files are matched according to the
-// semantics of filepath.Match, and the pattern must match at least one file.
-// The returned template will have the (base) name and (parsed) contents of the
-// first file matched by the pattern. ParseGlob is equivalent to calling
-// ParseFiles with the list of files matched by the pattern.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-func ParseGlob(pattern string) (*Template, error) {
- return parseGlob(nil, pattern)
-}
-
-// ParseGlob parses the template definitions in the files identified by the
-// pattern and associates the resulting templates with t. The files are matched
-// according to the semantics of filepath.Match, and the pattern must match at
-// least one file. ParseGlob is equivalent to calling t.ParseFiles with the
-// list of files matched by the pattern.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-//
-// ParseGlob returns an error if t or any associated template has already been executed.
-func (t *Template) ParseGlob(pattern string) (*Template, error) {
- return parseGlob(t, pattern)
-}
-
-// parseGlob is the implementation of the function and method ParseGlob.
-func parseGlob(t *Template, pattern string) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
- filenames, err := filepath.Glob(pattern)
- if err != nil {
- return nil, err
- }
- if len(filenames) == 0 {
- return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
- }
- return parseFiles(t, readFileOS, filenames...)
-}
-
-// IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
-// and whether the value has a meaningful truth value. This is the definition of
-// truth used by if and other such actions.
-func IsTrue(val any) (truth, ok bool) {
- return template.IsTrue(val)
-}
-
-// ParseFS is like ParseFiles or ParseGlob but reads from the file system fs
-// instead of the host operating system's file system.
-// It accepts a list of glob patterns.
-// (Note that most file names serve as glob patterns matching only themselves.)
-func ParseFS(fs fs.FS, patterns ...string) (*Template, error) {
- return parseFS(nil, fs, patterns)
-}
-
-// ParseFS is like ParseFiles or ParseGlob but reads from the file system fs
-// instead of the host operating system's file system.
-// It accepts a list of glob patterns.
-// (Note that most file names serve as glob patterns matching only themselves.)
-func (t *Template) ParseFS(fs fs.FS, patterns ...string) (*Template, error) {
- return parseFS(t, fs, patterns)
-}
-
-func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) {
- var filenames []string
- for _, pattern := range patterns {
- list, err := fs.Glob(fsys, pattern)
- if err != nil {
- return nil, err
- }
- if len(list) == 0 {
- return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
- }
- filenames = append(filenames, list...)
- }
- return parseFiles(t, readFileFS(fsys), filenames...)
-}
-
-func readFileOS(file string) (name string, b []byte, err error) {
- name = filepath.Base(file)
- b, err = os.ReadFile(file)
- return
-}
-
-func readFileFS(fsys fs.FS) func(string) (string, []byte, error) {
- return func(file string) (name string, b []byte, err error) {
- name = path.Base(file)
- b, err = fs.ReadFile(fsys, file)
- return
- }
-}
diff --git a/contrib/go/_std_1.22/src/internal/abi/map.go b/contrib/go/_std_1.22/src/internal/abi/map.go
deleted file mode 100644
index ad054e7d7779..000000000000
--- a/contrib/go/_std_1.22/src/internal/abi/map.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2023 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.
-
-package abi
-
-// Map constants common to several packages
-// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
-const (
- MapBucketCountBits = 3 // log2 of number of elements in a bucket.
- MapBucketCount = 1 << MapBucketCountBits
- MapMaxKeyBytes = 128 // Must fit in a uint8.
- MapMaxElemBytes = 128 // Must fit in a uint8.
-)
-
-// ZeroValSize is the size in bytes of runtime.zeroVal.
-const ZeroValSize = 1024
diff --git a/contrib/go/_std_1.22/src/internal/abi/symtab.go b/contrib/go/_std_1.22/src/internal/abi/symtab.go
deleted file mode 100644
index ce1b65015519..000000000000
--- a/contrib/go/_std_1.22/src/internal/abi/symtab.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2023 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.
-
-package abi
-
-// A FuncFlag records bits about a function, passed to the runtime.
-type FuncFlag uint8
-
-const (
- // FuncFlagTopFrame indicates a function that appears at the top of its stack.
- // The traceback routine stop at such a function and consider that a
- // successful, complete traversal of the stack.
- // Examples of TopFrame functions include goexit, which appears
- // at the top of a user goroutine stack, and mstart, which appears
- // at the top of a system goroutine stack.
- FuncFlagTopFrame FuncFlag = 1 << iota
-
- // FuncFlagSPWrite indicates a function that writes an arbitrary value to SP
- // (any write other than adding or subtracting a constant amount).
- // The traceback routines cannot encode such changes into the
- // pcsp tables, so the function traceback cannot safely unwind past
- // SPWrite functions. Stopping at an SPWrite function is considered
- // to be an incomplete unwinding of the stack. In certain contexts
- // (in particular garbage collector stack scans) that is a fatal error.
- FuncFlagSPWrite
-
- // FuncFlagAsm indicates that a function was implemented in assembly.
- FuncFlagAsm
-)
-
-// A FuncID identifies particular functions that need to be treated
-// specially by the runtime.
-// Note that in some situations involving plugins, there may be multiple
-// copies of a particular special runtime function.
-type FuncID uint8
-
-const (
- // If you add a FuncID, you probably also want to add an entry to the map in
- // ../../cmd/internal/objabi/funcid.go
-
- FuncIDNormal FuncID = iota // not a special function
- FuncID_abort
- FuncID_asmcgocall
- FuncID_asyncPreempt
- FuncID_cgocallback
- FuncID_corostart
- FuncID_debugCallV2
- FuncID_gcBgMarkWorker
- FuncID_goexit
- FuncID_gogo
- FuncID_gopanic
- FuncID_handleAsyncEvent
- FuncID_mcall
- FuncID_morestack
- FuncID_mstart
- FuncID_panicwrap
- FuncID_rt0_go
- FuncID_runfinq
- FuncID_runtime_main
- FuncID_sigpanic
- FuncID_systemstack
- FuncID_systemstack_switch
- FuncIDWrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
-)
-
-// ArgsSizeUnknown is set in Func.argsize to mark all functions
-// whose argument size is unknown (C vararg functions, and
-// assembly code without an explicit specification).
-// This value is generated by the compiler, assembler, or linker.
-const ArgsSizeUnknown = -0x80000000
-
-// IDs for PCDATA and FUNCDATA tables in Go binaries.
-//
-// These must agree with ../../../runtime/funcdata.h.
-const (
- PCDATA_UnsafePoint = 0
- PCDATA_StackMapIndex = 1
- PCDATA_InlTreeIndex = 2
- PCDATA_ArgLiveIndex = 3
-
- FUNCDATA_ArgsPointerMaps = 0
- FUNCDATA_LocalsPointerMaps = 1
- FUNCDATA_StackObjects = 2
- FUNCDATA_InlTree = 3
- FUNCDATA_OpenCodedDeferInfo = 4
- FUNCDATA_ArgInfo = 5
- FUNCDATA_ArgLiveInfo = 6
- FUNCDATA_WrapInfo = 7
-)
-
-// Special values for the PCDATA_UnsafePoint table.
-const (
- UnsafePointSafe = -1 // Safe for async preemption
- UnsafePointUnsafe = -2 // Unsafe for async preemption
-
- // UnsafePointRestart1(2) apply on a sequence of instructions, within
- // which if an async preemption happens, we should back off the PC
- // to the start of the sequence when resuming.
- // We need two so we can distinguish the start/end of the sequence
- // in case that two sequences are next to each other.
- UnsafePointRestart1 = -3
- UnsafePointRestart2 = -4
-
- // Like UnsafePointRestart1, but back to function entry if async preempted.
- UnsafePointRestartAtEntry = -5
-)
diff --git a/contrib/go/_std_1.22/src/internal/abi/type.go b/contrib/go/_std_1.22/src/internal/abi/type.go
deleted file mode 100644
index 659fb7bffd32..000000000000
--- a/contrib/go/_std_1.22/src/internal/abi/type.go
+++ /dev/null
@@ -1,718 +0,0 @@
-// Copyright 2023 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.
-
-package abi
-
-import (
- "unsafe"
-)
-
-// Type is the runtime representation of a Go type.
-//
-// Be careful about accessing this type at build time, as the version
-// of this type in the compiler/linker may not have the same layout
-// as the version in the target binary, due to pointer width
-// differences and any experiments. Use cmd/compile/internal/rttype
-// or the functions in compiletype.go to access this type instead.
-// (TODO: this admonition applies to every type in this package.
-// Put it in some shared location?)
-type Type struct {
- Size_ uintptr
- PtrBytes uintptr // number of (prefix) bytes in the type that can contain pointers
- Hash uint32 // hash of type; avoids computation in hash tables
- TFlag TFlag // extra type information flags
- Align_ uint8 // alignment of variable with this type
- FieldAlign_ uint8 // alignment of struct field with this type
- Kind_ uint8 // enumeration for C
- // function for comparing objects of this type
- // (ptr to object A, ptr to object B) -> ==?
- Equal func(unsafe.Pointer, unsafe.Pointer) bool
- // GCData stores the GC type data for the garbage collector.
- // If the KindGCProg bit is set in kind, GCData is a GC program.
- // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
- GCData *byte
- Str NameOff // string form
- PtrToThis TypeOff // type for pointer to this type, may be zero
-}
-
-// A Kind represents the specific kind of type that a Type represents.
-// The zero Kind is not a valid kind.
-type Kind uint
-
-const (
- Invalid Kind = iota
- Bool
- Int
- Int8
- Int16
- Int32
- Int64
- Uint
- Uint8
- Uint16
- Uint32
- Uint64
- Uintptr
- Float32
- Float64
- Complex64
- Complex128
- Array
- Chan
- Func
- Interface
- Map
- Pointer
- Slice
- String
- Struct
- UnsafePointer
-)
-
-const (
- // TODO (khr, drchase) why aren't these in TFlag? Investigate, fix if possible.
- KindDirectIface = 1 << 5
- KindGCProg = 1 << 6 // Type.gc points to GC program
- KindMask = (1 << 5) - 1
-)
-
-// TFlag is used by a Type to signal what extra type information is
-// available in the memory directly following the Type value.
-type TFlag uint8
-
-const (
- // TFlagUncommon means that there is a data with a type, UncommonType,
- // just beyond the shared-per-type common data. That is, the data
- // for struct types will store their UncommonType at one offset, the
- // data for interface types will store their UncommonType at a different
- // offset. UncommonType is always accessed via a pointer that is computed
- // using trust-us-we-are-the-implementors pointer arithmetic.
- //
- // For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0,
- // then t has UncommonType data and it can be accessed as:
- //
- // type structTypeUncommon struct {
- // structType
- // u UncommonType
- // }
- // u := &(*structTypeUncommon)(unsafe.Pointer(t)).u
- TFlagUncommon TFlag = 1 << 0
-
- // TFlagExtraStar means the name in the str field has an
- // extraneous '*' prefix. This is because for most types T in
- // a program, the type *T also exists and reusing the str data
- // saves binary size.
- TFlagExtraStar TFlag = 1 << 1
-
- // TFlagNamed means the type has a name.
- TFlagNamed TFlag = 1 << 2
-
- // TFlagRegularMemory means that equal and hash functions can treat
- // this type as a single region of t.size bytes.
- TFlagRegularMemory TFlag = 1 << 3
-
- // TFlagUnrolledBitmap marks special types that are unrolled-bitmap
- // versions of types with GC programs.
- // These types need to be deallocated when the underlying object
- // is freed.
- TFlagUnrolledBitmap TFlag = 1 << 4
-)
-
-// NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime.
-type NameOff int32
-
-// TypeOff is the offset to a type from moduledata.types. See resolveTypeOff in runtime.
-type TypeOff int32
-
-// TextOff is an offset from the top of a text section. See (rtype).textOff in runtime.
-type TextOff int32
-
-// String returns the name of k.
-func (k Kind) String() string {
- if int(k) < len(kindNames) {
- return kindNames[k]
- }
- return kindNames[0]
-}
-
-var kindNames = []string{
- Invalid: "invalid",
- Bool: "bool",
- Int: "int",
- Int8: "int8",
- Int16: "int16",
- Int32: "int32",
- Int64: "int64",
- Uint: "uint",
- Uint8: "uint8",
- Uint16: "uint16",
- Uint32: "uint32",
- Uint64: "uint64",
- Uintptr: "uintptr",
- Float32: "float32",
- Float64: "float64",
- Complex64: "complex64",
- Complex128: "complex128",
- Array: "array",
- Chan: "chan",
- Func: "func",
- Interface: "interface",
- Map: "map",
- Pointer: "ptr",
- Slice: "slice",
- String: "string",
- Struct: "struct",
- UnsafePointer: "unsafe.Pointer",
-}
-
-func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) }
-
-func (t *Type) HasName() bool {
- return t.TFlag&TFlagNamed != 0
-}
-
-func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
-
-// IfaceIndir reports whether t is stored indirectly in an interface value.
-func (t *Type) IfaceIndir() bool {
- return t.Kind_&KindDirectIface == 0
-}
-
-// isDirectIface reports whether t is stored directly in an interface value.
-func (t *Type) IsDirectIface() bool {
- return t.Kind_&KindDirectIface != 0
-}
-
-func (t *Type) GcSlice(begin, end uintptr) []byte {
- return unsafe.Slice(t.GCData, int(end))[begin:]
-}
-
-// Method on non-interface type
-type Method struct {
- Name NameOff // name of method
- Mtyp TypeOff // method type (without receiver)
- Ifn TextOff // fn used in interface call (one-word receiver)
- Tfn TextOff // fn used for normal method call
-}
-
-// UncommonType is present only for defined types or types with methods
-// (if T is a defined type, the uncommonTypes for T and *T have methods).
-// Using a pointer to this struct reduces the overall size required
-// to describe a non-defined type with no methods.
-type UncommonType struct {
- PkgPath NameOff // import path; empty for built-in types like int, string
- Mcount uint16 // number of methods
- Xcount uint16 // number of exported methods
- Moff uint32 // offset from this uncommontype to [mcount]Method
- _ uint32 // unused
-}
-
-func (t *UncommonType) Methods() []Method {
- if t.Mcount == 0 {
- return nil
- }
- return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
-}
-
-func (t *UncommonType) ExportedMethods() []Method {
- if t.Xcount == 0 {
- return nil
- }
- return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
-}
-
-// addChecked returns p+x.
-//
-// The whySafe string is ignored, so that the function still inlines
-// as efficiently as p+x, but all call sites should use the string to
-// record why the addition is safe, which is to say why the addition
-// does not cause x to advance to the very end of p's allocation
-// and therefore point incorrectly at the next block in memory.
-func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
- return unsafe.Pointer(uintptr(p) + x)
-}
-
-// Imethod represents a method on an interface type
-type Imethod struct {
- Name NameOff // name of method
- Typ TypeOff // .(*FuncType) underneath
-}
-
-// ArrayType represents a fixed array type.
-type ArrayType struct {
- Type
- Elem *Type // array element type
- Slice *Type // slice type
- Len uintptr
-}
-
-// Len returns the length of t if t is an array type, otherwise 0
-func (t *Type) Len() int {
- if t.Kind() == Array {
- return int((*ArrayType)(unsafe.Pointer(t)).Len)
- }
- return 0
-}
-
-func (t *Type) Common() *Type {
- return t
-}
-
-type ChanDir int
-
-const (
- RecvDir ChanDir = 1 << iota // <-chan
- SendDir // chan<-
- BothDir = RecvDir | SendDir // chan
- InvalidDir ChanDir = 0
-)
-
-// ChanType represents a channel type
-type ChanType struct {
- Type
- Elem *Type
- Dir ChanDir
-}
-
-type structTypeUncommon struct {
- StructType
- u UncommonType
-}
-
-// ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).
-func (t *Type) ChanDir() ChanDir {
- if t.Kind() == Chan {
- ch := (*ChanType)(unsafe.Pointer(t))
- return ch.Dir
- }
- return InvalidDir
-}
-
-// Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nil
-func (t *Type) Uncommon() *UncommonType {
- if t.TFlag&TFlagUncommon == 0 {
- return nil
- }
- switch t.Kind() {
- case Struct:
- return &(*structTypeUncommon)(unsafe.Pointer(t)).u
- case Pointer:
- type u struct {
- PtrType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- case Func:
- type u struct {
- FuncType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- case Slice:
- type u struct {
- SliceType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- case Array:
- type u struct {
- ArrayType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- case Chan:
- type u struct {
- ChanType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- case Map:
- type u struct {
- MapType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- case Interface:
- type u struct {
- InterfaceType
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- default:
- type u struct {
- Type
- u UncommonType
- }
- return &(*u)(unsafe.Pointer(t)).u
- }
-}
-
-// Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.
-func (t *Type) Elem() *Type {
- switch t.Kind() {
- case Array:
- tt := (*ArrayType)(unsafe.Pointer(t))
- return tt.Elem
- case Chan:
- tt := (*ChanType)(unsafe.Pointer(t))
- return tt.Elem
- case Map:
- tt := (*MapType)(unsafe.Pointer(t))
- return tt.Elem
- case Pointer:
- tt := (*PtrType)(unsafe.Pointer(t))
- return tt.Elem
- case Slice:
- tt := (*SliceType)(unsafe.Pointer(t))
- return tt.Elem
- }
- return nil
-}
-
-// StructType returns t cast to a *StructType, or nil if its tag does not match.
-func (t *Type) StructType() *StructType {
- if t.Kind() != Struct {
- return nil
- }
- return (*StructType)(unsafe.Pointer(t))
-}
-
-// MapType returns t cast to a *MapType, or nil if its tag does not match.
-func (t *Type) MapType() *MapType {
- if t.Kind() != Map {
- return nil
- }
- return (*MapType)(unsafe.Pointer(t))
-}
-
-// ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.
-func (t *Type) ArrayType() *ArrayType {
- if t.Kind() != Array {
- return nil
- }
- return (*ArrayType)(unsafe.Pointer(t))
-}
-
-// FuncType returns t cast to a *FuncType, or nil if its tag does not match.
-func (t *Type) FuncType() *FuncType {
- if t.Kind() != Func {
- return nil
- }
- return (*FuncType)(unsafe.Pointer(t))
-}
-
-// InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.
-func (t *Type) InterfaceType() *InterfaceType {
- if t.Kind() != Interface {
- return nil
- }
- return (*InterfaceType)(unsafe.Pointer(t))
-}
-
-// Size returns the size of data with type t.
-func (t *Type) Size() uintptr { return t.Size_ }
-
-// Align returns the alignment of data with type t.
-func (t *Type) Align() int { return int(t.Align_) }
-
-func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
-
-type InterfaceType struct {
- Type
- PkgPath Name // import path
- Methods []Imethod // sorted by hash
-}
-
-func (t *Type) ExportedMethods() []Method {
- ut := t.Uncommon()
- if ut == nil {
- return nil
- }
- return ut.ExportedMethods()
-}
-
-func (t *Type) NumMethod() int {
- if t.Kind() == Interface {
- tt := (*InterfaceType)(unsafe.Pointer(t))
- return tt.NumMethod()
- }
- return len(t.ExportedMethods())
-}
-
-// NumMethod returns the number of interface methods in the type's method set.
-func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
-
-type MapType struct {
- Type
- Key *Type
- Elem *Type
- Bucket *Type // internal type representing a hash bucket
- // function for hashing keys (ptr to key, seed) -> hash
- Hasher func(unsafe.Pointer, uintptr) uintptr
- KeySize uint8 // size of key slot
- ValueSize uint8 // size of elem slot
- BucketSize uint16 // size of bucket
- Flags uint32
-}
-
-// Note: flag values must match those used in the TMAP case
-// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
-func (mt *MapType) IndirectKey() bool { // store ptr to key instead of key itself
- return mt.Flags&1 != 0
-}
-func (mt *MapType) IndirectElem() bool { // store ptr to elem instead of elem itself
- return mt.Flags&2 != 0
-}
-func (mt *MapType) ReflexiveKey() bool { // true if k==k for all keys
- return mt.Flags&4 != 0
-}
-func (mt *MapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite
- return mt.Flags&8 != 0
-}
-func (mt *MapType) HashMightPanic() bool { // true if hash function might panic
- return mt.Flags&16 != 0
-}
-
-func (t *Type) Key() *Type {
- if t.Kind() == Map {
- return (*MapType)(unsafe.Pointer(t)).Key
- }
- return nil
-}
-
-type SliceType struct {
- Type
- Elem *Type // slice element type
-}
-
-// funcType represents a function type.
-//
-// A *Type for each in and out parameter is stored in an array that
-// directly follows the funcType (and possibly its uncommonType). So
-// a function type with one method, one input, and one output is:
-//
-// struct {
-// funcType
-// uncommonType
-// [2]*rtype // [0] is in, [1] is out
-// }
-type FuncType struct {
- Type
- InCount uint16
- OutCount uint16 // top bit is set if last input parameter is ...
-}
-
-func (t *FuncType) In(i int) *Type {
- return t.InSlice()[i]
-}
-
-func (t *FuncType) NumIn() int {
- return int(t.InCount)
-}
-
-func (t *FuncType) NumOut() int {
- return int(t.OutCount & (1<<15 - 1))
-}
-
-func (t *FuncType) Out(i int) *Type {
- return (t.OutSlice()[i])
-}
-
-func (t *FuncType) InSlice() []*Type {
- uadd := unsafe.Sizeof(*t)
- if t.TFlag&TFlagUncommon != 0 {
- uadd += unsafe.Sizeof(UncommonType{})
- }
- if t.InCount == 0 {
- return nil
- }
- return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
-}
-func (t *FuncType) OutSlice() []*Type {
- outCount := uint16(t.NumOut())
- if outCount == 0 {
- return nil
- }
- uadd := unsafe.Sizeof(*t)
- if t.TFlag&TFlagUncommon != 0 {
- uadd += unsafe.Sizeof(UncommonType{})
- }
- return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
-}
-
-func (t *FuncType) IsVariadic() bool {
- return t.OutCount&(1<<15) != 0
-}
-
-type PtrType struct {
- Type
- Elem *Type // pointer element (pointed at) type
-}
-
-type StructField struct {
- Name Name // name is always non-empty
- Typ *Type // type of field
- Offset uintptr // byte offset of field
-}
-
-func (f *StructField) Embedded() bool {
- return f.Name.IsEmbedded()
-}
-
-type StructType struct {
- Type
- PkgPath Name
- Fields []StructField
-}
-
-// Name is an encoded type Name with optional extra data.
-//
-// The first byte is a bit field containing:
-//
-// 1<<0 the name is exported
-// 1<<1 tag data follows the name
-// 1<<2 pkgPath nameOff follows the name and tag
-// 1<<3 the name is of an embedded (a.k.a. anonymous) field
-//
-// Following that, there is a varint-encoded length of the name,
-// followed by the name itself.
-//
-// If tag data is present, it also has a varint-encoded length
-// followed by the tag itself.
-//
-// If the import path follows, then 4 bytes at the end of
-// the data form a nameOff. The import path is only set for concrete
-// methods that are defined in a different package than their type.
-//
-// If a name starts with "*", then the exported bit represents
-// whether the pointed to type is exported.
-//
-// Note: this encoding must match here and in:
-// cmd/compile/internal/reflectdata/reflect.go
-// cmd/link/internal/ld/decodesym.go
-
-type Name struct {
- Bytes *byte
-}
-
-// DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
-// be safe for the reason in whySafe (which can appear in a backtrace, etc.)
-func (n Name) DataChecked(off int, whySafe string) *byte {
- return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
-}
-
-// Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to
-// be safe because the runtime made the call (other packages use DataChecked)
-func (n Name) Data(off int) *byte {
- return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
-}
-
-// IsExported returns "is n exported?"
-func (n Name) IsExported() bool {
- return (*n.Bytes)&(1<<0) != 0
-}
-
-// HasTag returns true iff there is tag data following this name
-func (n Name) HasTag() bool {
- return (*n.Bytes)&(1<<1) != 0
-}
-
-// IsEmbedded returns true iff n is embedded (an anonymous field).
-func (n Name) IsEmbedded() bool {
- return (*n.Bytes)&(1<<3) != 0
-}
-
-// ReadVarint parses a varint as encoded by encoding/binary.
-// It returns the number of encoded bytes and the encoded value.
-func (n Name) ReadVarint(off int) (int, int) {
- v := 0
- for i := 0; ; i++ {
- x := *n.DataChecked(off+i, "read varint")
- v += int(x&0x7f) << (7 * i)
- if x&0x80 == 0 {
- return i + 1, v
- }
- }
-}
-
-// IsBlank indicates whether n is "_".
-func (n Name) IsBlank() bool {
- if n.Bytes == nil {
- return false
- }
- _, l := n.ReadVarint(1)
- return l == 1 && *n.Data(2) == '_'
-}
-
-// writeVarint writes n to buf in varint form. Returns the
-// number of bytes written. n must be nonnegative.
-// Writes at most 10 bytes.
-func writeVarint(buf []byte, n int) int {
- for i := 0; ; i++ {
- b := byte(n & 0x7f)
- n >>= 7
- if n == 0 {
- buf[i] = b
- return i + 1
- }
- buf[i] = b | 0x80
- }
-}
-
-// Name returns the tag string for n, or empty if there is none.
-func (n Name) Name() string {
- if n.Bytes == nil {
- return ""
- }
- i, l := n.ReadVarint(1)
- return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
-}
-
-// Tag returns the tag string for n, or empty if there is none.
-func (n Name) Tag() string {
- if !n.HasTag() {
- return ""
- }
- i, l := n.ReadVarint(1)
- i2, l2 := n.ReadVarint(1 + i + l)
- return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
-}
-
-func NewName(n, tag string, exported, embedded bool) Name {
- if len(n) >= 1<<29 {
- panic("abi.NewName: name too long: " + n[:1024] + "...")
- }
- if len(tag) >= 1<<29 {
- panic("abi.NewName: tag too long: " + tag[:1024] + "...")
- }
- var nameLen [10]byte
- var tagLen [10]byte
- nameLenLen := writeVarint(nameLen[:], len(n))
- tagLenLen := writeVarint(tagLen[:], len(tag))
-
- var bits byte
- l := 1 + nameLenLen + len(n)
- if exported {
- bits |= 1 << 0
- }
- if len(tag) > 0 {
- l += tagLenLen + len(tag)
- bits |= 1 << 1
- }
- if embedded {
- bits |= 1 << 3
- }
-
- b := make([]byte, l)
- b[0] = bits
- copy(b[1:], nameLen[:nameLenLen])
- copy(b[1+nameLenLen:], n)
- if len(tag) > 0 {
- tb := b[1+nameLenLen+len(n):]
- copy(tb, tagLen[:tagLenLen])
- copy(tb[tagLenLen:], tag)
- }
-
- return Name{Bytes: &b[0]}
-}
diff --git a/contrib/go/_std_1.22/src/internal/abi/ya.make b/contrib/go/_std_1.22/src/internal/abi/ya.make
deleted file mode 100644
index 62a84b9fc36e..000000000000
--- a/contrib/go/_std_1.22/src/internal/abi/ya.make
+++ /dev/null
@@ -1,31 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- abi.go
- abi_arm64.go
- abi_test.s
- compiletype.go
- funcpc.go
- map.go
- stack.go
- stub.s
- switch.go
- symtab.go
- type.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- abi.go
- abi_amd64.go
- abi_test.s
- compiletype.go
- funcpc.go
- map.go
- stack.go
- stub.s
- switch.go
- symtab.go
- type.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/buildcfg/cfg.go b/contrib/go/_std_1.22/src/internal/buildcfg/cfg.go
deleted file mode 100644
index 8b97a653d773..000000000000
--- a/contrib/go/_std_1.22/src/internal/buildcfg/cfg.go
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2021 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.
-
-// Package buildcfg provides access to the build configuration
-// described by the current environment. It is for use by build tools
-// such as cmd/go or cmd/compile and for setting up go/build's Default context.
-//
-// Note that it does NOT provide access to the build configuration used to
-// build the currently-running binary. For that, use runtime.GOOS etc
-// as well as internal/goexperiment.
-package buildcfg
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "runtime"
- "strconv"
- "strings"
-)
-
-var (
- GOROOT = runtime.GOROOT() // cached for efficiency
- GOARCH = envOr("GOARCH", defaultGOARCH)
- GOOS = envOr("GOOS", defaultGOOS)
- GO386 = envOr("GO386", defaultGO386)
- GOAMD64 = goamd64()
- GOARM = goarm()
- GOMIPS = gomips()
- GOMIPS64 = gomips64()
- GOPPC64 = goppc64()
- GOWASM = gowasm()
- ToolTags = toolTags()
- GO_LDSO = defaultGO_LDSO
- Version = version
-)
-
-// Error is one of the errors found (if any) in the build configuration.
-var Error error
-
-// Check exits the program with a fatal error if Error is non-nil.
-func Check() {
- if Error != nil {
- fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), Error)
- os.Exit(2)
- }
-}
-
-func envOr(key, value string) string {
- if x := os.Getenv(key); x != "" {
- return x
- }
- return value
-}
-
-func goamd64() int {
- switch v := envOr("GOAMD64", defaultGOAMD64); v {
- case "v1":
- return 1
- case "v2":
- return 2
- case "v3":
- return 3
- case "v4":
- return 4
- }
- Error = fmt.Errorf("invalid GOAMD64: must be v1, v2, v3, v4")
- return int(defaultGOAMD64[len("v")] - '0')
-}
-
-type goarmFeatures struct {
- Version int
- SoftFloat bool
-}
-
-func (g goarmFeatures) String() string {
- armStr := strconv.Itoa(g.Version)
- if g.SoftFloat {
- armStr += ",softfloat"
- } else {
- armStr += ",hardfloat"
- }
- return armStr
-}
-
-func goarm() (g goarmFeatures) {
- const (
- softFloatOpt = ",softfloat"
- hardFloatOpt = ",hardfloat"
- )
- def := defaultGOARM
- if GOOS == "android" && GOARCH == "arm" {
- // Android arm devices always support GOARM=7.
- def = "7"
- }
- v := envOr("GOARM", def)
-
- floatSpecified := false
- if strings.HasSuffix(v, softFloatOpt) {
- g.SoftFloat = true
- floatSpecified = true
- v = v[:len(v)-len(softFloatOpt)]
- }
- if strings.HasSuffix(v, hardFloatOpt) {
- floatSpecified = true
- v = v[:len(v)-len(hardFloatOpt)]
- }
-
- switch v {
- case "5":
- g.Version = 5
- case "6":
- g.Version = 6
- case "7":
- g.Version = 7
- default:
- Error = fmt.Errorf("invalid GOARM: must start with 5, 6, or 7, and may optionally end in either %q or %q", hardFloatOpt, softFloatOpt)
- g.Version = int(def[0] - '0')
- }
-
- // 5 defaults to softfloat. 6 and 7 default to hardfloat.
- if !floatSpecified && g.Version == 5 {
- g.SoftFloat = true
- }
- return
-}
-
-func gomips() string {
- switch v := envOr("GOMIPS", defaultGOMIPS); v {
- case "hardfloat", "softfloat":
- return v
- }
- Error = fmt.Errorf("invalid GOMIPS: must be hardfloat, softfloat")
- return defaultGOMIPS
-}
-
-func gomips64() string {
- switch v := envOr("GOMIPS64", defaultGOMIPS64); v {
- case "hardfloat", "softfloat":
- return v
- }
- Error = fmt.Errorf("invalid GOMIPS64: must be hardfloat, softfloat")
- return defaultGOMIPS64
-}
-
-func goppc64() int {
- switch v := envOr("GOPPC64", defaultGOPPC64); v {
- case "power8":
- return 8
- case "power9":
- return 9
- case "power10":
- return 10
- }
- Error = fmt.Errorf("invalid GOPPC64: must be power8, power9, power10")
- return int(defaultGOPPC64[len("power")] - '0')
-}
-
-type gowasmFeatures struct {
- SatConv bool
- SignExt bool
-}
-
-func (f gowasmFeatures) String() string {
- var flags []string
- if f.SatConv {
- flags = append(flags, "satconv")
- }
- if f.SignExt {
- flags = append(flags, "signext")
- }
- return strings.Join(flags, ",")
-}
-
-func gowasm() (f gowasmFeatures) {
- for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
- switch opt {
- case "satconv":
- f.SatConv = true
- case "signext":
- f.SignExt = true
- case "":
- // ignore
- default:
- Error = fmt.Errorf("invalid GOWASM: no such feature %q", opt)
- }
- }
- return
-}
-
-func Getgoextlinkenabled() string {
- return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED)
-}
-
-func toolTags() []string {
- tags := experimentTags()
- tags = append(tags, gogoarchTags()...)
- return tags
-}
-
-func experimentTags() []string {
- var list []string
- // For each experiment that has been enabled in the toolchain, define a
- // build tag with the same name but prefixed by "goexperiment." which can be
- // used for compiling alternative files for the experiment. This allows
- // changes for the experiment, like extra struct fields in the runtime,
- // without affecting the base non-experiment code at all.
- for _, exp := range Experiment.Enabled() {
- list = append(list, "goexperiment."+exp)
- }
- return list
-}
-
-// GOGOARCH returns the name and value of the GO$GOARCH setting.
-// For example, if GOARCH is "amd64" it might return "GOAMD64", "v2".
-func GOGOARCH() (name, value string) {
- switch GOARCH {
- case "386":
- return "GO386", GO386
- case "amd64":
- return "GOAMD64", fmt.Sprintf("v%d", GOAMD64)
- case "arm":
- return "GOARM", GOARM.String()
- case "mips", "mipsle":
- return "GOMIPS", GOMIPS
- case "mips64", "mips64le":
- return "GOMIPS64", GOMIPS64
- case "ppc64", "ppc64le":
- return "GOPPC64", fmt.Sprintf("power%d", GOPPC64)
- case "wasm":
- return "GOWASM", GOWASM.String()
- }
- return "", ""
-}
-
-func gogoarchTags() []string {
- switch GOARCH {
- case "386":
- return []string{GOARCH + "." + GO386}
- case "amd64":
- var list []string
- for i := 1; i <= GOAMD64; i++ {
- list = append(list, fmt.Sprintf("%s.v%d", GOARCH, i))
- }
- return list
- case "arm":
- var list []string
- for i := 5; i <= GOARM.Version; i++ {
- list = append(list, fmt.Sprintf("%s.%d", GOARCH, i))
- }
- return list
- case "mips", "mipsle":
- return []string{GOARCH + "." + GOMIPS}
- case "mips64", "mips64le":
- return []string{GOARCH + "." + GOMIPS64}
- case "ppc64", "ppc64le":
- var list []string
- for i := 8; i <= GOPPC64; i++ {
- list = append(list, fmt.Sprintf("%s.power%d", GOARCH, i))
- }
- return list
- case "wasm":
- var list []string
- if GOWASM.SatConv {
- list = append(list, GOARCH+".satconv")
- }
- if GOWASM.SignExt {
- list = append(list, GOARCH+".signext")
- }
- return list
- }
- return nil
-}
diff --git a/contrib/go/_std_1.22/src/internal/bytealg/compare_generic.go b/contrib/go/_std_1.22/src/internal/bytealg/compare_generic.go
deleted file mode 100644
index b04e2750611b..000000000000
--- a/contrib/go/_std_1.22/src/internal/bytealg/compare_generic.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2018 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.
-
-//go:build !386 && !amd64 && !s390x && !arm && !arm64 && !loong64 && !ppc64 && !ppc64le && !mips && !mipsle && !wasm && !mips64 && !mips64le && !riscv64
-
-package bytealg
-
-import _ "unsafe" // for go:linkname
-
-func Compare(a, b []byte) int {
- l := len(a)
- if len(b) < l {
- l = len(b)
- }
- if l == 0 || &a[0] == &b[0] {
- goto samebytes
- }
- for i := 0; i < l; i++ {
- c1, c2 := a[i], b[i]
- if c1 < c2 {
- return -1
- }
- if c1 > c2 {
- return +1
- }
- }
-samebytes:
- if len(a) < len(b) {
- return -1
- }
- if len(a) > len(b) {
- return +1
- }
- return 0
-}
-
-//go:linkname runtime_cmpstring runtime.cmpstring
-func runtime_cmpstring(a, b string) int {
- l := len(a)
- if len(b) < l {
- l = len(b)
- }
- for i := 0; i < l; i++ {
- c1, c2 := a[i], b[i]
- if c1 < c2 {
- return -1
- }
- if c1 > c2 {
- return +1
- }
- }
- if len(a) < len(b) {
- return -1
- }
- if len(a) > len(b) {
- return +1
- }
- return 0
-}
diff --git a/contrib/go/_std_1.22/src/internal/bytealg/equal_loong64.s b/contrib/go/_std_1.22/src/internal/bytealg/equal_loong64.s
deleted file mode 100644
index a3ad5c1b35b6..000000000000
--- a/contrib/go/_std_1.22/src/internal/bytealg/equal_loong64.s
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2022 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.
-
-#include "go_asm.h"
-#include "textflag.h"
-
-#define REGCTXT R29
-
-// memequal(a, b unsafe.Pointer, size uintptr) bool
-TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25
-#ifndef GOEXPERIMENT_regabiargs
- MOVV a+0(FP), R4
- MOVV b+8(FP), R5
- MOVV size+16(FP), R6
-#endif
- BEQ R4, R5, eq
- ADDV R4, R6, R7
- PCALIGN $16
-loop:
- BNE R4, R7, test
- MOVV $1, R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVB R4, ret+24(FP)
-#endif
- RET
-test:
- MOVBU (R4), R9
- ADDV $1, R4
- MOVBU (R5), R10
- ADDV $1, R5
- BEQ R9, R10, loop
-
- MOVB R0, R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVB R0, ret+24(FP)
-#endif
- RET
-eq:
- MOVV $1, R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVB R4, ret+24(FP)
-#endif
- RET
-
-// memequal_varlen(a, b unsafe.Pointer) bool
-TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
-#ifndef GOEXPERIMENT_regabiargs
- MOVV a+0(FP), R4
- MOVV b+8(FP), R5
-#endif
- BEQ R4, R5, eq
- MOVV 8(REGCTXT), R6 // compiler stores size at offset 8 in the closure
- MOVV R4, 8(R3)
- MOVV R5, 16(R3)
- MOVV R6, 24(R3)
- JAL runtime·memequal(SB)
- MOVBU 32(R3), R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVB R4, ret+16(FP)
-#endif
- RET
-eq:
- MOVV $1, R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVB R4, ret+16(FP)
-#endif
- RET
diff --git a/contrib/go/_std_1.22/src/internal/bytealg/indexbyte_loong64.s b/contrib/go/_std_1.22/src/internal/bytealg/indexbyte_loong64.s
deleted file mode 100644
index 03e066097312..000000000000
--- a/contrib/go/_std_1.22/src/internal/bytealg/indexbyte_loong64.s
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2022 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.
-
-#include "go_asm.h"
-#include "textflag.h"
-
-TEXT ·IndexByte(SB),NOSPLIT,$0-40
-#ifndef GOEXPERIMENT_regabiargs
- MOVV b_base+0(FP), R4
- MOVV b_len+8(FP), R5
- MOVBU c+24(FP), R7 // byte to find
-#endif
- // R4 = b_base
- // R5 = b_len
- // R6 = b_cap (unused)
- // R7 = byte to find
- AND $0xff, R7
- MOVV R4, R6 // store base for later
- ADDV R4, R5 // end
- ADDV $-1, R4
-
- PCALIGN $16
-loop:
- ADDV $1, R4
- BEQ R4, R5, notfound
- MOVBU (R4), R8
- BNE R7, R8, loop
-
- SUBV R6, R4 // remove base
-#ifndef GOEXPERIMENT_regabiargs
- MOVV R4, ret+32(FP)
-#endif
- RET
-
-notfound:
- MOVV $-1, R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVV R4, ret+32(FP)
-#endif
- RET
-
-TEXT ·IndexByteString(SB),NOSPLIT,$0-32
-#ifndef GOEXPERIMENT_regabiargs
- MOVV s_base+0(FP), R4
- MOVV s_len+8(FP), R5
- MOVBU c+16(FP), R6 // byte to find
-#endif
- // R4 = s_base
- // R5 = s_len
- // R6 = byte to find
- MOVV R4, R7 // store base for later
- ADDV R4, R5 // end
- ADDV $-1, R4
-
- PCALIGN $16
-loop:
- ADDV $1, R4
- BEQ R4, R5, notfound
- MOVBU (R4), R8
- BNE R6, R8, loop
-
- SUBV R7, R4 // remove base
-#ifndef GOEXPERIMENT_regabiargs
- MOVV R4, ret+24(FP)
-#endif
- RET
-
-notfound:
- MOVV $-1, R4
-#ifndef GOEXPERIMENT_regabiargs
- MOVV R4, ret+24(FP)
-#endif
- RET
diff --git a/contrib/go/_std_1.22/src/internal/bytealg/ya.make b/contrib/go/_std_1.22/src/internal/bytealg/ya.make
deleted file mode 100644
index 522d0c3728bf..000000000000
--- a/contrib/go/_std_1.22/src/internal/bytealg/ya.make
+++ /dev/null
@@ -1,37 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- bytealg.go
- compare_arm64.s
- compare_native.go
- count_arm64.s
- count_native.go
- equal_arm64.s
- equal_generic.go
- equal_native.go
- index_arm64.go
- index_arm64.s
- index_native.go
- indexbyte_arm64.s
- indexbyte_native.go
- lastindexbyte_generic.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- bytealg.go
- compare_amd64.s
- compare_native.go
- count_amd64.s
- count_native.go
- equal_amd64.s
- equal_generic.go
- equal_native.go
- index_amd64.go
- index_amd64.s
- index_native.go
- indexbyte_amd64.s
- indexbyte_native.go
- lastindexbyte_generic.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/chacha8rand/chacha8.go b/contrib/go/_std_1.22/src/internal/chacha8rand/chacha8.go
deleted file mode 100644
index ce55c07d058a..000000000000
--- a/contrib/go/_std_1.22/src/internal/chacha8rand/chacha8.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2023 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.
-
-// Package chacha8rand implements a pseudorandom generator
-// based on ChaCha8. It is used by both runtime and math/rand/v2
-// and must have no dependencies.
-package chacha8rand
-
-const (
- ctrInc = 4 // increment counter by 4 between block calls
- ctrMax = 16 // reseed when counter reaches 16
- chunk = 32 // each chunk produced by block is 32 uint64s
- reseed = 4 // reseed with 4 words
-)
-
-// block is the chacha8rand block function.
-func block(seed *[4]uint64, blocks *[32]uint64, counter uint32)
-
-// A State holds the state for a single random generator.
-// It must be used from one goroutine at a time.
-// If used by multiple goroutines at a time, the goroutines
-// may see the same random values, but the code will not
-// crash or cause out-of-bounds memory accesses.
-type State struct {
- buf [32]uint64
- seed [4]uint64
- i uint32
- n uint32
- c uint32
-}
-
-// Next returns the next random value, along with a boolean
-// indicating whether one was available.
-// If one is not available, the caller should call Refill
-// and then repeat the call to Next.
-//
-// Next is //go:nosplit to allow its use in the runtime
-// with per-m data without holding the per-m lock.
-//go:nosplit
-func (s *State) Next() (uint64, bool) {
- i := s.i
- if i >= s.n {
- return 0, false
- }
- s.i = i + 1
- return s.buf[i&31], true // i&31 eliminates bounds check
-}
-
-// Init seeds the State with the given seed value.
-func (s *State) Init(seed [32]byte) {
- s.Init64([4]uint64{
- leUint64(seed[0*8:]),
- leUint64(seed[1*8:]),
- leUint64(seed[2*8:]),
- leUint64(seed[3*8:]),
- })
-}
-
-// Init64 seeds the state with the given seed value.
-func (s *State) Init64(seed [4]uint64) {
- s.seed = seed
- block(&s.seed, &s.buf, 0)
- s.c = 0
- s.i = 0
- s.n = chunk
-}
-
-// Refill refills the state with more random values.
-// After a call to Refill, an immediate call to Next will succeed
-// (unless multiple goroutines are incorrectly sharing a state).
-func (s *State) Refill() {
- s.c += ctrInc
- if s.c == ctrMax {
- // Reseed with generated uint64s for forward secrecy.
- // Normally this is done immediately after computing a block,
- // but we do it immediately before computing the next block,
- // to allow a much smaller serialized state (just the seed plus offset).
- // This gives a delayed benefit for the forward secrecy
- // (you can reconstruct the recent past given a memory dump),
- // which we deem acceptable in exchange for the reduced size.
- s.seed[0] = s.buf[len(s.buf)-reseed+0]
- s.seed[1] = s.buf[len(s.buf)-reseed+1]
- s.seed[2] = s.buf[len(s.buf)-reseed+2]
- s.seed[3] = s.buf[len(s.buf)-reseed+3]
- s.c = 0
- }
- block(&s.seed, &s.buf, s.c)
- s.i = 0
- s.n = uint32(len(s.buf))
- if s.c == ctrMax-ctrInc {
- s.n = uint32(len(s.buf)) - reseed
- }
-}
-
-// Reseed reseeds the state with new random values.
-// After a call to Reseed, any previously returned random values
-// have been erased from the memory of the state and cannot be
-// recovered.
-func (s *State) Reseed() {
- var seed [4]uint64
- for i := range seed {
- for {
- x, ok := s.Next()
- if ok {
- seed[i] = x
- break
- }
- s.Refill()
- }
- }
- s.Init64(seed)
-}
-
-// Marshal marshals the state into a byte slice.
-// Marshal and Unmarshal are functions, not methods,
-// so that they will not be linked into the runtime
-// when it uses the State struct, since the runtime
-// does not need these.
-func Marshal(s *State) []byte {
- data := make([]byte, 6*8)
- copy(data, "chacha8:")
- used := (s.c/ctrInc)*chunk + s.i
- bePutUint64(data[1*8:], uint64(used))
- for i, seed := range s.seed {
- lePutUint64(data[(2+i)*8:], seed)
- }
- return data
-}
-
-type errUnmarshalChaCha8 struct{}
-
-func (*errUnmarshalChaCha8) Error() string {
- return "invalid ChaCha8 encoding"
-}
-
-// Unmarshal unmarshals the state from a byte slice.
-func Unmarshal(s *State, data []byte) error {
- if len(data) != 6*8 || string(data[:8]) != "chacha8:" {
- return new(errUnmarshalChaCha8)
- }
- used := beUint64(data[1*8:])
- if used > (ctrMax/ctrInc)*chunk-reseed {
- return new(errUnmarshalChaCha8)
- }
- for i := range s.seed {
- s.seed[i] = leUint64(data[(2+i)*8:])
- }
- s.c = ctrInc * (uint32(used) / chunk)
- block(&s.seed, &s.buf, s.c)
- s.i = uint32(used) % chunk
- s.n = chunk
- if s.c == ctrMax-ctrInc {
- s.n = chunk - reseed
- }
- return nil
-}
-
-// binary.bigEndian.Uint64, copied to avoid dependency
-func beUint64(b []byte) uint64 {
- _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
- return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
- uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
-}
-
-// binary.bigEndian.PutUint64, copied to avoid dependency
-func bePutUint64(b []byte, v uint64) {
- _ = b[7] // early bounds check to guarantee safety of writes below
- b[0] = byte(v >> 56)
- b[1] = byte(v >> 48)
- b[2] = byte(v >> 40)
- b[3] = byte(v >> 32)
- b[4] = byte(v >> 24)
- b[5] = byte(v >> 16)
- b[6] = byte(v >> 8)
- b[7] = byte(v)
-}
-
-// binary.littleEndian.Uint64, copied to avoid dependency
-func leUint64(b []byte) uint64 {
- _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
- return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
- uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
-}
-
-// binary.littleEndian.PutUint64, copied to avoid dependency
-func lePutUint64(b []byte, v uint64) {
- _ = b[7] // early bounds check to guarantee safety of writes below
- b[0] = byte(v)
- b[1] = byte(v >> 8)
- b[2] = byte(v >> 16)
- b[3] = byte(v >> 24)
- b[4] = byte(v >> 32)
- b[5] = byte(v >> 40)
- b[6] = byte(v >> 48)
- b[7] = byte(v >> 56)
-}
diff --git a/contrib/go/_std_1.22/src/internal/chacha8rand/ya.make b/contrib/go/_std_1.22/src/internal/chacha8rand/ya.make
deleted file mode 100644
index c70335c29003..000000000000
--- a/contrib/go/_std_1.22/src/internal/chacha8rand/ya.make
+++ /dev/null
@@ -1,15 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- chacha8.go
- chacha8_arm64.s
- chacha8_generic.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- chacha8.go
- chacha8_amd64.s
- chacha8_generic.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/coverage/rtcov/rtcov.go b/contrib/go/_std_1.22/src/internal/coverage/rtcov/rtcov.go
deleted file mode 100644
index bbb93acced7d..000000000000
--- a/contrib/go/_std_1.22/src/internal/coverage/rtcov/rtcov.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2022 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.
-
-package rtcov
-
-// This package contains types whose structure is shared between
-// the runtime package and the "runtime/coverage" package.
-
-// CovMetaBlob is a container for holding the meta-data symbol (an
-// RODATA variable) for an instrumented Go package. Here "p" points to
-// the symbol itself, "len" is the length of the sym in bytes, and
-// "hash" is an md5sum for the sym computed by the compiler. When
-// the init function for a coverage-instrumented package executes, it
-// will make a call into the runtime which will create a covMetaBlob
-// object for the package and chain it onto a global list.
-type CovMetaBlob struct {
- P *byte
- Len uint32
- Hash [16]byte
- PkgPath string
- PkgID int
- CounterMode uint8 // coverage.CounterMode
- CounterGranularity uint8 // coverage.CounterGranularity
-}
-
-// CovCounterBlob is a container for encapsulating a counter section
-// (BSS variable) for an instrumented Go module. Here "counters"
-// points to the counter payload and "len" is the number of uint32
-// entries in the section.
-type CovCounterBlob struct {
- Counters *uint32
- Len uint64
-}
diff --git a/contrib/go/_std_1.22/src/internal/cpu/cpu.go b/contrib/go/_std_1.22/src/internal/cpu/cpu.go
deleted file mode 100644
index d794e53ceeef..000000000000
--- a/contrib/go/_std_1.22/src/internal/cpu/cpu.go
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2017 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.
-
-// Package cpu implements processor feature detection
-// used by the Go standard library.
-package cpu
-
-// DebugOptions is set to true by the runtime if the OS supports reading
-// GODEBUG early in runtime startup.
-// This should not be changed after it is initialized.
-var DebugOptions bool
-
-// CacheLinePad is used to pad structs to avoid false sharing.
-type CacheLinePad struct{ _ [CacheLinePadSize]byte }
-
-// CacheLineSize is the CPU's assumed cache line size.
-// There is currently no runtime detection of the real cache line size
-// so we use the constant per GOARCH CacheLinePadSize as an approximation.
-var CacheLineSize uintptr = CacheLinePadSize
-
-// The booleans in X86 contain the correspondingly named cpuid feature bit.
-// HasAVX and HasAVX2 are only set if the OS does support XMM and YMM registers
-// in addition to the cpuid feature bit being set.
-// The struct is padded to avoid false sharing.
-var X86 struct {
- _ CacheLinePad
- HasAES bool
- HasADX bool
- HasAVX bool
- HasAVX2 bool
- HasAVX512F bool
- HasAVX512BW bool
- HasAVX512VL bool
- HasBMI1 bool
- HasBMI2 bool
- HasERMS bool
- HasFMA bool
- HasOSXSAVE bool
- HasPCLMULQDQ bool
- HasPOPCNT bool
- HasRDTSCP bool
- HasSHA bool
- HasSSE3 bool
- HasSSSE3 bool
- HasSSE41 bool
- HasSSE42 bool
- _ CacheLinePad
-}
-
-// The booleans in ARM contain the correspondingly named cpu feature bit.
-// The struct is padded to avoid false sharing.
-var ARM struct {
- _ CacheLinePad
- HasVFPv4 bool
- HasIDIVA bool
- HasV7Atomics bool
- _ CacheLinePad
-}
-
-// The booleans in ARM64 contain the correspondingly named cpu feature bit.
-// The struct is padded to avoid false sharing.
-var ARM64 struct {
- _ CacheLinePad
- HasAES bool
- HasPMULL bool
- HasSHA1 bool
- HasSHA2 bool
- HasSHA512 bool
- HasCRC32 bool
- HasATOMICS bool
- HasCPUID bool
- IsNeoverse bool
- _ CacheLinePad
-}
-
-var MIPS64X struct {
- _ CacheLinePad
- HasMSA bool // MIPS SIMD architecture
- _ CacheLinePad
-}
-
-// For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
-// since there are no optional categories. There are some exceptions that also
-// require kernel support to work (darn, scv), so there are feature bits for
-// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
-// The struct is padded to avoid false sharing.
-var PPC64 struct {
- _ CacheLinePad
- HasDARN bool // Hardware random number generator (requires kernel enablement)
- HasSCV bool // Syscall vectored (requires kernel enablement)
- IsPOWER8 bool // ISA v2.07 (POWER8)
- IsPOWER9 bool // ISA v3.00 (POWER9)
- IsPOWER10 bool // ISA v3.1 (POWER10)
- _ CacheLinePad
-}
-
-var S390X struct {
- _ CacheLinePad
- HasZARCH bool // z architecture mode is active [mandatory]
- HasSTFLE bool // store facility list extended [mandatory]
- HasLDISP bool // long (20-bit) displacements [mandatory]
- HasEIMM bool // 32-bit immediates [mandatory]
- HasDFP bool // decimal floating point
- HasETF3EH bool // ETF-3 enhanced
- HasMSA bool // message security assist (CPACF)
- HasAES bool // KM-AES{128,192,256} functions
- HasAESCBC bool // KMC-AES{128,192,256} functions
- HasAESCTR bool // KMCTR-AES{128,192,256} functions
- HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
- HasGHASH bool // KIMD-GHASH function
- HasSHA1 bool // K{I,L}MD-SHA-1 functions
- HasSHA256 bool // K{I,L}MD-SHA-256 functions
- HasSHA512 bool // K{I,L}MD-SHA-512 functions
- HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions
- HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records.
- HasVXE bool // vector-enhancements facility 1
- HasKDSA bool // elliptic curve functions
- HasECDSA bool // NIST curves
- HasEDDSA bool // Edwards curves
- _ CacheLinePad
-}
-
-// Initialize examines the processor and sets the relevant variables above.
-// This is called by the runtime package early in program initialization,
-// before normal init functions are run. env is set by runtime if the OS supports
-// cpu feature options in GODEBUG.
-func Initialize(env string) {
- doinit()
- processOptions(env)
-}
-
-// options contains the cpu debug options that can be used in GODEBUG.
-// Options are arch dependent and are added by the arch specific doinit functions.
-// Features that are mandatory for the specific GOARCH should not be added to options
-// (e.g. SSE2 on amd64).
-var options []option
-
-// Option names should be lower case. e.g. avx instead of AVX.
-type option struct {
- Name string
- Feature *bool
- Specified bool // whether feature value was specified in GODEBUG
- Enable bool // whether feature should be enabled
-}
-
-// processOptions enables or disables CPU feature values based on the parsed env string.
-// The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2...
-// where feature names is one of the architecture specific list stored in the
-// cpu packages options variable and values are either 'on' or 'off'.
-// If env contains cpu.all=off then all cpu features referenced through the options
-// variable are disabled. Other feature names and values result in warning messages.
-func processOptions(env string) {
-field:
- for env != "" {
- field := ""
- i := indexByte(env, ',')
- if i < 0 {
- field, env = env, ""
- } else {
- field, env = env[:i], env[i+1:]
- }
- if len(field) < 4 || field[:4] != "cpu." {
- continue
- }
- i = indexByte(field, '=')
- if i < 0 {
- print("GODEBUG: no value specified for \"", field, "\"\n")
- continue
- }
- key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on"
-
- var enable bool
- switch value {
- case "on":
- enable = true
- case "off":
- enable = false
- default:
- print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n")
- continue field
- }
-
- if key == "all" {
- for i := range options {
- options[i].Specified = true
- options[i].Enable = enable
- }
- continue field
- }
-
- for i := range options {
- if options[i].Name == key {
- options[i].Specified = true
- options[i].Enable = enable
- continue field
- }
- }
-
- print("GODEBUG: unknown cpu feature \"", key, "\"\n")
- }
-
- for _, o := range options {
- if !o.Specified {
- continue
- }
-
- if o.Enable && !*o.Feature {
- print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n")
- continue
- }
-
- *o.Feature = o.Enable
- }
-}
-
-// indexByte returns the index of the first instance of c in s,
-// or -1 if c is not present in s.
-// indexByte is semantically the same as [strings.IndexByte].
-// We copy this function because "internal/cpu" should not have external dependencies.
-func indexByte(s string, c byte) int {
- for i := 0; i < len(s); i++ {
- if s[i] == c {
- return i
- }
- }
- return -1
-}
diff --git a/contrib/go/_std_1.22/src/internal/cpu/cpu_arm64_darwin.go b/contrib/go/_std_1.22/src/internal/cpu/cpu_arm64_darwin.go
deleted file mode 100644
index 60beadddbb1d..000000000000
--- a/contrib/go/_std_1.22/src/internal/cpu/cpu_arm64_darwin.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2020 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.
-
-//go:build arm64 && darwin && !ios
-
-package cpu
-
-func osInit() {
- ARM64.HasATOMICS = sysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00"))
- ARM64.HasCRC32 = sysctlEnabled([]byte("hw.optional.armv8_crc32\x00"))
- ARM64.HasSHA512 = sysctlEnabled([]byte("hw.optional.armv8_2_sha512\x00"))
-
- // There are no hw.optional sysctl values for the below features on Mac OS 11.0
- // to detect their supported state dynamically. Assume the CPU features that
- // Apple Silicon M1 supports to be available as a minimal set of features
- // to all Go programs running on darwin/arm64.
- ARM64.HasAES = true
- ARM64.HasPMULL = true
- ARM64.HasSHA1 = true
- ARM64.HasSHA2 = true
-}
-
-//go:noescape
-func getsysctlbyname(name []byte) (int32, int32)
-
-func sysctlEnabled(name []byte) bool {
- ret, value := getsysctlbyname(name)
- if ret < 0 {
- return false
- }
- return value > 0
-}
diff --git a/contrib/go/_std_1.22/src/internal/cpu/ya.make b/contrib/go/_std_1.22/src/internal/cpu/ya.make
deleted file mode 100644
index b9d0c3e3a331..000000000000
--- a/contrib/go/_std_1.22/src/internal/cpu/ya.make
+++ /dev/null
@@ -1,29 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- cpu.go
- cpu.s
- cpu_arm64.go
- cpu_arm64.s
- cpu_arm64_darwin.go
- cpu_no_name.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- cpu.go
- cpu.s
- cpu_x86.go
- cpu_x86.s
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- cpu.go
- cpu.s
- cpu_arm64.go
- cpu_arm64.s
- cpu_arm64_hwcap.go
- cpu_arm64_linux.go
- cpu_no_name.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/fmtsort/sort.go b/contrib/go/_std_1.22/src/internal/fmtsort/sort.go
deleted file mode 100644
index 278a89bd75d4..000000000000
--- a/contrib/go/_std_1.22/src/internal/fmtsort/sort.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2018 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.
-
-// Package fmtsort provides a general stable ordering mechanism
-// for maps, on behalf of the fmt and text/template packages.
-// It is not guaranteed to be efficient and works only for types
-// that are valid map keys.
-package fmtsort
-
-import (
- "reflect"
- "sort"
-)
-
-// Note: Throughout this package we avoid calling reflect.Value.Interface as
-// it is not always legal to do so and it's easier to avoid the issue than to face it.
-
-// SortedMap represents a map's keys and values. The keys and values are
-// aligned in index order: Value[i] is the value in the map corresponding to Key[i].
-type SortedMap struct {
- Key []reflect.Value
- Value []reflect.Value
-}
-
-func (o *SortedMap) Len() int { return len(o.Key) }
-func (o *SortedMap) Less(i, j int) bool { return compare(o.Key[i], o.Key[j]) < 0 }
-func (o *SortedMap) Swap(i, j int) {
- o.Key[i], o.Key[j] = o.Key[j], o.Key[i]
- o.Value[i], o.Value[j] = o.Value[j], o.Value[i]
-}
-
-// Sort accepts a map and returns a SortedMap that has the same keys and
-// values but in a stable sorted order according to the keys, modulo issues
-// raised by unorderable key values such as NaNs.
-//
-// The ordering rules are more general than with Go's < operator:
-//
-// - when applicable, nil compares low
-// - ints, floats, and strings order by <
-// - NaN compares less than non-NaN floats
-// - bool compares false before true
-// - complex compares real, then imag
-// - pointers compare by machine address
-// - channel values compare by machine address
-// - structs compare each field in turn
-// - arrays compare each element in turn.
-// Otherwise identical arrays compare by length.
-// - interface values compare first by reflect.Type describing the concrete type
-// and then by concrete value as described in the previous rules.
-func Sort(mapValue reflect.Value) *SortedMap {
- if mapValue.Type().Kind() != reflect.Map {
- return nil
- }
- // Note: this code is arranged to not panic even in the presence
- // of a concurrent map update. The runtime is responsible for
- // yelling loudly if that happens. See issue 33275.
- n := mapValue.Len()
- key := make([]reflect.Value, 0, n)
- value := make([]reflect.Value, 0, n)
- iter := mapValue.MapRange()
- for iter.Next() {
- key = append(key, iter.Key())
- value = append(value, iter.Value())
- }
- sorted := &SortedMap{
- Key: key,
- Value: value,
- }
- sort.Stable(sorted)
- return sorted
-}
-
-// compare compares two values of the same type. It returns -1, 0, 1
-// according to whether a > b (1), a == b (0), or a < b (-1).
-// If the types differ, it returns -1.
-// See the comment on Sort for the comparison rules.
-func compare(aVal, bVal reflect.Value) int {
- aType, bType := aVal.Type(), bVal.Type()
- if aType != bType {
- return -1 // No good answer possible, but don't return 0: they're not equal.
- }
- switch aVal.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- a, b := aVal.Int(), bVal.Int()
- switch {
- case a < b:
- return -1
- case a > b:
- return 1
- default:
- return 0
- }
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- a, b := aVal.Uint(), bVal.Uint()
- switch {
- case a < b:
- return -1
- case a > b:
- return 1
- default:
- return 0
- }
- case reflect.String:
- a, b := aVal.String(), bVal.String()
- switch {
- case a < b:
- return -1
- case a > b:
- return 1
- default:
- return 0
- }
- case reflect.Float32, reflect.Float64:
- return floatCompare(aVal.Float(), bVal.Float())
- case reflect.Complex64, reflect.Complex128:
- a, b := aVal.Complex(), bVal.Complex()
- if c := floatCompare(real(a), real(b)); c != 0 {
- return c
- }
- return floatCompare(imag(a), imag(b))
- case reflect.Bool:
- a, b := aVal.Bool(), bVal.Bool()
- switch {
- case a == b:
- return 0
- case a:
- return 1
- default:
- return -1
- }
- case reflect.Pointer, reflect.UnsafePointer:
- a, b := aVal.Pointer(), bVal.Pointer()
- switch {
- case a < b:
- return -1
- case a > b:
- return 1
- default:
- return 0
- }
- case reflect.Chan:
- if c, ok := nilCompare(aVal, bVal); ok {
- return c
- }
- ap, bp := aVal.Pointer(), bVal.Pointer()
- switch {
- case ap < bp:
- return -1
- case ap > bp:
- return 1
- default:
- return 0
- }
- case reflect.Struct:
- for i := 0; i < aVal.NumField(); i++ {
- if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 {
- return c
- }
- }
- return 0
- case reflect.Array:
- for i := 0; i < aVal.Len(); i++ {
- if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 {
- return c
- }
- }
- return 0
- case reflect.Interface:
- if c, ok := nilCompare(aVal, bVal); ok {
- return c
- }
- c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type()))
- if c != 0 {
- return c
- }
- return compare(aVal.Elem(), bVal.Elem())
- default:
- // Certain types cannot appear as keys (maps, funcs, slices), but be explicit.
- panic("bad type in compare: " + aType.String())
- }
-}
-
-// nilCompare checks whether either value is nil. If not, the boolean is false.
-// If either value is nil, the boolean is true and the integer is the comparison
-// value. The comparison is defined to be 0 if both are nil, otherwise the one
-// nil value compares low. Both arguments must represent a chan, func,
-// interface, map, pointer, or slice.
-func nilCompare(aVal, bVal reflect.Value) (int, bool) {
- if aVal.IsNil() {
- if bVal.IsNil() {
- return 0, true
- }
- return -1, true
- }
- if bVal.IsNil() {
- return 1, true
- }
- return 0, false
-}
-
-// floatCompare compares two floating-point values. NaNs compare low.
-func floatCompare(a, b float64) int {
- switch {
- case isNaN(a):
- return -1 // No good answer if b is a NaN so don't bother checking.
- case isNaN(b):
- return 1
- case a < b:
- return -1
- case a > b:
- return 1
- }
- return 0
-}
-
-func isNaN(a float64) bool {
- return a != a
-}
diff --git a/contrib/go/_std_1.22/src/internal/goarch/ya.make b/contrib/go/_std_1.22/src/internal/goarch/ya.make
deleted file mode 100644
index 53ba46790f9e..000000000000
--- a/contrib/go/_std_1.22/src/internal/goarch/ya.make
+++ /dev/null
@@ -1,15 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- goarch.go
- goarch_arm64.go
- zgoarch_arm64.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- goarch.go
- goarch_amd64.go
- zgoarch_amd64.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/exp_allocheaders_off.go b/contrib/go/_std_1.22/src/internal/goexperiment/exp_allocheaders_off.go
deleted file mode 100644
index 72c702f9e706..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/exp_allocheaders_off.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build !goexperiment.allocheaders
-
-package goexperiment
-
-const AllocHeaders = false
-const AllocHeadersInt = 0
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/exp_allocheaders_on.go b/contrib/go/_std_1.22/src/internal/goexperiment/exp_allocheaders_on.go
deleted file mode 100644
index f9f2965fe2e4..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/exp_allocheaders_on.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build goexperiment.allocheaders
-
-package goexperiment
-
-const AllocHeaders = true
-const AllocHeadersInt = 1
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/exp_exectracer2_off.go b/contrib/go/_std_1.22/src/internal/goexperiment/exp_exectracer2_off.go
deleted file mode 100644
index 2f9c8269d891..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/exp_exectracer2_off.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build !goexperiment.exectracer2
-// +build !goexperiment.exectracer2
-
-package goexperiment
-
-const ExecTracer2 = false
-const ExecTracer2Int = 0
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/exp_exectracer2_on.go b/contrib/go/_std_1.22/src/internal/goexperiment/exp_exectracer2_on.go
deleted file mode 100644
index f94a29247fac..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/exp_exectracer2_on.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build goexperiment.exectracer2
-// +build goexperiment.exectracer2
-
-package goexperiment
-
-const ExecTracer2 = true
-const ExecTracer2Int = 1
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/exp_pagetrace_off.go b/contrib/go/_std_1.22/src/internal/goexperiment/exp_pagetrace_off.go
deleted file mode 100644
index 142be47d963d..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/exp_pagetrace_off.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build !goexperiment.pagetrace
-
-package goexperiment
-
-const PageTrace = false
-const PageTraceInt = 0
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/exp_pagetrace_on.go b/contrib/go/_std_1.22/src/internal/goexperiment/exp_pagetrace_on.go
deleted file mode 100644
index f3b161478901..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/exp_pagetrace_on.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Code generated by mkconsts.go. DO NOT EDIT.
-
-//go:build goexperiment.pagetrace
-
-package goexperiment
-
-const PageTrace = true
-const PageTraceInt = 1
diff --git a/contrib/go/_std_1.22/src/internal/goexperiment/ya.make b/contrib/go/_std_1.22/src/internal/goexperiment/ya.make
deleted file mode 100644
index 1c716226c606..000000000000
--- a/contrib/go/_std_1.22/src/internal/goexperiment/ya.make
+++ /dev/null
@@ -1,24 +0,0 @@
-GO_LIBRARY()
-IF (TRUE)
- SRCS(
- exp_allocheaders_off.go
- exp_arenas_off.go
- exp_boringcrypto_off.go
- exp_cacheprog_off.go
- exp_cgocheck2_off.go
- exp_coverageredesign_off.go
- exp_exectracer2_off.go
- exp_fieldtrack_off.go
- exp_heapminimum512kib_off.go
- exp_loopvar_off.go
- exp_newinliner_off.go
- exp_pagetrace_off.go
- exp_preemptibleloops_off.go
- exp_rangefunc_off.go
- exp_regabiargs_off.go
- exp_regabiwrappers_off.go
- exp_staticlockranking_off.go
- flags.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/goos/ya.make b/contrib/go/_std_1.22/src/internal/goos/ya.make
deleted file mode 100644
index 703feb1fbe86..000000000000
--- a/contrib/go/_std_1.22/src/internal/goos/ya.make
+++ /dev/null
@@ -1,21 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- goos.go
- unix.go
- zgoos_darwin.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- goos.go
- unix.go
- zgoos_linux.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- goos.go
- nonunix.go
- zgoos_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/intern/intern.go b/contrib/go/_std_1.22/src/internal/intern/intern.go
deleted file mode 100644
index 2f97c2e66942..000000000000
--- a/contrib/go/_std_1.22/src/internal/intern/intern.go
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2020 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.
-
-// Package intern lets you make smaller comparable values by boxing
-// a larger comparable value (such as a 16 byte string header) down
-// into a globally unique 8 byte pointer.
-//
-// The globally unique pointers are garbage collected with weak
-// references and finalizers. This package hides that.
-package intern
-
-import (
- "internal/godebug"
- "runtime"
- "sync"
- "unsafe"
-)
-
-// A Value pointer is the handle to an underlying comparable value.
-// See func Get for how Value pointers may be used.
-type Value struct {
- _ [0]func() // prevent people from accidentally using value type as comparable
- cmpVal any
- // resurrected is guarded by mu (for all instances of Value).
- // It is set true whenever v is synthesized from a uintptr.
- resurrected bool
-}
-
-// Get returns the comparable value passed to the Get func
-// that returned v.
-func (v *Value) Get() any { return v.cmpVal }
-
-// key is a key in our global value map.
-// It contains type-specialized fields to avoid allocations
-// when converting common types to empty interfaces.
-type key struct {
- s string
- cmpVal any
- // isString reports whether key contains a string.
- // Without it, the zero value of key is ambiguous.
- isString bool
-}
-
-// keyFor returns a key to use with cmpVal.
-func keyFor(cmpVal any) key {
- if s, ok := cmpVal.(string); ok {
- return key{s: s, isString: true}
- }
- return key{cmpVal: cmpVal}
-}
-
-// Value returns a *Value built from k.
-func (k key) Value() *Value {
- if k.isString {
- return &Value{cmpVal: k.s}
- }
- return &Value{cmpVal: k.cmpVal}
-}
-
-var (
- // mu guards valMap, a weakref map of *Value by underlying value.
- // It also guards the resurrected field of all *Values.
- mu sync.Mutex
- valMap = map[key]uintptr{} // to uintptr(*Value)
- valSafe = safeMap() // non-nil in safe+leaky mode
-)
-
-var intern = godebug.New("#intern")
-
-// safeMap returns a non-nil map if we're in safe-but-leaky mode,
-// as controlled by GODEBUG=intern=leaky
-func safeMap() map[key]*Value {
- if intern.Value() == "leaky" {
- return map[key]*Value{}
- }
- return nil
-}
-
-// Get returns a pointer representing the comparable value cmpVal.
-//
-// The returned pointer will be the same for Get(v) and Get(v2)
-// if and only if v == v2, and can be used as a map key.
-func Get(cmpVal any) *Value {
- return get(keyFor(cmpVal))
-}
-
-// GetByString is identical to Get, except that it is specialized for strings.
-// This avoids an allocation from putting a string into an interface{}
-// to pass as an argument to Get.
-func GetByString(s string) *Value {
- return get(key{s: s, isString: true})
-}
-
-// We play unsafe games that violate Go's rules (and assume a non-moving
-// collector). So we quiet Go here.
-// See the comment below Get for more implementation details.
-//
-//go:nocheckptr
-func get(k key) *Value {
- mu.Lock()
- defer mu.Unlock()
-
- var v *Value
- if valSafe != nil {
- v = valSafe[k]
- } else if addr, ok := valMap[k]; ok {
- v = (*Value)(unsafe.Pointer(addr))
- v.resurrected = true
- }
- if v != nil {
- return v
- }
- v = k.Value()
- if valSafe != nil {
- valSafe[k] = v
- } else {
- // SetFinalizer before uintptr conversion (theoretical concern;
- // see https://github.com/go4org/intern/issues/13)
- runtime.SetFinalizer(v, finalize)
- valMap[k] = uintptr(unsafe.Pointer(v))
- }
- return v
-}
-
-func finalize(v *Value) {
- mu.Lock()
- defer mu.Unlock()
- if v.resurrected {
- // We lost the race. Somebody resurrected it while we
- // were about to finalize it. Try again next round.
- v.resurrected = false
- runtime.SetFinalizer(v, finalize)
- return
- }
- delete(valMap, keyFor(v.cmpVal))
-}
-
-// Interning is simple if you don't require that unused values be
-// garbage collectable. But we do require that; we don't want to be
-// DOS vector. We do this by using a uintptr to hide the pointer from
-// the garbage collector, and using a finalizer to eliminate the
-// pointer when no other code is using it.
-//
-// The obvious implementation of this is to use a
-// map[interface{}]uintptr-of-*interface{}, and set up a finalizer to
-// delete from the map. Unfortunately, this is racy. Because pointers
-// are being created in violation of Go's unsafety rules, it's
-// possible to create a pointer to a value concurrently with the GC
-// concluding that the value can be collected. There are other races
-// that break the equality invariant as well, but the use-after-free
-// will cause a runtime crash.
-//
-// To make this work, the finalizer needs to know that no references
-// have been unsafely created since the finalizer was set up. To do
-// this, values carry a "resurrected" sentinel, which gets set
-// whenever a pointer is unsafely created. If the finalizer encounters
-// the sentinel, it clears the sentinel and delays collection for one
-// additional GC cycle, by re-installing itself as finalizer. This
-// ensures that the unsafely created pointer is visible to the GC, and
-// will correctly prevent collection.
-//
-// This technique does mean that interned values that get reused take
-// at least 3 GC cycles to fully collect (1 to clear the sentinel, 1
-// to clean up the unsafe map, 1 to be actually deleted).
-//
-// @ianlancetaylor commented in
-// https://github.com/golang/go/issues/41303#issuecomment-717401656
-// that it is possible to implement weak references in terms of
-// finalizers without unsafe. Unfortunately, the approach he outlined
-// does not work here, for two reasons. First, there is no way to
-// construct a strong pointer out of a weak pointer; our map stores
-// weak pointers, but we must return strong pointers to callers.
-// Second, and more fundamentally, we must return not just _a_ strong
-// pointer to callers, but _the same_ strong pointer to callers. In
-// order to return _the same_ strong pointer to callers, we must track
-// it, which is exactly what we cannot do with strong pointers.
-//
-// See https://github.com/inetaf/netaddr/issues/53 for more
-// discussion, and https://github.com/go4org/intern/issues/2 for an
-// illustration of the subtleties at play.
diff --git a/contrib/go/_std_1.22/src/internal/intern/ya.make b/contrib/go/_std_1.22/src/internal/intern/ya.make
deleted file mode 100644
index 2aa90abdbac8..000000000000
--- a/contrib/go/_std_1.22/src/internal/intern/ya.make
+++ /dev/null
@@ -1,7 +0,0 @@
-GO_LIBRARY()
-IF (TRUE)
- SRCS(
- intern.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/poll/fd_fsync_darwin.go b/contrib/go/_std_1.22/src/internal/poll/fd_fsync_darwin.go
deleted file mode 100644
index 731b7fd5bd65..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/fd_fsync_darwin.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 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.
-
-package poll
-
-import (
- "internal/syscall/unix"
- "syscall"
-)
-
-// Fsync invokes SYS_FCNTL with SYS_FULLFSYNC because
-// on OS X, SYS_FSYNC doesn't fully flush contents to disk.
-// See Issue #26650 as well as the man page for fsync on OS X.
-func (fd *FD) Fsync() error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
- return ignoringEINTR(func() error {
- _, err := unix.Fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
- return err
- })
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/fd_windows.go b/contrib/go/_std_1.22/src/internal/poll/fd_windows.go
deleted file mode 100644
index 2095a6aa2927..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/fd_windows.go
+++ /dev/null
@@ -1,1331 +0,0 @@
-// Copyright 2017 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.
-
-package poll
-
-import (
- "errors"
- "internal/race"
- "internal/syscall/windows"
- "io"
- "sync"
- "syscall"
- "unicode/utf16"
- "unicode/utf8"
- "unsafe"
-)
-
-var (
- initErr error
- ioSync uint64
-)
-
-// This package uses the SetFileCompletionNotificationModes Windows
-// API to skip calling GetQueuedCompletionStatus if an IO operation
-// completes synchronously. There is a known bug where
-// SetFileCompletionNotificationModes crashes on some systems (see
-// https://support.microsoft.com/kb/2568167 for details).
-
-var useSetFileCompletionNotificationModes bool // determines is SetFileCompletionNotificationModes is present and safe to use
-
-// checkSetFileCompletionNotificationModes verifies that
-// SetFileCompletionNotificationModes Windows API is present
-// on the system and is safe to use.
-// See https://support.microsoft.com/kb/2568167 for details.
-func checkSetFileCompletionNotificationModes() {
- err := syscall.LoadSetFileCompletionNotificationModes()
- if err != nil {
- return
- }
- protos := [2]int32{syscall.IPPROTO_TCP, 0}
- var buf [32]syscall.WSAProtocolInfo
- len := uint32(unsafe.Sizeof(buf))
- n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
- if err != nil {
- return
- }
- for i := int32(0); i < n; i++ {
- if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
- return
- }
- }
- useSetFileCompletionNotificationModes = true
-}
-
-func init() {
- var d syscall.WSAData
- e := syscall.WSAStartup(uint32(0x202), &d)
- if e != nil {
- initErr = e
- }
- checkSetFileCompletionNotificationModes()
-}
-
-// operation contains superset of data necessary to perform all async IO.
-type operation struct {
- // Used by IOCP interface, it must be first field
- // of the struct, as our code rely on it.
- o syscall.Overlapped
-
- // fields used by runtime.netpoll
- runtimeCtx uintptr
- mode int32
- errno int32
- qty uint32
-
- // fields used only by net package
- fd *FD
- buf syscall.WSABuf
- msg windows.WSAMsg
- sa syscall.Sockaddr
- rsa *syscall.RawSockaddrAny
- rsan int32
- handle syscall.Handle
- flags uint32
- bufs []syscall.WSABuf
-}
-
-func (o *operation) InitBuf(buf []byte) {
- o.buf.Len = uint32(len(buf))
- o.buf.Buf = nil
- if len(buf) != 0 {
- o.buf.Buf = &buf[0]
- }
-}
-
-func (o *operation) InitBufs(buf *[][]byte) {
- if o.bufs == nil {
- o.bufs = make([]syscall.WSABuf, 0, len(*buf))
- } else {
- o.bufs = o.bufs[:0]
- }
- for _, b := range *buf {
- if len(b) == 0 {
- o.bufs = append(o.bufs, syscall.WSABuf{})
- continue
- }
- for len(b) > maxRW {
- o.bufs = append(o.bufs, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
- b = b[maxRW:]
- }
- if len(b) > 0 {
- o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
- }
- }
-}
-
-// ClearBufs clears all pointers to Buffers parameter captured
-// by InitBufs, so it can be released by garbage collector.
-func (o *operation) ClearBufs() {
- for i := range o.bufs {
- o.bufs[i].Buf = nil
- }
- o.bufs = o.bufs[:0]
-}
-
-func (o *operation) InitMsg(p []byte, oob []byte) {
- o.InitBuf(p)
- o.msg.Buffers = &o.buf
- o.msg.BufferCount = 1
-
- o.msg.Name = nil
- o.msg.Namelen = 0
-
- o.msg.Flags = 0
- o.msg.Control.Len = uint32(len(oob))
- o.msg.Control.Buf = nil
- if len(oob) != 0 {
- o.msg.Control.Buf = &oob[0]
- }
-}
-
-// execIO executes a single IO operation o. It submits and cancels
-// IO in the current thread for systems where Windows CancelIoEx API
-// is available. Alternatively, it passes the request onto
-// runtime netpoll and waits for completion or cancels request.
-func execIO(o *operation, submit func(o *operation) error) (int, error) {
- if o.fd.pd.runtimeCtx == 0 {
- return 0, errors.New("internal error: polling on unsupported descriptor type")
- }
-
- fd := o.fd
- // Notify runtime netpoll about starting IO.
- err := fd.pd.prepare(int(o.mode), fd.isFile)
- if err != nil {
- return 0, err
- }
- // Start IO.
- err = submit(o)
- switch err {
- case nil:
- // IO completed immediately
- if o.fd.skipSyncNotif {
- // No completion message will follow, so return immediately.
- return int(o.qty), nil
- }
- // Need to get our completion message anyway.
- case syscall.ERROR_IO_PENDING:
- // IO started, and we have to wait for its completion.
- err = nil
- default:
- return 0, err
- }
- // Wait for our request to complete.
- err = fd.pd.wait(int(o.mode), fd.isFile)
- if err == nil {
- // All is good. Extract our IO results and return.
- if o.errno != 0 {
- err = syscall.Errno(o.errno)
- // More data available. Return back the size of received data.
- if err == syscall.ERROR_MORE_DATA || err == windows.WSAEMSGSIZE {
- return int(o.qty), err
- }
- return 0, err
- }
- return int(o.qty), nil
- }
- // IO is interrupted by "close" or "timeout"
- netpollErr := err
- switch netpollErr {
- case ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
- // will deal with those.
- default:
- panic("unexpected runtime.netpoll error: " + netpollErr.Error())
- }
- // Cancel our request.
- err = syscall.CancelIoEx(fd.Sysfd, &o.o)
- // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
- if err != nil && err != syscall.ERROR_NOT_FOUND {
- // TODO(brainman): maybe do something else, but panic.
- panic(err)
- }
- // Wait for cancellation to complete.
- fd.pd.waitCanceled(int(o.mode))
- if o.errno != 0 {
- err = syscall.Errno(o.errno)
- if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
- err = netpollErr
- }
- return 0, err
- }
- // We issued a cancellation request. But, it seems, IO operation succeeded
- // before the cancellation request run. We need to treat the IO operation as
- // succeeded (the bytes are actually sent/recv from network).
- return int(o.qty), nil
-}
-
-// FD is a file descriptor. The net and os packages embed this type in
-// a larger type representing a network connection or OS file.
-type FD struct {
- // Lock sysfd and serialize access to Read and Write methods.
- fdmu fdMutex
-
- // System file descriptor. Immutable until Close.
- Sysfd syscall.Handle
-
- // Read operation.
- rop operation
- // Write operation.
- wop operation
-
- // I/O poller.
- pd pollDesc
-
- // Used to implement pread/pwrite.
- l sync.Mutex
-
- // For console I/O.
- lastbits []byte // first few bytes of the last incomplete rune in last write
- readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole
- readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8
- readbyteOffset int // readbyte[readOffset:] is yet to be consumed with file.Read
-
- // Semaphore signaled when file is closed.
- csema uint32
-
- skipSyncNotif bool
-
- // Whether this is a streaming descriptor, as opposed to a
- // packet-based descriptor like a UDP socket.
- IsStream bool
-
- // Whether a zero byte read indicates EOF. This is false for a
- // message based socket connection.
- ZeroReadIsEOF bool
-
- // Whether this is a file rather than a network socket.
- isFile bool
-
- // The kind of this file.
- kind fileKind
-}
-
-// fileKind describes the kind of file.
-type fileKind byte
-
-const (
- kindNet fileKind = iota
- kindFile
- kindConsole
- kindPipe
-)
-
-// logInitFD is set by tests to enable file descriptor initialization logging.
-var logInitFD func(net string, fd *FD, err error)
-
-// Init initializes the FD. The Sysfd field should already be set.
-// This can be called multiple times on a single FD.
-// The net argument is a network name from the net package (e.g., "tcp"),
-// or "file" or "console" or "dir".
-// Set pollable to true if fd should be managed by runtime netpoll.
-func (fd *FD) Init(net string, pollable bool) (string, error) {
- if initErr != nil {
- return "", initErr
- }
-
- switch net {
- case "file", "dir":
- fd.kind = kindFile
- case "console":
- fd.kind = kindConsole
- case "pipe":
- fd.kind = kindPipe
- case "tcp", "tcp4", "tcp6",
- "udp", "udp4", "udp6",
- "ip", "ip4", "ip6",
- "unix", "unixgram", "unixpacket":
- fd.kind = kindNet
- default:
- return "", errors.New("internal error: unknown network type " + net)
- }
- fd.isFile = fd.kind != kindNet
-
- var err error
- if pollable {
- // Only call init for a network socket.
- // This means that we don't add files to the runtime poller.
- // Adding files to the runtime poller can confuse matters
- // if the user is doing their own overlapped I/O.
- // See issue #21172.
- //
- // In general the code below avoids calling the execIO
- // function for non-network sockets. If some method does
- // somehow call execIO, then execIO, and therefore the
- // calling method, will return an error, because
- // fd.pd.runtimeCtx will be 0.
- err = fd.pd.init(fd)
- }
- if logInitFD != nil {
- logInitFD(net, fd, err)
- }
- if err != nil {
- return "", err
- }
- if pollable && useSetFileCompletionNotificationModes {
- // We do not use events, so we can skip them always.
- flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
- switch net {
- case "tcp", "tcp4", "tcp6",
- "udp", "udp4", "udp6":
- flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
- }
- err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, flags)
- if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
- fd.skipSyncNotif = true
- }
- }
- // Disable SIO_UDP_CONNRESET behavior.
- // http://support.microsoft.com/kb/263823
- switch net {
- case "udp", "udp4", "udp6":
- ret := uint32(0)
- flag := uint32(0)
- size := uint32(unsafe.Sizeof(flag))
- err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
- if err != nil {
- return "wsaioctl", err
- }
- }
- fd.rop.mode = 'r'
- fd.wop.mode = 'w'
- fd.rop.fd = fd
- fd.wop.fd = fd
- fd.rop.runtimeCtx = fd.pd.runtimeCtx
- fd.wop.runtimeCtx = fd.pd.runtimeCtx
- return "", nil
-}
-
-func (fd *FD) destroy() error {
- if fd.Sysfd == syscall.InvalidHandle {
- return syscall.EINVAL
- }
- // Poller may want to unregister fd in readiness notification mechanism,
- // so this must be executed before fd.CloseFunc.
- fd.pd.close()
- var err error
- switch fd.kind {
- case kindNet:
- // The net package uses the CloseFunc variable for testing.
- err = CloseFunc(fd.Sysfd)
- default:
- err = syscall.CloseHandle(fd.Sysfd)
- }
- fd.Sysfd = syscall.InvalidHandle
- runtime_Semrelease(&fd.csema)
- return err
-}
-
-// Close closes the FD. The underlying file descriptor is closed by
-// the destroy method when there are no remaining references.
-func (fd *FD) Close() error {
- if !fd.fdmu.increfAndClose() {
- return errClosing(fd.isFile)
- }
- if fd.kind == kindPipe {
- syscall.CancelIoEx(fd.Sysfd, nil)
- }
- // unblock pending reader and writer
- fd.pd.evict()
- err := fd.decref()
- // Wait until the descriptor is closed. If this was the only
- // reference, it is already closed.
- runtime_Semacquire(&fd.csema)
- return err
-}
-
-// Windows ReadFile and WSARecv use DWORD (uint32) parameter to pass buffer length.
-// This prevents us reading blocks larger than 4GB.
-// See golang.org/issue/26923.
-const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned
-
-// Read implements io.Reader.
-func (fd *FD) Read(buf []byte) (int, error) {
- if err := fd.readLock(); err != nil {
- return 0, err
- }
- defer fd.readUnlock()
-
- if len(buf) > maxRW {
- buf = buf[:maxRW]
- }
-
- var n int
- var err error
- if fd.isFile {
- fd.l.Lock()
- defer fd.l.Unlock()
- switch fd.kind {
- case kindConsole:
- n, err = fd.readConsole(buf)
- default:
- n, err = syscall.Read(fd.Sysfd, buf)
- if fd.kind == kindPipe && err == syscall.ERROR_OPERATION_ABORTED {
- // Close uses CancelIoEx to interrupt concurrent I/O for pipes.
- // If the fd is a pipe and the Read was interrupted by CancelIoEx,
- // we assume it is interrupted by Close.
- err = ErrFileClosing
- }
- }
- if err != nil {
- n = 0
- }
- } else {
- o := &fd.rop
- o.InitBuf(buf)
- n, err = execIO(o, func(o *operation) error {
- return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
- })
- if race.Enabled {
- race.Acquire(unsafe.Pointer(&ioSync))
- }
- }
- if len(buf) != 0 {
- err = fd.eofError(n, err)
- }
- return n, err
-}
-
-var ReadConsole = syscall.ReadConsole // changed for testing
-
-// readConsole reads utf16 characters from console File,
-// encodes them into utf8 and stores them in buffer b.
-// It returns the number of utf8 bytes read and an error, if any.
-func (fd *FD) readConsole(b []byte) (int, error) {
- if len(b) == 0 {
- return 0, nil
- }
-
- if fd.readuint16 == nil {
- // Note: syscall.ReadConsole fails for very large buffers.
- // The limit is somewhere around (but not exactly) 16384.
- // Stay well below.
- fd.readuint16 = make([]uint16, 0, 10000)
- fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16))
- }
-
- for fd.readbyteOffset >= len(fd.readbyte) {
- n := cap(fd.readuint16) - len(fd.readuint16)
- if n > len(b) {
- n = len(b)
- }
- var nw uint32
- err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil)
- if err != nil {
- return 0, err
- }
- uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)]
- fd.readuint16 = fd.readuint16[:0]
- buf := fd.readbyte[:0]
- for i := 0; i < len(uint16s); i++ {
- r := rune(uint16s[i])
- if utf16.IsSurrogate(r) {
- if i+1 == len(uint16s) {
- if nw > 0 {
- // Save half surrogate pair for next time.
- fd.readuint16 = fd.readuint16[:1]
- fd.readuint16[0] = uint16(r)
- break
- }
- r = utf8.RuneError
- } else {
- r = utf16.DecodeRune(r, rune(uint16s[i+1]))
- if r != utf8.RuneError {
- i++
- }
- }
- }
- buf = utf8.AppendRune(buf, r)
- }
- fd.readbyte = buf
- fd.readbyteOffset = 0
- if nw == 0 {
- break
- }
- }
-
- src := fd.readbyte[fd.readbyteOffset:]
- var i int
- for i = 0; i < len(src) && i < len(b); i++ {
- x := src[i]
- if x == 0x1A { // Ctrl-Z
- if i == 0 {
- fd.readbyteOffset++
- }
- break
- }
- b[i] = x
- }
- fd.readbyteOffset += i
- return i, nil
-}
-
-// Pread emulates the Unix pread system call.
-func (fd *FD) Pread(b []byte, off int64) (int, error) {
- if fd.kind == kindPipe {
- // Pread does not work with pipes
- return 0, syscall.ESPIPE
- }
- // Call incref, not readLock, because since pread specifies the
- // offset it is independent from other reads.
- if err := fd.incref(); err != nil {
- return 0, err
- }
- defer fd.decref()
-
- if len(b) > maxRW {
- b = b[:maxRW]
- }
-
- fd.l.Lock()
- defer fd.l.Unlock()
- curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
- if e != nil {
- return 0, e
- }
- defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
- o := syscall.Overlapped{
- OffsetHigh: uint32(off >> 32),
- Offset: uint32(off),
- }
- var done uint32
- e = syscall.ReadFile(fd.Sysfd, b, &done, &o)
- if e != nil {
- done = 0
- if e == syscall.ERROR_HANDLE_EOF {
- e = io.EOF
- }
- }
- if len(b) != 0 {
- e = fd.eofError(int(done), e)
- }
- return int(done), e
-}
-
-// ReadFrom wraps the recvfrom network call.
-func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
- if len(buf) == 0 {
- return 0, nil, nil
- }
- if len(buf) > maxRW {
- buf = buf[:maxRW]
- }
- if err := fd.readLock(); err != nil {
- return 0, nil, err
- }
- defer fd.readUnlock()
- o := &fd.rop
- o.InitBuf(buf)
- n, err := execIO(o, func(o *operation) error {
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- o.rsan = int32(unsafe.Sizeof(*o.rsa))
- return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
- })
- err = fd.eofError(n, err)
- if err != nil {
- return n, nil, err
- }
- sa, _ := o.rsa.Sockaddr()
- return n, sa, nil
-}
-
-// ReadFromInet4 wraps the recvfrom network call for IPv4.
-func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
- if len(buf) == 0 {
- return 0, nil
- }
- if len(buf) > maxRW {
- buf = buf[:maxRW]
- }
- if err := fd.readLock(); err != nil {
- return 0, err
- }
- defer fd.readUnlock()
- o := &fd.rop
- o.InitBuf(buf)
- n, err := execIO(o, func(o *operation) error {
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- o.rsan = int32(unsafe.Sizeof(*o.rsa))
- return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
- })
- err = fd.eofError(n, err)
- if err != nil {
- return n, err
- }
- rawToSockaddrInet4(o.rsa, sa4)
- return n, err
-}
-
-// ReadFromInet6 wraps the recvfrom network call for IPv6.
-func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
- if len(buf) == 0 {
- return 0, nil
- }
- if len(buf) > maxRW {
- buf = buf[:maxRW]
- }
- if err := fd.readLock(); err != nil {
- return 0, err
- }
- defer fd.readUnlock()
- o := &fd.rop
- o.InitBuf(buf)
- n, err := execIO(o, func(o *operation) error {
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- o.rsan = int32(unsafe.Sizeof(*o.rsa))
- return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
- })
- err = fd.eofError(n, err)
- if err != nil {
- return n, err
- }
- rawToSockaddrInet6(o.rsa, sa6)
- return n, err
-}
-
-// Write implements io.Writer.
-func (fd *FD) Write(buf []byte) (int, error) {
- if err := fd.writeLock(); err != nil {
- return 0, err
- }
- defer fd.writeUnlock()
- if fd.isFile {
- fd.l.Lock()
- defer fd.l.Unlock()
- }
-
- ntotal := 0
- for len(buf) > 0 {
- b := buf
- if len(b) > maxRW {
- b = b[:maxRW]
- }
- var n int
- var err error
- if fd.isFile {
- switch fd.kind {
- case kindConsole:
- n, err = fd.writeConsole(b)
- default:
- n, err = syscall.Write(fd.Sysfd, b)
- if fd.kind == kindPipe && err == syscall.ERROR_OPERATION_ABORTED {
- // Close uses CancelIoEx to interrupt concurrent I/O for pipes.
- // If the fd is a pipe and the Write was interrupted by CancelIoEx,
- // we assume it is interrupted by Close.
- err = ErrFileClosing
- }
- }
- if err != nil {
- n = 0
- }
- } else {
- if race.Enabled {
- race.ReleaseMerge(unsafe.Pointer(&ioSync))
- }
- o := &fd.wop
- o.InitBuf(b)
- n, err = execIO(o, func(o *operation) error {
- return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
- })
- }
- ntotal += n
- if err != nil {
- return ntotal, err
- }
- buf = buf[n:]
- }
- return ntotal, nil
-}
-
-// writeConsole writes len(b) bytes to the console File.
-// It returns the number of bytes written and an error, if any.
-func (fd *FD) writeConsole(b []byte) (int, error) {
- n := len(b)
- runes := make([]rune, 0, 256)
- if len(fd.lastbits) > 0 {
- b = append(fd.lastbits, b...)
- fd.lastbits = nil
-
- }
- for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
- r, l := utf8.DecodeRune(b)
- runes = append(runes, r)
- b = b[l:]
- }
- if len(b) > 0 {
- fd.lastbits = make([]byte, len(b))
- copy(fd.lastbits, b)
- }
- // syscall.WriteConsole seems to fail, if given large buffer.
- // So limit the buffer to 16000 characters. This number was
- // discovered by experimenting with syscall.WriteConsole.
- const maxWrite = 16000
- for len(runes) > 0 {
- m := len(runes)
- if m > maxWrite {
- m = maxWrite
- }
- chunk := runes[:m]
- runes = runes[m:]
- uint16s := utf16.Encode(chunk)
- for len(uint16s) > 0 {
- var written uint32
- err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil)
- if err != nil {
- return 0, err
- }
- uint16s = uint16s[written:]
- }
- }
- return n, nil
-}
-
-// Pwrite emulates the Unix pwrite system call.
-func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
- if fd.kind == kindPipe {
- // Pwrite does not work with pipes
- return 0, syscall.ESPIPE
- }
- // Call incref, not writeLock, because since pwrite specifies the
- // offset it is independent from other writes.
- if err := fd.incref(); err != nil {
- return 0, err
- }
- defer fd.decref()
-
- fd.l.Lock()
- defer fd.l.Unlock()
- curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
- if e != nil {
- return 0, e
- }
- defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
-
- ntotal := 0
- for len(buf) > 0 {
- b := buf
- if len(b) > maxRW {
- b = b[:maxRW]
- }
- var n uint32
- o := syscall.Overlapped{
- OffsetHigh: uint32(off >> 32),
- Offset: uint32(off),
- }
- e = syscall.WriteFile(fd.Sysfd, b, &n, &o)
- ntotal += int(n)
- if e != nil {
- return ntotal, e
- }
- buf = buf[n:]
- off += int64(n)
- }
- return ntotal, nil
-}
-
-// Writev emulates the Unix writev system call.
-func (fd *FD) Writev(buf *[][]byte) (int64, error) {
- if len(*buf) == 0 {
- return 0, nil
- }
- if err := fd.writeLock(); err != nil {
- return 0, err
- }
- defer fd.writeUnlock()
- if race.Enabled {
- race.ReleaseMerge(unsafe.Pointer(&ioSync))
- }
- o := &fd.wop
- o.InitBufs(buf)
- n, err := execIO(o, func(o *operation) error {
- return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(o.bufs)), &o.qty, 0, &o.o, nil)
- })
- o.ClearBufs()
- TestHookDidWritev(n)
- consume(buf, int64(n))
- return int64(n), err
-}
-
-// WriteTo wraps the sendto network call.
-func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
- if err := fd.writeLock(); err != nil {
- return 0, err
- }
- defer fd.writeUnlock()
-
- if len(buf) == 0 {
- // handle zero-byte payload
- o := &fd.wop
- o.InitBuf(buf)
- o.sa = sa
- n, err := execIO(o, func(o *operation) error {
- return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
- })
- return n, err
- }
-
- ntotal := 0
- for len(buf) > 0 {
- b := buf
- if len(b) > maxRW {
- b = b[:maxRW]
- }
- o := &fd.wop
- o.InitBuf(b)
- o.sa = sa
- n, err := execIO(o, func(o *operation) error {
- return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
- })
- ntotal += int(n)
- if err != nil {
- return ntotal, err
- }
- buf = buf[n:]
- }
- return ntotal, nil
-}
-
-// WriteToInet4 is WriteTo, specialized for syscall.SockaddrInet4.
-func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
- if err := fd.writeLock(); err != nil {
- return 0, err
- }
- defer fd.writeUnlock()
-
- if len(buf) == 0 {
- // handle zero-byte payload
- o := &fd.wop
- o.InitBuf(buf)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil)
- })
- return n, err
- }
-
- ntotal := 0
- for len(buf) > 0 {
- b := buf
- if len(b) > maxRW {
- b = b[:maxRW]
- }
- o := &fd.wop
- o.InitBuf(b)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa4, &o.o, nil)
- })
- ntotal += int(n)
- if err != nil {
- return ntotal, err
- }
- buf = buf[n:]
- }
- return ntotal, nil
-}
-
-// WriteToInet6 is WriteTo, specialized for syscall.SockaddrInet6.
-func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
- if err := fd.writeLock(); err != nil {
- return 0, err
- }
- defer fd.writeUnlock()
-
- if len(buf) == 0 {
- // handle zero-byte payload
- o := &fd.wop
- o.InitBuf(buf)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil)
- })
- return n, err
- }
-
- ntotal := 0
- for len(buf) > 0 {
- b := buf
- if len(b) > maxRW {
- b = b[:maxRW]
- }
- o := &fd.wop
- o.InitBuf(b)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendtoInet6(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, sa6, &o.o, nil)
- })
- ntotal += int(n)
- if err != nil {
- return ntotal, err
- }
- buf = buf[n:]
- }
- return ntotal, nil
-}
-
-// Call ConnectEx. This doesn't need any locking, since it is only
-// called when the descriptor is first created. This is here rather
-// than in the net package so that it can use fd.wop.
-func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
- o := &fd.wop
- o.sa = ra
- _, err := execIO(o, func(o *operation) error {
- return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o)
- })
- return err
-}
-
-func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) {
- // Submit accept request.
- o.handle = s
- o.rsan = int32(unsafe.Sizeof(rawsa[0]))
- _, err := execIO(o, func(o *operation) error {
- return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
- })
- if err != nil {
- CloseFunc(s)
- return "acceptex", err
- }
-
- // Inherit properties of the listening socket.
- err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd)))
- if err != nil {
- CloseFunc(s)
- return "setsockopt", err
- }
-
- return "", nil
-}
-
-// Accept handles accepting a socket. The sysSocket parameter is used
-// to allocate the net socket.
-func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) {
- if err := fd.readLock(); err != nil {
- return syscall.InvalidHandle, nil, 0, "", err
- }
- defer fd.readUnlock()
-
- o := &fd.rop
- var rawsa [2]syscall.RawSockaddrAny
- for {
- s, err := sysSocket()
- if err != nil {
- return syscall.InvalidHandle, nil, 0, "", err
- }
-
- errcall, err := fd.acceptOne(s, rawsa[:], o)
- if err == nil {
- return s, rawsa[:], uint32(o.rsan), "", nil
- }
-
- // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
- // returned here. These happen if connection reset is received
- // before AcceptEx could complete. These errors relate to new
- // connection, not to AcceptEx, so ignore broken connection and
- // try AcceptEx again for more connections.
- errno, ok := err.(syscall.Errno)
- if !ok {
- return syscall.InvalidHandle, nil, 0, errcall, err
- }
- switch errno {
- case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
- // ignore these and try again
- default:
- return syscall.InvalidHandle, nil, 0, errcall, err
- }
- }
-}
-
-// Seek wraps syscall.Seek.
-func (fd *FD) Seek(offset int64, whence int) (int64, error) {
- if fd.kind == kindPipe {
- return 0, syscall.ESPIPE
- }
- if err := fd.incref(); err != nil {
- return 0, err
- }
- defer fd.decref()
-
- fd.l.Lock()
- defer fd.l.Unlock()
-
- return syscall.Seek(fd.Sysfd, offset, whence)
-}
-
-// Fchmod updates syscall.ByHandleFileInformation.Fileattributes when needed.
-func (fd *FD) Fchmod(mode uint32) error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
-
- var d syscall.ByHandleFileInformation
- if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
- return err
- }
- attrs := d.FileAttributes
- if mode&syscall.S_IWRITE != 0 {
- attrs &^= syscall.FILE_ATTRIBUTE_READONLY
- } else {
- attrs |= syscall.FILE_ATTRIBUTE_READONLY
- }
- if attrs == d.FileAttributes {
- return nil
- }
-
- var du windows.FILE_BASIC_INFO
- du.FileAttributes = attrs
- return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, unsafe.Pointer(&du), uint32(unsafe.Sizeof(du)))
-}
-
-// Fchdir wraps syscall.Fchdir.
-func (fd *FD) Fchdir() error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
- return syscall.Fchdir(fd.Sysfd)
-}
-
-// GetFileType wraps syscall.GetFileType.
-func (fd *FD) GetFileType() (uint32, error) {
- if err := fd.incref(); err != nil {
- return 0, err
- }
- defer fd.decref()
- return syscall.GetFileType(fd.Sysfd)
-}
-
-// GetFileInformationByHandle wraps GetFileInformationByHandle.
-func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error {
- if err := fd.incref(); err != nil {
- return err
- }
- defer fd.decref()
- return syscall.GetFileInformationByHandle(fd.Sysfd, data)
-}
-
-// RawRead invokes the user-defined function f for a read operation.
-func (fd *FD) RawRead(f func(uintptr) bool) error {
- if err := fd.readLock(); err != nil {
- return err
- }
- defer fd.readUnlock()
- for {
- if f(uintptr(fd.Sysfd)) {
- return nil
- }
-
- // Use a zero-byte read as a way to get notified when this
- // socket is readable. h/t https://stackoverflow.com/a/42019668/332798
- o := &fd.rop
- o.InitBuf(nil)
- if !fd.IsStream {
- o.flags |= windows.MSG_PEEK
- }
- _, err := execIO(o, func(o *operation) error {
- return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
- })
- if err == windows.WSAEMSGSIZE {
- // expected with a 0-byte peek, ignore.
- } else if err != nil {
- return err
- }
- }
-}
-
-// RawWrite invokes the user-defined function f for a write operation.
-func (fd *FD) RawWrite(f func(uintptr) bool) error {
- if err := fd.writeLock(); err != nil {
- return err
- }
- defer fd.writeUnlock()
-
- if f(uintptr(fd.Sysfd)) {
- return nil
- }
-
- // TODO(tmm1): find a way to detect socket writability
- return syscall.EWINDOWS
-}
-
-func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 {
- *rsa = syscall.RawSockaddrAny{}
- raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
- raw.Family = syscall.AF_INET
- p := (*[2]byte)(unsafe.Pointer(&raw.Port))
- p[0] = byte(sa.Port >> 8)
- p[1] = byte(sa.Port)
- raw.Addr = sa.Addr
- return int32(unsafe.Sizeof(*raw))
-}
-
-func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 {
- *rsa = syscall.RawSockaddrAny{}
- raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
- raw.Family = syscall.AF_INET6
- p := (*[2]byte)(unsafe.Pointer(&raw.Port))
- p[0] = byte(sa.Port >> 8)
- p[1] = byte(sa.Port)
- raw.Scope_id = sa.ZoneId
- raw.Addr = sa.Addr
- return int32(unsafe.Sizeof(*raw))
-}
-
-func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) {
- pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
- p := (*[2]byte)(unsafe.Pointer(&pp.Port))
- sa.Port = int(p[0])<<8 + int(p[1])
- sa.Addr = pp.Addr
-}
-
-func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) {
- pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
- p := (*[2]byte)(unsafe.Pointer(&pp.Port))
- sa.Port = int(p[0])<<8 + int(p[1])
- sa.ZoneId = pp.Scope_id
- sa.Addr = pp.Addr
-}
-
-func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) {
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- sz := sockaddrInet4ToRaw(rsa, sa)
- return sz, nil
- case *syscall.SockaddrInet6:
- sz := sockaddrInet6ToRaw(rsa, sa)
- return sz, nil
- default:
- return 0, syscall.EWINDOWS
- }
-}
-
-// ReadMsg wraps the WSARecvMsg network call.
-func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
- if err := fd.readLock(); err != nil {
- return 0, 0, 0, nil, err
- }
- defer fd.readUnlock()
-
- if len(p) > maxRW {
- p = p[:maxRW]
- }
-
- o := &fd.rop
- o.InitMsg(p, oob)
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
- o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
- o.msg.Flags = uint32(flags)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
- })
- err = fd.eofError(n, err)
- var sa syscall.Sockaddr
- if err == nil {
- sa, err = o.rsa.Sockaddr()
- }
- return n, int(o.msg.Control.Len), int(o.msg.Flags), sa, err
-}
-
-// ReadMsgInet4 is ReadMsg, but specialized to return a syscall.SockaddrInet4.
-func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
- if err := fd.readLock(); err != nil {
- return 0, 0, 0, err
- }
- defer fd.readUnlock()
-
- if len(p) > maxRW {
- p = p[:maxRW]
- }
-
- o := &fd.rop
- o.InitMsg(p, oob)
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
- o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
- o.msg.Flags = uint32(flags)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
- })
- err = fd.eofError(n, err)
- if err == nil {
- rawToSockaddrInet4(o.rsa, sa4)
- }
- return n, int(o.msg.Control.Len), int(o.msg.Flags), err
-}
-
-// ReadMsgInet6 is ReadMsg, but specialized to return a syscall.SockaddrInet6.
-func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
- if err := fd.readLock(); err != nil {
- return 0, 0, 0, err
- }
- defer fd.readUnlock()
-
- if len(p) > maxRW {
- p = p[:maxRW]
- }
-
- o := &fd.rop
- o.InitMsg(p, oob)
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
- o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
- o.msg.Flags = uint32(flags)
- n, err := execIO(o, func(o *operation) error {
- return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
- })
- err = fd.eofError(n, err)
- if err == nil {
- rawToSockaddrInet6(o.rsa, sa6)
- }
- return n, int(o.msg.Control.Len), int(o.msg.Flags), err
-}
-
-// WriteMsg wraps the WSASendMsg network call.
-func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
- if len(p) > maxRW {
- return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
- }
-
- if err := fd.writeLock(); err != nil {
- return 0, 0, err
- }
- defer fd.writeUnlock()
-
- o := &fd.wop
- o.InitMsg(p, oob)
- if sa != nil {
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- len, err := sockaddrToRaw(o.rsa, sa)
- if err != nil {
- return 0, 0, err
- }
- o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
- o.msg.Namelen = len
- }
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
- })
- return n, int(o.msg.Control.Len), err
-}
-
-// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
-func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) {
- if len(p) > maxRW {
- return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
- }
-
- if err := fd.writeLock(); err != nil {
- return 0, 0, err
- }
- defer fd.writeUnlock()
-
- o := &fd.wop
- o.InitMsg(p, oob)
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- len := sockaddrInet4ToRaw(o.rsa, sa)
- o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
- o.msg.Namelen = len
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
- })
- return n, int(o.msg.Control.Len), err
-}
-
-// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
-func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) {
- if len(p) > maxRW {
- return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
- }
-
- if err := fd.writeLock(); err != nil {
- return 0, 0, err
- }
- defer fd.writeUnlock()
-
- o := &fd.wop
- o.InitMsg(p, oob)
- if o.rsa == nil {
- o.rsa = new(syscall.RawSockaddrAny)
- }
- len := sockaddrInet6ToRaw(o.rsa, sa)
- o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
- o.msg.Namelen = len
- n, err := execIO(o, func(o *operation) error {
- return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
- })
- return n, int(o.msg.Control.Len), err
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/sendfile_bsd.go b/contrib/go/_std_1.22/src/internal/poll/sendfile_bsd.go
deleted file mode 100644
index 0f55cad73dc3..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/sendfile_bsd.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2011 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.
-
-//go:build darwin || dragonfly || freebsd
-
-package poll
-
-import "syscall"
-
-// maxSendfileSize is the largest chunk size we ask the kernel to copy
-// at a time.
-const maxSendfileSize int = 4 << 20
-
-// SendFile wraps the sendfile system call.
-func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error, bool) {
- if err := dstFD.writeLock(); err != nil {
- return 0, err, false
- }
- defer dstFD.writeUnlock()
- if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil {
- return 0, err, false
- }
-
- dst := dstFD.Sysfd
- var (
- written int64
- err error
- handled = true
- )
- for remain > 0 {
- n := maxSendfileSize
- if int64(n) > remain {
- n = int(remain)
- }
- pos1 := pos
- n, err1 := syscall.Sendfile(dst, src, &pos1, n)
- if n > 0 {
- pos += int64(n)
- written += int64(n)
- remain -= int64(n)
- } else if n == 0 && err1 == nil {
- break
- }
- if err1 == syscall.EINTR {
- continue
- }
- if err1 == syscall.EAGAIN {
- if err1 = dstFD.pd.waitWrite(dstFD.isFile); err1 == nil {
- continue
- }
- }
- if err1 != nil {
- // This includes syscall.ENOSYS (no kernel
- // support) and syscall.EINVAL (fd types which
- // don't implement sendfile)
- err = err1
- handled = false
- break
- }
- }
- return written, err, handled
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/sendfile_linux.go b/contrib/go/_std_1.22/src/internal/poll/sendfile_linux.go
deleted file mode 100644
index cc31969a43f9..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/sendfile_linux.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2011 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.
-
-package poll
-
-import "syscall"
-
-// maxSendfileSize is the largest chunk size we ask the kernel to copy
-// at a time.
-const maxSendfileSize int = 4 << 20
-
-// SendFile wraps the sendfile system call.
-func SendFile(dstFD *FD, src int, remain int64) (int64, error, bool) {
- if err := dstFD.writeLock(); err != nil {
- return 0, err, false
- }
- defer dstFD.writeUnlock()
- if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil {
- return 0, err, false
- }
-
- dst := dstFD.Sysfd
- var (
- written int64
- err error
- handled = true
- )
- for remain > 0 {
- n := maxSendfileSize
- if int64(n) > remain {
- n = int(remain)
- }
- n, err1 := syscall.Sendfile(dst, src, nil, n)
- if n > 0 {
- written += int64(n)
- remain -= int64(n)
- } else if n == 0 && err1 == nil {
- break
- }
- if err1 == syscall.EINTR {
- continue
- }
- if err1 == syscall.EAGAIN {
- if err1 = dstFD.pd.waitWrite(dstFD.isFile); err1 == nil {
- continue
- }
- }
- if err1 != nil {
- // This includes syscall.ENOSYS (no kernel
- // support) and syscall.EINVAL (fd types which
- // don't implement sendfile)
- err = err1
- handled = false
- break
- }
- }
- return written, err, handled
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/sendfile_solaris.go b/contrib/go/_std_1.22/src/internal/poll/sendfile_solaris.go
deleted file mode 100644
index f9f685c64a64..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/sendfile_solaris.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2015 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.
-
-package poll
-
-import "syscall"
-
-// Not strictly needed, but very helpful for debugging, see issue #10221.
-//
-//go:cgo_import_dynamic _ _ "libsendfile.so"
-//go:cgo_import_dynamic _ _ "libsocket.so"
-
-// maxSendfileSize is the largest chunk size we ask the kernel to copy
-// at a time.
-const maxSendfileSize int = 4 << 20
-
-// SendFile wraps the sendfile system call.
-func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error, bool) {
- if err := dstFD.writeLock(); err != nil {
- return 0, err, false
- }
- defer dstFD.writeUnlock()
- if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil {
- return 0, err, false
- }
-
- dst := dstFD.Sysfd
- var (
- written int64
- err error
- handled = true
- )
- for remain > 0 {
- n := maxSendfileSize
- if int64(n) > remain {
- n = int(remain)
- }
- pos1 := pos
- n, err1 := syscall.Sendfile(dst, src, &pos1, n)
- if err1 == syscall.EAGAIN || err1 == syscall.EINTR {
- // partial write may have occurred
- n = int(pos1 - pos)
- }
- if n > 0 {
- pos += int64(n)
- written += int64(n)
- remain -= int64(n)
- } else if n == 0 && err1 == nil {
- break
- }
- if err1 == syscall.EAGAIN {
- if err1 = dstFD.pd.waitWrite(dstFD.isFile); err1 == nil {
- continue
- }
- }
- if err1 == syscall.EINTR {
- continue
- }
- if err1 != nil {
- // This includes syscall.ENOSYS (no kernel
- // support) and syscall.EINVAL (fd types which
- // don't implement sendfile)
- err = err1
- handled = false
- break
- }
- }
- return written, err, handled
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/sendfile_windows.go b/contrib/go/_std_1.22/src/internal/poll/sendfile_windows.go
deleted file mode 100644
index 8c3353bc6ffa..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/sendfile_windows.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2011 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.
-
-package poll
-
-import (
- "io"
- "syscall"
-)
-
-// SendFile wraps the TransmitFile call.
-func SendFile(fd *FD, src syscall.Handle, n int64) (written int64, err error) {
- if fd.kind == kindPipe {
- // TransmitFile does not work with pipes
- return 0, syscall.ESPIPE
- }
- if ft, _ := syscall.GetFileType(src); ft == syscall.FILE_TYPE_PIPE {
- return 0, syscall.ESPIPE
- }
-
- if err := fd.writeLock(); err != nil {
- return 0, err
- }
- defer fd.writeUnlock()
-
- o := &fd.wop
- o.handle = src
-
- // TODO(brainman): skip calling syscall.Seek if OS allows it
- curpos, err := syscall.Seek(o.handle, 0, io.SeekCurrent)
- if err != nil {
- return 0, err
- }
-
- if n <= 0 { // We don't know the size of the file so infer it.
- // Find the number of bytes offset from curpos until the end of the file.
- n, err = syscall.Seek(o.handle, -curpos, io.SeekEnd)
- if err != nil {
- return
- }
- // Now seek back to the original position.
- if _, err = syscall.Seek(o.handle, curpos, io.SeekStart); err != nil {
- return
- }
- }
-
- // TransmitFile can be invoked in one call with at most
- // 2,147,483,646 bytes: the maximum value for a 32-bit integer minus 1.
- // See https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
- const maxChunkSizePerCall = int64(0x7fffffff - 1)
-
- for n > 0 {
- chunkSize := maxChunkSizePerCall
- if chunkSize > n {
- chunkSize = n
- }
-
- o.qty = uint32(chunkSize)
- o.o.Offset = uint32(curpos)
- o.o.OffsetHigh = uint32(curpos >> 32)
-
- nw, err := execIO(o, func(o *operation) error {
- return syscall.TransmitFile(o.fd.Sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
- })
- if err != nil {
- return written, err
- }
-
- curpos += int64(nw)
-
- // Some versions of Windows (Windows 10 1803) do not set
- // file position after TransmitFile completes.
- // So just use Seek to set file position.
- if _, err = syscall.Seek(o.handle, curpos, io.SeekStart); err != nil {
- return written, err
- }
-
- n -= int64(nw)
- written += int64(nw)
- }
-
- return
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/sock_cloexec.go b/contrib/go/_std_1.22/src/internal/poll/sock_cloexec.go
deleted file mode 100644
index 361c11bc57c3..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/sock_cloexec.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 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.
-
-// This file implements accept for platforms that provide a fast path for
-// setting SetNonblock and CloseOnExec.
-
-//go:build dragonfly || freebsd || (linux && !arm) || netbsd || openbsd || solaris
-
-package poll
-
-import "syscall"
-
-// Wrapper around the accept system call that marks the returned file
-// descriptor as nonblocking and close-on-exec.
-func accept(s int) (int, syscall.Sockaddr, string, error) {
- ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
- // TODO: We can remove the fallback on Linux and *BSD,
- // as currently supported versions all support accept4
- // with SOCK_CLOEXEC, but Solaris does not. See issue #59359.
- switch err {
- case nil:
- return ns, sa, "", nil
- default: // errors other than the ones listed
- return -1, sa, "accept4", err
- case syscall.ENOSYS: // syscall missing
- case syscall.EINVAL: // some Linux use this instead of ENOSYS
- case syscall.EACCES: // some Linux use this instead of ENOSYS
- case syscall.EFAULT: // some Linux use this instead of ENOSYS
- }
-
- // See ../syscall/exec_unix.go for description of ForkLock.
- // It is probably okay to hold the lock across syscall.Accept
- // because we have put fd.sysfd into non-blocking mode.
- // However, a call to the File method will put it back into
- // blocking mode. We can't take that risk, so no use of ForkLock here.
- ns, sa, err = AcceptFunc(s)
- if err == nil {
- syscall.CloseOnExec(ns)
- }
- if err != nil {
- return -1, nil, "accept", err
- }
- if err = syscall.SetNonblock(ns, true); err != nil {
- CloseFunc(ns)
- return -1, nil, "setnonblock", err
- }
- return ns, sa, "", nil
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/splice_linux.go b/contrib/go/_std_1.22/src/internal/poll/splice_linux.go
deleted file mode 100644
index 72cca34fe4ae..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/splice_linux.go
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2018 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.
-
-package poll
-
-import (
- "internal/syscall/unix"
- "runtime"
- "sync"
- "syscall"
- "unsafe"
-)
-
-const (
- // spliceNonblock doesn't make the splice itself necessarily nonblocking
- // (because the actual file descriptors that are spliced from/to may block
- // unless they have the O_NONBLOCK flag set), but it makes the splice pipe
- // operations nonblocking.
- spliceNonblock = 0x2
-
- // maxSpliceSize is the maximum amount of data Splice asks
- // the kernel to move in a single call to splice(2).
- // We use 1MB as Splice writes data through a pipe, and 1MB is the default maximum pipe buffer size,
- // which is determined by /proc/sys/fs/pipe-max-size.
- maxSpliceSize = 1 << 20
-)
-
-// Splice transfers at most remain bytes of data from src to dst, using the
-// splice system call to minimize copies of data from and to userspace.
-//
-// Splice gets a pipe buffer from the pool or creates a new one if needed, to serve as a buffer for the data transfer.
-// src and dst must both be stream-oriented sockets.
-//
-// If err != nil, sc is the system call which caused the error.
-func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string, err error) {
- p, sc, err := getPipe()
- if err != nil {
- return 0, false, sc, err
- }
- defer putPipe(p)
- var inPipe, n int
- for err == nil && remain > 0 {
- max := maxSpliceSize
- if int64(max) > remain {
- max = int(remain)
- }
- inPipe, err = spliceDrain(p.wfd, src, max)
- // The operation is considered handled if splice returns no
- // error, or an error other than EINVAL. An EINVAL means the
- // kernel does not support splice for the socket type of src.
- // The failed syscall does not consume any data so it is safe
- // to fall back to a generic copy.
- //
- // spliceDrain should never return EAGAIN, so if err != nil,
- // Splice cannot continue.
- //
- // If inPipe == 0 && err == nil, src is at EOF, and the
- // transfer is complete.
- handled = handled || (err != syscall.EINVAL)
- if err != nil || inPipe == 0 {
- break
- }
- p.data += inPipe
-
- n, err = splicePump(dst, p.rfd, inPipe)
- if n > 0 {
- written += int64(n)
- remain -= int64(n)
- p.data -= n
- }
- }
- if err != nil {
- return written, handled, "splice", err
- }
- return written, true, "", nil
-}
-
-// spliceDrain moves data from a socket to a pipe.
-//
-// Invariant: when entering spliceDrain, the pipe is empty. It is either in its
-// initial state, or splicePump has emptied it previously.
-//
-// Given this, spliceDrain can reasonably assume that the pipe is ready for
-// writing, so if splice returns EAGAIN, it must be because the socket is not
-// ready for reading.
-//
-// If spliceDrain returns (0, nil), src is at EOF.
-func spliceDrain(pipefd int, sock *FD, max int) (int, error) {
- if err := sock.readLock(); err != nil {
- return 0, err
- }
- defer sock.readUnlock()
- if err := sock.pd.prepareRead(sock.isFile); err != nil {
- return 0, err
- }
- for {
- // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here,
- // because it could return EAGAIN ceaselessly when the write end of the pipe is full,
- // but this shouldn't be a concern here, since the pipe buffer must be sufficient for
- // this data transmission on the basis of the workflow in Splice.
- n, err := splice(pipefd, sock.Sysfd, max, spliceNonblock)
- if err == syscall.EINTR {
- continue
- }
- if err != syscall.EAGAIN {
- return n, err
- }
- if sock.pd.pollable() {
- if err := sock.pd.waitRead(sock.isFile); err != nil {
- return n, err
- }
- }
- }
-}
-
-// splicePump moves all the buffered data from a pipe to a socket.
-//
-// Invariant: when entering splicePump, there are exactly inPipe
-// bytes of data in the pipe, from a previous call to spliceDrain.
-//
-// By analogy to the condition from spliceDrain, splicePump
-// only needs to poll the socket for readiness, if splice returns
-// EAGAIN.
-//
-// If splicePump cannot move all the data in a single call to
-// splice(2), it loops over the buffered data until it has written
-// all of it to the socket. This behavior is similar to the Write
-// step of an io.Copy in userspace.
-func splicePump(sock *FD, pipefd int, inPipe int) (int, error) {
- if err := sock.writeLock(); err != nil {
- return 0, err
- }
- defer sock.writeUnlock()
- if err := sock.pd.prepareWrite(sock.isFile); err != nil {
- return 0, err
- }
- written := 0
- for inPipe > 0 {
- // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here,
- // because it could return EAGAIN ceaselessly when the read end of the pipe is empty,
- // but this shouldn't be a concern here, since the pipe buffer must contain inPipe size of
- // data on the basis of the workflow in Splice.
- n, err := splice(sock.Sysfd, pipefd, inPipe, spliceNonblock)
- if err == syscall.EINTR {
- continue
- }
- // Here, the condition n == 0 && err == nil should never be
- // observed, since Splice controls the write side of the pipe.
- if n > 0 {
- inPipe -= n
- written += n
- continue
- }
- if err != syscall.EAGAIN {
- return written, err
- }
- if sock.pd.pollable() {
- if err := sock.pd.waitWrite(sock.isFile); err != nil {
- return written, err
- }
- }
- }
- return written, nil
-}
-
-// splice wraps the splice system call. Since the current implementation
-// only uses splice on sockets and pipes, the offset arguments are unused.
-// splice returns int instead of int64, because callers never ask it to
-// move more data in a single call than can fit in an int32.
-func splice(out int, in int, max int, flags int) (int, error) {
- n, err := syscall.Splice(in, nil, out, nil, max, flags)
- return int(n), err
-}
-
-type splicePipeFields struct {
- rfd int
- wfd int
- data int
-}
-
-type splicePipe struct {
- splicePipeFields
-
- // We want to use a finalizer, so ensure that the size is
- // large enough to not use the tiny allocator.
- _ [24 - unsafe.Sizeof(splicePipeFields{})%24]byte
-}
-
-// splicePipePool caches pipes to avoid high-frequency construction and destruction of pipe buffers.
-// The garbage collector will free all pipes in the sync.Pool periodically, thus we need to set up
-// a finalizer for each pipe to close its file descriptors before the actual GC.
-var splicePipePool = sync.Pool{New: newPoolPipe}
-
-func newPoolPipe() any {
- // Discard the error which occurred during the creation of pipe buffer,
- // redirecting the data transmission to the conventional way utilizing read() + write() as a fallback.
- p := newPipe()
- if p == nil {
- return nil
- }
- runtime.SetFinalizer(p, destroyPipe)
- return p
-}
-
-// getPipe tries to acquire a pipe buffer from the pool or create a new one with newPipe() if it gets nil from the cache.
-//
-// Note that it may fail to create a new pipe buffer by newPipe(), in which case getPipe() will return a generic error
-// and system call name splice in a string as the indication.
-func getPipe() (*splicePipe, string, error) {
- v := splicePipePool.Get()
- if v == nil {
- return nil, "splice", syscall.EINVAL
- }
- return v.(*splicePipe), "", nil
-}
-
-func putPipe(p *splicePipe) {
- // If there is still data left in the pipe,
- // then close and discard it instead of putting it back into the pool.
- if p.data != 0 {
- runtime.SetFinalizer(p, nil)
- destroyPipe(p)
- return
- }
- splicePipePool.Put(p)
-}
-
-// newPipe sets up a pipe for a splice operation.
-func newPipe() *splicePipe {
- var fds [2]int
- if err := syscall.Pipe2(fds[:], syscall.O_CLOEXEC|syscall.O_NONBLOCK); err != nil {
- return nil
- }
-
- // Splice will loop writing maxSpliceSize bytes from the source to the pipe,
- // and then write those bytes from the pipe to the destination.
- // Set the pipe buffer size to maxSpliceSize to optimize that.
- // Ignore errors here, as a smaller buffer size will work,
- // although it will require more system calls.
- unix.Fcntl(fds[0], syscall.F_SETPIPE_SZ, maxSpliceSize)
-
- return &splicePipe{splicePipeFields: splicePipeFields{rfd: fds[0], wfd: fds[1]}}
-}
-
-// destroyPipe destroys a pipe.
-func destroyPipe(p *splicePipe) {
- CloseFunc(p.rfd)
- CloseFunc(p.wfd)
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/strconv.go b/contrib/go/_std_1.22/src/internal/poll/strconv.go
deleted file mode 100644
index 2b052fa1747f..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/strconv.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2009 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.
-
-//go:build plan9
-
-package poll
-
-// stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
-// suffix.
-func stringsHasSuffix(s, suffix string) bool {
- return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
-}
diff --git a/contrib/go/_std_1.22/src/internal/poll/ya.make b/contrib/go/_std_1.22/src/internal/poll/ya.make
deleted file mode 100644
index 175eda755a51..000000000000
--- a/contrib/go/_std_1.22/src/internal/poll/ya.make
+++ /dev/null
@@ -1,63 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- errno_unix.go
- fd.go
- fd_fsync_darwin.go
- fd_mutex.go
- fd_opendir_darwin.go
- fd_poll_runtime.go
- fd_posix.go
- fd_unix.go
- fd_unixjs.go
- fd_writev_libc.go
- hook_unix.go
- iovec_unix.go
- sendfile_bsd.go
- sockopt.go
- sockopt_unix.go
- sockoptip.go
- sys_cloexec.go
- writev.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- copy_file_range_linux.go
- errno_unix.go
- fd.go
- fd_fsync_posix.go
- fd_mutex.go
- fd_poll_runtime.go
- fd_posix.go
- fd_unix.go
- fd_unixjs.go
- fd_writev_unix.go
- hook_cloexec.go
- hook_unix.go
- iovec_unix.go
- sendfile_linux.go
- sock_cloexec.go
- sockopt.go
- sockopt_linux.go
- sockopt_unix.go
- sockoptip.go
- splice_linux.go
- writev.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- errno_windows.go
- fd.go
- fd_fsync_windows.go
- fd_mutex.go
- fd_poll_runtime.go
- fd_posix.go
- fd_windows.go
- hook_windows.go
- sendfile_windows.go
- sockopt.go
- sockopt_windows.go
- sockoptip.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/race/ya.make b/contrib/go/_std_1.22/src/internal/race/ya.make
deleted file mode 100644
index 3e33723a5ec0..000000000000
--- a/contrib/go/_std_1.22/src/internal/race/ya.make
+++ /dev/null
@@ -1,13 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED)
- SRCS(
- doc.go
- race.go
- )
-ELSEIF (OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- doc.go
- norace.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/reflectlite/swapper.go b/contrib/go/_std_1.22/src/internal/reflectlite/swapper.go
deleted file mode 100644
index ac17d9bbc465..000000000000
--- a/contrib/go/_std_1.22/src/internal/reflectlite/swapper.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 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.
-
-package reflectlite
-
-import (
- "internal/goarch"
- "internal/unsafeheader"
- "unsafe"
-)
-
-// Swapper returns a function that swaps the elements in the provided
-// slice.
-//
-// Swapper panics if the provided interface is not a slice.
-func Swapper(slice any) func(i, j int) {
- v := ValueOf(slice)
- if v.Kind() != Slice {
- panic(&ValueError{Method: "Swapper", Kind: v.Kind()})
- }
- // Fast path for slices of size 0 and 1. Nothing to swap.
- switch v.Len() {
- case 0:
- return func(i, j int) { panic("reflect: slice index out of range") }
- case 1:
- return func(i, j int) {
- if i != 0 || j != 0 {
- panic("reflect: slice index out of range")
- }
- }
- }
-
- typ := v.Type().Elem().common()
- size := typ.Size()
- hasPtr := typ.PtrBytes != 0
-
- // Some common & small cases, without using memmove:
- if hasPtr {
- if size == goarch.PtrSize {
- ps := *(*[]unsafe.Pointer)(v.ptr)
- return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] }
- }
- if typ.Kind() == String {
- ss := *(*[]string)(v.ptr)
- return func(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
- }
- } else {
- switch size {
- case 8:
- is := *(*[]int64)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- case 4:
- is := *(*[]int32)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- case 2:
- is := *(*[]int16)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- case 1:
- is := *(*[]int8)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- }
- }
-
- s := (*unsafeheader.Slice)(v.ptr)
- tmp := unsafe_New(typ) // swap scratch space
-
- return func(i, j int) {
- if uint(i) >= uint(s.Len) || uint(j) >= uint(s.Len) {
- panic("reflect: slice index out of range")
- }
- val1 := arrayAt(s.Data, i, size, "i < s.Len")
- val2 := arrayAt(s.Data, j, size, "j < s.Len")
- typedmemmove(typ, tmp, val1)
- typedmemmove(typ, val1, val2)
- typedmemmove(typ, val2, tmp)
- }
-}
diff --git a/contrib/go/_std_1.22/src/internal/reflectlite/type.go b/contrib/go/_std_1.22/src/internal/reflectlite/type.go
deleted file mode 100644
index e585d24f538c..000000000000
--- a/contrib/go/_std_1.22/src/internal/reflectlite/type.go
+++ /dev/null
@@ -1,665 +0,0 @@
-// Copyright 2009 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.
-
-// Package reflectlite implements lightweight version of reflect, not using
-// any package except for "runtime", "unsafe", and "internal/abi"
-package reflectlite
-
-import (
- "internal/abi"
- "unsafe"
-)
-
-// Type is the representation of a Go type.
-//
-// Not all methods apply to all kinds of types. Restrictions,
-// if any, are noted in the documentation for each method.
-// Use the Kind method to find out the kind of type before
-// calling kind-specific methods. Calling a method
-// inappropriate to the kind of type causes a run-time panic.
-//
-// Type values are comparable, such as with the == operator,
-// so they can be used as map keys.
-// Two Type values are equal if they represent identical types.
-type Type interface {
- // Methods applicable to all types.
-
- // Name returns the type's name within its package for a defined type.
- // For other (non-defined) types it returns the empty string.
- Name() string
-
- // PkgPath returns a defined type's package path, that is, the import path
- // that uniquely identifies the package, such as "encoding/base64".
- // If the type was predeclared (string, error) or not defined (*T, struct{},
- // []int, or A where A is an alias for a non-defined type), the package path
- // will be the empty string.
- PkgPath() string
-
- // Size returns the number of bytes needed to store
- // a value of the given type; it is analogous to unsafe.Sizeof.
- Size() uintptr
-
- // Kind returns the specific kind of this type.
- Kind() Kind
-
- // Implements reports whether the type implements the interface type u.
- Implements(u Type) bool
-
- // AssignableTo reports whether a value of the type is assignable to type u.
- AssignableTo(u Type) bool
-
- // Comparable reports whether values of this type are comparable.
- Comparable() bool
-
- // String returns a string representation of the type.
- // The string representation may use shortened package names
- // (e.g., base64 instead of "encoding/base64") and is not
- // guaranteed to be unique among types. To test for type identity,
- // compare the Types directly.
- String() string
-
- // Elem returns a type's element type.
- // It panics if the type's Kind is not Ptr.
- Elem() Type
-
- common() *abi.Type
- uncommon() *uncommonType
-}
-
-/*
- * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
- * A few are known to ../runtime/type.go to convey to debuggers.
- * They are also known to ../runtime/type.go.
- */
-
-// A Kind represents the specific kind of type that a Type represents.
-// The zero Kind is not a valid kind.
-type Kind = abi.Kind
-
-const Ptr = abi.Pointer
-
-const (
- // Import-and-export these constants as necessary
- Interface = abi.Interface
- Slice = abi.Slice
- String = abi.String
- Struct = abi.Struct
-)
-
-type nameOff = abi.NameOff
-type typeOff = abi.TypeOff
-type textOff = abi.TextOff
-
-type rtype struct {
- *abi.Type
-}
-
-// uncommonType is present only for defined types or types with methods
-// (if T is a defined type, the uncommonTypes for T and *T have methods).
-// Using a pointer to this struct reduces the overall size required
-// to describe a non-defined type with no methods.
-type uncommonType = abi.UncommonType
-
-// arrayType represents a fixed array type.
-type arrayType = abi.ArrayType
-
-// chanType represents a channel type.
-type chanType = abi.ChanType
-
-type funcType = abi.FuncType
-
-type interfaceType = abi.InterfaceType
-
-// mapType represents a map type.
-type mapType struct {
- rtype
- Key *abi.Type // map key type
- Elem *abi.Type // map element (value) type
- Bucket *abi.Type // internal bucket structure
- // function for hashing keys (ptr to key, seed) -> hash
- Hasher func(unsafe.Pointer, uintptr) uintptr
- KeySize uint8 // size of key slot
- ValueSize uint8 // size of value slot
- BucketSize uint16 // size of bucket
- Flags uint32
-}
-
-// ptrType represents a pointer type.
-type ptrType = abi.PtrType
-
-// sliceType represents a slice type.
-type sliceType = abi.SliceType
-
-// structType represents a struct type.
-type structType = abi.StructType
-
-// name is an encoded type name with optional extra data.
-//
-// The first byte is a bit field containing:
-//
-// 1<<0 the name is exported
-// 1<<1 tag data follows the name
-// 1<<2 pkgPath nameOff follows the name and tag
-//
-// The next two bytes are the data length:
-//
-// l := uint16(data[1])<<8 | uint16(data[2])
-//
-// Bytes [3:3+l] are the string data.
-//
-// If tag data follows then bytes 3+l and 3+l+1 are the tag length,
-// with the data following.
-//
-// If the import path follows, then 4 bytes at the end of
-// the data form a nameOff. The import path is only set for concrete
-// methods that are defined in a different package than their type.
-//
-// If a name starts with "*", then the exported bit represents
-// whether the pointed to type is exported.
-type name struct {
- bytes *byte
-}
-
-func (n name) data(off int, whySafe string) *byte {
- return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
-}
-
-func (n name) isExported() bool {
- return (*n.bytes)&(1<<0) != 0
-}
-
-func (n name) hasTag() bool {
- return (*n.bytes)&(1<<1) != 0
-}
-
-func (n name) embedded() bool {
- return (*n.bytes)&(1<<3) != 0
-}
-
-// readVarint parses a varint as encoded by encoding/binary.
-// It returns the number of encoded bytes and the encoded value.
-func (n name) readVarint(off int) (int, int) {
- v := 0
- for i := 0; ; i++ {
- x := *n.data(off+i, "read varint")
- v += int(x&0x7f) << (7 * i)
- if x&0x80 == 0 {
- return i + 1, v
- }
- }
-}
-
-func (n name) name() string {
- if n.bytes == nil {
- return ""
- }
- i, l := n.readVarint(1)
- return unsafe.String(n.data(1+i, "non-empty string"), l)
-}
-
-func (n name) tag() string {
- if !n.hasTag() {
- return ""
- }
- i, l := n.readVarint(1)
- i2, l2 := n.readVarint(1 + i + l)
- return unsafe.String(n.data(1+i+l+i2, "non-empty string"), l2)
-}
-
-func pkgPath(n abi.Name) string {
- if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
- return ""
- }
- i, l := n.ReadVarint(1)
- off := 1 + i + l
- if n.HasTag() {
- i2, l2 := n.ReadVarint(off)
- off += i2 + l2
- }
- var nameOff int32
- // Note that this field may not be aligned in memory,
- // so we cannot use a direct int32 assignment here.
- copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
- pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
- return pkgPathName.name()
-}
-
-/*
- * The compiler knows the exact layout of all the data structures above.
- * The compiler does not know about the data structures and methods below.
- */
-
-// resolveNameOff resolves a name offset from a base pointer.
-// The (*rtype).nameOff method is a convenience wrapper for this function.
-// Implemented in the runtime package.
-//
-//go:noescape
-func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
-
-// resolveTypeOff resolves an *rtype offset from a base type.
-// The (*rtype).typeOff method is a convenience wrapper for this function.
-// Implemented in the runtime package.
-//
-//go:noescape
-func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
-
-func (t rtype) nameOff(off nameOff) abi.Name {
- return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t.Type), int32(off)))}
-}
-
-func (t rtype) typeOff(off typeOff) *abi.Type {
- return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t.Type), int32(off)))
-}
-
-func (t rtype) uncommon() *uncommonType {
- return t.Uncommon()
-}
-
-func (t rtype) String() string {
- s := t.nameOff(t.Str).Name()
- if t.TFlag&abi.TFlagExtraStar != 0 {
- return s[1:]
- }
- return s
-}
-
-func (t rtype) common() *abi.Type { return t.Type }
-
-func (t rtype) exportedMethods() []abi.Method {
- ut := t.uncommon()
- if ut == nil {
- return nil
- }
- return ut.ExportedMethods()
-}
-
-func (t rtype) NumMethod() int {
- tt := t.Type.InterfaceType()
- if tt != nil {
- return tt.NumMethod()
- }
- return len(t.exportedMethods())
-}
-
-func (t rtype) PkgPath() string {
- if t.TFlag&abi.TFlagNamed == 0 {
- return ""
- }
- ut := t.uncommon()
- if ut == nil {
- return ""
- }
- return t.nameOff(ut.PkgPath).Name()
-}
-
-func (t rtype) Name() string {
- if !t.HasName() {
- return ""
- }
- s := t.String()
- i := len(s) - 1
- sqBrackets := 0
- for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
- switch s[i] {
- case ']':
- sqBrackets++
- case '[':
- sqBrackets--
- }
- i--
- }
- return s[i+1:]
-}
-
-func toRType(t *abi.Type) rtype {
- return rtype{t}
-}
-
-func elem(t *abi.Type) *abi.Type {
- et := t.Elem()
- if et != nil {
- return et
- }
- panic("reflect: Elem of invalid type " + toRType(t).String())
-}
-
-func (t rtype) Elem() Type {
- return toType(elem(t.common()))
-}
-
-func (t rtype) In(i int) Type {
- tt := t.Type.FuncType()
- if tt == nil {
- panic("reflect: In of non-func type")
- }
- return toType(tt.InSlice()[i])
-}
-
-func (t rtype) Key() Type {
- tt := t.Type.MapType()
- if tt == nil {
- panic("reflect: Key of non-map type")
- }
- return toType(tt.Key)
-}
-
-func (t rtype) Len() int {
- tt := t.Type.ArrayType()
- if tt == nil {
- panic("reflect: Len of non-array type")
- }
- return int(tt.Len)
-}
-
-func (t rtype) NumField() int {
- tt := t.Type.StructType()
- if tt == nil {
- panic("reflect: NumField of non-struct type")
- }
- return len(tt.Fields)
-}
-
-func (t rtype) NumIn() int {
- tt := t.Type.FuncType()
- if tt == nil {
- panic("reflect: NumIn of non-func type")
- }
- return int(tt.InCount)
-}
-
-func (t rtype) NumOut() int {
- tt := t.Type.FuncType()
- if tt == nil {
- panic("reflect: NumOut of non-func type")
- }
- return tt.NumOut()
-}
-
-func (t rtype) Out(i int) Type {
- tt := t.Type.FuncType()
- if tt == nil {
- panic("reflect: Out of non-func type")
- }
- return toType(tt.OutSlice()[i])
-}
-
-// add returns p+x.
-//
-// The whySafe string is ignored, so that the function still inlines
-// as efficiently as p+x, but all call sites should use the string to
-// record why the addition is safe, which is to say why the addition
-// does not cause x to advance to the very end of p's allocation
-// and therefore point incorrectly at the next block in memory.
-func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
- return unsafe.Pointer(uintptr(p) + x)
-}
-
-// TypeOf returns the reflection Type that represents the dynamic type of i.
-// If i is a nil interface value, TypeOf returns nil.
-func TypeOf(i any) Type {
- eface := *(*emptyInterface)(unsafe.Pointer(&i))
- // Noescape so this doesn't make i to escape. See the comment
- // at Value.typ for why this is safe.
- return toType((*abi.Type)(noescape(unsafe.Pointer(eface.typ))))
-}
-
-func (t rtype) Implements(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.Implements")
- }
- if u.Kind() != Interface {
- panic("reflect: non-interface type passed to Type.Implements")
- }
- return implements(u.common(), t.common())
-}
-
-func (t rtype) AssignableTo(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.AssignableTo")
- }
- uu := u.common()
- tt := t.common()
- return directlyAssignable(uu, tt) || implements(uu, tt)
-}
-
-func (t rtype) Comparable() bool {
- return t.Equal != nil
-}
-
-// implements reports whether the type V implements the interface type T.
-func implements(T, V *abi.Type) bool {
- t := T.InterfaceType()
- if t == nil {
- return false
- }
- if len(t.Methods) == 0 {
- return true
- }
- rT := toRType(T)
- rV := toRType(V)
-
- // The same algorithm applies in both cases, but the
- // method tables for an interface type and a concrete type
- // are different, so the code is duplicated.
- // In both cases the algorithm is a linear scan over the two
- // lists - T's methods and V's methods - simultaneously.
- // Since method tables are stored in a unique sorted order
- // (alphabetical, with no duplicate method names), the scan
- // through V's methods must hit a match for each of T's
- // methods along the way, or else V does not implement T.
- // This lets us run the scan in overall linear time instead of
- // the quadratic time a naive search would require.
- // See also ../runtime/iface.go.
- if V.Kind() == Interface {
- v := (*interfaceType)(unsafe.Pointer(V))
- i := 0
- for j := 0; j < len(v.Methods); j++ {
- tm := &t.Methods[i]
- tmName := rT.nameOff(tm.Name)
- vm := &v.Methods[j]
- vmName := rV.nameOff(vm.Name)
- if vmName.Name() == tmName.Name() && rV.typeOff(vm.Typ) == rT.typeOff(tm.Typ) {
- if !tmName.IsExported() {
- tmPkgPath := pkgPath(tmName)
- if tmPkgPath == "" {
- tmPkgPath = t.PkgPath.Name()
- }
- vmPkgPath := pkgPath(vmName)
- if vmPkgPath == "" {
- vmPkgPath = v.PkgPath.Name()
- }
- if tmPkgPath != vmPkgPath {
- continue
- }
- }
- if i++; i >= len(t.Methods) {
- return true
- }
- }
- }
- return false
- }
-
- v := V.Uncommon()
- if v == nil {
- return false
- }
- i := 0
- vmethods := v.Methods()
- for j := 0; j < int(v.Mcount); j++ {
- tm := &t.Methods[i]
- tmName := rT.nameOff(tm.Name)
- vm := vmethods[j]
- vmName := rV.nameOff(vm.Name)
- if vmName.Name() == tmName.Name() && rV.typeOff(vm.Mtyp) == rT.typeOff(tm.Typ) {
- if !tmName.IsExported() {
- tmPkgPath := pkgPath(tmName)
- if tmPkgPath == "" {
- tmPkgPath = t.PkgPath.Name()
- }
- vmPkgPath := pkgPath(vmName)
- if vmPkgPath == "" {
- vmPkgPath = rV.nameOff(v.PkgPath).Name()
- }
- if tmPkgPath != vmPkgPath {
- continue
- }
- }
- if i++; i >= len(t.Methods) {
- return true
- }
- }
- }
- return false
-}
-
-// directlyAssignable reports whether a value x of type V can be directly
-// assigned (using memmove) to a value of type T.
-// https://golang.org/doc/go_spec.html#Assignability
-// Ignoring the interface rules (implemented elsewhere)
-// and the ideal constant rules (no ideal constants at run time).
-func directlyAssignable(T, V *abi.Type) bool {
- // x's type V is identical to T?
- if T == V {
- return true
- }
-
- // Otherwise at least one of T and V must not be defined
- // and they must have the same kind.
- if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
- return false
- }
-
- // x's type T and V must have identical underlying types.
- return haveIdenticalUnderlyingType(T, V, true)
-}
-
-func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
- if cmpTags {
- return T == V
- }
-
- if toRType(T).Name() != toRType(V).Name() || T.Kind() != V.Kind() {
- return false
- }
-
- return haveIdenticalUnderlyingType(T, V, false)
-}
-
-func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
- if T == V {
- return true
- }
-
- kind := T.Kind()
- if kind != V.Kind() {
- return false
- }
-
- // Non-composite types of equal kind have same underlying type
- // (the predefined instance of the type).
- if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
- return true
- }
-
- // Composite types.
- switch kind {
- case abi.Array:
- return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case abi.Chan:
- // Special case:
- // x is a bidirectional channel value, T is a channel type,
- // and x's type V and T have identical element types.
- if V.ChanDir() == abi.BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
- return true
- }
-
- // Otherwise continue test for identical underlying type.
- return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case abi.Func:
- t := (*funcType)(unsafe.Pointer(T))
- v := (*funcType)(unsafe.Pointer(V))
- if t.OutCount != v.OutCount || t.InCount != v.InCount {
- return false
- }
- for i := 0; i < t.NumIn(); i++ {
- if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
- return false
- }
- }
- for i := 0; i < t.NumOut(); i++ {
- if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
- return false
- }
- }
- return true
-
- case Interface:
- t := (*interfaceType)(unsafe.Pointer(T))
- v := (*interfaceType)(unsafe.Pointer(V))
- if len(t.Methods) == 0 && len(v.Methods) == 0 {
- return true
- }
- // Might have the same methods but still
- // need a run time conversion.
- return false
-
- case abi.Map:
- return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case Ptr, abi.Slice:
- return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case abi.Struct:
- t := (*structType)(unsafe.Pointer(T))
- v := (*structType)(unsafe.Pointer(V))
- if len(t.Fields) != len(v.Fields) {
- return false
- }
- if t.PkgPath.Name() != v.PkgPath.Name() {
- return false
- }
- for i := range t.Fields {
- tf := &t.Fields[i]
- vf := &v.Fields[i]
- if tf.Name.Name() != vf.Name.Name() {
- return false
- }
- if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
- return false
- }
- if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
- return false
- }
- if tf.Offset != vf.Offset {
- return false
- }
- if tf.Embedded() != vf.Embedded() {
- return false
- }
- }
- return true
- }
-
- return false
-}
-
-// toType converts from a *rtype to a Type that can be returned
-// to the client of package reflect. In gc, the only concern is that
-// a nil *rtype must be replaced by a nil Type, but in gccgo this
-// function takes care of ensuring that multiple *rtype for the same
-// type are coalesced into a single Type.
-func toType(t *abi.Type) Type {
- if t == nil {
- return nil
- }
- return toRType(t)
-}
-
-// ifaceIndir reports whether t is stored indirectly in an interface value.
-func ifaceIndir(t *abi.Type) bool {
- return t.Kind_&abi.KindDirectIface == 0
-}
diff --git a/contrib/go/_std_1.22/src/internal/reflectlite/value.go b/contrib/go/_std_1.22/src/internal/reflectlite/value.go
deleted file mode 100644
index c47e5ea12b3c..000000000000
--- a/contrib/go/_std_1.22/src/internal/reflectlite/value.go
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright 2009 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.
-
-package reflectlite
-
-import (
- "internal/abi"
- "internal/goarch"
- "internal/unsafeheader"
- "runtime"
- "unsafe"
-)
-
-// Value is the reflection interface to a Go value.
-//
-// Not all methods apply to all kinds of values. Restrictions,
-// if any, are noted in the documentation for each method.
-// Use the Kind method to find out the kind of value before
-// calling kind-specific methods. Calling a method
-// inappropriate to the kind of type causes a run time panic.
-//
-// The zero Value represents no value.
-// Its IsValid method returns false, its Kind method returns Invalid,
-// its String method returns "", and all other methods panic.
-// Most functions and methods never return an invalid value.
-// If one does, its documentation states the conditions explicitly.
-//
-// A Value can be used concurrently by multiple goroutines provided that
-// the underlying Go value can be used concurrently for the equivalent
-// direct operations.
-//
-// To compare two Values, compare the results of the Interface method.
-// Using == on two Values does not compare the underlying values
-// they represent.
-type Value struct {
- // typ_ holds the type of the value represented by a Value.
- // Access using the typ method to avoid escape of v.
- typ_ *abi.Type
-
- // Pointer-valued data or, if flagIndir is set, pointer to data.
- // Valid when either flagIndir is set or typ.pointers() is true.
- ptr unsafe.Pointer
-
- // flag holds metadata about the value.
- // The lowest bits are flag bits:
- // - flagStickyRO: obtained via unexported not embedded field, so read-only
- // - flagEmbedRO: obtained via unexported embedded field, so read-only
- // - flagIndir: val holds a pointer to the data
- // - flagAddr: v.CanAddr is true (implies flagIndir)
- // Value cannot represent method values.
- // The next five bits give the Kind of the value.
- // This repeats typ.Kind() except for method values.
- // The remaining 23+ bits give a method number for method values.
- // If flag.kind() != Func, code can assume that flagMethod is unset.
- // If ifaceIndir(typ), code can assume that flagIndir is set.
- flag
-
- // A method value represents a curried method invocation
- // like r.Read for some receiver r. The typ+val+flag bits describe
- // the receiver r, but the flag's Kind bits say Func (methods are
- // functions), and the top bits of the flag give the method number
- // in r's type's method table.
-}
-
-type flag uintptr
-
-const (
- flagKindWidth = 5 // there are 27 kinds
- flagKindMask flag = 1<= len,
-// because then the result will point outside the array.
-// whySafe must explain why i < len. (Passing "i < len" is fine;
-// the benefit is to surface this assumption at the call site.)
-func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
- return add(p, uintptr(i)*eltSize, "i < len")
-}
-
-func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
-
-// typedmemmove copies a value of type t to dst from src.
-//
-//go:noescape
-func typedmemmove(t *abi.Type, dst, src unsafe.Pointer)
-
-// Dummy annotation marking that the value x escapes,
-// for use in cases where the reflect code is so clever that
-// the compiler cannot follow.
-func escapes(x any) {
- if dummy.b {
- dummy.x = x
- }
-}
-
-var dummy struct {
- b bool
- x any
-}
-
-//go:nosplit
-func noescape(p unsafe.Pointer) unsafe.Pointer {
- x := uintptr(p)
- return unsafe.Pointer(x ^ 0)
-}
diff --git a/contrib/go/_std_1.22/src/internal/safefilepath/path.go b/contrib/go/_std_1.22/src/internal/safefilepath/path.go
deleted file mode 100644
index 0f0a270c3034..000000000000
--- a/contrib/go/_std_1.22/src/internal/safefilepath/path.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 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.
-
-// Package safefilepath manipulates operating-system file paths.
-package safefilepath
-
-import (
- "errors"
-)
-
-var errInvalidPath = errors.New("invalid path")
-
-// FromFS converts a slash-separated path into an operating-system path.
-//
-// FromFS returns an error if the path cannot be represented by the operating
-// system. For example, paths containing '\' and ':' characters are rejected
-// on Windows.
-func FromFS(path string) (string, error) {
- return fromFS(path)
-}
diff --git a/contrib/go/_std_1.22/src/internal/safefilepath/path_other.go b/contrib/go/_std_1.22/src/internal/safefilepath/path_other.go
deleted file mode 100644
index 974e7751a290..000000000000
--- a/contrib/go/_std_1.22/src/internal/safefilepath/path_other.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2022 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.
-
-//go:build !windows
-
-package safefilepath
-
-import "runtime"
-
-func fromFS(path string) (string, error) {
- if runtime.GOOS == "plan9" {
- if len(path) > 0 && path[0] == '#' {
- return "", errInvalidPath
- }
- }
- for i := range path {
- if path[i] == 0 {
- return "", errInvalidPath
- }
- }
- return path, nil
-}
diff --git a/contrib/go/_std_1.22/src/internal/safefilepath/path_windows.go b/contrib/go/_std_1.22/src/internal/safefilepath/path_windows.go
deleted file mode 100644
index 7cfd6ce2eac2..000000000000
--- a/contrib/go/_std_1.22/src/internal/safefilepath/path_windows.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2022 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.
-
-package safefilepath
-
-import (
- "syscall"
- "unicode/utf8"
-)
-
-func fromFS(path string) (string, error) {
- if !utf8.ValidString(path) {
- return "", errInvalidPath
- }
- for len(path) > 1 && path[0] == '/' && path[1] == '/' {
- path = path[1:]
- }
- containsSlash := false
- for p := path; p != ""; {
- // Find the next path element.
- i := 0
- for i < len(p) && p[i] != '/' {
- switch p[i] {
- case 0, '\\', ':':
- return "", errInvalidPath
- }
- i++
- }
- part := p[:i]
- if i < len(p) {
- containsSlash = true
- p = p[i+1:]
- } else {
- p = ""
- }
- if IsReservedName(part) {
- return "", errInvalidPath
- }
- }
- if containsSlash {
- // We can't depend on strings, so substitute \ for / manually.
- buf := []byte(path)
- for i, b := range buf {
- if b == '/' {
- buf[i] = '\\'
- }
- }
- path = string(buf)
- }
- return path, nil
-}
-
-// IsReservedName reports if name is a Windows reserved device name.
-// It does not detect names with an extension, which are also reserved on some Windows versions.
-//
-// For details, search for PRN in
-// https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file.
-func IsReservedName(name string) bool {
- // Device names can have arbitrary trailing characters following a dot or colon.
- base := name
- for i := 0; i < len(base); i++ {
- switch base[i] {
- case ':', '.':
- base = base[:i]
- }
- }
- // Trailing spaces in the last path element are ignored.
- for len(base) > 0 && base[len(base)-1] == ' ' {
- base = base[:len(base)-1]
- }
- if !isReservedBaseName(base) {
- return false
- }
- if len(base) == len(name) {
- return true
- }
- // The path element is a reserved name with an extension.
- // Some Windows versions consider this a reserved name,
- // while others do not. Use FullPath to see if the name is
- // reserved.
- if p, _ := syscall.FullPath(name); len(p) >= 4 && p[:4] == `\\.\` {
- return true
- }
- return false
-}
-
-func isReservedBaseName(name string) bool {
- if len(name) == 3 {
- switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) {
- case "CON", "PRN", "AUX", "NUL":
- return true
- }
- }
- if len(name) >= 4 {
- switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) {
- case "COM", "LPT":
- if len(name) == 4 && '1' <= name[3] && name[3] <= '9' {
- return true
- }
- // Superscript ¹, ², and ³ are considered numbers as well.
- switch name[3:] {
- case "\u00b2", "\u00b3", "\u00b9":
- return true
- }
- return false
- }
- }
-
- // Passing CONIN$ or CONOUT$ to CreateFile opens a console handle.
- // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#consoles
- //
- // While CONIN$ and CONOUT$ aren't documented as being files,
- // they behave the same as CON. For example, ./CONIN$ also opens the console input.
- if len(name) == 6 && name[5] == '$' && equalFold(name, "CONIN$") {
- return true
- }
- if len(name) == 7 && name[6] == '$' && equalFold(name, "CONOUT$") {
- return true
- }
- return false
-}
-
-func equalFold(a, b string) bool {
- if len(a) != len(b) {
- return false
- }
- for i := 0; i < len(a); i++ {
- if toUpper(a[i]) != toUpper(b[i]) {
- return false
- }
- }
- return true
-}
-
-func toUpper(c byte) byte {
- if 'a' <= c && c <= 'z' {
- return c - ('a' - 'A')
- }
- return c
-}
diff --git a/contrib/go/_std_1.22/src/internal/safefilepath/ya.make b/contrib/go/_std_1.22/src/internal/safefilepath/ya.make
deleted file mode 100644
index 9b77c8250297..000000000000
--- a/contrib/go/_std_1.22/src/internal/safefilepath/ya.make
+++ /dev/null
@@ -1,13 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- path.go
- path_other.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- path.go
- path_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/syscall/execenv/ya.make b/contrib/go/_std_1.22/src/internal/syscall/execenv/ya.make
deleted file mode 100644
index 523cb40ae2e6..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/execenv/ya.make
+++ /dev/null
@@ -1,11 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- execenv_default.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- execenv_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/at_solaris.go b/contrib/go/_std_1.22/src/internal/syscall/unix/at_solaris.go
deleted file mode 100644
index 4ab224d670b9..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/at_solaris.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 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.
-
-package unix
-
-import "syscall"
-
-// Implemented as sysvicall6 in runtime/syscall_solaris.go.
-func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
-
-//go:cgo_import_dynamic libc_fstatat fstatat "libc.so"
-//go:cgo_import_dynamic libc_openat openat "libc.so"
-//go:cgo_import_dynamic libc_unlinkat unlinkat "libc.so"
-
-const (
- AT_REMOVEDIR = 0x1
- AT_SYMLINK_NOFOLLOW = 0x1000
-
- UTIME_OMIT = -0x2
-)
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_darwin.go b/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_darwin.go
deleted file mode 100644
index 208ff34d038e..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_darwin.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2018 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.
-
-package unix
-
-const AT_REMOVEDIR = 0x80
-const AT_SYMLINK_NOFOLLOW = 0x0020
-
-const UTIME_OMIT = -0x2
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_dragonfly.go b/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_dragonfly.go
deleted file mode 100644
index 9ac1f919f147..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_dragonfly.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 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.
-
-package unix
-
-import "syscall"
-
-const unlinkatTrap uintptr = syscall.SYS_UNLINKAT
-const openatTrap uintptr = syscall.SYS_OPENAT
-const fstatatTrap uintptr = syscall.SYS_FSTATAT
-
-const (
- AT_EACCESS = 0x4
- AT_FDCWD = 0xfffafdcd
- AT_REMOVEDIR = 0x2
- AT_SYMLINK_NOFOLLOW = 0x1
-
- UTIME_OMIT = -0x1
-)
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_openbsd.go b/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_openbsd.go
deleted file mode 100644
index fd389477ec33..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/at_sysnum_openbsd.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 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.
-
-package unix
-
-import "syscall"
-
-const unlinkatTrap uintptr = syscall.SYS_UNLINKAT
-const openatTrap uintptr = syscall.SYS_OPENAT
-const fstatatTrap uintptr = syscall.SYS_FSTATAT
-
-const AT_REMOVEDIR = 0x08
-const AT_SYMLINK_NOFOLLOW = 0x02
-
-const UTIME_OMIT = -0x1
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/constants.go b/contrib/go/_std_1.22/src/internal/syscall/unix/constants.go
deleted file mode 100644
index e3245897055c..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/constants.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2022 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.
-
-//go:build unix
-
-package unix
-
-const (
- R_OK = 0x4
- W_OK = 0x2
- X_OK = 0x1
-)
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/getentropy_darwin.go b/contrib/go/_std_1.22/src/internal/syscall/unix/getentropy_darwin.go
deleted file mode 100644
index 834099ffed64..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/getentropy_darwin.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2021 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.
-
-//go:build darwin && !ios
-
-package unix
-
-import (
- "internal/abi"
- "unsafe"
-)
-
-//go:cgo_import_dynamic libc_getentropy getentropy "/usr/lib/libSystem.B.dylib"
-
-func libc_getentropy_trampoline()
-
-// GetEntropy calls the macOS getentropy system call.
-func GetEntropy(p []byte) error {
- _, _, errno := syscall_syscall(abi.FuncPCABI0(libc_getentropy_trampoline),
- uintptr(unsafe.Pointer(&p[0])),
- uintptr(len(p)),
- 0)
- if errno != 0 {
- return errno
- }
- return nil
-}
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/getentropy_darwin.s b/contrib/go/_std_1.22/src/internal/syscall/unix/getentropy_darwin.s
deleted file mode 100644
index f41e0fe97b09..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/getentropy_darwin.s
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2021 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.
-
-//go:build darwin && !ios
-
-#include "textflag.h"
-
-TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0; JMP libc_getentropy(SB)
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/pidfd_linux.go b/contrib/go/_std_1.22/src/internal/syscall/unix/pidfd_linux.go
deleted file mode 100644
index 02cfaa062cae..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/pidfd_linux.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2023 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.
-
-package unix
-
-import "syscall"
-
-func PidFDSendSignal(pidfd uintptr, s syscall.Signal) error {
- _, _, errno := syscall.Syscall(pidfdSendSignalTrap, pidfd, uintptr(s), 0)
- if errno != 0 {
- return errno
- }
- return nil
-}
diff --git a/contrib/go/_std_1.22/src/internal/syscall/unix/ya.make b/contrib/go/_std_1.22/src/internal/syscall/unix/ya.make
deleted file mode 100644
index a8f44da8e800..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/unix/ya.make
+++ /dev/null
@@ -1,60 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- asm_darwin.s
- at_libc2.go
- at_sysnum_darwin.go
- constants.go
- eaccess_other.go
- fcntl_unix.go
- getentropy_darwin.go
- getentropy_darwin.s
- kernel_version_other.go
- net.go
- net_darwin.go
- nonblocking_unix.go
- pty_darwin.go
- user_darwin.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- at.go
- at_fstatat.go
- at_sysnum_fstatat_linux.go
- at_sysnum_linux.go
- constants.go
- copy_file_range_linux.go
- eaccess_linux.go
- fcntl_unix.go
- getrandom.go
- getrandom_linux.go
- kernel_version_linux.go
- net.go
- nonblocking_unix.go
- pidfd_linux.go
- sysnum_linux_generic.go
- )
-ELSEIF (OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- at.go
- at_fstatat.go
- at_sysnum_linux.go
- at_sysnum_newfstatat_linux.go
- constants.go
- copy_file_range_linux.go
- eaccess_linux.go
- fcntl_unix.go
- getrandom.go
- getrandom_linux.go
- kernel_version_linux.go
- net.go
- nonblocking_unix.go
- pidfd_linux.go
- sysnum_linux_amd64.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- kernel_version_other.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/syscall/windows/net_windows.go b/contrib/go/_std_1.22/src/internal/syscall/windows/net_windows.go
deleted file mode 100644
index 42c600c1447d..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/windows/net_windows.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2021 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.
-
-package windows
-
-import (
- "sync"
- "syscall"
- _ "unsafe"
-)
-
-//go:linkname WSASendtoInet4 syscall.wsaSendtoInet4
-//go:noescape
-func WSASendtoInet4(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet4, overlapped *syscall.Overlapped, croutine *byte) (err error)
-
-//go:linkname WSASendtoInet6 syscall.wsaSendtoInet6
-//go:noescape
-func WSASendtoInet6(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet6, overlapped *syscall.Overlapped, croutine *byte) (err error)
-
-const (
- SIO_TCP_INITIAL_RTO = syscall.IOC_IN | syscall.IOC_VENDOR | 17
- TCP_INITIAL_RTO_UNSPECIFIED_RTT = ^uint16(0)
- TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS = ^uint8(1)
-)
-
-type TCP_INITIAL_RTO_PARAMETERS struct {
- Rtt uint16
- MaxSynRetransmissions uint8
-}
-
-var Support_TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS = sync.OnceValue(func() bool {
- var maj, min, build uint32
- rtlGetNtVersionNumbers(&maj, &min, &build)
- return maj >= 10 && build&0xffff >= 16299
-})
-
-//go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers
-//go:noescape
-func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32)
diff --git a/contrib/go/_std_1.22/src/internal/syscall/windows/syscall_windows.go b/contrib/go/_std_1.22/src/internal/syscall/windows/syscall_windows.go
deleted file mode 100644
index d10e30cb6825..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/windows/syscall_windows.go
+++ /dev/null
@@ -1,445 +0,0 @@
-// Copyright 2014 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.
-
-package windows
-
-import (
- "sync"
- "syscall"
- "unsafe"
-)
-
-// UTF16PtrToString is like UTF16ToString, but takes *uint16
-// as a parameter instead of []uint16.
-func UTF16PtrToString(p *uint16) string {
- if p == nil {
- return ""
- }
- end := unsafe.Pointer(p)
- n := 0
- for *(*uint16)(end) != 0 {
- end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
- n++
- }
- return syscall.UTF16ToString(unsafe.Slice(p, n))
-}
-
-const (
- ERROR_BAD_LENGTH syscall.Errno = 24
- ERROR_SHARING_VIOLATION syscall.Errno = 32
- ERROR_LOCK_VIOLATION syscall.Errno = 33
- ERROR_NOT_SUPPORTED syscall.Errno = 50
- ERROR_CALL_NOT_IMPLEMENTED syscall.Errno = 120
- ERROR_INVALID_NAME syscall.Errno = 123
- ERROR_LOCK_FAILED syscall.Errno = 167
- ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113
-)
-
-const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
-
-const (
- IF_TYPE_OTHER = 1
- IF_TYPE_ETHERNET_CSMACD = 6
- IF_TYPE_ISO88025_TOKENRING = 9
- IF_TYPE_PPP = 23
- IF_TYPE_SOFTWARE_LOOPBACK = 24
- IF_TYPE_ATM = 37
- IF_TYPE_IEEE80211 = 71
- IF_TYPE_TUNNEL = 131
- IF_TYPE_IEEE1394 = 144
-)
-
-type SocketAddress struct {
- Sockaddr *syscall.RawSockaddrAny
- SockaddrLength int32
-}
-
-type IpAdapterUnicastAddress struct {
- Length uint32
- Flags uint32
- Next *IpAdapterUnicastAddress
- Address SocketAddress
- PrefixOrigin int32
- SuffixOrigin int32
- DadState int32
- ValidLifetime uint32
- PreferredLifetime uint32
- LeaseLifetime uint32
- OnLinkPrefixLength uint8
-}
-
-type IpAdapterAnycastAddress struct {
- Length uint32
- Flags uint32
- Next *IpAdapterAnycastAddress
- Address SocketAddress
-}
-
-type IpAdapterMulticastAddress struct {
- Length uint32
- Flags uint32
- Next *IpAdapterMulticastAddress
- Address SocketAddress
-}
-
-type IpAdapterDnsServerAdapter struct {
- Length uint32
- Reserved uint32
- Next *IpAdapterDnsServerAdapter
- Address SocketAddress
-}
-
-type IpAdapterPrefix struct {
- Length uint32
- Flags uint32
- Next *IpAdapterPrefix
- Address SocketAddress
- PrefixLength uint32
-}
-
-type IpAdapterAddresses struct {
- Length uint32
- IfIndex uint32
- Next *IpAdapterAddresses
- AdapterName *byte
- FirstUnicastAddress *IpAdapterUnicastAddress
- FirstAnycastAddress *IpAdapterAnycastAddress
- FirstMulticastAddress *IpAdapterMulticastAddress
- FirstDnsServerAddress *IpAdapterDnsServerAdapter
- DnsSuffix *uint16
- Description *uint16
- FriendlyName *uint16
- PhysicalAddress [syscall.MAX_ADAPTER_ADDRESS_LENGTH]byte
- PhysicalAddressLength uint32
- Flags uint32
- Mtu uint32
- IfType uint32
- OperStatus uint32
- Ipv6IfIndex uint32
- ZoneIndices [16]uint32
- FirstPrefix *IpAdapterPrefix
- /* more fields might be present here. */
-}
-
-type SecurityAttributes struct {
- Length uint16
- SecurityDescriptor uintptr
- InheritHandle bool
-}
-
-type FILE_BASIC_INFO struct {
- CreationTime int64
- LastAccessTime int64
- LastWriteTime int64
- ChangedTime int64
- FileAttributes uint32
-
- // Pad out to 8-byte alignment.
- //
- // Without this padding, TestChmod fails due to an argument validation error
- // in SetFileInformationByHandle on windows/386.
- //
- // https://learn.microsoft.com/en-us/cpp/build/reference/zp-struct-member-alignment?view=msvc-170
- // says that “The C/C++ headers in the Windows SDK assume the platform's
- // default alignment is used.” What we see here is padding rather than
- // alignment, but maybe it is related.
- _ uint32
-}
-
-const (
- IfOperStatusUp = 1
- IfOperStatusDown = 2
- IfOperStatusTesting = 3
- IfOperStatusUnknown = 4
- IfOperStatusDormant = 5
- IfOperStatusNotPresent = 6
- IfOperStatusLowerLayerDown = 7
-)
-
-//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
-//sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
-//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
-//sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
-//sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
-//sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery
-//sys GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W
-
-const (
- // flags for CreateToolhelp32Snapshot
- TH32CS_SNAPMODULE = 0x08
- TH32CS_SNAPMODULE32 = 0x10
-)
-
-const MAX_MODULE_NAME32 = 255
-
-type ModuleEntry32 struct {
- Size uint32
- ModuleID uint32
- ProcessID uint32
- GlblcntUsage uint32
- ProccntUsage uint32
- ModBaseAddr uintptr
- ModBaseSize uint32
- ModuleHandle syscall.Handle
- Module [MAX_MODULE_NAME32 + 1]uint16
- ExePath [syscall.MAX_PATH]uint16
-}
-
-const SizeofModuleEntry32 = unsafe.Sizeof(ModuleEntry32{})
-
-//sys Module32First(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
-//sys Module32Next(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32NextW
-
-const (
- WSA_FLAG_OVERLAPPED = 0x01
- WSA_FLAG_NO_HANDLE_INHERIT = 0x80
-
- WSAEMSGSIZE syscall.Errno = 10040
-
- MSG_PEEK = 0x2
- MSG_TRUNC = 0x0100
- MSG_CTRUNC = 0x0200
-
- socket_error = uintptr(^uint32(0))
-)
-
-var WSAID_WSASENDMSG = syscall.GUID{
- Data1: 0xa441e712,
- Data2: 0x754f,
- Data3: 0x43ca,
- Data4: [8]byte{0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d},
-}
-
-var WSAID_WSARECVMSG = syscall.GUID{
- Data1: 0xf689d7c8,
- Data2: 0x6f1f,
- Data3: 0x436b,
- Data4: [8]byte{0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22},
-}
-
-var sendRecvMsgFunc struct {
- once sync.Once
- sendAddr uintptr
- recvAddr uintptr
- err error
-}
-
-type WSAMsg struct {
- Name syscall.Pointer
- Namelen int32
- Buffers *syscall.WSABuf
- BufferCount uint32
- Control syscall.WSABuf
- Flags uint32
-}
-
-//sys WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = ws2_32.WSASocketW
-
-func loadWSASendRecvMsg() error {
- sendRecvMsgFunc.once.Do(func() {
- var s syscall.Handle
- s, sendRecvMsgFunc.err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
- if sendRecvMsgFunc.err != nil {
- return
- }
- defer syscall.CloseHandle(s)
- var n uint32
- sendRecvMsgFunc.err = syscall.WSAIoctl(s,
- syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
- (*byte)(unsafe.Pointer(&WSAID_WSARECVMSG)),
- uint32(unsafe.Sizeof(WSAID_WSARECVMSG)),
- (*byte)(unsafe.Pointer(&sendRecvMsgFunc.recvAddr)),
- uint32(unsafe.Sizeof(sendRecvMsgFunc.recvAddr)),
- &n, nil, 0)
- if sendRecvMsgFunc.err != nil {
- return
- }
- sendRecvMsgFunc.err = syscall.WSAIoctl(s,
- syscall.SIO_GET_EXTENSION_FUNCTION_POINTER,
- (*byte)(unsafe.Pointer(&WSAID_WSASENDMSG)),
- uint32(unsafe.Sizeof(WSAID_WSASENDMSG)),
- (*byte)(unsafe.Pointer(&sendRecvMsgFunc.sendAddr)),
- uint32(unsafe.Sizeof(sendRecvMsgFunc.sendAddr)),
- &n, nil, 0)
- })
- return sendRecvMsgFunc.err
-}
-
-func WSASendMsg(fd syscall.Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
- err := loadWSASendRecvMsg()
- if err != nil {
- return err
- }
- r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.sendAddr, 6, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
- if r1 == socket_error {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return err
-}
-
-func WSARecvMsg(fd syscall.Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *syscall.Overlapped, croutine *byte) error {
- err := loadWSASendRecvMsg()
- if err != nil {
- return err
- }
- r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.recvAddr, 5, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(bytesReceived)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0)
- if r1 == socket_error {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return err
-}
-
-const (
- ComputerNameNetBIOS = 0
- ComputerNameDnsHostname = 1
- ComputerNameDnsDomain = 2
- ComputerNameDnsFullyQualified = 3
- ComputerNamePhysicalNetBIOS = 4
- ComputerNamePhysicalDnsHostname = 5
- ComputerNamePhysicalDnsDomain = 6
- ComputerNamePhysicalDnsFullyQualified = 7
- ComputerNameMax = 8
-
- MOVEFILE_REPLACE_EXISTING = 0x1
- MOVEFILE_COPY_ALLOWED = 0x2
- MOVEFILE_DELAY_UNTIL_REBOOT = 0x4
- MOVEFILE_WRITE_THROUGH = 0x8
- MOVEFILE_CREATE_HARDLINK = 0x10
- MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20
-)
-
-func Rename(oldpath, newpath string) error {
- from, err := syscall.UTF16PtrFromString(oldpath)
- if err != nil {
- return err
- }
- to, err := syscall.UTF16PtrFromString(newpath)
- if err != nil {
- return err
- }
- return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
-}
-
-//sys LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.LockFileEx
-//sys UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) = kernel32.UnlockFileEx
-
-const (
- LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
- LOCKFILE_EXCLUSIVE_LOCK = 0x00000002
-)
-
-const MB_ERR_INVALID_CHARS = 8
-
-//sys GetACP() (acp uint32) = kernel32.GetACP
-//sys GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
-//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
-//sys GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread
-
-// Constants from lmshare.h
-const (
- STYPE_DISKTREE = 0x00
- STYPE_TEMPORARY = 0x40000000
-)
-
-type SHARE_INFO_2 struct {
- Netname *uint16
- Type uint32
- Remark *uint16
- Permissions uint32
- MaxUses uint32
- CurrentUses uint32
- Path *uint16
- Passwd *uint16
-}
-
-//sys NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd
-//sys NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel
-
-const (
- FILE_NAME_NORMALIZED = 0x0
- FILE_NAME_OPENED = 0x8
-
- VOLUME_NAME_DOS = 0x0
- VOLUME_NAME_GUID = 0x1
- VOLUME_NAME_NONE = 0x4
- VOLUME_NAME_NT = 0x2
-)
-
-//sys GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW
-
-func ErrorLoadingGetTempPath2() error {
- return procGetTempPath2W.Find()
-}
-
-//sys CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
-//sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
-//sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
-
-//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng
-
-type FILE_ID_BOTH_DIR_INFO struct {
- NextEntryOffset uint32
- FileIndex uint32
- CreationTime syscall.Filetime
- LastAccessTime syscall.Filetime
- LastWriteTime syscall.Filetime
- ChangeTime syscall.Filetime
- EndOfFile uint64
- AllocationSize uint64
- FileAttributes uint32
- FileNameLength uint32
- EaSize uint32
- ShortNameLength uint32
- ShortName [12]uint16
- FileID uint64
- FileName [1]uint16
-}
-
-type FILE_FULL_DIR_INFO struct {
- NextEntryOffset uint32
- FileIndex uint32
- CreationTime syscall.Filetime
- LastAccessTime syscall.Filetime
- LastWriteTime syscall.Filetime
- ChangeTime syscall.Filetime
- EndOfFile uint64
- AllocationSize uint64
- FileAttributes uint32
- FileNameLength uint32
- EaSize uint32
- FileName [1]uint16
-}
-
-//sys GetVolumeInformationByHandle(file syscall.Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) = GetVolumeInformationByHandleW
-//sys GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) = GetVolumeNameForVolumeMountPointW
-
-//sys RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry
-//sys RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind
-
-type SERVICE_STATUS struct {
- ServiceType uint32
- CurrentState uint32
- ControlsAccepted uint32
- Win32ExitCode uint32
- ServiceSpecificExitCode uint32
- CheckPoint uint32
- WaitHint uint32
-}
-
-const (
- SERVICE_RUNNING = 4
- SERVICE_QUERY_STATUS = 4
-)
-
-//sys OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) = advapi32.OpenServiceW
-//sys QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error) = advapi32.QueryServiceStatus
-//sys OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error) [failretval==0] = advapi32.OpenSCManagerW
diff --git a/contrib/go/_std_1.22/src/internal/syscall/windows/ya.make b/contrib/go/_std_1.22/src/internal/syscall/windows/ya.make
deleted file mode 100644
index e1b38ff2f290..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/windows/ya.make
+++ /dev/null
@@ -1,14 +0,0 @@
-GO_LIBRARY()
-IF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- memory_windows.go
- net_windows.go
- psapi_windows.go
- reparse_windows.go
- security_windows.go
- symlink_windows.go
- syscall_windows.go
- zsyscall_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/internal/syscall/windows/zsyscall_windows.go b/contrib/go/_std_1.22/src/internal/syscall/windows/zsyscall_windows.go
deleted file mode 100644
index 931f157cf166..000000000000
--- a/contrib/go/_std_1.22/src/internal/syscall/windows/zsyscall_windows.go
+++ /dev/null
@@ -1,436 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package windows
-
-import (
- "internal/syscall/windows/sysdll"
- "syscall"
- "unsafe"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
- errERROR_EINVAL error = syscall.EINVAL
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
- switch e {
- case 0:
- return errERROR_EINVAL
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
- modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
- modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll"))
- modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
- modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
- modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
- modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))
- moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll"))
- modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll"))
-
- procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
- procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
- procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
- procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
- procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW")
- procOpenServiceW = modadvapi32.NewProc("OpenServiceW")
- procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
- procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus")
- procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
- procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
- procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng")
- procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
- procCreateEventW = modkernel32.NewProc("CreateEventW")
- procGetACP = modkernel32.NewProc("GetACP")
- procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
- procGetConsoleCP = modkernel32.NewProc("GetConsoleCP")
- procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
- procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx")
- procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW")
- procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW")
- procGetTempPath2W = modkernel32.NewProc("GetTempPath2W")
- procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW")
- procGetVolumeNameForVolumeMountPointW = modkernel32.NewProc("GetVolumeNameForVolumeMountPointW")
- procLockFileEx = modkernel32.NewProc("LockFileEx")
- procModule32FirstW = modkernel32.NewProc("Module32FirstW")
- procModule32NextW = modkernel32.NewProc("Module32NextW")
- procMoveFileExW = modkernel32.NewProc("MoveFileExW")
- procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar")
- procRtlLookupFunctionEntry = modkernel32.NewProc("RtlLookupFunctionEntry")
- procRtlVirtualUnwind = modkernel32.NewProc("RtlVirtualUnwind")
- procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle")
- procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
- procVirtualQuery = modkernel32.NewProc("VirtualQuery")
- procNetShareAdd = modnetapi32.NewProc("NetShareAdd")
- procNetShareDel = modnetapi32.NewProc("NetShareDel")
- procNetUserGetLocalGroups = modnetapi32.NewProc("NetUserGetLocalGroups")
- procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
- procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock")
- procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock")
- procGetProfilesDirectoryW = moduserenv.NewProc("GetProfilesDirectoryW")
- procWSASocketW = modws2_32.NewProc("WSASocketW")
-)
-
-func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) {
- var _p0 uint32
- if disableAllPrivileges {
- _p0 = 1
- }
- r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
- ret = uint32(r0)
- if true {
- err = errnoErr(e1)
- }
- return
-}
-
-func DuplicateTokenEx(hExistingToken syscall.Token, dwDesiredAccess uint32, lpTokenAttributes *syscall.SecurityAttributes, impersonationLevel uint32, tokenType TokenType, phNewToken *syscall.Token) (err error) {
- r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), uintptr(unsafe.Pointer(lpTokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(phNewToken)))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func ImpersonateSelf(impersonationlevel uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) {
- r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access))
- handle = syscall.Handle(r0)
- if handle == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func OpenService(mgr syscall.Handle, serviceName *uint16, access uint32) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall(procOpenServiceW.Addr(), 3, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access))
- handle = syscall.Handle(r0)
- if handle == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) {
- var _p0 uint32
- if openasself {
- _p0 = 1
- }
- r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(h), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func QueryServiceStatus(hService syscall.Handle, lpServiceStatus *SERVICE_STATUS) (err error) {
- r1, _, e1 := syscall.Syscall(procQueryServiceStatus.Addr(), 2, uintptr(hService), uintptr(unsafe.Pointer(lpServiceStatus)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func RevertToSelf() (err error) {
- r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32, tokenInformation uintptr, tokenInformationLength uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(tokenHandle), uintptr(tokenInformationClass), uintptr(tokenInformation), uintptr(tokenInformationLength), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func ProcessPrng(buf []byte) (err error) {
- var _p0 *byte
- if len(buf) > 0 {
- _p0 = &buf[0]
- }
- r1, _, e1 := syscall.Syscall(procProcessPrng.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
- r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0)
- if r0 != 0 {
- errcode = syscall.Errno(r0)
- }
- return
-}
-
-func CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name)), 0, 0)
- handle = syscall.Handle(r0)
- if handle == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetACP() (acp uint32) {
- r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0)
- acp = uint32(r0)
- return
-}
-
-func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetConsoleCP() (ccp uint32) {
- r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0)
- ccp = uint32(r0)
- return
-}
-
-func GetCurrentThread() (pseudoHandle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
- pseudoHandle = syscall.Handle(r0)
- if pseudoHandle == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byte, bufsize uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(info)), uintptr(bufsize), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) {
- r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0)
- n = uint32(r0)
- if n == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) {
- r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(fn)), uintptr(len))
- n = uint32(r0)
- if n == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) {
- r0, _, e1 := syscall.Syscall(procGetTempPath2W.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
- n = uint32(r0)
- if n == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetVolumeInformationByHandle(file syscall.Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) {
- r1, _, e1 := syscall.Syscall9(procGetVolumeInformationByHandleW.Addr(), 8, uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetVolumeNameForVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) {
- r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func Module32First(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) {
- r1, _, e1 := syscall.Syscall(procModule32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func Module32Next(snapshot syscall.Handle, moduleEntry *ModuleEntry32) (err error) {
- r1, _, e1 := syscall.Syscall(procModule32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(moduleEntry)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) {
- r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar))
- nwrite = int32(r0)
- if nwrite == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) {
- r0, _, _ := syscall.Syscall(procRtlLookupFunctionEntry.Addr(), 3, uintptr(pc), uintptr(unsafe.Pointer(baseAddress)), uintptr(unsafe.Pointer(table)))
- ret = uintptr(r0)
- return
-}
-
-func RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) {
- r0, _, _ := syscall.Syscall9(procRtlVirtualUnwind.Addr(), 8, uintptr(handlerType), uintptr(baseAddress), uintptr(pc), uintptr(entry), uintptr(ctxt), uintptr(unsafe.Pointer(data)), uintptr(unsafe.Pointer(frame)), uintptr(unsafe.Pointer(ctxptrs)), 0)
- ret = uintptr(r0)
- return
-}
-
-func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) {
- r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) {
- r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) {
- r1, _, e1 := syscall.Syscall(procVirtualQuery.Addr(), 3, uintptr(address), uintptr(unsafe.Pointer(buffer)), uintptr(length))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) {
- r0, _, _ := syscall.Syscall6(procNetShareAdd.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(parmErr)), 0, 0)
- if r0 != 0 {
- neterr = syscall.Errno(r0)
- }
- return
-}
-
-func NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) {
- r0, _, _ := syscall.Syscall(procNetShareDel.Addr(), 3, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(netName)), uintptr(reserved))
- if r0 != 0 {
- neterr = syscall.Errno(r0)
- }
- return
-}
-
-func NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, flags uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32) (neterr error) {
- r0, _, _ := syscall.Syscall9(procNetUserGetLocalGroups.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(flags), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), 0)
- if r0 != 0 {
- neterr = syscall.Errno(r0)
- }
- return
-}
-
-func GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(memCounters)), uintptr(cb))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) {
- var _p0 uint32
- if inheritExisting {
- _p0 = 1
- }
- r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0))
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func DestroyEnvironmentBlock(block *uint16) (err error) {
- r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func GetProfilesDirectory(dir *uint16, dirLen *uint32) (err error) {
- r1, _, e1 := syscall.Syscall(procGetProfilesDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) {
- r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags))
- handle = syscall.Handle(r0)
- if handle == syscall.InvalidHandle {
- err = errnoErr(e1)
- }
- return
-}
diff --git a/contrib/go/_std_1.22/src/log/slog/doc.go b/contrib/go/_std_1.22/src/log/slog/doc.go
deleted file mode 100644
index 001559326b3e..000000000000
--- a/contrib/go/_std_1.22/src/log/slog/doc.go
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2022 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.
-
-/*
-Package slog provides structured logging,
-in which log records include a message,
-a severity level, and various other attributes
-expressed as key-value pairs.
-
-It defines a type, [Logger],
-which provides several methods (such as [Logger.Info] and [Logger.Error])
-for reporting events of interest.
-
-Each Logger is associated with a [Handler].
-A Logger output method creates a [Record] from the method arguments
-and passes it to the Handler, which decides how to handle it.
-There is a default Logger accessible through top-level functions
-(such as [Info] and [Error]) that call the corresponding Logger methods.
-
-A log record consists of a time, a level, a message, and a set of key-value
-pairs, where the keys are strings and the values may be of any type.
-As an example,
-
- slog.Info("hello", "count", 3)
-
-creates a record containing the time of the call,
-a level of Info, the message "hello", and a single
-pair with key "count" and value 3.
-
-The [Info] top-level function calls the [Logger.Info] method on the default Logger.
-In addition to [Logger.Info], there are methods for Debug, Warn and Error levels.
-Besides these convenience methods for common levels,
-there is also a [Logger.Log] method which takes the level as an argument.
-Each of these methods has a corresponding top-level function that uses the
-default logger.
-
-The default handler formats the log record's message, time, level, and attributes
-as a string and passes it to the [log] package.
-
- 2022/11/08 15:28:26 INFO hello count=3
-
-For more control over the output format, create a logger with a different handler.
-This statement uses [New] to create a new logger with a [TextHandler]
-that writes structured records in text form to standard error:
-
- logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
-
-[TextHandler] output is a sequence of key=value pairs, easily and unambiguously
-parsed by machine. This statement:
-
- logger.Info("hello", "count", 3)
-
-produces this output:
-
- time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3
-
-The package also provides [JSONHandler], whose output is line-delimited JSON:
-
- logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
- logger.Info("hello", "count", 3)
-
-produces this output:
-
- {"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3}
-
-Both [TextHandler] and [JSONHandler] can be configured with [HandlerOptions].
-There are options for setting the minimum level (see Levels, below),
-displaying the source file and line of the log call, and
-modifying attributes before they are logged.
-
-Setting a logger as the default with
-
- slog.SetDefault(logger)
-
-will cause the top-level functions like [Info] to use it.
-[SetDefault] also updates the default logger used by the [log] package,
-so that existing applications that use [log.Printf] and related functions
-will send log records to the logger's handler without needing to be rewritten.
-
-Some attributes are common to many log calls.
-For example, you may wish to include the URL or trace identifier of a server request
-with all log events arising from the request.
-Rather than repeat the attribute with every log call, you can use [Logger.With]
-to construct a new Logger containing the attributes:
-
- logger2 := logger.With("url", r.URL)
-
-The arguments to With are the same key-value pairs used in [Logger.Info].
-The result is a new Logger with the same handler as the original, but additional
-attributes that will appear in the output of every call.
-
-# Levels
-
-A [Level] is an integer representing the importance or severity of a log event.
-The higher the level, the more severe the event.
-This package defines constants for the most common levels,
-but any int can be used as a level.
-
-In an application, you may wish to log messages only at a certain level or greater.
-One common configuration is to log messages at Info or higher levels,
-suppressing debug logging until it is needed.
-The built-in handlers can be configured with the minimum level to output by
-setting [HandlerOptions.Level].
-The program's `main` function typically does this.
-The default value is LevelInfo.
-
-Setting the [HandlerOptions.Level] field to a [Level] value
-fixes the handler's minimum level throughout its lifetime.
-Setting it to a [LevelVar] allows the level to be varied dynamically.
-A LevelVar holds a Level and is safe to read or write from multiple
-goroutines.
-To vary the level dynamically for an entire program, first initialize
-a global LevelVar:
-
- var programLevel = new(slog.LevelVar) // Info by default
-
-Then use the LevelVar to construct a handler, and make it the default:
-
- h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel})
- slog.SetDefault(slog.New(h))
-
-Now the program can change its logging level with a single statement:
-
- programLevel.Set(slog.LevelDebug)
-
-# Groups
-
-Attributes can be collected into groups.
-A group has a name that is used to qualify the names of its attributes.
-How this qualification is displayed depends on the handler.
-[TextHandler] separates the group and attribute names with a dot.
-[JSONHandler] treats each group as a separate JSON object, with the group name as the key.
-
-Use [Group] to create a Group attribute from a name and a list of key-value pairs:
-
- slog.Group("request",
- "method", r.Method,
- "url", r.URL)
-
-TextHandler would display this group as
-
- request.method=GET request.url=http://example.com
-
-JSONHandler would display it as
-
- "request":{"method":"GET","url":"http://example.com"}
-
-Use [Logger.WithGroup] to qualify all of a Logger's output
-with a group name. Calling WithGroup on a Logger results in a
-new Logger with the same Handler as the original, but with all
-its attributes qualified by the group name.
-
-This can help prevent duplicate attribute keys in large systems,
-where subsystems might use the same keys.
-Pass each subsystem a different Logger with its own group name so that
-potential duplicates are qualified:
-
- logger := slog.Default().With("id", systemID)
- parserLogger := logger.WithGroup("parser")
- parseInput(input, parserLogger)
-
-When parseInput logs with parserLogger, its keys will be qualified with "parser",
-so even if it uses the common key "id", the log line will have distinct keys.
-
-# Contexts
-
-Some handlers may wish to include information from the [context.Context] that is
-available at the call site. One example of such information
-is the identifier for the current span when tracing is enabled.
-
-The [Logger.Log] and [Logger.LogAttrs] methods take a context as a first
-argument, as do their corresponding top-level functions.
-
-Although the convenience methods on Logger (Info and so on) and the
-corresponding top-level functions do not take a context, the alternatives ending
-in "Context" do. For example,
-
- slog.InfoContext(ctx, "message")
-
-It is recommended to pass a context to an output method if one is available.
-
-# Attrs and Values
-
-An [Attr] is a key-value pair. The Logger output methods accept Attrs as well as
-alternating keys and values. The statement
-
- slog.Info("hello", slog.Int("count", 3))
-
-behaves the same as
-
- slog.Info("hello", "count", 3)
-
-There are convenience constructors for [Attr] such as [Int], [String], and [Bool]
-for common types, as well as the function [Any] for constructing Attrs of any
-type.
-
-The value part of an Attr is a type called [Value].
-Like an [any], a Value can hold any Go value,
-but it can represent typical values, including all numbers and strings,
-without an allocation.
-
-For the most efficient log output, use [Logger.LogAttrs].
-It is similar to [Logger.Log] but accepts only Attrs, not alternating
-keys and values; this allows it, too, to avoid allocation.
-
-The call
-
- logger.LogAttrs(ctx, slog.LevelInfo, "hello", slog.Int("count", 3))
-
-is the most efficient way to achieve the same output as
-
- slog.InfoContext(ctx, "hello", "count", 3)
-
-# Customizing a type's logging behavior
-
-If a type implements the [LogValuer] interface, the [Value] returned from its LogValue
-method is used for logging. You can use this to control how values of the type
-appear in logs. For example, you can redact secret information like passwords,
-or gather a struct's fields in a Group. See the examples under [LogValuer] for
-details.
-
-A LogValue method may return a Value that itself implements [LogValuer]. The [Value.Resolve]
-method handles these cases carefully, avoiding infinite loops and unbounded recursion.
-Handler authors and others may wish to use [Value.Resolve] instead of calling LogValue directly.
-
-# Wrapping output methods
-
-The logger functions use reflection over the call stack to find the file name
-and line number of the logging call within the application. This can produce
-incorrect source information for functions that wrap slog. For instance, if you
-define this function in file mylog.go:
-
- func Infof(logger *slog.Logger, format string, args ...any) {
- logger.Info(fmt.Sprintf(format, args...))
- }
-
-and you call it like this in main.go:
-
- Infof(slog.Default(), "hello, %s", "world")
-
-then slog will report the source file as mylog.go, not main.go.
-
-A correct implementation of Infof will obtain the source location
-(pc) and pass it to NewRecord.
-The Infof function in the package-level example called "wrapping"
-demonstrates how to do this.
-
-# Working with Records
-
-Sometimes a Handler will need to modify a Record
-before passing it on to another Handler or backend.
-A Record contains a mixture of simple public fields (e.g. Time, Level, Message)
-and hidden fields that refer to state (such as attributes) indirectly. This
-means that modifying a simple copy of a Record (e.g. by calling
-[Record.Add] or [Record.AddAttrs] to add attributes)
-may have unexpected effects on the original.
-Before modifying a Record, use [Record.Clone] to
-create a copy that shares no state with the original,
-or create a new Record with [NewRecord]
-and build up its Attrs by traversing the old ones with [Record.Attrs].
-
-# Performance considerations
-
-If profiling your application demonstrates that logging is taking significant time,
-the following suggestions may help.
-
-If many log lines have a common attribute, use [Logger.With] to create a Logger with
-that attribute. The built-in handlers will format that attribute only once, at the
-call to [Logger.With]. The [Handler] interface is designed to allow that optimization,
-and a well-written Handler should take advantage of it.
-
-The arguments to a log call are always evaluated, even if the log event is discarded.
-If possible, defer computation so that it happens only if the value is actually logged.
-For example, consider the call
-
- slog.Info("starting request", "url", r.URL.String()) // may compute String unnecessarily
-
-The URL.String method will be called even if the logger discards Info-level events.
-Instead, pass the URL directly:
-
- slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed
-
-The built-in [TextHandler] will call its String method, but only
-if the log event is enabled.
-Avoiding the call to String also preserves the structure of the underlying value.
-For example [JSONHandler] emits the components of the parsed URL as a JSON object.
-If you want to avoid eagerly paying the cost of the String call
-without causing the handler to potentially inspect the structure of the value,
-wrap the value in a fmt.Stringer implementation that hides its Marshal methods.
-
-You can also use the [LogValuer] interface to avoid unnecessary work in disabled log
-calls. Say you need to log some expensive value:
-
- slog.Debug("frobbing", "value", computeExpensiveValue(arg))
-
-Even if this line is disabled, computeExpensiveValue will be called.
-To avoid that, define a type implementing LogValuer:
-
- type expensive struct { arg int }
-
- func (e expensive) LogValue() slog.Value {
- return slog.AnyValue(computeExpensiveValue(e.arg))
- }
-
-Then use a value of that type in log calls:
-
- slog.Debug("frobbing", "value", expensive{arg})
-
-Now computeExpensiveValue will only be called when the line is enabled.
-
-The built-in handlers acquire a lock before calling [io.Writer.Write]
-to ensure that each record is written in one piece. User-defined
-handlers are responsible for their own locking.
-
-# Writing a handler
-
-For a guide to writing a custom handler, see https://golang.org/s/slog-handler-guide.
-*/
-package slog
diff --git a/contrib/go/_std_1.22/src/log/slog/internal/buffer/buffer.go b/contrib/go/_std_1.22/src/log/slog/internal/buffer/buffer.go
deleted file mode 100644
index 310ec37d4a12..000000000000
--- a/contrib/go/_std_1.22/src/log/slog/internal/buffer/buffer.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2022 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.
-
-// Package buffer provides a pool-allocated byte buffer.
-package buffer
-
-import "sync"
-
-// buffer adapted from go/src/fmt/print.go
-type Buffer []byte
-
-// Having an initial size gives a dramatic speedup.
-var bufPool = sync.Pool{
- New: func() any {
- b := make([]byte, 0, 1024)
- return (*Buffer)(&b)
- },
-}
-
-func New() *Buffer {
- return bufPool.Get().(*Buffer)
-}
-
-func (b *Buffer) Free() {
- // To reduce peak allocation, return only smaller buffers to the pool.
- const maxBufferSize = 16 << 10
- if cap(*b) <= maxBufferSize {
- *b = (*b)[:0]
- bufPool.Put(b)
- }
-}
-
-func (b *Buffer) Reset() {
- b.SetLen(0)
-}
-
-func (b *Buffer) Write(p []byte) (int, error) {
- *b = append(*b, p...)
- return len(p), nil
-}
-
-func (b *Buffer) WriteString(s string) (int, error) {
- *b = append(*b, s...)
- return len(s), nil
-}
-
-func (b *Buffer) WriteByte(c byte) error {
- *b = append(*b, c)
- return nil
-}
-
-func (b *Buffer) String() string {
- return string(*b)
-}
-
-func (b *Buffer) Len() int {
- return len(*b)
-}
-
-func (b *Buffer) SetLen(n int) {
- *b = (*b)[:n]
-}
diff --git a/contrib/go/_std_1.22/src/log/slog/value.go b/contrib/go/_std_1.22/src/log/slog/value.go
deleted file mode 100644
index d278d9b92355..000000000000
--- a/contrib/go/_std_1.22/src/log/slog/value.go
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2022 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.
-
-package slog
-
-import (
- "fmt"
- "math"
- "runtime"
- "slices"
- "strconv"
- "strings"
- "time"
- "unsafe"
-)
-
-// A Value can represent any Go value, but unlike type any,
-// it can represent most small values without an allocation.
-// The zero Value corresponds to nil.
-type Value struct {
- _ [0]func() // disallow ==
- // num holds the value for Kinds Int64, Uint64, Float64, Bool and Duration,
- // the string length for KindString, and nanoseconds since the epoch for KindTime.
- num uint64
- // If any is of type Kind, then the value is in num as described above.
- // If any is of type *time.Location, then the Kind is Time and time.Time value
- // can be constructed from the Unix nanos in num and the location (monotonic time
- // is not preserved).
- // If any is of type stringptr, then the Kind is String and the string value
- // consists of the length in num and the pointer in any.
- // Otherwise, the Kind is Any and any is the value.
- // (This implies that Attrs cannot store values of type Kind, *time.Location
- // or stringptr.)
- any any
-}
-
-type (
- stringptr *byte // used in Value.any when the Value is a string
- groupptr *Attr // used in Value.any when the Value is a []Attr
-)
-
-// Kind is the kind of a [Value].
-type Kind int
-
-// The following list is sorted alphabetically, but it's also important that
-// KindAny is 0 so that a zero Value represents nil.
-
-const (
- KindAny Kind = iota
- KindBool
- KindDuration
- KindFloat64
- KindInt64
- KindString
- KindTime
- KindUint64
- KindGroup
- KindLogValuer
-)
-
-var kindStrings = []string{
- "Any",
- "Bool",
- "Duration",
- "Float64",
- "Int64",
- "String",
- "Time",
- "Uint64",
- "Group",
- "LogValuer",
-}
-
-func (k Kind) String() string {
- if k >= 0 && int(k) < len(kindStrings) {
- return kindStrings[k]
- }
- return ""
-}
-
-// Unexported version of Kind, just so we can store Kinds in Values.
-// (No user-provided value has this type.)
-type kind Kind
-
-// Kind returns v's Kind.
-func (v Value) Kind() Kind {
- switch x := v.any.(type) {
- case Kind:
- return x
- case stringptr:
- return KindString
- case timeLocation:
- return KindTime
- case groupptr:
- return KindGroup
- case LogValuer:
- return KindLogValuer
- case kind: // a kind is just a wrapper for a Kind
- return KindAny
- default:
- return KindAny
- }
-}
-
-//////////////// Constructors
-
-// StringValue returns a new [Value] for a string.
-func StringValue(value string) Value {
- return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))}
-}
-
-// IntValue returns a [Value] for an int.
-func IntValue(v int) Value {
- return Int64Value(int64(v))
-}
-
-// Int64Value returns a [Value] for an int64.
-func Int64Value(v int64) Value {
- return Value{num: uint64(v), any: KindInt64}
-}
-
-// Uint64Value returns a [Value] for a uint64.
-func Uint64Value(v uint64) Value {
- return Value{num: v, any: KindUint64}
-}
-
-// Float64Value returns a [Value] for a floating-point number.
-func Float64Value(v float64) Value {
- return Value{num: math.Float64bits(v), any: KindFloat64}
-}
-
-// BoolValue returns a [Value] for a bool.
-func BoolValue(v bool) Value {
- u := uint64(0)
- if v {
- u = 1
- }
- return Value{num: u, any: KindBool}
-}
-
-// Unexported version of *time.Location, just so we can store *time.Locations in
-// Values. (No user-provided value has this type.)
-type timeLocation *time.Location
-
-// TimeValue returns a [Value] for a [time.Time].
-// It discards the monotonic portion.
-func TimeValue(v time.Time) Value {
- if v.IsZero() {
- // UnixNano on the zero time is undefined, so represent the zero time
- // with a nil *time.Location instead. time.Time.Location method never
- // returns nil, so a Value with any == timeLocation(nil) cannot be
- // mistaken for any other Value, time.Time or otherwise.
- return Value{any: timeLocation(nil)}
- }
- return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())}
-}
-
-// DurationValue returns a [Value] for a [time.Duration].
-func DurationValue(v time.Duration) Value {
- return Value{num: uint64(v.Nanoseconds()), any: KindDuration}
-}
-
-// GroupValue returns a new [Value] for a list of Attrs.
-// The caller must not subsequently mutate the argument slice.
-func GroupValue(as ...Attr) Value {
- // Remove empty groups.
- // It is simpler overall to do this at construction than
- // to check each Group recursively for emptiness.
- if n := countEmptyGroups(as); n > 0 {
- as2 := make([]Attr, 0, len(as)-n)
- for _, a := range as {
- if !a.Value.isEmptyGroup() {
- as2 = append(as2, a)
- }
- }
- as = as2
- }
- return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))}
-}
-
-// countEmptyGroups returns the number of empty group values in its argument.
-func countEmptyGroups(as []Attr) int {
- n := 0
- for _, a := range as {
- if a.Value.isEmptyGroup() {
- n++
- }
- }
- return n
-}
-
-// AnyValue returns a [Value] for the supplied value.
-//
-// If the supplied value is of type Value, it is returned
-// unmodified.
-//
-// Given a value of one of Go's predeclared string, bool, or
-// (non-complex) numeric types, AnyValue returns a Value of kind
-// [KindString], [KindBool], [KindUint64], [KindInt64], or [KindFloat64].
-// The width of the original numeric type is not preserved.
-//
-// Given a [time.Time] or [time.Duration] value, AnyValue returns a Value of kind
-// [KindTime] or [KindDuration]. The monotonic time is not preserved.
-//
-// For nil, or values of all other types, including named types whose
-// underlying type is numeric, AnyValue returns a value of kind [KindAny].
-func AnyValue(v any) Value {
- switch v := v.(type) {
- case string:
- return StringValue(v)
- case int:
- return Int64Value(int64(v))
- case uint:
- return Uint64Value(uint64(v))
- case int64:
- return Int64Value(v)
- case uint64:
- return Uint64Value(v)
- case bool:
- return BoolValue(v)
- case time.Duration:
- return DurationValue(v)
- case time.Time:
- return TimeValue(v)
- case uint8:
- return Uint64Value(uint64(v))
- case uint16:
- return Uint64Value(uint64(v))
- case uint32:
- return Uint64Value(uint64(v))
- case uintptr:
- return Uint64Value(uint64(v))
- case int8:
- return Int64Value(int64(v))
- case int16:
- return Int64Value(int64(v))
- case int32:
- return Int64Value(int64(v))
- case float64:
- return Float64Value(v)
- case float32:
- return Float64Value(float64(v))
- case []Attr:
- return GroupValue(v...)
- case Kind:
- return Value{any: kind(v)}
- case Value:
- return v
- default:
- return Value{any: v}
- }
-}
-
-//////////////// Accessors
-
-// Any returns v's value as an any.
-func (v Value) Any() any {
- switch v.Kind() {
- case KindAny:
- if k, ok := v.any.(kind); ok {
- return Kind(k)
- }
- return v.any
- case KindLogValuer:
- return v.any
- case KindGroup:
- return v.group()
- case KindInt64:
- return int64(v.num)
- case KindUint64:
- return v.num
- case KindFloat64:
- return v.float()
- case KindString:
- return v.str()
- case KindBool:
- return v.bool()
- case KindDuration:
- return v.duration()
- case KindTime:
- return v.time()
- default:
- panic(fmt.Sprintf("bad kind: %s", v.Kind()))
- }
-}
-
-// String returns Value's value as a string, formatted like [fmt.Sprint]. Unlike
-// the methods Int64, Float64, and so on, which panic if v is of the
-// wrong kind, String never panics.
-func (v Value) String() string {
- if sp, ok := v.any.(stringptr); ok {
- return unsafe.String(sp, v.num)
- }
- var buf []byte
- return string(v.append(buf))
-}
-
-func (v Value) str() string {
- return unsafe.String(v.any.(stringptr), v.num)
-}
-
-// Int64 returns v's value as an int64. It panics
-// if v is not a signed integer.
-func (v Value) Int64() int64 {
- if g, w := v.Kind(), KindInt64; g != w {
- panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
- }
- return int64(v.num)
-}
-
-// Uint64 returns v's value as a uint64. It panics
-// if v is not an unsigned integer.
-func (v Value) Uint64() uint64 {
- if g, w := v.Kind(), KindUint64; g != w {
- panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
- }
- return v.num
-}
-
-// Bool returns v's value as a bool. It panics
-// if v is not a bool.
-func (v Value) Bool() bool {
- if g, w := v.Kind(), KindBool; g != w {
- panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
- }
- return v.bool()
-}
-
-func (v Value) bool() bool {
- return v.num == 1
-}
-
-// Duration returns v's value as a [time.Duration]. It panics
-// if v is not a time.Duration.
-func (v Value) Duration() time.Duration {
- if g, w := v.Kind(), KindDuration; g != w {
- panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
- }
-
- return v.duration()
-}
-
-func (v Value) duration() time.Duration {
- return time.Duration(int64(v.num))
-}
-
-// Float64 returns v's value as a float64. It panics
-// if v is not a float64.
-func (v Value) Float64() float64 {
- if g, w := v.Kind(), KindFloat64; g != w {
- panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
- }
-
- return v.float()
-}
-
-func (v Value) float() float64 {
- return math.Float64frombits(v.num)
-}
-
-// Time returns v's value as a [time.Time]. It panics
-// if v is not a time.Time.
-func (v Value) Time() time.Time {
- if g, w := v.Kind(), KindTime; g != w {
- panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
- }
- return v.time()
-}
-
-func (v Value) time() time.Time {
- loc := v.any.(timeLocation)
- if loc == nil {
- return time.Time{}
- }
- return time.Unix(0, int64(v.num)).In(loc)
-}
-
-// LogValuer returns v's value as a LogValuer. It panics
-// if v is not a LogValuer.
-func (v Value) LogValuer() LogValuer {
- return v.any.(LogValuer)
-}
-
-// Group returns v's value as a []Attr.
-// It panics if v's [Kind] is not [KindGroup].
-func (v Value) Group() []Attr {
- if sp, ok := v.any.(groupptr); ok {
- return unsafe.Slice((*Attr)(sp), v.num)
- }
- panic("Group: bad kind")
-}
-
-func (v Value) group() []Attr {
- return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num)
-}
-
-//////////////// Other
-
-// Equal reports whether v and w represent the same Go value.
-func (v Value) Equal(w Value) bool {
- k1 := v.Kind()
- k2 := w.Kind()
- if k1 != k2 {
- return false
- }
- switch k1 {
- case KindInt64, KindUint64, KindBool, KindDuration:
- return v.num == w.num
- case KindString:
- return v.str() == w.str()
- case KindFloat64:
- return v.float() == w.float()
- case KindTime:
- return v.time().Equal(w.time())
- case KindAny, KindLogValuer:
- return v.any == w.any // may panic if non-comparable
- case KindGroup:
- return slices.EqualFunc(v.group(), w.group(), Attr.Equal)
- default:
- panic(fmt.Sprintf("bad kind: %s", k1))
- }
-}
-
-// isEmptyGroup reports whether v is a group that has no attributes.
-func (v Value) isEmptyGroup() bool {
- if v.Kind() != KindGroup {
- return false
- }
- // We do not need to recursively examine the group's Attrs for emptiness,
- // because GroupValue removed them when the group was constructed, and
- // groups are immutable.
- return len(v.group()) == 0
-}
-
-// append appends a text representation of v to dst.
-// v is formatted as with fmt.Sprint.
-func (v Value) append(dst []byte) []byte {
- switch v.Kind() {
- case KindString:
- return append(dst, v.str()...)
- case KindInt64:
- return strconv.AppendInt(dst, int64(v.num), 10)
- case KindUint64:
- return strconv.AppendUint(dst, v.num, 10)
- case KindFloat64:
- return strconv.AppendFloat(dst, v.float(), 'g', -1, 64)
- case KindBool:
- return strconv.AppendBool(dst, v.bool())
- case KindDuration:
- return append(dst, v.duration().String()...)
- case KindTime:
- return append(dst, v.time().String()...)
- case KindGroup:
- return fmt.Append(dst, v.group())
- case KindAny, KindLogValuer:
- return fmt.Append(dst, v.any)
- default:
- panic(fmt.Sprintf("bad kind: %s", v.Kind()))
- }
-}
-
-// A LogValuer is any Go value that can convert itself into a Value for logging.
-//
-// This mechanism may be used to defer expensive operations until they are
-// needed, or to expand a single value into a sequence of components.
-type LogValuer interface {
- LogValue() Value
-}
-
-const maxLogValues = 100
-
-// Resolve repeatedly calls LogValue on v while it implements [LogValuer],
-// and returns the result.
-// If v resolves to a group, the group's attributes' values are not recursively
-// resolved.
-// If the number of LogValue calls exceeds a threshold, a Value containing an
-// error is returned.
-// Resolve's return value is guaranteed not to be of Kind [KindLogValuer].
-func (v Value) Resolve() (rv Value) {
- orig := v
- defer func() {
- if r := recover(); r != nil {
- rv = AnyValue(fmt.Errorf("LogValue panicked\n%s", stack(3, 5)))
- }
- }()
-
- for i := 0; i < maxLogValues; i++ {
- if v.Kind() != KindLogValuer {
- return v
- }
- v = v.LogValuer().LogValue()
- }
- err := fmt.Errorf("LogValue called too many times on Value of type %T", orig.Any())
- return AnyValue(err)
-}
-
-func stack(skip, nFrames int) string {
- pcs := make([]uintptr, nFrames+1)
- n := runtime.Callers(skip+1, pcs)
- if n == 0 {
- return "(no stack)"
- }
- frames := runtime.CallersFrames(pcs[:n])
- var b strings.Builder
- i := 0
- for {
- frame, more := frames.Next()
- fmt.Fprintf(&b, "called from %s (%s:%d)\n", frame.Function, frame.File, frame.Line)
- if !more {
- break
- }
- i++
- if i >= nFrames {
- fmt.Fprintf(&b, "(rest of stack elided)\n")
- break
- }
- }
- return b.String()
-}
diff --git a/contrib/go/_std_1.22/src/log/syslog/ya.make b/contrib/go/_std_1.22/src/log/syslog/ya.make
deleted file mode 100644
index a0bf92b6113f..000000000000
--- a/contrib/go/_std_1.22/src/log/syslog/ya.make
+++ /dev/null
@@ -1,15 +0,0 @@
-SUBSCRIBER(g:contrib)
-
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- doc.go
- syslog.go
- syslog_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- doc.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/math/big/arith_decl.go b/contrib/go/_std_1.22/src/math/big/arith_decl.go
deleted file mode 100644
index f14f8d6794ee..000000000000
--- a/contrib/go/_std_1.22/src/math/big/arith_decl.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2010 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.
-
-//go:build !math_big_pure_go
-
-package big
-
-// implemented in arith_$GOARCH.s
-
-//go:noescape
-func addVV(z, x, y []Word) (c Word)
-
-//go:noescape
-func subVV(z, x, y []Word) (c Word)
-
-//go:noescape
-func addVW(z, x []Word, y Word) (c Word)
-
-//go:noescape
-func subVW(z, x []Word, y Word) (c Word)
-
-//go:noescape
-func shlVU(z, x []Word, s uint) (c Word)
-
-//go:noescape
-func shrVU(z, x []Word, s uint) (c Word)
-
-//go:noescape
-func mulAddVWW(z, x []Word, y, r Word) (c Word)
-
-//go:noescape
-func addMulVVW(z, x []Word, y Word) (c Word)
diff --git a/contrib/go/_std_1.22/src/math/big/nat.go b/contrib/go/_std_1.22/src/math/big/nat.go
deleted file mode 100644
index ecb7d363d4fb..000000000000
--- a/contrib/go/_std_1.22/src/math/big/nat.go
+++ /dev/null
@@ -1,1422 +0,0 @@
-// Copyright 2009 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.
-
-// This file implements unsigned multi-precision integers (natural
-// numbers). They are the building blocks for the implementation
-// of signed integers, rationals, and floating-point numbers.
-//
-// Caution: This implementation relies on the function "alias"
-// which assumes that (nat) slice capacities are never
-// changed (no 3-operand slice expressions). If that
-// changes, alias needs to be updated for correctness.
-
-package big
-
-import (
- "encoding/binary"
- "math/bits"
- "math/rand"
- "sync"
-)
-
-// An unsigned integer x of the form
-//
-// x = x[n-1]*_B^(n-1) + x[n-2]*_B^(n-2) + ... + x[1]*_B + x[0]
-//
-// with 0 <= x[i] < _B and 0 <= i < n is stored in a slice of length n,
-// with the digits x[i] as the slice elements.
-//
-// A number is normalized if the slice contains no leading 0 digits.
-// During arithmetic operations, denormalized values may occur but are
-// always normalized before returning the final result. The normalized
-// representation of 0 is the empty or nil slice (length = 0).
-type nat []Word
-
-var (
- natOne = nat{1}
- natTwo = nat{2}
- natFive = nat{5}
- natTen = nat{10}
-)
-
-func (z nat) String() string {
- return "0x" + string(z.itoa(false, 16))
-}
-
-func (z nat) clear() {
- for i := range z {
- z[i] = 0
- }
-}
-
-func (z nat) norm() nat {
- i := len(z)
- for i > 0 && z[i-1] == 0 {
- i--
- }
- return z[0:i]
-}
-
-func (z nat) make(n int) nat {
- if n <= cap(z) {
- return z[:n] // reuse z
- }
- if n == 1 {
- // Most nats start small and stay that way; don't over-allocate.
- return make(nat, 1)
- }
- // Choosing a good value for e has significant performance impact
- // because it increases the chance that a value can be reused.
- const e = 4 // extra capacity
- return make(nat, n, n+e)
-}
-
-func (z nat) setWord(x Word) nat {
- if x == 0 {
- return z[:0]
- }
- z = z.make(1)
- z[0] = x
- return z
-}
-
-func (z nat) setUint64(x uint64) nat {
- // single-word value
- if w := Word(x); uint64(w) == x {
- return z.setWord(w)
- }
- // 2-word value
- z = z.make(2)
- z[1] = Word(x >> 32)
- z[0] = Word(x)
- return z
-}
-
-func (z nat) set(x nat) nat {
- z = z.make(len(x))
- copy(z, x)
- return z
-}
-
-func (z nat) add(x, y nat) nat {
- m := len(x)
- n := len(y)
-
- switch {
- case m < n:
- return z.add(y, x)
- case m == 0:
- // n == 0 because m >= n; result is 0
- return z[:0]
- case n == 0:
- // result is x
- return z.set(x)
- }
- // m > 0
-
- z = z.make(m + 1)
- c := addVV(z[0:n], x, y)
- if m > n {
- c = addVW(z[n:m], x[n:], c)
- }
- z[m] = c
-
- return z.norm()
-}
-
-func (z nat) sub(x, y nat) nat {
- m := len(x)
- n := len(y)
-
- switch {
- case m < n:
- panic("underflow")
- case m == 0:
- // n == 0 because m >= n; result is 0
- return z[:0]
- case n == 0:
- // result is x
- return z.set(x)
- }
- // m > 0
-
- z = z.make(m)
- c := subVV(z[0:n], x, y)
- if m > n {
- c = subVW(z[n:], x[n:], c)
- }
- if c != 0 {
- panic("underflow")
- }
-
- return z.norm()
-}
-
-func (x nat) cmp(y nat) (r int) {
- m := len(x)
- n := len(y)
- if m != n || m == 0 {
- switch {
- case m < n:
- r = -1
- case m > n:
- r = 1
- }
- return
- }
-
- i := m - 1
- for i > 0 && x[i] == y[i] {
- i--
- }
-
- switch {
- case x[i] < y[i]:
- r = -1
- case x[i] > y[i]:
- r = 1
- }
- return
-}
-
-func (z nat) mulAddWW(x nat, y, r Word) nat {
- m := len(x)
- if m == 0 || y == 0 {
- return z.setWord(r) // result is r
- }
- // m > 0
-
- z = z.make(m + 1)
- z[m] = mulAddVWW(z[0:m], x, y, r)
-
- return z.norm()
-}
-
-// basicMul multiplies x and y and leaves the result in z.
-// The (non-normalized) result is placed in z[0 : len(x) + len(y)].
-func basicMul(z, x, y nat) {
- z[0 : len(x)+len(y)].clear() // initialize z
- for i, d := range y {
- if d != 0 {
- z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
- }
- }
-}
-
-// montgomery computes z mod m = x*y*2**(-n*_W) mod m,
-// assuming k = -1/m mod 2**_W.
-// z is used for storing the result which is returned;
-// z must not alias x, y or m.
-// See Gueron, "Efficient Software Implementations of Modular Exponentiation".
-// https://eprint.iacr.org/2011/239.pdf
-// In the terminology of that paper, this is an "Almost Montgomery Multiplication":
-// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result
-// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m.
-func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
- // This code assumes x, y, m are all the same length, n.
- // (required by addMulVVW and the for loop).
- // It also assumes that x, y are already reduced mod m,
- // or else the result will not be properly reduced.
- if len(x) != n || len(y) != n || len(m) != n {
- panic("math/big: mismatched montgomery number lengths")
- }
- z = z.make(n * 2)
- z.clear()
- var c Word
- for i := 0; i < n; i++ {
- d := y[i]
- c2 := addMulVVW(z[i:n+i], x, d)
- t := z[i] * k
- c3 := addMulVVW(z[i:n+i], m, t)
- cx := c + c2
- cy := cx + c3
- z[n+i] = cy
- if cx < c2 || cy < c3 {
- c = 1
- } else {
- c = 0
- }
- }
- if c != 0 {
- subVV(z[:n], z[n:], m)
- } else {
- copy(z[:n], z[n:])
- }
- return z[:n]
-}
-
-// Fast version of z[0:n+n>>1].add(z[0:n+n>>1], x[0:n]) w/o bounds checks.
-// Factored out for readability - do not use outside karatsuba.
-func karatsubaAdd(z, x nat, n int) {
- if c := addVV(z[0:n], z, x); c != 0 {
- addVW(z[n:n+n>>1], z[n:], c)
- }
-}
-
-// Like karatsubaAdd, but does subtract.
-func karatsubaSub(z, x nat, n int) {
- if c := subVV(z[0:n], z, x); c != 0 {
- subVW(z[n:n+n>>1], z[n:], c)
- }
-}
-
-// Operands that are shorter than karatsubaThreshold are multiplied using
-// "grade school" multiplication; for longer operands the Karatsuba algorithm
-// is used.
-var karatsubaThreshold = 40 // computed by calibrate_test.go
-
-// karatsuba multiplies x and y and leaves the result in z.
-// Both x and y must have the same length n and n must be a
-// power of 2. The result vector z must have len(z) >= 6*n.
-// The (non-normalized) result is placed in z[0 : 2*n].
-func karatsuba(z, x, y nat) {
- n := len(y)
-
- // Switch to basic multiplication if numbers are odd or small.
- // (n is always even if karatsubaThreshold is even, but be
- // conservative)
- if n&1 != 0 || n < karatsubaThreshold || n < 2 {
- basicMul(z, x, y)
- return
- }
- // n&1 == 0 && n >= karatsubaThreshold && n >= 2
-
- // Karatsuba multiplication is based on the observation that
- // for two numbers x and y with:
- //
- // x = x1*b + x0
- // y = y1*b + y0
- //
- // the product x*y can be obtained with 3 products z2, z1, z0
- // instead of 4:
- //
- // x*y = x1*y1*b*b + (x1*y0 + x0*y1)*b + x0*y0
- // = z2*b*b + z1*b + z0
- //
- // with:
- //
- // xd = x1 - x0
- // yd = y0 - y1
- //
- // z1 = xd*yd + z2 + z0
- // = (x1-x0)*(y0 - y1) + z2 + z0
- // = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z2 + z0
- // = x1*y0 - z2 - z0 + x0*y1 + z2 + z0
- // = x1*y0 + x0*y1
-
- // split x, y into "digits"
- n2 := n >> 1 // n2 >= 1
- x1, x0 := x[n2:], x[0:n2] // x = x1*b + y0
- y1, y0 := y[n2:], y[0:n2] // y = y1*b + y0
-
- // z is used for the result and temporary storage:
- //
- // 6*n 5*n 4*n 3*n 2*n 1*n 0*n
- // z = [z2 copy|z0 copy| xd*yd | yd:xd | x1*y1 | x0*y0 ]
- //
- // For each recursive call of karatsuba, an unused slice of
- // z is passed in that has (at least) half the length of the
- // caller's z.
-
- // compute z0 and z2 with the result "in place" in z
- karatsuba(z, x0, y0) // z0 = x0*y0
- karatsuba(z[n:], x1, y1) // z2 = x1*y1
-
- // compute xd (or the negative value if underflow occurs)
- s := 1 // sign of product xd*yd
- xd := z[2*n : 2*n+n2]
- if subVV(xd, x1, x0) != 0 { // x1-x0
- s = -s
- subVV(xd, x0, x1) // x0-x1
- }
-
- // compute yd (or the negative value if underflow occurs)
- yd := z[2*n+n2 : 3*n]
- if subVV(yd, y0, y1) != 0 { // y0-y1
- s = -s
- subVV(yd, y1, y0) // y1-y0
- }
-
- // p = (x1-x0)*(y0-y1) == x1*y0 - x1*y1 - x0*y0 + x0*y1 for s > 0
- // p = (x0-x1)*(y0-y1) == x0*y0 - x0*y1 - x1*y0 + x1*y1 for s < 0
- p := z[n*3:]
- karatsuba(p, xd, yd)
-
- // save original z2:z0
- // (ok to use upper half of z since we're done recurring)
- r := z[n*4:]
- copy(r, z[:n*2])
-
- // add up all partial products
- //
- // 2*n n 0
- // z = [ z2 | z0 ]
- // + [ z0 ]
- // + [ z2 ]
- // + [ p ]
- //
- karatsubaAdd(z[n2:], r, n)
- karatsubaAdd(z[n2:], r[n:], n)
- if s > 0 {
- karatsubaAdd(z[n2:], p, n)
- } else {
- karatsubaSub(z[n2:], p, n)
- }
-}
-
-// alias reports whether x and y share the same base array.
-//
-// Note: alias assumes that the capacity of underlying arrays
-// is never changed for nat values; i.e. that there are
-// no 3-operand slice expressions in this code (or worse,
-// reflect-based operations to the same effect).
-func alias(x, y nat) bool {
- return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
-}
-
-// addAt implements z += x<<(_W*i); z must be long enough.
-// (we don't use nat.add because we need z to stay the same
-// slice, and we don't need to normalize z after each addition)
-func addAt(z, x nat, i int) {
- if n := len(x); n > 0 {
- if c := addVV(z[i:i+n], z[i:], x); c != 0 {
- j := i + n
- if j < len(z) {
- addVW(z[j:], z[j:], c)
- }
- }
- }
-}
-
-// karatsubaLen computes an approximation to the maximum k <= n such that
-// k = p<= 0. Thus, the
-// result is the largest number that can be divided repeatedly by 2 before
-// becoming about the value of threshold.
-func karatsubaLen(n, threshold int) int {
- i := uint(0)
- for n > threshold {
- n >>= 1
- i++
- }
- return n << i
-}
-
-func (z nat) mul(x, y nat) nat {
- m := len(x)
- n := len(y)
-
- switch {
- case m < n:
- return z.mul(y, x)
- case m == 0 || n == 0:
- return z[:0]
- case n == 1:
- return z.mulAddWW(x, y[0], 0)
- }
- // m >= n > 1
-
- // determine if z can be reused
- if alias(z, x) || alias(z, y) {
- z = nil // z is an alias for x or y - cannot reuse
- }
-
- // use basic multiplication if the numbers are small
- if n < karatsubaThreshold {
- z = z.make(m + n)
- basicMul(z, x, y)
- return z.norm()
- }
- // m >= n && n >= karatsubaThreshold && n >= 2
-
- // determine Karatsuba length k such that
- //
- // x = xh*b + x0 (0 <= x0 < b)
- // y = yh*b + y0 (0 <= y0 < b)
- // b = 1<<(_W*k) ("base" of digits xi, yi)
- //
- k := karatsubaLen(n, karatsubaThreshold)
- // k <= n
-
- // multiply x0 and y0 via Karatsuba
- x0 := x[0:k] // x0 is not normalized
- y0 := y[0:k] // y0 is not normalized
- z = z.make(max(6*k, m+n)) // enough space for karatsuba of x0*y0 and full result of x*y
- karatsuba(z, x0, y0)
- z = z[0 : m+n] // z has final length but may be incomplete
- z[2*k:].clear() // upper portion of z is garbage (and 2*k <= m+n since k <= n <= m)
-
- // If xh != 0 or yh != 0, add the missing terms to z. For
- //
- // xh = xi*b^i + ... + x2*b^2 + x1*b (0 <= xi < b)
- // yh = y1*b (0 <= y1 < b)
- //
- // the missing terms are
- //
- // x0*y1*b and xi*y0*b^i, xi*y1*b^(i+1) for i > 0
- //
- // since all the yi for i > 1 are 0 by choice of k: If any of them
- // were > 0, then yh >= b^2 and thus y >= b^2. Then k' = k*2 would
- // be a larger valid threshold contradicting the assumption about k.
- //
- if k < n || m != n {
- tp := getNat(3 * k)
- t := *tp
-
- // add x0*y1*b
- x0 := x0.norm()
- y1 := y[k:] // y1 is normalized because y is
- t = t.mul(x0, y1) // update t so we don't lose t's underlying array
- addAt(z, t, k)
-
- // add xi*y0< k {
- xi = xi[:k]
- }
- xi = xi.norm()
- t = t.mul(xi, y0)
- addAt(z, t, i)
- t = t.mul(xi, y1)
- addAt(z, t, i+k)
- }
-
- putNat(tp)
- }
-
- return z.norm()
-}
-
-// basicSqr sets z = x*x and is asymptotically faster than basicMul
-// by about a factor of 2, but slower for small arguments due to overhead.
-// Requirements: len(x) > 0, len(z) == 2*len(x)
-// The (non-normalized) result is placed in z.
-func basicSqr(z, x nat) {
- n := len(x)
- tp := getNat(2 * n)
- t := *tp // temporary variable to hold the products
- t.clear()
- z[1], z[0] = mulWW(x[0], x[0]) // the initial square
- for i := 1; i < n; i++ {
- d := x[i]
- // z collects the squares x[i] * x[i]
- z[2*i+1], z[2*i] = mulWW(d, d)
- // t collects the products x[i] * x[j] where j < i
- t[2*i] = addMulVVW(t[i:2*i], x[0:i], d)
- }
- t[2*n-1] = shlVU(t[1:2*n-1], t[1:2*n-1], 1) // double the j < i products
- addVV(z, z, t) // combine the result
- putNat(tp)
-}
-
-// karatsubaSqr squares x and leaves the result in z.
-// len(x) must be a power of 2 and len(z) >= 6*len(x).
-// The (non-normalized) result is placed in z[0 : 2*len(x)].
-//
-// The algorithm and the layout of z are the same as for karatsuba.
-func karatsubaSqr(z, x nat) {
- n := len(x)
-
- if n&1 != 0 || n < karatsubaSqrThreshold || n < 2 {
- basicSqr(z[:2*n], x)
- return
- }
-
- n2 := n >> 1
- x1, x0 := x[n2:], x[0:n2]
-
- karatsubaSqr(z, x0)
- karatsubaSqr(z[n:], x1)
-
- // s = sign(xd*yd) == -1 for xd != 0; s == 1 for xd == 0
- xd := z[2*n : 2*n+n2]
- if subVV(xd, x1, x0) != 0 {
- subVV(xd, x0, x1)
- }
-
- p := z[n*3:]
- karatsubaSqr(p, xd)
-
- r := z[n*4:]
- copy(r, z[:n*2])
-
- karatsubaAdd(z[n2:], r, n)
- karatsubaAdd(z[n2:], r[n:], n)
- karatsubaSub(z[n2:], p, n) // s == -1 for p != 0; s == 1 for p == 0
-}
-
-// Operands that are shorter than basicSqrThreshold are squared using
-// "grade school" multiplication; for operands longer than karatsubaSqrThreshold
-// we use the Karatsuba algorithm optimized for x == y.
-var basicSqrThreshold = 20 // computed by calibrate_test.go
-var karatsubaSqrThreshold = 260 // computed by calibrate_test.go
-
-// z = x*x
-func (z nat) sqr(x nat) nat {
- n := len(x)
- switch {
- case n == 0:
- return z[:0]
- case n == 1:
- d := x[0]
- z = z.make(2)
- z[1], z[0] = mulWW(d, d)
- return z.norm()
- }
-
- if alias(z, x) {
- z = nil // z is an alias for x - cannot reuse
- }
-
- if n < basicSqrThreshold {
- z = z.make(2 * n)
- basicMul(z, x, x)
- return z.norm()
- }
- if n < karatsubaSqrThreshold {
- z = z.make(2 * n)
- basicSqr(z, x)
- return z.norm()
- }
-
- // Use Karatsuba multiplication optimized for x == y.
- // The algorithm and layout of z are the same as for mul.
-
- // z = (x1*b + x0)^2 = x1^2*b^2 + 2*x1*x0*b + x0^2
-
- k := karatsubaLen(n, karatsubaSqrThreshold)
-
- x0 := x[0:k]
- z = z.make(max(6*k, 2*n))
- karatsubaSqr(z, x0) // z = x0^2
- z = z[0 : 2*n]
- z[2*k:].clear()
-
- if k < n {
- tp := getNat(2 * k)
- t := *tp
- x0 := x0.norm()
- x1 := x[k:]
- t = t.mul(x0, x1)
- addAt(z, t, k)
- addAt(z, t, k) // z = 2*x1*x0*b + x0^2
- t = t.sqr(x1)
- addAt(z, t, 2*k) // z = x1^2*b^2 + 2*x1*x0*b + x0^2
- putNat(tp)
- }
-
- return z.norm()
-}
-
-// mulRange computes the product of all the unsigned integers in the
-// range [a, b] inclusively. If a > b (empty range), the result is 1.
-func (z nat) mulRange(a, b uint64) nat {
- switch {
- case a == 0:
- // cut long ranges short (optimization)
- return z.setUint64(0)
- case a > b:
- return z.setUint64(1)
- case a == b:
- return z.setUint64(a)
- case a+1 == b:
- return z.mul(nat(nil).setUint64(a), nat(nil).setUint64(b))
- }
- m := a + (b-a)/2 // avoid overflow
- return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b))
-}
-
-// getNat returns a *nat of len n. The contents may not be zero.
-// The pool holds *nat to avoid allocation when converting to interface{}.
-func getNat(n int) *nat {
- var z *nat
- if v := natPool.Get(); v != nil {
- z = v.(*nat)
- }
- if z == nil {
- z = new(nat)
- }
- *z = z.make(n)
- if n > 0 {
- (*z)[0] = 0xfedcb // break code expecting zero
- }
- return z
-}
-
-func putNat(x *nat) {
- natPool.Put(x)
-}
-
-var natPool sync.Pool
-
-// bitLen returns the length of x in bits.
-// Unlike most methods, it works even if x is not normalized.
-func (x nat) bitLen() int {
- // This function is used in cryptographic operations. It must not leak
- // anything but the Int's sign and bit size through side-channels. Any
- // changes must be reviewed by a security expert.
- if i := len(x) - 1; i >= 0 {
- // bits.Len uses a lookup table for the low-order bits on some
- // architectures. Neutralize any input-dependent behavior by setting all
- // bits after the first one bit.
- top := uint(x[i])
- top |= top >> 1
- top |= top >> 2
- top |= top >> 4
- top |= top >> 8
- top |= top >> 16
- top |= top >> 16 >> 16 // ">> 32" doesn't compile on 32-bit architectures
- return i*_W + bits.Len(top)
- }
- return 0
-}
-
-// trailingZeroBits returns the number of consecutive least significant zero
-// bits of x.
-func (x nat) trailingZeroBits() uint {
- if len(x) == 0 {
- return 0
- }
- var i uint
- for x[i] == 0 {
- i++
- }
- // x[i] != 0
- return i*_W + uint(bits.TrailingZeros(uint(x[i])))
-}
-
-// isPow2 returns i, true when x == 2**i and 0, false otherwise.
-func (x nat) isPow2() (uint, bool) {
- var i uint
- for x[i] == 0 {
- i++
- }
- if i == uint(len(x))-1 && x[i]&(x[i]-1) == 0 {
- return i*_W + uint(bits.TrailingZeros(uint(x[i]))), true
- }
- return 0, false
-}
-
-func same(x, y nat) bool {
- return len(x) == len(y) && len(x) > 0 && &x[0] == &y[0]
-}
-
-// z = x << s
-func (z nat) shl(x nat, s uint) nat {
- if s == 0 {
- if same(z, x) {
- return z
- }
- if !alias(z, x) {
- return z.set(x)
- }
- }
-
- m := len(x)
- if m == 0 {
- return z[:0]
- }
- // m > 0
-
- n := m + int(s/_W)
- z = z.make(n + 1)
- z[n] = shlVU(z[n-m:n], x, s%_W)
- z[0 : n-m].clear()
-
- return z.norm()
-}
-
-// z = x >> s
-func (z nat) shr(x nat, s uint) nat {
- if s == 0 {
- if same(z, x) {
- return z
- }
- if !alias(z, x) {
- return z.set(x)
- }
- }
-
- m := len(x)
- n := m - int(s/_W)
- if n <= 0 {
- return z[:0]
- }
- // n > 0
-
- z = z.make(n)
- shrVU(z, x[m-n:], s%_W)
-
- return z.norm()
-}
-
-func (z nat) setBit(x nat, i uint, b uint) nat {
- j := int(i / _W)
- m := Word(1) << (i % _W)
- n := len(x)
- switch b {
- case 0:
- z = z.make(n)
- copy(z, x)
- if j >= n {
- // no need to grow
- return z
- }
- z[j] &^= m
- return z.norm()
- case 1:
- if j >= n {
- z = z.make(j + 1)
- z[n:].clear()
- } else {
- z = z.make(n)
- }
- copy(z, x)
- z[j] |= m
- // no need to normalize
- return z
- }
- panic("set bit is not 0 or 1")
-}
-
-// bit returns the value of the i'th bit, with lsb == bit 0.
-func (x nat) bit(i uint) uint {
- j := i / _W
- if j >= uint(len(x)) {
- return 0
- }
- // 0 <= j < len(x)
- return uint(x[j] >> (i % _W) & 1)
-}
-
-// sticky returns 1 if there's a 1 bit within the
-// i least significant bits, otherwise it returns 0.
-func (x nat) sticky(i uint) uint {
- j := i / _W
- if j >= uint(len(x)) {
- if len(x) == 0 {
- return 0
- }
- return 1
- }
- // 0 <= j < len(x)
- for _, x := range x[:j] {
- if x != 0 {
- return 1
- }
- }
- if x[j]<<(_W-i%_W) != 0 {
- return 1
- }
- return 0
-}
-
-func (z nat) and(x, y nat) nat {
- m := len(x)
- n := len(y)
- if m > n {
- m = n
- }
- // m <= n
-
- z = z.make(m)
- for i := 0; i < m; i++ {
- z[i] = x[i] & y[i]
- }
-
- return z.norm()
-}
-
-// trunc returns z = x mod 2ⁿ.
-func (z nat) trunc(x nat, n uint) nat {
- w := (n + _W - 1) / _W
- if uint(len(x)) < w {
- return z.set(x)
- }
- z = z.make(int(w))
- copy(z, x)
- if n%_W != 0 {
- z[len(z)-1] &= 1<<(n%_W) - 1
- }
- return z.norm()
-}
-
-func (z nat) andNot(x, y nat) nat {
- m := len(x)
- n := len(y)
- if n > m {
- n = m
- }
- // m >= n
-
- z = z.make(m)
- for i := 0; i < n; i++ {
- z[i] = x[i] &^ y[i]
- }
- copy(z[n:m], x[n:m])
-
- return z.norm()
-}
-
-func (z nat) or(x, y nat) nat {
- m := len(x)
- n := len(y)
- s := x
- if m < n {
- n, m = m, n
- s = y
- }
- // m >= n
-
- z = z.make(m)
- for i := 0; i < n; i++ {
- z[i] = x[i] | y[i]
- }
- copy(z[n:m], s[n:m])
-
- return z.norm()
-}
-
-func (z nat) xor(x, y nat) nat {
- m := len(x)
- n := len(y)
- s := x
- if m < n {
- n, m = m, n
- s = y
- }
- // m >= n
-
- z = z.make(m)
- for i := 0; i < n; i++ {
- z[i] = x[i] ^ y[i]
- }
- copy(z[n:m], s[n:m])
-
- return z.norm()
-}
-
-// random creates a random integer in [0..limit), using the space in z if
-// possible. n is the bit length of limit.
-func (z nat) random(rand *rand.Rand, limit nat, n int) nat {
- if alias(z, limit) {
- z = nil // z is an alias for limit - cannot reuse
- }
- z = z.make(len(limit))
-
- bitLengthOfMSW := uint(n % _W)
- if bitLengthOfMSW == 0 {
- bitLengthOfMSW = _W
- }
- mask := Word((1 << bitLengthOfMSW) - 1)
-
- for {
- switch _W {
- case 32:
- for i := range z {
- z[i] = Word(rand.Uint32())
- }
- case 64:
- for i := range z {
- z[i] = Word(rand.Uint32()) | Word(rand.Uint32())<<32
- }
- default:
- panic("unknown word size")
- }
- z[len(limit)-1] &= mask
- if z.cmp(limit) < 0 {
- break
- }
- }
-
- return z.norm()
-}
-
-// If m != 0 (i.e., len(m) != 0), expNN sets z to x**y mod m;
-// otherwise it sets z to x**y. The result is the value of z.
-func (z nat) expNN(x, y, m nat, slow bool) nat {
- if alias(z, x) || alias(z, y) {
- // We cannot allow in-place modification of x or y.
- z = nil
- }
-
- // x**y mod 1 == 0
- if len(m) == 1 && m[0] == 1 {
- return z.setWord(0)
- }
- // m == 0 || m > 1
-
- // x**0 == 1
- if len(y) == 0 {
- return z.setWord(1)
- }
- // y > 0
-
- // 0**y = 0
- if len(x) == 0 {
- return z.setWord(0)
- }
- // x > 0
-
- // 1**y = 1
- if len(x) == 1 && x[0] == 1 {
- return z.setWord(1)
- }
- // x > 1
-
- // x**1 == x
- if len(y) == 1 && y[0] == 1 {
- if len(m) != 0 {
- return z.rem(x, m)
- }
- return z.set(x)
- }
- // y > 1
-
- if len(m) != 0 {
- // We likely end up being as long as the modulus.
- z = z.make(len(m))
-
- // If the exponent is large, we use the Montgomery method for odd values,
- // and a 4-bit, windowed exponentiation for powers of two,
- // and a CRT-decomposed Montgomery method for the remaining values
- // (even values times non-trivial odd values, which decompose into one
- // instance of each of the first two cases).
- if len(y) > 1 && !slow {
- if m[0]&1 == 1 {
- return z.expNNMontgomery(x, y, m)
- }
- if logM, ok := m.isPow2(); ok {
- return z.expNNWindowed(x, y, logM)
- }
- return z.expNNMontgomeryEven(x, y, m)
- }
- }
-
- z = z.set(x)
- v := y[len(y)-1] // v > 0 because y is normalized and y > 0
- shift := nlz(v) + 1
- v <<= shift
- var q nat
-
- const mask = 1 << (_W - 1)
-
- // We walk through the bits of the exponent one by one. Each time we
- // see a bit, we square, thus doubling the power. If the bit is a one,
- // we also multiply by x, thus adding one to the power.
-
- w := _W - int(shift)
- // zz and r are used to avoid allocating in mul and div as
- // otherwise the arguments would alias.
- var zz, r nat
- for j := 0; j < w; j++ {
- zz = zz.sqr(z)
- zz, z = z, zz
-
- if v&mask != 0 {
- zz = zz.mul(z, x)
- zz, z = z, zz
- }
-
- if len(m) != 0 {
- zz, r = zz.div(r, z, m)
- zz, r, q, z = q, z, zz, r
- }
-
- v <<= 1
- }
-
- for i := len(y) - 2; i >= 0; i-- {
- v = y[i]
-
- for j := 0; j < _W; j++ {
- zz = zz.sqr(z)
- zz, z = z, zz
-
- if v&mask != 0 {
- zz = zz.mul(z, x)
- zz, z = z, zz
- }
-
- if len(m) != 0 {
- zz, r = zz.div(r, z, m)
- zz, r, q, z = q, z, zz, r
- }
-
- v <<= 1
- }
- }
-
- return z.norm()
-}
-
-// expNNMontgomeryEven calculates x**y mod m where m = m1 × m2 for m1 = 2ⁿ and m2 odd.
-// It uses two recursive calls to expNN for x**y mod m1 and x**y mod m2
-// and then uses the Chinese Remainder Theorem to combine the results.
-// The recursive call using m1 will use expNNWindowed,
-// while the recursive call using m2 will use expNNMontgomery.
-// For more details, see Ç. K. Koç, “Montgomery Reduction with Even Modulus”,
-// IEE Proceedings: Computers and Digital Techniques, 141(5) 314-316, September 1994.
-// http://www.people.vcu.edu/~jwang3/CMSC691/j34monex.pdf
-func (z nat) expNNMontgomeryEven(x, y, m nat) nat {
- // Split m = m₁ × m₂ where m₁ = 2ⁿ
- n := m.trailingZeroBits()
- m1 := nat(nil).shl(natOne, n)
- m2 := nat(nil).shr(m, n)
-
- // We want z = x**y mod m.
- // z₁ = x**y mod m1 = (x**y mod m) mod m1 = z mod m1
- // z₂ = x**y mod m2 = (x**y mod m) mod m2 = z mod m2
- // (We are using the math/big convention for names here,
- // where the computation is z = x**y mod m, so its parts are z1 and z2.
- // The paper is computing x = a**e mod n; it refers to these as x2 and z1.)
- z1 := nat(nil).expNN(x, y, m1, false)
- z2 := nat(nil).expNN(x, y, m2, false)
-
- // Reconstruct z from z₁, z₂ using CRT, using algorithm from paper,
- // which uses only a single modInverse (and an easy one at that).
- // p = (z₁ - z₂) × m₂⁻¹ (mod m₁)
- // z = z₂ + p × m₂
- // The final addition is in range because:
- // z = z₂ + p × m₂
- // ≤ z₂ + (m₁-1) × m₂
- // < m₂ + (m₁-1) × m₂
- // = m₁ × m₂
- // = m.
- z = z.set(z2)
-
- // Compute (z₁ - z₂) mod m1 [m1 == 2**n] into z1.
- z1 = z1.subMod2N(z1, z2, n)
-
- // Reuse z2 for p = (z₁ - z₂) [in z1] * m2⁻¹ (mod m₁ [= 2ⁿ]).
- m2inv := nat(nil).modInverse(m2, m1)
- z2 = z2.mul(z1, m2inv)
- z2 = z2.trunc(z2, n)
-
- // Reuse z1 for p * m2.
- z = z.add(z, z1.mul(z2, m2))
-
- return z
-}
-
-// expNNWindowed calculates x**y mod m using a fixed, 4-bit window,
-// where m = 2**logM.
-func (z nat) expNNWindowed(x, y nat, logM uint) nat {
- if len(y) <= 1 {
- panic("big: misuse of expNNWindowed")
- }
- if x[0]&1 == 0 {
- // len(y) > 1, so y > logM.
- // x is even, so x**y is a multiple of 2**y which is a multiple of 2**logM.
- return z.setWord(0)
- }
- if logM == 1 {
- return z.setWord(1)
- }
-
- // zz is used to avoid allocating in mul as otherwise
- // the arguments would alias.
- w := int((logM + _W - 1) / _W)
- zzp := getNat(w)
- zz := *zzp
-
- const n = 4
- // powers[i] contains x^i.
- var powers [1 << n]*nat
- for i := range powers {
- powers[i] = getNat(w)
- }
- *powers[0] = powers[0].set(natOne)
- *powers[1] = powers[1].trunc(x, logM)
- for i := 2; i < 1< mtop {
- i = mtop
- }
- advance := false
- z = z.setWord(1)
- for ; i >= 0; i-- {
- yi := y[i]
- if i == mtop {
- yi &= mmask
- }
- for j := 0; j < _W; j += n {
- if advance {
- // Account for use of 4 bits in previous iteration.
- // Unrolled loop for significant performance
- // gain. Use go test -bench=".*" in crypto/rsa
- // to check performance before making changes.
- zz = zz.sqr(z)
- zz, z = z, zz
- z = z.trunc(z, logM)
-
- zz = zz.sqr(z)
- zz, z = z, zz
- z = z.trunc(z, logM)
-
- zz = zz.sqr(z)
- zz, z = z, zz
- z = z.trunc(z, logM)
-
- zz = zz.sqr(z)
- zz, z = z, zz
- z = z.trunc(z, logM)
- }
-
- zz = zz.mul(z, *powers[yi>>(_W-n)])
- zz, z = z, zz
- z = z.trunc(z, logM)
-
- yi <<= n
- advance = true
- }
- }
-
- *zzp = zz
- putNat(zzp)
- for i := range powers {
- putNat(powers[i])
- }
-
- return z.norm()
-}
-
-// expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
-// Uses Montgomery representation.
-func (z nat) expNNMontgomery(x, y, m nat) nat {
- numWords := len(m)
-
- // We want the lengths of x and m to be equal.
- // It is OK if x >= m as long as len(x) == len(m).
- if len(x) > numWords {
- _, x = nat(nil).div(nil, x, m)
- // Note: now len(x) <= numWords, not guaranteed ==.
- }
- if len(x) < numWords {
- rr := make(nat, numWords)
- copy(rr, x)
- x = rr
- }
-
- // Ideally the precomputations would be performed outside, and reused
- // k0 = -m**-1 mod 2**_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
- // Iteration for Multiplicative Inverses Modulo Prime Powers".
- k0 := 2 - m[0]
- t := m[0] - 1
- for i := 1; i < _W; i <<= 1 {
- t *= t
- k0 *= (t + 1)
- }
- k0 = -k0
-
- // RR = 2**(2*_W*len(m)) mod m
- RR := nat(nil).setWord(1)
- zz := nat(nil).shl(RR, uint(2*numWords*_W))
- _, RR = nat(nil).div(RR, zz, m)
- if len(RR) < numWords {
- zz = zz.make(numWords)
- copy(zz, RR)
- RR = zz
- }
- // one = 1, with equal length to that of m
- one := make(nat, numWords)
- one[0] = 1
-
- const n = 4
- // powers[i] contains x^i
- var powers [1 << n]nat
- powers[0] = powers[0].montgomery(one, RR, m, k0, numWords)
- powers[1] = powers[1].montgomery(x, RR, m, k0, numWords)
- for i := 2; i < 1<= 0; i-- {
- yi := y[i]
- for j := 0; j < _W; j += n {
- if i != len(y)-1 || j != 0 {
- zz = zz.montgomery(z, z, m, k0, numWords)
- z = z.montgomery(zz, zz, m, k0, numWords)
- zz = zz.montgomery(z, z, m, k0, numWords)
- z = z.montgomery(zz, zz, m, k0, numWords)
- }
- zz = zz.montgomery(z, powers[yi>>(_W-n)], m, k0, numWords)
- z, zz = zz, z
- yi <<= n
- }
- }
- // convert to regular number
- zz = zz.montgomery(z, one, m, k0, numWords)
-
- // One last reduction, just in case.
- // See golang.org/issue/13907.
- if zz.cmp(m) >= 0 {
- // Common case is m has high bit set; in that case,
- // since zz is the same length as m, there can be just
- // one multiple of m to remove. Just subtract.
- // We think that the subtract should be sufficient in general,
- // so do that unconditionally, but double-check,
- // in case our beliefs are wrong.
- // The div is not expected to be reached.
- zz = zz.sub(zz, m)
- if zz.cmp(m) >= 0 {
- _, zz = nat(nil).div(nil, zz, m)
- }
- }
-
- return zz.norm()
-}
-
-// bytes writes the value of z into buf using big-endian encoding.
-// The value of z is encoded in the slice buf[i:]. If the value of z
-// cannot be represented in buf, bytes panics. The number i of unused
-// bytes at the beginning of buf is returned as result.
-func (z nat) bytes(buf []byte) (i int) {
- // This function is used in cryptographic operations. It must not leak
- // anything but the Int's sign and bit size through side-channels. Any
- // changes must be reviewed by a security expert.
- i = len(buf)
- for _, d := range z {
- for j := 0; j < _S; j++ {
- i--
- if i >= 0 {
- buf[i] = byte(d)
- } else if byte(d) != 0 {
- panic("math/big: buffer too small to fit value")
- }
- d >>= 8
- }
- }
-
- if i < 0 {
- i = 0
- }
- for i < len(buf) && buf[i] == 0 {
- i++
- }
-
- return
-}
-
-// bigEndianWord returns the contents of buf interpreted as a big-endian encoded Word value.
-func bigEndianWord(buf []byte) Word {
- if _W == 64 {
- return Word(binary.BigEndian.Uint64(buf))
- }
- return Word(binary.BigEndian.Uint32(buf))
-}
-
-// setBytes interprets buf as the bytes of a big-endian unsigned
-// integer, sets z to that value, and returns z.
-func (z nat) setBytes(buf []byte) nat {
- z = z.make((len(buf) + _S - 1) / _S)
-
- i := len(buf)
- for k := 0; i >= _S; k++ {
- z[k] = bigEndianWord(buf[i-_S : i])
- i -= _S
- }
- if i > 0 {
- var d Word
- for s := uint(0); i > 0; s += 8 {
- d |= Word(buf[i-1]) << s
- i--
- }
- z[len(z)-1] = d
- }
-
- return z.norm()
-}
-
-// sqrt sets z = ⌊√x⌋
-func (z nat) sqrt(x nat) nat {
- if x.cmp(natOne) <= 0 {
- return z.set(x)
- }
- if alias(z, x) {
- z = nil
- }
-
- // Start with value known to be too large and repeat "z = ⌊(z + ⌊x/z⌋)/2⌋" until it stops getting smaller.
- // See Brent and Zimmermann, Modern Computer Arithmetic, Algorithm 1.13 (SqrtInt).
- // https://members.loria.fr/PZimmermann/mca/pub226.html
- // If x is one less than a perfect square, the sequence oscillates between the correct z and z+1;
- // otherwise it converges to the correct z and stays there.
- var z1, z2 nat
- z1 = z
- z1 = z1.setUint64(1)
- z1 = z1.shl(z1, uint(x.bitLen()+1)/2) // must be ≥ √x
- for n := 0; ; n++ {
- z2, _ = z2.div(nil, x, z1)
- z2 = z2.add(z2, z1)
- z2 = z2.shr(z2, 1)
- if z2.cmp(z1) >= 0 {
- // z1 is answer.
- // Figure out whether z1 or z2 is currently aliased to z by looking at loop count.
- if n&1 == 0 {
- return z1
- }
- return z.set(z1)
- }
- z1, z2 = z2, z1
- }
-}
-
-// subMod2N returns z = (x - y) mod 2ⁿ.
-func (z nat) subMod2N(x, y nat, n uint) nat {
- if uint(x.bitLen()) > n {
- if alias(z, x) {
- // ok to overwrite x in place
- x = x.trunc(x, n)
- } else {
- x = nat(nil).trunc(x, n)
- }
- }
- if uint(y.bitLen()) > n {
- if alias(z, y) {
- // ok to overwrite y in place
- y = y.trunc(y, n)
- } else {
- y = nat(nil).trunc(y, n)
- }
- }
- if x.cmp(y) >= 0 {
- return z.sub(x, y)
- }
- // x - y < 0; x - y mod 2ⁿ = x - y + 2ⁿ = 2ⁿ - (y - x) = 1 + 2ⁿ-1 - (y - x) = 1 + ^(y - x).
- z = z.sub(y, x)
- for uint(len(z))*_W < n {
- z = append(z, 0)
- }
- for i := range z {
- z[i] = ^z[i]
- }
- z = z.trunc(z, n)
- return z.add(z, natOne)
-}
diff --git a/contrib/go/_std_1.22/src/math/big/ya.make b/contrib/go/_std_1.22/src/math/big/ya.make
deleted file mode 100644
index 02c6a9f230ec..000000000000
--- a/contrib/go/_std_1.22/src/math/big/ya.make
+++ /dev/null
@@ -1,54 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- accuracy_string.go
- arith.go
- arith_arm64.s
- arith_decl.go
- decimal.go
- doc.go
- float.go
- floatconv.go
- floatmarsh.go
- ftoa.go
- int.go
- intconv.go
- intmarsh.go
- nat.go
- natconv.go
- natdiv.go
- prime.go
- rat.go
- ratconv.go
- ratmarsh.go
- roundingmode_string.go
- sqrt.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- accuracy_string.go
- arith.go
- arith_amd64.go
- arith_amd64.s
- arith_decl.go
- decimal.go
- doc.go
- float.go
- floatconv.go
- floatmarsh.go
- ftoa.go
- int.go
- intconv.go
- intmarsh.go
- nat.go
- natconv.go
- natdiv.go
- prime.go
- rat.go
- ratconv.go
- ratmarsh.go
- roundingmode_string.go
- sqrt.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/math/rand/rand.go b/contrib/go/_std_1.22/src/math/rand/rand.go
deleted file mode 100644
index a8ed9c0cb7cf..000000000000
--- a/contrib/go/_std_1.22/src/math/rand/rand.go
+++ /dev/null
@@ -1,547 +0,0 @@
-// Copyright 2009 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.
-
-// Package rand implements pseudo-random number generators suitable for tasks
-// such as simulation, but it should not be used for security-sensitive work.
-//
-// Random numbers are generated by a [Source], usually wrapped in a [Rand].
-// Both types should be used by a single goroutine at a time: sharing among
-// multiple goroutines requires some kind of synchronization.
-//
-// Top-level functions, such as [Float64] and [Int],
-// are safe for concurrent use by multiple goroutines.
-//
-// This package's outputs might be easily predictable regardless of how it's
-// seeded. For random numbers suitable for security-sensitive work, see the
-// crypto/rand package.
-package rand
-
-import (
- "internal/godebug"
- "sync"
- "sync/atomic"
- _ "unsafe" // for go:linkname
-)
-
-// A Source represents a source of uniformly-distributed
-// pseudo-random int64 values in the range [0, 1<<63).
-//
-// A Source is not safe for concurrent use by multiple goroutines.
-type Source interface {
- Int63() int64
- Seed(seed int64)
-}
-
-// A Source64 is a [Source] that can also generate
-// uniformly-distributed pseudo-random uint64 values in
-// the range [0, 1<<64) directly.
-// If a [Rand] r's underlying [Source] s implements Source64,
-// then r.Uint64 returns the result of one call to s.Uint64
-// instead of making two calls to s.Int63.
-type Source64 interface {
- Source
- Uint64() uint64
-}
-
-// NewSource returns a new pseudo-random [Source] seeded with the given value.
-// Unlike the default [Source] used by top-level functions, this source is not
-// safe for concurrent use by multiple goroutines.
-// The returned [Source] implements [Source64].
-func NewSource(seed int64) Source {
- return newSource(seed)
-}
-
-func newSource(seed int64) *rngSource {
- var rng rngSource
- rng.Seed(seed)
- return &rng
-}
-
-// A Rand is a source of random numbers.
-type Rand struct {
- src Source
- s64 Source64 // non-nil if src is source64
-
- // readVal contains remainder of 63-bit integer used for bytes
- // generation during most recent Read call.
- // It is saved so next Read call can start where the previous
- // one finished.
- readVal int64
- // readPos indicates the number of low-order bytes of readVal
- // that are still valid.
- readPos int8
-}
-
-// New returns a new [Rand] that uses random values from src
-// to generate other random values.
-func New(src Source) *Rand {
- s64, _ := src.(Source64)
- return &Rand{src: src, s64: s64}
-}
-
-// Seed uses the provided seed value to initialize the generator to a deterministic state.
-// Seed should not be called concurrently with any other [Rand] method.
-func (r *Rand) Seed(seed int64) {
- if lk, ok := r.src.(*lockedSource); ok {
- lk.seedPos(seed, &r.readPos)
- return
- }
-
- r.src.Seed(seed)
- r.readPos = 0
-}
-
-// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
-func (r *Rand) Int63() int64 { return r.src.Int63() }
-
-// Uint32 returns a pseudo-random 32-bit value as a uint32.
-func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
-
-// Uint64 returns a pseudo-random 64-bit value as a uint64.
-func (r *Rand) Uint64() uint64 {
- if r.s64 != nil {
- return r.s64.Uint64()
- }
- return uint64(r.Int63())>>31 | uint64(r.Int63())<<32
-}
-
-// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
-func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
-
-// Int returns a non-negative pseudo-random int.
-func (r *Rand) Int() int {
- u := uint(r.Int63())
- return int(u << 1 >> 1) // clear sign bit if int == int32
-}
-
-// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n <= 0.
-func (r *Rand) Int63n(n int64) int64 {
- if n <= 0 {
- panic("invalid argument to Int63n")
- }
- if n&(n-1) == 0 { // n is power of two, can mask
- return r.Int63() & (n - 1)
- }
- max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
- v := r.Int63()
- for v > max {
- v = r.Int63()
- }
- return v % n
-}
-
-// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n <= 0.
-func (r *Rand) Int31n(n int32) int32 {
- if n <= 0 {
- panic("invalid argument to Int31n")
- }
- if n&(n-1) == 0 { // n is power of two, can mask
- return r.Int31() & (n - 1)
- }
- max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
- v := r.Int31()
- for v > max {
- v = r.Int31()
- }
- return v % n
-}
-
-// int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
-// n must be > 0, but int31n does not check this; the caller must ensure it.
-// int31n exists because Int31n is inefficient, but Go 1 compatibility
-// requires that the stream of values produced by math/rand remain unchanged.
-// int31n can thus only be used internally, by newly introduced APIs.
-//
-// For implementation details, see:
-// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction
-// https://lemire.me/blog/2016/06/30/fast-random-shuffling
-func (r *Rand) int31n(n int32) int32 {
- v := r.Uint32()
- prod := uint64(v) * uint64(n)
- low := uint32(prod)
- if low < uint32(n) {
- thresh := uint32(-n) % uint32(n)
- for low < thresh {
- v = r.Uint32()
- prod = uint64(v) * uint64(n)
- low = uint32(prod)
- }
- }
- return int32(prod >> 32)
-}
-
-// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n <= 0.
-func (r *Rand) Intn(n int) int {
- if n <= 0 {
- panic("invalid argument to Intn")
- }
- if n <= 1<<31-1 {
- return int(r.Int31n(int32(n)))
- }
- return int(r.Int63n(int64(n)))
-}
-
-// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
-func (r *Rand) Float64() float64 {
- // A clearer, simpler implementation would be:
- // return float64(r.Int63n(1<<53)) / (1<<53)
- // However, Go 1 shipped with
- // return float64(r.Int63()) / (1 << 63)
- // and we want to preserve that value stream.
- //
- // There is one bug in the value stream: r.Int63() may be so close
- // to 1<<63 that the division rounds up to 1.0, and we've guaranteed
- // that the result is always less than 1.0.
- //
- // We tried to fix this by mapping 1.0 back to 0.0, but since float64
- // values near 0 are much denser than near 1, mapping 1 to 0 caused
- // a theoretically significant overshoot in the probability of returning 0.
- // Instead of that, if we round up to 1, just try again.
- // Getting 1 only happens 1/2⁵³ of the time, so most clients
- // will not observe it anyway.
-again:
- f := float64(r.Int63()) / (1 << 63)
- if f == 1 {
- goto again // resample; this branch is taken O(never)
- }
- return f
-}
-
-// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
-func (r *Rand) Float32() float32 {
- // Same rationale as in Float64: we want to preserve the Go 1 value
- // stream except we want to fix it not to return 1.0
- // This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
-again:
- f := float32(r.Float64())
- if f == 1 {
- goto again // resample; this branch is taken O(very rarely)
- }
- return f
-}
-
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
-// in the half-open interval [0,n).
-func (r *Rand) Perm(n int) []int {
- m := make([]int, n)
- // In the following loop, the iteration when i=0 always swaps m[0] with m[0].
- // A change to remove this useless iteration is to assign 1 to i in the init
- // statement. But Perm also effects r. Making this change will affect
- // the final state of r. So this change can't be made for compatibility
- // reasons for Go 1.
- for i := 0; i < n; i++ {
- j := r.Intn(i + 1)
- m[i] = m[j]
- m[j] = i
- }
- return m
-}
-
-// Shuffle pseudo-randomizes the order of elements.
-// n is the number of elements. Shuffle panics if n < 0.
-// swap swaps the elements with indexes i and j.
-func (r *Rand) Shuffle(n int, swap func(i, j int)) {
- if n < 0 {
- panic("invalid argument to Shuffle")
- }
-
- // Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
- // Shuffle really ought not be called with n that doesn't fit in 32 bits.
- // Not only will it take a very long time, but with 2³¹! possible permutations,
- // there's no way that any PRNG can have a big enough internal state to
- // generate even a minuscule percentage of the possible permutations.
- // Nevertheless, the right API signature accepts an int n, so handle it as best we can.
- i := n - 1
- for ; i > 1<<31-1-1; i-- {
- j := int(r.Int63n(int64(i + 1)))
- swap(i, j)
- }
- for ; i > 0; i-- {
- j := int(r.int31n(int32(i + 1)))
- swap(i, j)
- }
-}
-
-// Read generates len(p) random bytes and writes them into p. It
-// always returns len(p) and a nil error.
-// Read should not be called concurrently with any other Rand method.
-func (r *Rand) Read(p []byte) (n int, err error) {
- switch src := r.src.(type) {
- case *lockedSource:
- return src.read(p, &r.readVal, &r.readPos)
- case *runtimeSource:
- return src.read(p, &r.readVal, &r.readPos)
- }
- return read(p, r.src, &r.readVal, &r.readPos)
-}
-
-func read(p []byte, src Source, readVal *int64, readPos *int8) (n int, err error) {
- pos := *readPos
- val := *readVal
- rng, _ := src.(*rngSource)
- for n = 0; n < len(p); n++ {
- if pos == 0 {
- if rng != nil {
- val = rng.Int63()
- } else {
- val = src.Int63()
- }
- pos = 7
- }
- p[n] = byte(val)
- val >>= 8
- pos--
- }
- *readPos = pos
- *readVal = val
- return
-}
-
-/*
- * Top-level convenience functions
- */
-
-// globalRandGenerator is the source of random numbers for the top-level
-// convenience functions. When possible it uses the runtime fastrand64
-// function to avoid locking. This is not possible if the user called Seed,
-// either explicitly or implicitly via GODEBUG=randautoseed=0.
-var globalRandGenerator atomic.Pointer[Rand]
-
-var randautoseed = godebug.New("randautoseed")
-
-// globalRand returns the generator to use for the top-level convenience
-// functions.
-func globalRand() *Rand {
- if r := globalRandGenerator.Load(); r != nil {
- return r
- }
-
- // This is the first call. Initialize based on GODEBUG.
- var r *Rand
- if randautoseed.Value() == "0" {
- randautoseed.IncNonDefault()
- r = New(new(lockedSource))
- r.Seed(1)
- } else {
- r = &Rand{
- src: &runtimeSource{},
- s64: &runtimeSource{},
- }
- }
-
- if !globalRandGenerator.CompareAndSwap(nil, r) {
- // Two different goroutines called some top-level
- // function at the same time. While the results in
- // that case are unpredictable, if we just use r here,
- // and we are using a seed, we will most likely return
- // the same value for both calls. That doesn't seem ideal.
- // Just use the first one to get in.
- return globalRandGenerator.Load()
- }
-
- return r
-}
-
-//go:linkname runtime_rand runtime.rand
-func runtime_rand() uint64
-
-// runtimeSource is an implementation of Source64 that uses the runtime
-// fastrand functions.
-type runtimeSource struct {
- // The mutex is used to avoid race conditions in Read.
- mu sync.Mutex
-}
-
-func (*runtimeSource) Int63() int64 {
- return int64(runtime_rand() & rngMask)
-}
-
-func (*runtimeSource) Seed(int64) {
- panic("internal error: call to runtimeSource.Seed")
-}
-
-func (*runtimeSource) Uint64() uint64 {
- return runtime_rand()
-}
-
-func (fs *runtimeSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
- fs.mu.Lock()
- n, err = read(p, fs, readVal, readPos)
- fs.mu.Unlock()
- return
-}
-
-// Seed uses the provided seed value to initialize the default Source to a
-// deterministic state. Seed values that have the same remainder when
-// divided by 2³¹-1 generate the same pseudo-random sequence.
-// Seed, unlike the [Rand.Seed] method, is safe for concurrent use.
-//
-// If Seed is not called, the generator is seeded randomly at program startup.
-//
-// Prior to Go 1.20, the generator was seeded like Seed(1) at program startup.
-// To force the old behavior, call Seed(1) at program startup.
-// Alternately, set GODEBUG=randautoseed=0 in the environment
-// before making any calls to functions in this package.
-//
-// Deprecated: As of Go 1.20 there is no reason to call Seed with
-// a random value. Programs that call Seed with a known value to get
-// a specific sequence of results should use New(NewSource(seed)) to
-// obtain a local random generator.
-func Seed(seed int64) {
- orig := globalRandGenerator.Load()
-
- // If we are already using a lockedSource, we can just re-seed it.
- if orig != nil {
- if _, ok := orig.src.(*lockedSource); ok {
- orig.Seed(seed)
- return
- }
- }
-
- // Otherwise either
- // 1) orig == nil, which is the normal case when Seed is the first
- // top-level function to be called, or
- // 2) orig is already a runtimeSource, in which case we need to change
- // to a lockedSource.
- // Either way we do the same thing.
-
- r := New(new(lockedSource))
- r.Seed(seed)
-
- if !globalRandGenerator.CompareAndSwap(orig, r) {
- // Something changed underfoot. Retry to be safe.
- Seed(seed)
- }
-}
-
-// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
-// from the default [Source].
-func Int63() int64 { return globalRand().Int63() }
-
-// Uint32 returns a pseudo-random 32-bit value as a uint32
-// from the default [Source].
-func Uint32() uint32 { return globalRand().Uint32() }
-
-// Uint64 returns a pseudo-random 64-bit value as a uint64
-// from the default [Source].
-func Uint64() uint64 { return globalRand().Uint64() }
-
-// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
-// from the default [Source].
-func Int31() int32 { return globalRand().Int31() }
-
-// Int returns a non-negative pseudo-random int from the default [Source].
-func Int() int { return globalRand().Int() }
-
-// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n)
-// from the default [Source].
-// It panics if n <= 0.
-func Int63n(n int64) int64 { return globalRand().Int63n(n) }
-
-// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n)
-// from the default [Source].
-// It panics if n <= 0.
-func Int31n(n int32) int32 { return globalRand().Int31n(n) }
-
-// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n)
-// from the default [Source].
-// It panics if n <= 0.
-func Intn(n int) int { return globalRand().Intn(n) }
-
-// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)
-// from the default [Source].
-func Float64() float64 { return globalRand().Float64() }
-
-// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)
-// from the default [Source].
-func Float32() float32 { return globalRand().Float32() }
-
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
-// in the half-open interval [0,n) from the default [Source].
-func Perm(n int) []int { return globalRand().Perm(n) }
-
-// Shuffle pseudo-randomizes the order of elements using the default [Source].
-// n is the number of elements. Shuffle panics if n < 0.
-// swap swaps the elements with indexes i and j.
-func Shuffle(n int, swap func(i, j int)) { globalRand().Shuffle(n, swap) }
-
-// Read generates len(p) random bytes from the default [Source] and
-// writes them into p. It always returns len(p) and a nil error.
-// Read, unlike the [Rand.Read] method, is safe for concurrent use.
-//
-// Deprecated: For almost all use cases, [crypto/rand.Read] is more appropriate.
-func Read(p []byte) (n int, err error) { return globalRand().Read(p) }
-
-// NormFloat64 returns a normally distributed float64 in the range
-// [-[math.MaxFloat64], +[math.MaxFloat64]] with
-// standard normal distribution (mean = 0, stddev = 1)
-// from the default [Source].
-// To produce a different normal distribution, callers can
-// adjust the output using:
-//
-// sample = NormFloat64() * desiredStdDev + desiredMean
-func NormFloat64() float64 { return globalRand().NormFloat64() }
-
-// ExpFloat64 returns an exponentially distributed float64 in the range
-// (0, +[math.MaxFloat64]] with an exponential distribution whose rate parameter
-// (lambda) is 1 and whose mean is 1/lambda (1) from the default [Source].
-// To produce a distribution with a different rate parameter,
-// callers can adjust the output using:
-//
-// sample = ExpFloat64() / desiredRateParameter
-func ExpFloat64() float64 { return globalRand().ExpFloat64() }
-
-type lockedSource struct {
- lk sync.Mutex
- s *rngSource
-}
-
-func (r *lockedSource) Int63() (n int64) {
- r.lk.Lock()
- n = r.s.Int63()
- r.lk.Unlock()
- return
-}
-
-func (r *lockedSource) Uint64() (n uint64) {
- r.lk.Lock()
- n = r.s.Uint64()
- r.lk.Unlock()
- return
-}
-
-func (r *lockedSource) Seed(seed int64) {
- r.lk.Lock()
- r.seed(seed)
- r.lk.Unlock()
-}
-
-// seedPos implements Seed for a lockedSource without a race condition.
-func (r *lockedSource) seedPos(seed int64, readPos *int8) {
- r.lk.Lock()
- r.seed(seed)
- *readPos = 0
- r.lk.Unlock()
-}
-
-// seed seeds the underlying source.
-// The caller must have locked r.lk.
-func (r *lockedSource) seed(seed int64) {
- if r.s == nil {
- r.s = newSource(seed)
- } else {
- r.s.Seed(seed)
- }
-}
-
-// read implements Read for a lockedSource without a race condition.
-func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
- r.lk.Lock()
- n, err = read(p, r.s, readVal, readPos)
- r.lk.Unlock()
- return
-}
diff --git a/contrib/go/_std_1.22/src/math/rand/v2/chacha8.go b/contrib/go/_std_1.22/src/math/rand/v2/chacha8.go
deleted file mode 100644
index 6b9aa7278250..000000000000
--- a/contrib/go/_std_1.22/src/math/rand/v2/chacha8.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2023 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.
-
-package rand
-
-import "internal/chacha8rand"
-
-// A ChaCha8 is a ChaCha8-based cryptographically strong
-// random number generator.
-type ChaCha8 struct {
- state chacha8rand.State
-}
-
-// NewChaCha8 returns a new ChaCha8 seeded with the given seed.
-func NewChaCha8(seed [32]byte) *ChaCha8 {
- c := new(ChaCha8)
- c.state.Init(seed)
- return c
-}
-
-// Seed resets the ChaCha8 to behave the same way as NewChaCha8(seed).
-func (c *ChaCha8) Seed(seed [32]byte) {
- c.state.Init(seed)
-}
-
-// Uint64 returns a uniformly distributed random uint64 value.
-func (c *ChaCha8) Uint64() uint64 {
- for {
- x, ok := c.state.Next()
- if ok {
- return x
- }
- c.state.Refill()
- }
-}
-
-// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
-func (c *ChaCha8) UnmarshalBinary(data []byte) error {
- return chacha8rand.Unmarshal(&c.state, data)
-}
-
-// MarshalBinary implements the encoding.BinaryMarshaler interface.
-func (c *ChaCha8) MarshalBinary() ([]byte, error) {
- return chacha8rand.Marshal(&c.state), nil
-}
diff --git a/contrib/go/_std_1.22/src/math/rand/v2/rand.go b/contrib/go/_std_1.22/src/math/rand/v2/rand.go
deleted file mode 100644
index f490408472ba..000000000000
--- a/contrib/go/_std_1.22/src/math/rand/v2/rand.go
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright 2009 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.
-
-// Package rand implements pseudo-random number generators suitable for tasks
-// such as simulation, but it should not be used for security-sensitive work.
-//
-// Random numbers are generated by a [Source], usually wrapped in a [Rand].
-// Both types should be used by a single goroutine at a time: sharing among
-// multiple goroutines requires some kind of synchronization.
-//
-// Top-level functions, such as [Float64] and [Int],
-// are safe for concurrent use by multiple goroutines.
-//
-// This package's outputs might be easily predictable regardless of how it's
-// seeded. For random numbers suitable for security-sensitive work, see the
-// crypto/rand package.
-package rand
-
-import (
- "math/bits"
- _ "unsafe" // for go:linkname
-)
-
-// A Source is a source of uniformly-distributed
-// pseudo-random uint64 values in the range [0, 1<<64).
-//
-// A Source is not safe for concurrent use by multiple goroutines.
-type Source interface {
- Uint64() uint64
-}
-
-// A Rand is a source of random numbers.
-type Rand struct {
- src Source
-}
-
-// New returns a new Rand that uses random values from src
-// to generate other random values.
-func New(src Source) *Rand {
- return &Rand{src: src}
-}
-
-// Int64 returns a non-negative pseudo-random 63-bit integer as an int64.
-func (r *Rand) Int64() int64 { return int64(r.src.Uint64() &^ (1 << 63)) }
-
-// Uint32 returns a pseudo-random 32-bit value as a uint32.
-func (r *Rand) Uint32() uint32 { return uint32(r.src.Uint64() >> 32) }
-
-// Uint64 returns a pseudo-random 64-bit value as a uint64.
-func (r *Rand) Uint64() uint64 { return r.src.Uint64() }
-
-// Int32 returns a non-negative pseudo-random 31-bit integer as an int32.
-func (r *Rand) Int32() int32 { return int32(r.src.Uint64() >> 33) }
-
-// Int returns a non-negative pseudo-random int.
-func (r *Rand) Int() int { return int(uint(r.src.Uint64()) << 1 >> 1) }
-
-// Int64N returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n <= 0.
-func (r *Rand) Int64N(n int64) int64 {
- if n <= 0 {
- panic("invalid argument to Int64N")
- }
- return int64(r.uint64n(uint64(n)))
-}
-
-// Uint64N returns, as a uint64, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n == 0.
-func (r *Rand) Uint64N(n uint64) uint64 {
- if n == 0 {
- panic("invalid argument to Uint64N")
- }
- return r.uint64n(n)
-}
-
-// uint64n is the no-bounds-checks version of Uint64N.
-func (r *Rand) uint64n(n uint64) uint64 {
- if is32bit && uint64(uint32(n)) == n {
- return uint64(r.uint32n(uint32(n)))
- }
- if n&(n-1) == 0 { // n is power of two, can mask
- return r.Uint64() & (n - 1)
- }
-
- // Suppose we have a uint64 x uniform in the range [0,2⁶⁴)
- // and want to reduce it to the range [0,n) preserving exact uniformity.
- // We can simulate a scaling arbitrary precision x * (n/2⁶⁴) by
- // the high bits of a double-width multiply of x*n, meaning (x*n)/2⁶⁴.
- // Since there are 2⁶⁴ possible inputs x and only n possible outputs,
- // the output is necessarily biased if n does not divide 2⁶⁴.
- // In general (x*n)/2⁶⁴ = k for x*n in [k*2⁶⁴,(k+1)*2⁶⁴).
- // There are either floor(2⁶⁴/n) or ceil(2⁶⁴/n) possible products
- // in that range, depending on k.
- // But suppose we reject the sample and try again when
- // x*n is in [k*2⁶⁴, k*2⁶⁴+(2⁶⁴%n)), meaning rejecting fewer than n possible
- // outcomes out of the 2⁶⁴.
- // Now there are exactly floor(2⁶⁴/n) possible ways to produce
- // each output value k, so we've restored uniformity.
- // To get valid uint64 math, 2⁶⁴ % n = (2⁶⁴ - n) % n = -n % n,
- // so the direct implementation of this algorithm would be:
- //
- // hi, lo := bits.Mul64(r.Uint64(), n)
- // thresh := -n % n
- // for lo < thresh {
- // hi, lo = bits.Mul64(r.Uint64(), n)
- // }
- //
- // That still leaves an expensive 64-bit division that we would rather avoid.
- // We know that thresh < n, and n is usually much less than 2⁶⁴, so we can
- // avoid the last four lines unless lo < n.
- //
- // See also:
- // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction
- // https://lemire.me/blog/2016/06/30/fast-random-shuffling
- hi, lo := bits.Mul64(r.Uint64(), n)
- if lo < n {
- thresh := -n % n
- for lo < thresh {
- hi, lo = bits.Mul64(r.Uint64(), n)
- }
- }
- return hi
-}
-
-// uint32n is an identical computation to uint64n
-// but optimized for 32-bit systems.
-func (r *Rand) uint32n(n uint32) uint32 {
- if n&(n-1) == 0 { // n is power of two, can mask
- return uint32(r.Uint64()) & (n - 1)
- }
- // On 64-bit systems we still use the uint64 code below because
- // the probability of a random uint64 lo being < a uint32 n is near zero,
- // meaning the unbiasing loop almost never runs.
- // On 32-bit systems, here we need to implement that same logic in 32-bit math,
- // both to preserve the exact output sequence observed on 64-bit machines
- // and to preserve the optimization that the unbiasing loop almost never runs.
- //
- // We want to compute
- // hi, lo := bits.Mul64(r.Uint64(), n)
- // In terms of 32-bit halves, this is:
- // x1:x0 := r.Uint64()
- // 0:hi, lo1:lo0 := bits.Mul64(x1:x0, 0:n)
- // Writing out the multiplication in terms of bits.Mul32 allows
- // using direct hardware instructions and avoiding
- // the computations involving these zeros.
- x := r.Uint64()
- lo1a, lo0 := bits.Mul32(uint32(x), n)
- hi, lo1b := bits.Mul32(uint32(x>>32), n)
- lo1, c := bits.Add32(lo1a, lo1b, 0)
- hi += c
- if lo1 == 0 && lo0 < uint32(n) {
- n64 := uint64(n)
- thresh := uint32(-n64 % n64)
- for lo1 == 0 && lo0 < thresh {
- x := r.Uint64()
- lo1a, lo0 = bits.Mul32(uint32(x), n)
- hi, lo1b = bits.Mul32(uint32(x>>32), n)
- lo1, c = bits.Add32(lo1a, lo1b, 0)
- hi += c
- }
- }
- return hi
-}
-
-// Int32N returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n <= 0.
-func (r *Rand) Int32N(n int32) int32 {
- if n <= 0 {
- panic("invalid argument to Int32N")
- }
- return int32(r.uint64n(uint64(n)))
-}
-
-// Uint32N returns, as a uint32, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n == 0.
-func (r *Rand) Uint32N(n uint32) uint32 {
- if n == 0 {
- panic("invalid argument to Uint32N")
- }
- return uint32(r.uint64n(uint64(n)))
-}
-
-const is32bit = ^uint(0)>>32 == 0
-
-// IntN returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n <= 0.
-func (r *Rand) IntN(n int) int {
- if n <= 0 {
- panic("invalid argument to IntN")
- }
- return int(r.uint64n(uint64(n)))
-}
-
-// UintN returns, as a uint, a non-negative pseudo-random number in the half-open interval [0,n).
-// It panics if n == 0.
-func (r *Rand) UintN(n uint) uint {
- if n == 0 {
- panic("invalid argument to UintN")
- }
- return uint(r.uint64n(uint64(n)))
-}
-
-// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
-func (r *Rand) Float64() float64 {
- // There are exactly 1<<53 float64s in [0,1). Use Intn(1<<53) / (1<<53).
- return float64(r.Uint64()<<11>>11) / (1 << 53)
-}
-
-// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
-func (r *Rand) Float32() float32 {
- // There are exactly 1<<24 float32s in [0,1). Use Intn(1<<24) / (1<<24).
- return float32(r.Uint32()<<8>>8) / (1 << 24)
-}
-
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
-// in the half-open interval [0,n).
-func (r *Rand) Perm(n int) []int {
- p := make([]int, n)
- for i := range p {
- p[i] = i
- }
- r.Shuffle(len(p), func(i, j int) { p[i], p[j] = p[j], p[i] })
- return p
-}
-
-// Shuffle pseudo-randomizes the order of elements.
-// n is the number of elements. Shuffle panics if n < 0.
-// swap swaps the elements with indexes i and j.
-func (r *Rand) Shuffle(n int, swap func(i, j int)) {
- if n < 0 {
- panic("invalid argument to Shuffle")
- }
-
- // Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
- // Shuffle really ought not be called with n that doesn't fit in 32 bits.
- // Not only will it take a very long time, but with 2³¹! possible permutations,
- // there's no way that any PRNG can have a big enough internal state to
- // generate even a minuscule percentage of the possible permutations.
- // Nevertheless, the right API signature accepts an int n, so handle it as best we can.
- for i := n - 1; i > 0; i-- {
- j := int(r.uint64n(uint64(i + 1)))
- swap(i, j)
- }
-}
-
-/*
- * Top-level convenience functions
- */
-
-// globalRand is the source of random numbers for the top-level
-// convenience functions.
-var globalRand = &Rand{src: &runtimeSource{}}
-
-//go:linkname runtime_rand runtime.rand
-func runtime_rand() uint64
-
-// runtimeSource is a Source that uses the runtime fastrand functions.
-type runtimeSource struct{}
-
-func (*runtimeSource) Uint64() uint64 {
- return runtime_rand()
-}
-
-// Int64 returns a non-negative pseudo-random 63-bit integer as an int64
-// from the default Source.
-func Int64() int64 { return globalRand.Int64() }
-
-// Uint32 returns a pseudo-random 32-bit value as a uint32
-// from the default Source.
-func Uint32() uint32 { return globalRand.Uint32() }
-
-// Uint64N returns, as a uint64, a pseudo-random number in the half-open interval [0,n)
-// from the default Source.
-// It panics if n <= 0.
-func Uint64N(n uint64) uint64 { return globalRand.Uint64N(n) }
-
-// Uint32N returns, as a uint32, a pseudo-random number in the half-open interval [0,n)
-// from the default Source.
-// It panics if n <= 0.
-func Uint32N(n uint32) uint32 { return globalRand.Uint32N(n) }
-
-// Uint64 returns a pseudo-random 64-bit value as a uint64
-// from the default Source.
-func Uint64() uint64 { return globalRand.Uint64() }
-
-// Int32 returns a non-negative pseudo-random 31-bit integer as an int32
-// from the default Source.
-func Int32() int32 { return globalRand.Int32() }
-
-// Int returns a non-negative pseudo-random int from the default Source.
-func Int() int { return globalRand.Int() }
-
-// Int64N returns, as an int64, a pseudo-random number in the half-open interval [0,n)
-// from the default Source.
-// It panics if n <= 0.
-func Int64N(n int64) int64 { return globalRand.Int64N(n) }
-
-// Int32N returns, as an int32, a pseudo-random number in the half-open interval [0,n)
-// from the default Source.
-// It panics if n <= 0.
-func Int32N(n int32) int32 { return globalRand.Int32N(n) }
-
-// IntN returns, as an int, a pseudo-random number in the half-open interval [0,n)
-// from the default Source.
-// It panics if n <= 0.
-func IntN(n int) int { return globalRand.IntN(n) }
-
-// UintN returns, as a uint, a pseudo-random number in the half-open interval [0,n)
-// from the default Source.
-// It panics if n <= 0.
-func UintN(n uint) uint { return globalRand.UintN(n) }
-
-// N returns a pseudo-random number in the half-open interval [0,n) from the default Source.
-// The type parameter Int can be any integer type.
-// It panics if n <= 0.
-func N[Int intType](n Int) Int {
- if n <= 0 {
- panic("invalid argument to N")
- }
- return Int(globalRand.uint64n(uint64(n)))
-}
-
-type intType interface {
- ~int | ~int8 | ~int16 | ~int32 | ~int64 |
- ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
-// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)
-// from the default Source.
-func Float64() float64 { return globalRand.Float64() }
-
-// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)
-// from the default Source.
-func Float32() float32 { return globalRand.Float32() }
-
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
-// in the half-open interval [0,n) from the default Source.
-func Perm(n int) []int { return globalRand.Perm(n) }
-
-// Shuffle pseudo-randomizes the order of elements using the default Source.
-// n is the number of elements. Shuffle panics if n < 0.
-// swap swaps the elements with indexes i and j.
-func Shuffle(n int, swap func(i, j int)) { globalRand.Shuffle(n, swap) }
-
-// NormFloat64 returns a normally distributed float64 in the range
-// [-math.MaxFloat64, +math.MaxFloat64] with
-// standard normal distribution (mean = 0, stddev = 1)
-// from the default Source.
-// To produce a different normal distribution, callers can
-// adjust the output using:
-//
-// sample = NormFloat64() * desiredStdDev + desiredMean
-func NormFloat64() float64 { return globalRand.NormFloat64() }
-
-// ExpFloat64 returns an exponentially distributed float64 in the range
-// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
-// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
-// To produce a distribution with a different rate parameter,
-// callers can adjust the output using:
-//
-// sample = ExpFloat64() / desiredRateParameter
-func ExpFloat64() float64 { return globalRand.ExpFloat64() }
diff --git a/contrib/go/_std_1.22/src/math/rand/v2/ya.make b/contrib/go/_std_1.22/src/math/rand/v2/ya.make
deleted file mode 100644
index 709d17ea4d94..000000000000
--- a/contrib/go/_std_1.22/src/math/rand/v2/ya.make
+++ /dev/null
@@ -1,14 +0,0 @@
-SUBSCRIBER(g:contrib)
-
-GO_LIBRARY()
-IF (TRUE)
- SRCS(
- chacha8.go
- exp.go
- normal.go
- pcg.go
- rand.go
- zipf.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/math/unsafe.go b/contrib/go/_std_1.22/src/math/unsafe.go
deleted file mode 100644
index e59f50ca62e5..000000000000
--- a/contrib/go/_std_1.22/src/math/unsafe.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2009 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.
-
-package math
-
-import "unsafe"
-
-// Float32bits returns the IEEE 754 binary representation of f,
-// with the sign bit of f and the result in the same bit position.
-// Float32bits(Float32frombits(x)) == x.
-func Float32bits(f float32) uint32 { return *(*uint32)(unsafe.Pointer(&f)) }
-
-// Float32frombits returns the floating-point number corresponding
-// to the IEEE 754 binary representation b, with the sign bit of b
-// and the result in the same bit position.
-// Float32frombits(Float32bits(x)) == x.
-func Float32frombits(b uint32) float32 { return *(*float32)(unsafe.Pointer(&b)) }
-
-// Float64bits returns the IEEE 754 binary representation of f,
-// with the sign bit of f and the result in the same bit position,
-// and Float64bits(Float64frombits(x)) == x.
-func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
-
-// Float64frombits returns the floating-point number corresponding
-// to the IEEE 754 binary representation b, with the sign bit of b
-// and the result in the same bit position.
-// Float64frombits(Float64bits(x)) == x.
-func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) }
diff --git a/contrib/go/_std_1.22/src/math/ya.make b/contrib/go/_std_1.22/src/math/ya.make
deleted file mode 100644
index daf65b084a79..000000000000
--- a/contrib/go/_std_1.22/src/math/ya.make
+++ /dev/null
@@ -1,125 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- abs.go
- acosh.go
- asin.go
- asinh.go
- atan.go
- atan2.go
- atanh.go
- bits.go
- cbrt.go
- const.go
- copysign.go
- dim.go
- dim_arm64.s
- dim_asm.go
- erf.go
- erfinv.go
- exp.go
- exp2_asm.go
- exp_arm64.s
- exp_asm.go
- expm1.go
- floor.go
- floor_arm64.s
- floor_asm.go
- fma.go
- frexp.go
- gamma.go
- hypot.go
- hypot_noasm.go
- j0.go
- j1.go
- jn.go
- ldexp.go
- lgamma.go
- log.go
- log10.go
- log1p.go
- log_stub.go
- logb.go
- mod.go
- modf.go
- modf_arm64.s
- modf_asm.go
- nextafter.go
- pow.go
- pow10.go
- remainder.go
- signbit.go
- sin.go
- sincos.go
- sinh.go
- sqrt.go
- stubs.go
- tan.go
- tanh.go
- trig_reduce.go
- unsafe.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- abs.go
- acosh.go
- asin.go
- asinh.go
- atan.go
- atan2.go
- atanh.go
- bits.go
- cbrt.go
- const.go
- copysign.go
- dim.go
- dim_amd64.s
- dim_asm.go
- erf.go
- erfinv.go
- exp.go
- exp2_noasm.go
- exp_amd64.go
- exp_amd64.s
- exp_asm.go
- expm1.go
- floor.go
- floor_amd64.s
- floor_asm.go
- fma.go
- frexp.go
- gamma.go
- hypot.go
- hypot_amd64.s
- hypot_asm.go
- j0.go
- j1.go
- jn.go
- ldexp.go
- lgamma.go
- log.go
- log10.go
- log1p.go
- log_amd64.s
- log_asm.go
- logb.go
- mod.go
- modf.go
- modf_noasm.go
- nextafter.go
- pow.go
- pow10.go
- remainder.go
- signbit.go
- sin.go
- sincos.go
- sinh.go
- sqrt.go
- stubs.go
- tan.go
- tanh.go
- trig_reduce.go
- unsafe.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/mime/multipart/writer.go b/contrib/go/_std_1.22/src/mime/multipart/writer.go
deleted file mode 100644
index d1ff151a7d1d..000000000000
--- a/contrib/go/_std_1.22/src/mime/multipart/writer.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2011 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.
-
-package multipart
-
-import (
- "bytes"
- "crypto/rand"
- "errors"
- "fmt"
- "io"
- "net/textproto"
- "sort"
- "strings"
-)
-
-// A Writer generates multipart messages.
-type Writer struct {
- w io.Writer
- boundary string
- lastpart *part
-}
-
-// NewWriter returns a new multipart Writer with a random boundary,
-// writing to w.
-func NewWriter(w io.Writer) *Writer {
- return &Writer{
- w: w,
- boundary: randomBoundary(),
- }
-}
-
-// Boundary returns the Writer's boundary.
-func (w *Writer) Boundary() string {
- return w.boundary
-}
-
-// SetBoundary overrides the Writer's default randomly-generated
-// boundary separator with an explicit value.
-//
-// SetBoundary must be called before any parts are created, may only
-// contain certain ASCII characters, and must be non-empty and
-// at most 70 bytes long.
-func (w *Writer) SetBoundary(boundary string) error {
- if w.lastpart != nil {
- return errors.New("mime: SetBoundary called after write")
- }
- // rfc2046#section-5.1.1
- if len(boundary) < 1 || len(boundary) > 70 {
- return errors.New("mime: invalid boundary length")
- }
- end := len(boundary) - 1
- for i, b := range boundary {
- if 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' {
- continue
- }
- switch b {
- case '\'', '(', ')', '+', '_', ',', '-', '.', '/', ':', '=', '?':
- continue
- case ' ':
- if i != end {
- continue
- }
- }
- return errors.New("mime: invalid boundary character")
- }
- w.boundary = boundary
- return nil
-}
-
-// FormDataContentType returns the Content-Type for an HTTP
-// multipart/form-data with this Writer's Boundary.
-func (w *Writer) FormDataContentType() string {
- b := w.boundary
- // We must quote the boundary if it contains any of the
- // tspecials characters defined by RFC 2045, or space.
- if strings.ContainsAny(b, `()<>@,;:\"/[]?= `) {
- b = `"` + b + `"`
- }
- return "multipart/form-data; boundary=" + b
-}
-
-func randomBoundary() string {
- var buf [30]byte
- _, err := io.ReadFull(rand.Reader, buf[:])
- if err != nil {
- panic(err)
- }
- return fmt.Sprintf("%x", buf[:])
-}
-
-// CreatePart creates a new multipart section with the provided
-// header. The body of the part should be written to the returned
-// Writer. After calling CreatePart, any previous part may no longer
-// be written to.
-func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error) {
- if w.lastpart != nil {
- if err := w.lastpart.close(); err != nil {
- return nil, err
- }
- }
- var b bytes.Buffer
- if w.lastpart != nil {
- fmt.Fprintf(&b, "\r\n--%s\r\n", w.boundary)
- } else {
- fmt.Fprintf(&b, "--%s\r\n", w.boundary)
- }
-
- keys := make([]string, 0, len(header))
- for k := range header {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- for _, v := range header[k] {
- fmt.Fprintf(&b, "%s: %s\r\n", k, v)
- }
- }
- fmt.Fprintf(&b, "\r\n")
- _, err := io.Copy(w.w, &b)
- if err != nil {
- return nil, err
- }
- p := &part{
- mw: w,
- }
- w.lastpart = p
- return p, nil
-}
-
-var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
-
-func escapeQuotes(s string) string {
- return quoteEscaper.Replace(s)
-}
-
-// CreateFormFile is a convenience wrapper around CreatePart. It creates
-// a new form-data header with the provided field name and file name.
-func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error) {
- h := make(textproto.MIMEHeader)
- h.Set("Content-Disposition",
- fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
- escapeQuotes(fieldname), escapeQuotes(filename)))
- h.Set("Content-Type", "application/octet-stream")
- return w.CreatePart(h)
-}
-
-// CreateFormField calls CreatePart with a header using the
-// given field name.
-func (w *Writer) CreateFormField(fieldname string) (io.Writer, error) {
- h := make(textproto.MIMEHeader)
- h.Set("Content-Disposition",
- fmt.Sprintf(`form-data; name="%s"`, escapeQuotes(fieldname)))
- return w.CreatePart(h)
-}
-
-// WriteField calls CreateFormField and then writes the given value.
-func (w *Writer) WriteField(fieldname, value string) error {
- p, err := w.CreateFormField(fieldname)
- if err != nil {
- return err
- }
- _, err = p.Write([]byte(value))
- return err
-}
-
-// Close finishes the multipart message and writes the trailing
-// boundary end line to the output.
-func (w *Writer) Close() error {
- if w.lastpart != nil {
- if err := w.lastpart.close(); err != nil {
- return err
- }
- w.lastpart = nil
- }
- _, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.boundary)
- return err
-}
-
-type part struct {
- mw *Writer
- closed bool
- we error // last error that occurred writing
-}
-
-func (p *part) close() error {
- p.closed = true
- return p.we
-}
-
-func (p *part) Write(d []byte) (n int, err error) {
- if p.closed {
- return 0, errors.New("multipart: can't write to finished part")
- }
- n, err = p.mw.w.Write(d)
- if err != nil {
- p.we = err
- }
- return
-}
diff --git a/contrib/go/_std_1.22/src/mime/quotedprintable/writer.go b/contrib/go/_std_1.22/src/mime/quotedprintable/writer.go
deleted file mode 100644
index 16ea0bf7d622..000000000000
--- a/contrib/go/_std_1.22/src/mime/quotedprintable/writer.go
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2015 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.
-
-package quotedprintable
-
-import "io"
-
-const lineMaxLen = 76
-
-// A Writer is a quoted-printable writer that implements io.WriteCloser.
-type Writer struct {
- // Binary mode treats the writer's input as pure binary and processes end of
- // line bytes as binary data.
- Binary bool
-
- w io.Writer
- i int
- line [78]byte
- cr bool
-}
-
-// NewWriter returns a new Writer that writes to w.
-func NewWriter(w io.Writer) *Writer {
- return &Writer{w: w}
-}
-
-// Write encodes p using quoted-printable encoding and writes it to the
-// underlying io.Writer. It limits line length to 76 characters. The encoded
-// bytes are not necessarily flushed until the Writer is closed.
-func (w *Writer) Write(p []byte) (n int, err error) {
- for i, b := range p {
- switch {
- // Simple writes are done in batch.
- case b >= '!' && b <= '~' && b != '=':
- continue
- case isWhitespace(b) || !w.Binary && (b == '\n' || b == '\r'):
- continue
- }
-
- if i > n {
- if err := w.write(p[n:i]); err != nil {
- return n, err
- }
- n = i
- }
-
- if err := w.encode(b); err != nil {
- return n, err
- }
- n++
- }
-
- if n == len(p) {
- return n, nil
- }
-
- if err := w.write(p[n:]); err != nil {
- return n, err
- }
-
- return len(p), nil
-}
-
-// Close closes the Writer, flushing any unwritten data to the underlying
-// io.Writer, but does not close the underlying io.Writer.
-func (w *Writer) Close() error {
- if err := w.checkLastByte(); err != nil {
- return err
- }
-
- return w.flush()
-}
-
-// write limits text encoded in quoted-printable to 76 characters per line.
-func (w *Writer) write(p []byte) error {
- for _, b := range p {
- if b == '\n' || b == '\r' {
- // If the previous byte was \r, the CRLF has already been inserted.
- if w.cr && b == '\n' {
- w.cr = false
- continue
- }
-
- if b == '\r' {
- w.cr = true
- }
-
- if err := w.checkLastByte(); err != nil {
- return err
- }
- if err := w.insertCRLF(); err != nil {
- return err
- }
- continue
- }
-
- if w.i == lineMaxLen-1 {
- if err := w.insertSoftLineBreak(); err != nil {
- return err
- }
- }
-
- w.line[w.i] = b
- w.i++
- w.cr = false
- }
-
- return nil
-}
-
-func (w *Writer) encode(b byte) error {
- if lineMaxLen-1-w.i < 3 {
- if err := w.insertSoftLineBreak(); err != nil {
- return err
- }
- }
-
- w.line[w.i] = '='
- w.line[w.i+1] = upperhex[b>>4]
- w.line[w.i+2] = upperhex[b&0x0f]
- w.i += 3
-
- return nil
-}
-
-const upperhex = "0123456789ABCDEF"
-
-// checkLastByte encodes the last buffered byte if it is a space or a tab.
-func (w *Writer) checkLastByte() error {
- if w.i == 0 {
- return nil
- }
-
- b := w.line[w.i-1]
- if isWhitespace(b) {
- w.i--
- if err := w.encode(b); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func (w *Writer) insertSoftLineBreak() error {
- w.line[w.i] = '='
- w.i++
-
- return w.insertCRLF()
-}
-
-func (w *Writer) insertCRLF() error {
- w.line[w.i] = '\r'
- w.line[w.i+1] = '\n'
- w.i += 2
-
- return w.flush()
-}
-
-func (w *Writer) flush() error {
- if _, err := w.w.Write(w.line[:w.i]); err != nil {
- return err
- }
-
- w.i = 0
- return nil
-}
-
-func isWhitespace(b byte) bool {
- return b == ' ' || b == '\t'
-}
diff --git a/contrib/go/_std_1.22/src/mime/type.go b/contrib/go/_std_1.22/src/mime/type.go
deleted file mode 100644
index 465ecf0d599c..000000000000
--- a/contrib/go/_std_1.22/src/mime/type.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2010 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.
-
-// Package mime implements parts of the MIME spec.
-package mime
-
-import (
- "fmt"
- "sort"
- "strings"
- "sync"
-)
-
-var (
- mimeTypes sync.Map // map[string]string; ".Z" => "application/x-compress"
- mimeTypesLower sync.Map // map[string]string; ".z" => "application/x-compress"
-
- // extensions maps from MIME type to list of lowercase file
- // extensions: "image/jpeg" => [".jpg", ".jpeg"]
- extensionsMu sync.Mutex // Guards stores (but not loads) on extensions.
- extensions sync.Map // map[string][]string; slice values are append-only.
-)
-
-func clearSyncMap(m *sync.Map) {
- m.Range(func(k, _ any) bool {
- m.Delete(k)
- return true
- })
-}
-
-// setMimeTypes is used by initMime's non-test path, and by tests.
-func setMimeTypes(lowerExt, mixExt map[string]string) {
- clearSyncMap(&mimeTypes)
- clearSyncMap(&mimeTypesLower)
- clearSyncMap(&extensions)
-
- for k, v := range lowerExt {
- mimeTypesLower.Store(k, v)
- }
- for k, v := range mixExt {
- mimeTypes.Store(k, v)
- }
-
- extensionsMu.Lock()
- defer extensionsMu.Unlock()
- for k, v := range lowerExt {
- justType, _, err := ParseMediaType(v)
- if err != nil {
- panic(err)
- }
- var exts []string
- if ei, ok := extensions.Load(justType); ok {
- exts = ei.([]string)
- }
- extensions.Store(justType, append(exts, k))
- }
-}
-
-var builtinTypesLower = map[string]string{
- ".avif": "image/avif",
- ".css": "text/css; charset=utf-8",
- ".gif": "image/gif",
- ".htm": "text/html; charset=utf-8",
- ".html": "text/html; charset=utf-8",
- ".jpeg": "image/jpeg",
- ".jpg": "image/jpeg",
- ".js": "text/javascript; charset=utf-8",
- ".json": "application/json",
- ".mjs": "text/javascript; charset=utf-8",
- ".pdf": "application/pdf",
- ".png": "image/png",
- ".svg": "image/svg+xml",
- ".wasm": "application/wasm",
- ".webp": "image/webp",
- ".xml": "text/xml; charset=utf-8",
-}
-
-var once sync.Once // guards initMime
-
-var testInitMime, osInitMime func()
-
-func initMime() {
- if fn := testInitMime; fn != nil {
- fn()
- } else {
- setMimeTypes(builtinTypesLower, builtinTypesLower)
- osInitMime()
- }
-}
-
-// TypeByExtension returns the MIME type associated with the file extension ext.
-// The extension ext should begin with a leading dot, as in ".html".
-// When ext has no associated type, TypeByExtension returns "".
-//
-// Extensions are looked up first case-sensitively, then case-insensitively.
-//
-// The built-in table is small but on unix it is augmented by the local
-// system's MIME-info database or mime.types file(s) if available under one or
-// more of these names:
-//
-// /usr/local/share/mime/globs2
-// /usr/share/mime/globs2
-// /etc/mime.types
-// /etc/apache2/mime.types
-// /etc/apache/mime.types
-//
-// On Windows, MIME types are extracted from the registry.
-//
-// Text types have the charset parameter set to "utf-8" by default.
-func TypeByExtension(ext string) string {
- once.Do(initMime)
-
- // Case-sensitive lookup.
- if v, ok := mimeTypes.Load(ext); ok {
- return v.(string)
- }
-
- // Case-insensitive lookup.
- // Optimistically assume a short ASCII extension and be
- // allocation-free in that case.
- var buf [10]byte
- lower := buf[:0]
- const utf8RuneSelf = 0x80 // from utf8 package, but not importing it.
- for i := 0; i < len(ext); i++ {
- c := ext[i]
- if c >= utf8RuneSelf {
- // Slow path.
- si, _ := mimeTypesLower.Load(strings.ToLower(ext))
- s, _ := si.(string)
- return s
- }
- if 'A' <= c && c <= 'Z' {
- lower = append(lower, c+('a'-'A'))
- } else {
- lower = append(lower, c)
- }
- }
- si, _ := mimeTypesLower.Load(string(lower))
- s, _ := si.(string)
- return s
-}
-
-// ExtensionsByType returns the extensions known to be associated with the MIME
-// type typ. The returned extensions will each begin with a leading dot, as in
-// ".html". When typ has no associated extensions, ExtensionsByType returns an
-// nil slice.
-func ExtensionsByType(typ string) ([]string, error) {
- justType, _, err := ParseMediaType(typ)
- if err != nil {
- return nil, err
- }
-
- once.Do(initMime)
- s, ok := extensions.Load(justType)
- if !ok {
- return nil, nil
- }
- ret := append([]string(nil), s.([]string)...)
- sort.Strings(ret)
- return ret, nil
-}
-
-// AddExtensionType sets the MIME type associated with
-// the extension ext to typ. The extension should begin with
-// a leading dot, as in ".html".
-func AddExtensionType(ext, typ string) error {
- if !strings.HasPrefix(ext, ".") {
- return fmt.Errorf("mime: extension %q missing leading dot", ext)
- }
- once.Do(initMime)
- return setExtensionType(ext, typ)
-}
-
-func setExtensionType(extension, mimeType string) error {
- justType, param, err := ParseMediaType(mimeType)
- if err != nil {
- return err
- }
- if strings.HasPrefix(mimeType, "text/") && param["charset"] == "" {
- param["charset"] = "utf-8"
- mimeType = FormatMediaType(mimeType, param)
- }
- extLower := strings.ToLower(extension)
-
- mimeTypes.Store(extension, mimeType)
- mimeTypesLower.Store(extLower, mimeType)
-
- extensionsMu.Lock()
- defer extensionsMu.Unlock()
- var exts []string
- if ei, ok := extensions.Load(justType); ok {
- exts = ei.([]string)
- }
- for _, v := range exts {
- if v == extLower {
- return nil
- }
- }
- extensions.Store(justType, append(exts, extLower))
- return nil
-}
diff --git a/contrib/go/_std_1.22/src/mime/ya.make b/contrib/go/_std_1.22/src/mime/ya.make
deleted file mode 100644
index ef970c93b897..000000000000
--- a/contrib/go/_std_1.22/src/mime/ya.make
+++ /dev/null
@@ -1,19 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- encodedword.go
- grammar.go
- mediatype.go
- type.go
- type_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- encodedword.go
- grammar.go
- mediatype.go
- type.go
- type_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/net/cgo_unix_cgo_darwin.go b/contrib/go/_std_1.22/src/net/cgo_unix_cgo_darwin.go
deleted file mode 100644
index 40d5e426f25c..000000000000
--- a/contrib/go/_std_1.22/src/net/cgo_unix_cgo_darwin.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2023 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.
-
-//go:build !netgo && cgo && darwin
-
-package net
-
-/*
-#include
-*/
-import "C"
-
-import (
- "internal/syscall/unix"
- "unsafe"
-)
-
-// This will cause a compile error when the size of
-// unix.ResState is too small.
-type _ [unsafe.Sizeof(unix.ResState{}) - unsafe.Sizeof(C.struct___res_state{})]byte
diff --git a/contrib/go/_std_1.22/src/net/dnsconfig.go b/contrib/go/_std_1.22/src/net/dnsconfig.go
deleted file mode 100644
index c86a70be5afd..000000000000
--- a/contrib/go/_std_1.22/src/net/dnsconfig.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 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.
-
-package net
-
-import (
- "os"
- "sync/atomic"
- "time"
-)
-
-var (
- defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
- getHostname = os.Hostname // variable for testing
-)
-
-type dnsConfig struct {
- servers []string // server addresses (in host:port form) to use
- search []string // rooted suffixes to append to local name
- ndots int // number of dots in name to trigger absolute lookup
- timeout time.Duration // wait before giving up on a query, including retries
- attempts int // lost packets before giving up on server
- rotate bool // round robin among servers
- unknownOpt bool // anything unknown was encountered
- lookup []string // OpenBSD top-level database "lookup" order
- err error // any error that occurs during open of resolv.conf
- mtime time.Time // time of resolv.conf modification
- soffset uint32 // used by serverOffset
- singleRequest bool // use sequential A and AAAA queries instead of parallel queries
- useTCP bool // force usage of TCP for DNS resolutions
- trustAD bool // add AD flag to queries
- noReload bool // do not check for config file updates
-}
-
-// serverOffset returns an offset that can be used to determine
-// indices of servers in c.servers when making queries.
-// When the rotate option is enabled, this offset increases.
-// Otherwise it is always 0.
-func (c *dnsConfig) serverOffset() uint32 {
- if c.rotate {
- return atomic.AddUint32(&c.soffset, 1) - 1 // return 0 to start
- }
- return 0
-}
diff --git a/contrib/go/_std_1.22/src/net/dnsconfig_windows.go b/contrib/go/_std_1.22/src/net/dnsconfig_windows.go
deleted file mode 100644
index f3d242366ae2..000000000000
--- a/contrib/go/_std_1.22/src/net/dnsconfig_windows.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2022 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.
-
-package net
-
-import (
- "internal/syscall/windows"
- "syscall"
- "time"
-)
-
-func dnsReadConfig(ignoredFilename string) (conf *dnsConfig) {
- conf = &dnsConfig{
- ndots: 1,
- timeout: 5 * time.Second,
- attempts: 2,
- }
- defer func() {
- if len(conf.servers) == 0 {
- conf.servers = defaultNS
- }
- }()
- aas, err := adapterAddresses()
- if err != nil {
- return
- }
- // TODO(bradfitz): this just collects all the DNS servers on all
- // the interfaces in some random order. It should order it by
- // default route, or only use the default route(s) instead.
- // In practice, however, it mostly works.
- for _, aa := range aas {
- for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next {
- // Only take interfaces whose OperStatus is IfOperStatusUp(0x01) into DNS configs.
- if aa.OperStatus != windows.IfOperStatusUp {
- continue
- }
- sa, err := dns.Address.Sockaddr.Sockaddr()
- if err != nil {
- continue
- }
- var ip IP
- switch sa := sa.(type) {
- case *syscall.SockaddrInet4:
- ip = IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
- case *syscall.SockaddrInet6:
- ip = make(IP, IPv6len)
- copy(ip, sa.Addr[:])
- if ip[0] == 0xfe && ip[1] == 0xc0 {
- // Ignore these fec0/10 ones. Windows seems to
- // populate them as defaults on its misc rando
- // interfaces.
- continue
- }
- default:
- // Unexpected type.
- continue
- }
- conf.servers = append(conf.servers, JoinHostPort(ip.String(), "53"))
- }
- }
- return conf
-}
diff --git a/contrib/go/_std_1.22/src/net/fd_windows.go b/contrib/go/_std_1.22/src/net/fd_windows.go
deleted file mode 100644
index 45a10cf1eb01..000000000000
--- a/contrib/go/_std_1.22/src/net/fd_windows.go
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2010 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.
-
-package net
-
-import (
- "context"
- "internal/poll"
- "internal/syscall/windows"
- "os"
- "runtime"
- "syscall"
- "unsafe"
-)
-
-const (
- readSyscallName = "wsarecv"
- readFromSyscallName = "wsarecvfrom"
- readMsgSyscallName = "wsarecvmsg"
- writeSyscallName = "wsasend"
- writeToSyscallName = "wsasendto"
- writeMsgSyscallName = "wsasendmsg"
-)
-
-// canUseConnectEx reports whether we can use the ConnectEx Windows API call
-// for the given network type.
-func canUseConnectEx(net string) bool {
- switch net {
- case "tcp", "tcp4", "tcp6":
- return true
- }
- // ConnectEx windows API does not support connectionless sockets.
- return false
-}
-
-func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
- ret := &netFD{
- pfd: poll.FD{
- Sysfd: sysfd,
- IsStream: sotype == syscall.SOCK_STREAM,
- ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW,
- },
- family: family,
- sotype: sotype,
- net: net,
- }
- return ret, nil
-}
-
-func (fd *netFD) init() error {
- errcall, err := fd.pfd.Init(fd.net, true)
- if errcall != "" {
- err = wrapSyscallError(errcall, err)
- }
- return err
-}
-
-// Always returns nil for connected peer address result.
-func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
- // Do not need to call fd.writeLock here,
- // because fd is not yet accessible to user,
- // so no concurrent operations are possible.
- if err := fd.init(); err != nil {
- return nil, err
- }
-
- if ctx.Done() != nil {
- // Propagate the Context's deadline and cancellation.
- // If the context is already done, or if it has a nonzero deadline,
- // ensure that that is applied before the call to ConnectEx begins
- // so that we don't return spurious connections.
- defer fd.pfd.SetWriteDeadline(noDeadline)
-
- if ctx.Err() != nil {
- fd.pfd.SetWriteDeadline(aLongTimeAgo)
- } else {
- if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
- fd.pfd.SetWriteDeadline(deadline)
- }
-
- done := make(chan struct{})
- stop := context.AfterFunc(ctx, func() {
- // Force the runtime's poller to immediately give
- // up waiting for writability.
- fd.pfd.SetWriteDeadline(aLongTimeAgo)
- close(done)
- })
- defer func() {
- if !stop() {
- // Wait for the call to SetWriteDeadline to complete so that we can
- // reset the deadline if everything else succeeded.
- <-done
- }
- }()
- }
- }
-
- if !canUseConnectEx(fd.net) {
- err := connectFunc(fd.pfd.Sysfd, ra)
- return nil, os.NewSyscallError("connect", err)
- }
- // ConnectEx windows API requires an unconnected, previously bound socket.
- if la == nil {
- switch ra.(type) {
- case *syscall.SockaddrInet4:
- la = &syscall.SockaddrInet4{}
- case *syscall.SockaddrInet6:
- la = &syscall.SockaddrInet6{}
- default:
- panic("unexpected type in connect")
- }
- if err := syscall.Bind(fd.pfd.Sysfd, la); err != nil {
- return nil, os.NewSyscallError("bind", err)
- }
- }
-
- var isloopback bool
- switch ra := ra.(type) {
- case *syscall.SockaddrInet4:
- isloopback = ra.Addr[0] == 127
- case *syscall.SockaddrInet6:
- isloopback = ra.Addr == [16]byte(IPv6loopback)
- default:
- panic("unexpected type in connect")
- }
- if isloopback {
- // This makes ConnectEx() fails faster if the target port on the localhost
- // is not reachable, instead of waiting for 2s.
- params := windows.TCP_INITIAL_RTO_PARAMETERS{
- Rtt: windows.TCP_INITIAL_RTO_UNSPECIFIED_RTT, // use the default or overridden by the Administrator
- MaxSynRetransmissions: 1, // minimum possible value before Windows 10.0.16299
- }
- if windows.Support_TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS() {
- // In Windows 10.0.16299 TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS makes ConnectEx() fails instantly.
- params.MaxSynRetransmissions = windows.TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS
- }
- var out uint32
- // Don't abort the connection if WSAIoctl fails, as it is only an optimization.
- // If it fails reliably, we expect TestDialClosedPortFailFast to detect it.
- _ = fd.pfd.WSAIoctl(windows.SIO_TCP_INITIAL_RTO, (*byte)(unsafe.Pointer(¶ms)), uint32(unsafe.Sizeof(params)), nil, 0, &out, nil, 0)
- }
-
- // Call ConnectEx API.
- if err := fd.pfd.ConnectEx(ra); err != nil {
- select {
- case <-ctx.Done():
- return nil, mapErr(ctx.Err())
- default:
- if _, ok := err.(syscall.Errno); ok {
- err = os.NewSyscallError("connectex", err)
- }
- return nil, err
- }
- }
- // Refresh socket properties.
- return nil, os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.pfd.Sysfd)), int32(unsafe.Sizeof(fd.pfd.Sysfd))))
-}
-
-func (c *conn) writeBuffers(v *Buffers) (int64, error) {
- if !c.ok() {
- return 0, syscall.EINVAL
- }
- n, err := c.fd.writeBuffers(v)
- if err != nil {
- return n, &OpError{Op: "wsasend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
- }
- return n, nil
-}
-
-func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
- n, err := fd.pfd.Writev((*[][]byte)(buf))
- runtime.KeepAlive(fd)
- return n, wrapSyscallError("wsasend", err)
-}
-
-func (fd *netFD) accept() (*netFD, error) {
- s, rawsa, rsan, errcall, err := fd.pfd.Accept(func() (syscall.Handle, error) {
- return sysSocket(fd.family, fd.sotype, 0)
- })
-
- if err != nil {
- if errcall != "" {
- err = wrapSyscallError(errcall, err)
- }
- return nil, err
- }
-
- // Associate our new socket with IOCP.
- netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
- if err != nil {
- poll.CloseFunc(s)
- return nil, err
- }
- if err := netfd.init(); err != nil {
- fd.Close()
- return nil, err
- }
-
- // Get local and peer addr out of AcceptEx buffer.
- var lrsa, rrsa *syscall.RawSockaddrAny
- var llen, rlen int32
- syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
- 0, rsan, rsan, &lrsa, &llen, &rrsa, &rlen)
- lsa, _ := lrsa.Sockaddr()
- rsa, _ := rrsa.Sockaddr()
-
- netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
- return netfd, nil
-}
-
-// Unimplemented functions.
-
-func (fd *netFD) dup() (*os.File, error) {
- // TODO: Implement this
- return nil, syscall.EWINDOWS
-}
diff --git a/contrib/go/_std_1.22/src/net/file_plan9.go b/contrib/go/_std_1.22/src/net/file_plan9.go
deleted file mode 100644
index 64aabf93ee54..000000000000
--- a/contrib/go/_std_1.22/src/net/file_plan9.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2011 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.
-
-package net
-
-import (
- "errors"
- "io"
- "os"
- "syscall"
-)
-
-func (fd *netFD) status(ln int) (string, error) {
- if !fd.ok() {
- return "", syscall.EINVAL
- }
-
- status, err := os.Open(fd.dir + "/status")
- if err != nil {
- return "", err
- }
- defer status.Close()
- buf := make([]byte, ln)
- n, err := io.ReadFull(status, buf[:])
- if err != nil {
- return "", err
- }
- return string(buf[:n]), nil
-}
-
-func newFileFD(f *os.File) (net *netFD, err error) {
- var ctl *os.File
- close := func(fd int) {
- if err != nil {
- syscall.Close(fd)
- }
- }
-
- path, err := syscall.Fd2path(int(f.Fd()))
- if err != nil {
- return nil, os.NewSyscallError("fd2path", err)
- }
- comp := splitAtBytes(path, "/")
- n := len(comp)
- if n < 3 || comp[0][0:3] != "net" {
- return nil, syscall.EPLAN9
- }
-
- name := comp[2]
- switch file := comp[n-1]; file {
- case "ctl", "clone":
- fd, err := syscall.Dup(int(f.Fd()), -1)
- if err != nil {
- return nil, os.NewSyscallError("dup", err)
- }
- defer close(fd)
-
- dir := netdir + "/" + comp[n-2]
- ctl = os.NewFile(uintptr(fd), dir+"/"+file)
- ctl.Seek(0, io.SeekStart)
- var buf [16]byte
- n, err := ctl.Read(buf[:])
- if err != nil {
- return nil, err
- }
- name = string(buf[:n])
- default:
- if len(comp) < 4 {
- return nil, errors.New("could not find control file for connection")
- }
- dir := netdir + "/" + comp[1] + "/" + name
- ctl, err = os.OpenFile(dir+"/ctl", os.O_RDWR, 0)
- if err != nil {
- return nil, err
- }
- defer close(int(ctl.Fd()))
- }
- dir := netdir + "/" + comp[1] + "/" + name
- laddr, err := readPlan9Addr(comp[1], dir+"/local")
- if err != nil {
- return nil, err
- }
- return newFD(comp[1], name, nil, ctl, nil, laddr, nil)
-}
-
-func fileConn(f *os.File) (Conn, error) {
- fd, err := newFileFD(f)
- if err != nil {
- return nil, err
- }
- if !fd.ok() {
- return nil, syscall.EINVAL
- }
-
- fd.data, err = os.OpenFile(fd.dir+"/data", os.O_RDWR, 0)
- if err != nil {
- return nil, err
- }
-
- switch fd.laddr.(type) {
- case *TCPAddr:
- return newTCPConn(fd, defaultTCPKeepAlive, testHookSetKeepAlive), nil
- case *UDPAddr:
- return newUDPConn(fd), nil
- }
- return nil, syscall.EPLAN9
-}
-
-func fileListener(f *os.File) (Listener, error) {
- fd, err := newFileFD(f)
- if err != nil {
- return nil, err
- }
- switch fd.laddr.(type) {
- case *TCPAddr:
- default:
- return nil, syscall.EPLAN9
- }
-
- // check that file corresponds to a listener
- s, err := fd.status(len("Listen"))
- if err != nil {
- return nil, err
- }
- if s != "Listen" {
- return nil, errors.New("file does not represent a listener")
- }
-
- return &TCPListener{fd: fd}, nil
-}
-
-func filePacketConn(f *os.File) (PacketConn, error) {
- return nil, syscall.EPLAN9
-}
diff --git a/contrib/go/_std_1.22/src/net/file_unix.go b/contrib/go/_std_1.22/src/net/file_unix.go
deleted file mode 100644
index 8b9fc38916f7..000000000000
--- a/contrib/go/_std_1.22/src/net/file_unix.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2011 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.
-
-//go:build unix
-
-package net
-
-import (
- "internal/poll"
- "os"
- "syscall"
-)
-
-func dupSocket(f *os.File) (int, error) {
- s, call, err := poll.DupCloseOnExec(int(f.Fd()))
- if err != nil {
- if call != "" {
- err = os.NewSyscallError(call, err)
- }
- return -1, err
- }
- if err := syscall.SetNonblock(s, true); err != nil {
- poll.CloseFunc(s)
- return -1, os.NewSyscallError("setnonblock", err)
- }
- return s, nil
-}
-
-func newFileFD(f *os.File) (*netFD, error) {
- s, err := dupSocket(f)
- if err != nil {
- return nil, err
- }
- family := syscall.AF_UNSPEC
- sotype, err := syscall.GetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_TYPE)
- if err != nil {
- poll.CloseFunc(s)
- return nil, os.NewSyscallError("getsockopt", err)
- }
- lsa, _ := syscall.Getsockname(s)
- rsa, _ := syscall.Getpeername(s)
- switch lsa.(type) {
- case *syscall.SockaddrInet4:
- family = syscall.AF_INET
- case *syscall.SockaddrInet6:
- family = syscall.AF_INET6
- case *syscall.SockaddrUnix:
- family = syscall.AF_UNIX
- default:
- poll.CloseFunc(s)
- return nil, syscall.EPROTONOSUPPORT
- }
- fd, err := newFD(s, family, sotype, "")
- if err != nil {
- poll.CloseFunc(s)
- return nil, err
- }
- laddr := fd.addrFunc()(lsa)
- raddr := fd.addrFunc()(rsa)
- fd.net = laddr.Network()
- if err := fd.init(); err != nil {
- fd.Close()
- return nil, err
- }
- fd.setAddr(laddr, raddr)
- return fd, nil
-}
-
-func fileConn(f *os.File) (Conn, error) {
- fd, err := newFileFD(f)
- if err != nil {
- return nil, err
- }
- switch fd.laddr.(type) {
- case *TCPAddr:
- return newTCPConn(fd, defaultTCPKeepAlive, testHookSetKeepAlive), nil
- case *UDPAddr:
- return newUDPConn(fd), nil
- case *IPAddr:
- return newIPConn(fd), nil
- case *UnixAddr:
- return newUnixConn(fd), nil
- }
- fd.Close()
- return nil, syscall.EINVAL
-}
-
-func fileListener(f *os.File) (Listener, error) {
- fd, err := newFileFD(f)
- if err != nil {
- return nil, err
- }
- switch laddr := fd.laddr.(type) {
- case *TCPAddr:
- return &TCPListener{fd: fd}, nil
- case *UnixAddr:
- return &UnixListener{fd: fd, path: laddr.Name, unlink: false}, nil
- }
- fd.Close()
- return nil, syscall.EINVAL
-}
-
-func filePacketConn(f *os.File) (PacketConn, error) {
- fd, err := newFileFD(f)
- if err != nil {
- return nil, err
- }
- switch fd.laddr.(type) {
- case *UDPAddr:
- return newUDPConn(fd), nil
- case *IPAddr:
- return newIPConn(fd), nil
- case *UnixAddr:
- return newUnixConn(fd), nil
- }
- fd.Close()
- return nil, syscall.EINVAL
-}
diff --git a/contrib/go/_std_1.22/src/net/http/clone.go b/contrib/go/_std_1.22/src/net/http/clone.go
deleted file mode 100644
index 3a3375bff716..000000000000
--- a/contrib/go/_std_1.22/src/net/http/clone.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2019 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.
-
-package http
-
-import (
- "mime/multipart"
- "net/textproto"
- "net/url"
-)
-
-func cloneURLValues(v url.Values) url.Values {
- if v == nil {
- return nil
- }
- // http.Header and url.Values have the same representation, so temporarily
- // treat it like http.Header, which does have a clone:
- return url.Values(Header(v).Clone())
-}
-
-func cloneURL(u *url.URL) *url.URL {
- if u == nil {
- return nil
- }
- u2 := new(url.URL)
- *u2 = *u
- if u.User != nil {
- u2.User = new(url.Userinfo)
- *u2.User = *u.User
- }
- return u2
-}
-
-func cloneMultipartForm(f *multipart.Form) *multipart.Form {
- if f == nil {
- return nil
- }
- f2 := &multipart.Form{
- Value: (map[string][]string)(Header(f.Value).Clone()),
- }
- if f.File != nil {
- m := make(map[string][]*multipart.FileHeader)
- for k, vv := range f.File {
- vv2 := make([]*multipart.FileHeader, len(vv))
- for i, v := range vv {
- vv2[i] = cloneMultipartFileHeader(v)
- }
- m[k] = vv2
- }
- f2.File = m
- }
- return f2
-}
-
-func cloneMultipartFileHeader(fh *multipart.FileHeader) *multipart.FileHeader {
- if fh == nil {
- return nil
- }
- fh2 := new(multipart.FileHeader)
- *fh2 = *fh
- fh2.Header = textproto.MIMEHeader(Header(fh.Header).Clone())
- return fh2
-}
-
-// cloneOrMakeHeader invokes Header.Clone but if the
-// result is nil, it'll instead make and return a non-nil Header.
-func cloneOrMakeHeader(hdr Header) Header {
- clone := hdr.Clone()
- if clone == nil {
- clone = make(Header)
- }
- return clone
-}
diff --git a/contrib/go/_std_1.22/src/net/http/cookie.go b/contrib/go/_std_1.22/src/net/http/cookie.go
deleted file mode 100644
index c22897f3f99e..000000000000
--- a/contrib/go/_std_1.22/src/net/http/cookie.go
+++ /dev/null
@@ -1,468 +0,0 @@
-// Copyright 2009 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.
-
-package http
-
-import (
- "errors"
- "fmt"
- "log"
- "net"
- "net/http/internal/ascii"
- "net/textproto"
- "strconv"
- "strings"
- "time"
-)
-
-// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
-// HTTP response or the Cookie header of an HTTP request.
-//
-// See https://tools.ietf.org/html/rfc6265 for details.
-type Cookie struct {
- Name string
- Value string
-
- Path string // optional
- Domain string // optional
- Expires time.Time // optional
- RawExpires string // for reading cookies only
-
- // MaxAge=0 means no 'Max-Age' attribute specified.
- // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
- // MaxAge>0 means Max-Age attribute present and given in seconds
- MaxAge int
- Secure bool
- HttpOnly bool
- SameSite SameSite
- Raw string
- Unparsed []string // Raw text of unparsed attribute-value pairs
-}
-
-// SameSite allows a server to define a cookie attribute making it impossible for
-// the browser to send this cookie along with cross-site requests. The main
-// goal is to mitigate the risk of cross-origin information leakage, and provide
-// some protection against cross-site request forgery attacks.
-//
-// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
-type SameSite int
-
-const (
- SameSiteDefaultMode SameSite = iota + 1
- SameSiteLaxMode
- SameSiteStrictMode
- SameSiteNoneMode
-)
-
-// readSetCookies parses all "Set-Cookie" values from
-// the header h and returns the successfully parsed Cookies.
-func readSetCookies(h Header) []*Cookie {
- cookieCount := len(h["Set-Cookie"])
- if cookieCount == 0 {
- return []*Cookie{}
- }
- cookies := make([]*Cookie, 0, cookieCount)
- for _, line := range h["Set-Cookie"] {
- parts := strings.Split(textproto.TrimString(line), ";")
- if len(parts) == 1 && parts[0] == "" {
- continue
- }
- parts[0] = textproto.TrimString(parts[0])
- name, value, ok := strings.Cut(parts[0], "=")
- if !ok {
- continue
- }
- name = textproto.TrimString(name)
- if !isCookieNameValid(name) {
- continue
- }
- value, ok = parseCookieValue(value, true)
- if !ok {
- continue
- }
- c := &Cookie{
- Name: name,
- Value: value,
- Raw: line,
- }
- for i := 1; i < len(parts); i++ {
- parts[i] = textproto.TrimString(parts[i])
- if len(parts[i]) == 0 {
- continue
- }
-
- attr, val, _ := strings.Cut(parts[i], "=")
- lowerAttr, isASCII := ascii.ToLower(attr)
- if !isASCII {
- continue
- }
- val, ok = parseCookieValue(val, false)
- if !ok {
- c.Unparsed = append(c.Unparsed, parts[i])
- continue
- }
-
- switch lowerAttr {
- case "samesite":
- lowerVal, ascii := ascii.ToLower(val)
- if !ascii {
- c.SameSite = SameSiteDefaultMode
- continue
- }
- switch lowerVal {
- case "lax":
- c.SameSite = SameSiteLaxMode
- case "strict":
- c.SameSite = SameSiteStrictMode
- case "none":
- c.SameSite = SameSiteNoneMode
- default:
- c.SameSite = SameSiteDefaultMode
- }
- continue
- case "secure":
- c.Secure = true
- continue
- case "httponly":
- c.HttpOnly = true
- continue
- case "domain":
- c.Domain = val
- continue
- case "max-age":
- secs, err := strconv.Atoi(val)
- if err != nil || secs != 0 && val[0] == '0' {
- break
- }
- if secs <= 0 {
- secs = -1
- }
- c.MaxAge = secs
- continue
- case "expires":
- c.RawExpires = val
- exptime, err := time.Parse(time.RFC1123, val)
- if err != nil {
- exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
- if err != nil {
- c.Expires = time.Time{}
- break
- }
- }
- c.Expires = exptime.UTC()
- continue
- case "path":
- c.Path = val
- continue
- }
- c.Unparsed = append(c.Unparsed, parts[i])
- }
- cookies = append(cookies, c)
- }
- return cookies
-}
-
-// SetCookie adds a Set-Cookie header to the provided [ResponseWriter]'s headers.
-// The provided cookie must have a valid Name. Invalid cookies may be
-// silently dropped.
-func SetCookie(w ResponseWriter, cookie *Cookie) {
- if v := cookie.String(); v != "" {
- w.Header().Add("Set-Cookie", v)
- }
-}
-
-// String returns the serialization of the cookie for use in a [Cookie]
-// header (if only Name and Value are set) or a Set-Cookie response
-// header (if other fields are set).
-// If c is nil or c.Name is invalid, the empty string is returned.
-func (c *Cookie) String() string {
- if c == nil || !isCookieNameValid(c.Name) {
- return ""
- }
- // extraCookieLength derived from typical length of cookie attributes
- // see RFC 6265 Sec 4.1.
- const extraCookieLength = 110
- var b strings.Builder
- b.Grow(len(c.Name) + len(c.Value) + len(c.Domain) + len(c.Path) + extraCookieLength)
- b.WriteString(c.Name)
- b.WriteRune('=')
- b.WriteString(sanitizeCookieValue(c.Value))
-
- if len(c.Path) > 0 {
- b.WriteString("; Path=")
- b.WriteString(sanitizeCookiePath(c.Path))
- }
- if len(c.Domain) > 0 {
- if validCookieDomain(c.Domain) {
- // A c.Domain containing illegal characters is not
- // sanitized but simply dropped which turns the cookie
- // into a host-only cookie. A leading dot is okay
- // but won't be sent.
- d := c.Domain
- if d[0] == '.' {
- d = d[1:]
- }
- b.WriteString("; Domain=")
- b.WriteString(d)
- } else {
- log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute", c.Domain)
- }
- }
- var buf [len(TimeFormat)]byte
- if validCookieExpires(c.Expires) {
- b.WriteString("; Expires=")
- b.Write(c.Expires.UTC().AppendFormat(buf[:0], TimeFormat))
- }
- if c.MaxAge > 0 {
- b.WriteString("; Max-Age=")
- b.Write(strconv.AppendInt(buf[:0], int64(c.MaxAge), 10))
- } else if c.MaxAge < 0 {
- b.WriteString("; Max-Age=0")
- }
- if c.HttpOnly {
- b.WriteString("; HttpOnly")
- }
- if c.Secure {
- b.WriteString("; Secure")
- }
- switch c.SameSite {
- case SameSiteDefaultMode:
- // Skip, default mode is obtained by not emitting the attribute.
- case SameSiteNoneMode:
- b.WriteString("; SameSite=None")
- case SameSiteLaxMode:
- b.WriteString("; SameSite=Lax")
- case SameSiteStrictMode:
- b.WriteString("; SameSite=Strict")
- }
- return b.String()
-}
-
-// Valid reports whether the cookie is valid.
-func (c *Cookie) Valid() error {
- if c == nil {
- return errors.New("http: nil Cookie")
- }
- if !isCookieNameValid(c.Name) {
- return errors.New("http: invalid Cookie.Name")
- }
- if !c.Expires.IsZero() && !validCookieExpires(c.Expires) {
- return errors.New("http: invalid Cookie.Expires")
- }
- for i := 0; i < len(c.Value); i++ {
- if !validCookieValueByte(c.Value[i]) {
- return fmt.Errorf("http: invalid byte %q in Cookie.Value", c.Value[i])
- }
- }
- if len(c.Path) > 0 {
- for i := 0; i < len(c.Path); i++ {
- if !validCookiePathByte(c.Path[i]) {
- return fmt.Errorf("http: invalid byte %q in Cookie.Path", c.Path[i])
- }
- }
- }
- if len(c.Domain) > 0 {
- if !validCookieDomain(c.Domain) {
- return errors.New("http: invalid Cookie.Domain")
- }
- }
- return nil
-}
-
-// readCookies parses all "Cookie" values from the header h and
-// returns the successfully parsed Cookies.
-//
-// if filter isn't empty, only cookies of that name are returned.
-func readCookies(h Header, filter string) []*Cookie {
- lines := h["Cookie"]
- if len(lines) == 0 {
- return []*Cookie{}
- }
-
- cookies := make([]*Cookie, 0, len(lines)+strings.Count(lines[0], ";"))
- for _, line := range lines {
- line = textproto.TrimString(line)
-
- var part string
- for len(line) > 0 { // continue since we have rest
- part, line, _ = strings.Cut(line, ";")
- part = textproto.TrimString(part)
- if part == "" {
- continue
- }
- name, val, _ := strings.Cut(part, "=")
- name = textproto.TrimString(name)
- if !isCookieNameValid(name) {
- continue
- }
- if filter != "" && filter != name {
- continue
- }
- val, ok := parseCookieValue(val, true)
- if !ok {
- continue
- }
- cookies = append(cookies, &Cookie{Name: name, Value: val})
- }
- }
- return cookies
-}
-
-// validCookieDomain reports whether v is a valid cookie domain-value.
-func validCookieDomain(v string) bool {
- if isCookieDomainName(v) {
- return true
- }
- if net.ParseIP(v) != nil && !strings.Contains(v, ":") {
- return true
- }
- return false
-}
-
-// validCookieExpires reports whether v is a valid cookie expires-value.
-func validCookieExpires(t time.Time) bool {
- // IETF RFC 6265 Section 5.1.1.5, the year must not be less than 1601
- return t.Year() >= 1601
-}
-
-// isCookieDomainName reports whether s is a valid domain name or a valid
-// domain name with a leading dot '.'. It is almost a direct copy of
-// package net's isDomainName.
-func isCookieDomainName(s string) bool {
- if len(s) == 0 {
- return false
- }
- if len(s) > 255 {
- return false
- }
-
- if s[0] == '.' {
- // A cookie a domain attribute may start with a leading dot.
- s = s[1:]
- }
- last := byte('.')
- ok := false // Ok once we've seen a letter.
- partlen := 0
- for i := 0; i < len(s); i++ {
- c := s[i]
- switch {
- default:
- return false
- case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
- // No '_' allowed here (in contrast to package net).
- ok = true
- partlen++
- case '0' <= c && c <= '9':
- // fine
- partlen++
- case c == '-':
- // Byte before dash cannot be dot.
- if last == '.' {
- return false
- }
- partlen++
- case c == '.':
- // Byte before dot cannot be dot, dash.
- if last == '.' || last == '-' {
- return false
- }
- if partlen > 63 || partlen == 0 {
- return false
- }
- partlen = 0
- }
- last = c
- }
- if last == '-' || partlen > 63 {
- return false
- }
-
- return ok
-}
-
-var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
-
-func sanitizeCookieName(n string) string {
- return cookieNameSanitizer.Replace(n)
-}
-
-// sanitizeCookieValue produces a suitable cookie-value from v.
-// https://tools.ietf.org/html/rfc6265#section-4.1.1
-//
-// cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
-// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
-// ; US-ASCII characters excluding CTLs,
-// ; whitespace DQUOTE, comma, semicolon,
-// ; and backslash
-//
-// We loosen this as spaces and commas are common in cookie values
-// but we produce a quoted cookie-value if and only if v contains
-// commas or spaces.
-// See https://golang.org/issue/7243 for the discussion.
-func sanitizeCookieValue(v string) string {
- v = sanitizeOrWarn("Cookie.Value", validCookieValueByte, v)
- if len(v) == 0 {
- return v
- }
- if strings.ContainsAny(v, " ,") {
- return `"` + v + `"`
- }
- return v
-}
-
-func validCookieValueByte(b byte) bool {
- return 0x20 <= b && b < 0x7f && b != '"' && b != ';' && b != '\\'
-}
-
-// path-av = "Path=" path-value
-// path-value =
-func sanitizeCookiePath(v string) string {
- return sanitizeOrWarn("Cookie.Path", validCookiePathByte, v)
-}
-
-func validCookiePathByte(b byte) bool {
- return 0x20 <= b && b < 0x7f && b != ';'
-}
-
-func sanitizeOrWarn(fieldName string, valid func(byte) bool, v string) string {
- ok := true
- for i := 0; i < len(v); i++ {
- if valid(v[i]) {
- continue
- }
- log.Printf("net/http: invalid byte %q in %s; dropping invalid bytes", v[i], fieldName)
- ok = false
- break
- }
- if ok {
- return v
- }
- buf := make([]byte, 0, len(v))
- for i := 0; i < len(v); i++ {
- if b := v[i]; valid(b) {
- buf = append(buf, b)
- }
- }
- return string(buf)
-}
-
-func parseCookieValue(raw string, allowDoubleQuote bool) (string, bool) {
- // Strip the quotes, if present.
- if allowDoubleQuote && len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
- raw = raw[1 : len(raw)-1]
- }
- for i := 0; i < len(raw); i++ {
- if !validCookieValueByte(raw[i]) {
- return "", false
- }
- }
- return raw, true
-}
-
-func isCookieNameValid(raw string) bool {
- if raw == "" {
- return false
- }
- return strings.IndexFunc(raw, isNotToken) < 0
-}
diff --git a/contrib/go/_std_1.22/src/net/http/httptest/server.go b/contrib/go/_std_1.22/src/net/http/httptest/server.go
deleted file mode 100644
index 5095b438ec94..000000000000
--- a/contrib/go/_std_1.22/src/net/http/httptest/server.go
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright 2011 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.
-
-// Implementation of Server
-
-package httptest
-
-import (
- "crypto/tls"
- "crypto/x509"
- "flag"
- "fmt"
- "log"
- "net"
- "net/http"
- "net/http/internal/testcert"
- "os"
- "strings"
- "sync"
- "time"
-)
-
-// A Server is an HTTP server listening on a system-chosen port on the
-// local loopback interface, for use in end-to-end HTTP tests.
-type Server struct {
- URL string // base URL of form http://ipaddr:port with no trailing slash
- Listener net.Listener
-
- // EnableHTTP2 controls whether HTTP/2 is enabled
- // on the server. It must be set between calling
- // NewUnstartedServer and calling Server.StartTLS.
- EnableHTTP2 bool
-
- // TLS is the optional TLS configuration, populated with a new config
- // after TLS is started. If set on an unstarted server before StartTLS
- // is called, existing fields are copied into the new config.
- TLS *tls.Config
-
- // Config may be changed after calling NewUnstartedServer and
- // before Start or StartTLS.
- Config *http.Server
-
- // certificate is a parsed version of the TLS config certificate, if present.
- certificate *x509.Certificate
-
- // wg counts the number of outstanding HTTP requests on this server.
- // Close blocks until all requests are finished.
- wg sync.WaitGroup
-
- mu sync.Mutex // guards closed and conns
- closed bool
- conns map[net.Conn]http.ConnState // except terminal states
-
- // client is configured for use with the server.
- // Its transport is automatically closed when Close is called.
- client *http.Client
-}
-
-func newLocalListener() net.Listener {
- if serveFlag != "" {
- l, err := net.Listen("tcp", serveFlag)
- if err != nil {
- panic(fmt.Sprintf("httptest: failed to listen on %v: %v", serveFlag, err))
- }
- return l
- }
- l, err := net.Listen("tcp", "127.0.0.1:0")
- if err != nil {
- if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
- panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
- }
- }
- return l
-}
-
-// When debugging a particular http server-based test,
-// this flag lets you run
-//
-// go test -run='^BrokenTest$' -httptest.serve=127.0.0.1:8000
-//
-// to start the broken server so you can interact with it manually.
-// We only register this flag if it looks like the caller knows about it
-// and is trying to use it as we don't want to pollute flags and this
-// isn't really part of our API. Don't depend on this.
-var serveFlag string
-
-func init() {
- if strSliceContainsPrefix(os.Args, "-httptest.serve=") || strSliceContainsPrefix(os.Args, "--httptest.serve=") {
- flag.StringVar(&serveFlag, "httptest.serve", "", "if non-empty, httptest.NewServer serves on this address and blocks.")
- }
-}
-
-func strSliceContainsPrefix(v []string, pre string) bool {
- for _, s := range v {
- if strings.HasPrefix(s, pre) {
- return true
- }
- }
- return false
-}
-
-// NewServer starts and returns a new [Server].
-// The caller should call Close when finished, to shut it down.
-func NewServer(handler http.Handler) *Server {
- ts := NewUnstartedServer(handler)
- ts.Start()
- return ts
-}
-
-// NewUnstartedServer returns a new [Server] but doesn't start it.
-//
-// After changing its configuration, the caller should call Start or
-// StartTLS.
-//
-// The caller should call Close when finished, to shut it down.
-func NewUnstartedServer(handler http.Handler) *Server {
- return &Server{
- Listener: newLocalListener(),
- Config: &http.Server{Handler: handler},
- }
-}
-
-// Start starts a server from NewUnstartedServer.
-func (s *Server) Start() {
- if s.URL != "" {
- panic("Server already started")
- }
- if s.client == nil {
- s.client = &http.Client{Transport: &http.Transport{}}
- }
- s.URL = "http://" + s.Listener.Addr().String()
- s.wrap()
- s.goServe()
- if serveFlag != "" {
- fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
- select {}
- }
-}
-
-// StartTLS starts TLS on a server from NewUnstartedServer.
-func (s *Server) StartTLS() {
- if s.URL != "" {
- panic("Server already started")
- }
- if s.client == nil {
- s.client = &http.Client{}
- }
- cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey)
- if err != nil {
- panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
- }
-
- existingConfig := s.TLS
- if existingConfig != nil {
- s.TLS = existingConfig.Clone()
- } else {
- s.TLS = new(tls.Config)
- }
- if s.TLS.NextProtos == nil {
- nextProtos := []string{"http/1.1"}
- if s.EnableHTTP2 {
- nextProtos = []string{"h2"}
- }
- s.TLS.NextProtos = nextProtos
- }
- if len(s.TLS.Certificates) == 0 {
- s.TLS.Certificates = []tls.Certificate{cert}
- }
- s.certificate, err = x509.ParseCertificate(s.TLS.Certificates[0].Certificate[0])
- if err != nil {
- panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
- }
- certpool := x509.NewCertPool()
- certpool.AddCert(s.certificate)
- s.client.Transport = &http.Transport{
- TLSClientConfig: &tls.Config{
- RootCAs: certpool,
- },
- ForceAttemptHTTP2: s.EnableHTTP2,
- }
- s.Listener = tls.NewListener(s.Listener, s.TLS)
- s.URL = "https://" + s.Listener.Addr().String()
- s.wrap()
- s.goServe()
-}
-
-// NewTLSServer starts and returns a new [Server] using TLS.
-// The caller should call Close when finished, to shut it down.
-func NewTLSServer(handler http.Handler) *Server {
- ts := NewUnstartedServer(handler)
- ts.StartTLS()
- return ts
-}
-
-type closeIdleTransport interface {
- CloseIdleConnections()
-}
-
-// Close shuts down the server and blocks until all outstanding
-// requests on this server have completed.
-func (s *Server) Close() {
- s.mu.Lock()
- if !s.closed {
- s.closed = true
- s.Listener.Close()
- s.Config.SetKeepAlivesEnabled(false)
- for c, st := range s.conns {
- // Force-close any idle connections (those between
- // requests) and new connections (those which connected
- // but never sent a request). StateNew connections are
- // super rare and have only been seen (in
- // previously-flaky tests) in the case of
- // socket-late-binding races from the http Client
- // dialing this server and then getting an idle
- // connection before the dial completed. There is thus
- // a connected connection in StateNew with no
- // associated Request. We only close StateIdle and
- // StateNew because they're not doing anything. It's
- // possible StateNew is about to do something in a few
- // milliseconds, but a previous CL to check again in a
- // few milliseconds wasn't liked (early versions of
- // https://golang.org/cl/15151) so now we just
- // forcefully close StateNew. The docs for Server.Close say
- // we wait for "outstanding requests", so we don't close things
- // in StateActive.
- if st == http.StateIdle || st == http.StateNew {
- s.closeConn(c)
- }
- }
- // If this server doesn't shut down in 5 seconds, tell the user why.
- t := time.AfterFunc(5*time.Second, s.logCloseHangDebugInfo)
- defer t.Stop()
- }
- s.mu.Unlock()
-
- // Not part of httptest.Server's correctness, but assume most
- // users of httptest.Server will be using the standard
- // transport, so help them out and close any idle connections for them.
- if t, ok := http.DefaultTransport.(closeIdleTransport); ok {
- t.CloseIdleConnections()
- }
-
- // Also close the client idle connections.
- if s.client != nil {
- if t, ok := s.client.Transport.(closeIdleTransport); ok {
- t.CloseIdleConnections()
- }
- }
-
- s.wg.Wait()
-}
-
-func (s *Server) logCloseHangDebugInfo() {
- s.mu.Lock()
- defer s.mu.Unlock()
- var buf strings.Builder
- buf.WriteString("httptest.Server blocked in Close after 5 seconds, waiting for connections:\n")
- for c, st := range s.conns {
- fmt.Fprintf(&buf, " %T %p %v in state %v\n", c, c, c.RemoteAddr(), st)
- }
- log.Print(buf.String())
-}
-
-// CloseClientConnections closes any open HTTP connections to the test Server.
-func (s *Server) CloseClientConnections() {
- s.mu.Lock()
- nconn := len(s.conns)
- ch := make(chan struct{}, nconn)
- for c := range s.conns {
- go s.closeConnChan(c, ch)
- }
- s.mu.Unlock()
-
- // Wait for outstanding closes to finish.
- //
- // Out of paranoia for making a late change in Go 1.6, we
- // bound how long this can wait, since golang.org/issue/14291
- // isn't fully understood yet. At least this should only be used
- // in tests.
- timer := time.NewTimer(5 * time.Second)
- defer timer.Stop()
- for i := 0; i < nconn; i++ {
- select {
- case <-ch:
- case <-timer.C:
- // Too slow. Give up.
- return
- }
- }
-}
-
-// Certificate returns the certificate used by the server, or nil if
-// the server doesn't use TLS.
-func (s *Server) Certificate() *x509.Certificate {
- return s.certificate
-}
-
-// Client returns an HTTP client configured for making requests to the server.
-// It is configured to trust the server's TLS test certificate and will
-// close its idle connections on [Server.Close].
-func (s *Server) Client() *http.Client {
- return s.client
-}
-
-func (s *Server) goServe() {
- s.wg.Add(1)
- go func() {
- defer s.wg.Done()
- s.Config.Serve(s.Listener)
- }()
-}
-
-// wrap installs the connection state-tracking hook to know which
-// connections are idle.
-func (s *Server) wrap() {
- oldHook := s.Config.ConnState
- s.Config.ConnState = func(c net.Conn, cs http.ConnState) {
- s.mu.Lock()
- defer s.mu.Unlock()
-
- switch cs {
- case http.StateNew:
- if _, exists := s.conns[c]; exists {
- panic("invalid state transition")
- }
- if s.conns == nil {
- s.conns = make(map[net.Conn]http.ConnState)
- }
- // Add c to the set of tracked conns and increment it to the
- // waitgroup.
- s.wg.Add(1)
- s.conns[c] = cs
- if s.closed {
- // Probably just a socket-late-binding dial from
- // the default transport that lost the race (and
- // thus this connection is now idle and will
- // never be used).
- s.closeConn(c)
- }
- case http.StateActive:
- if oldState, ok := s.conns[c]; ok {
- if oldState != http.StateNew && oldState != http.StateIdle {
- panic("invalid state transition")
- }
- s.conns[c] = cs
- }
- case http.StateIdle:
- if oldState, ok := s.conns[c]; ok {
- if oldState != http.StateActive {
- panic("invalid state transition")
- }
- s.conns[c] = cs
- }
- if s.closed {
- s.closeConn(c)
- }
- case http.StateHijacked, http.StateClosed:
- // Remove c from the set of tracked conns and decrement it from the
- // waitgroup, unless it was previously removed.
- if _, ok := s.conns[c]; ok {
- delete(s.conns, c)
- // Keep Close from returning until the user's ConnState hook
- // (if any) finishes.
- defer s.wg.Done()
- }
- }
- if oldHook != nil {
- oldHook(c, cs)
- }
- }
-}
-
-// closeConn closes c.
-// s.mu must be held.
-func (s *Server) closeConn(c net.Conn) { s.closeConnChan(c, nil) }
-
-// closeConnChan is like closeConn, but takes an optional channel to receive a value
-// when the goroutine closing c is done.
-func (s *Server) closeConnChan(c net.Conn, done chan<- struct{}) {
- c.Close()
- if done != nil {
- done <- struct{}{}
- }
-}
diff --git a/contrib/go/_std_1.22/src/net/http/internal/testcert/testcert.go b/contrib/go/_std_1.22/src/net/http/internal/testcert/testcert.go
deleted file mode 100644
index d510e791d617..000000000000
--- a/contrib/go/_std_1.22/src/net/http/internal/testcert/testcert.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2015 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.
-
-// Package testcert contains a test-only localhost certificate.
-package testcert
-
-import "strings"
-
-// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
-// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
-// generated from src/crypto/tls:
-// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
-var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
-MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
-MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
-bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
-aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
-YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
-POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
-h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
-AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
-DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
-bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
-5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
-cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
-+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
-grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
-5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
-WkBKOclmOV2xlTVuPw==
------END CERTIFICATE-----`)
-
-// LocalhostKey is the private key for LocalhostCert.
-var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
-MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDoZtrm0dXV0Aqi
-4Bpc7f95sNRTiu/AJSD8I1onY9PnEsPg3VVxvytsVJbYdcqr4w99V3AgpH/UNzMS
-gAZ/8lZBNbsSDOVesJ3euVqMRfYPvd9pYl6QPRRpSDPm+2tNdn3QFAvta9EgJ3sW
-URnoU85w+W6aLI2bNSq3AaE771p3VbkGolpEjo9h+i42TBHo1rhPNKPkGupR8/QX
-AOLMpInRdeaHyDwb2a3DE5I3dG7VAVzrVfJ6W6Q84YoFX+rpEE2SVM17SAjy6xQy
-VjKgLvK2mk0xbtfa+h0B6VK7bmODHZqeP18NVm6HsBcXn7iclLgAC3SfWU1jucZK
-x1lqzw9tAgMBAAECggEABWzxS1Y2wckblnXY57Z+sl6YdmLV+gxj2r8Qib7g4ZIk
-lIlWR1OJNfw7kU4eryib4fc6nOh6O4AWZyYqAK6tqNQSS/eVG0LQTLTTEldHyVJL
-dvBe+MsUQOj4nTndZW+QvFzbcm2D8lY5n2nBSxU5ypVoKZ1EqQzytFcLZpTN7d89
-EPj0qDyrV4NZlWAwL1AygCwnlwhMQjXEalVF1ylXwU3QzyZ/6MgvF6d3SSUlh+sq
-XefuyigXw484cQQgbzopv6niMOmGP3of+yV4JQqUSb3IDmmT68XjGd2Dkxl4iPki
-6ZwXf3CCi+c+i/zVEcufgZ3SLf8D99kUGE7v7fZ6AQKBgQD1ZX3RAla9hIhxCf+O
-3D+I1j2LMrdjAh0ZKKqwMR4JnHX3mjQI6LwqIctPWTU8wYFECSh9klEclSdCa64s
-uI/GNpcqPXejd0cAAdqHEEeG5sHMDt0oFSurL4lyud0GtZvwlzLuwEweuDtvT9cJ
-Wfvl86uyO36IW8JdvUprYDctrQKBgQDycZ697qutBieZlGkHpnYWUAeImVA878sJ
-w44NuXHvMxBPz+lbJGAg8Cn8fcxNAPqHIraK+kx3po8cZGQywKHUWsxi23ozHoxo
-+bGqeQb9U661TnfdDspIXia+xilZt3mm5BPzOUuRqlh4Y9SOBpSWRmEhyw76w4ZP
-OPxjWYAgwQKBgA/FehSYxeJgRjSdo+MWnK66tjHgDJE8bYpUZsP0JC4R9DL5oiaA
-brd2fI6Y+SbyeNBallObt8LSgzdtnEAbjIH8uDJqyOmknNePRvAvR6mP4xyuR+Bv
-m+Lgp0DMWTw5J9CKpydZDItc49T/mJ5tPhdFVd+am0NAQnmr1MCZ6nHxAoGABS3Y
-LkaC9FdFUUqSU8+Chkd/YbOkuyiENdkvl6t2e52jo5DVc1T7mLiIrRQi4SI8N9bN
-/3oJWCT+uaSLX2ouCtNFunblzWHBrhxnZzTeqVq4SLc8aESAnbslKL4i8/+vYZlN
-s8xtiNcSvL+lMsOBORSXzpj/4Ot8WwTkn1qyGgECgYBKNTypzAHeLE6yVadFp3nQ
-Ckq9yzvP/ib05rvgbvrne00YeOxqJ9gtTrzgh7koqJyX1L4NwdkEza4ilDWpucn0
-xiUZS4SoaJq6ZvcBYS62Yr1t8n09iG47YL8ibgtmH3L+svaotvpVxVK+d7BLevA/
-ZboOWVe3icTy64BT3OQhmg==
------END RSA TESTING KEY-----`))
-
-func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
diff --git a/contrib/go/_std_1.22/src/net/http/pprof/pprof.go b/contrib/go/_std_1.22/src/net/http/pprof/pprof.go
deleted file mode 100644
index bc48f1183413..000000000000
--- a/contrib/go/_std_1.22/src/net/http/pprof/pprof.go
+++ /dev/null
@@ -1,464 +0,0 @@
-// Copyright 2010 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.
-
-// Package pprof serves via its HTTP server runtime profiling data
-// in the format expected by the pprof visualization tool.
-//
-// The package is typically only imported for the side effect of
-// registering its HTTP handlers.
-// The handled paths all begin with /debug/pprof/.
-//
-// To use pprof, link this package into your program:
-//
-// import _ "net/http/pprof"
-//
-// If your application is not already running an http server, you
-// need to start one. Add "net/http" and "log" to your imports and
-// the following code to your main function:
-//
-// go func() {
-// log.Println(http.ListenAndServe("localhost:6060", nil))
-// }()
-//
-// By default, all the profiles listed in [runtime/pprof.Profile] are
-// available (via [Handler]), in addition to the [Cmdline], [Profile], [Symbol],
-// and [Trace] profiles defined in this package.
-// If you are not using DefaultServeMux, you will have to register handlers
-// with the mux you are using.
-//
-// # Parameters
-//
-// Parameters can be passed via GET query params:
-//
-// - debug=N (all profiles): response format: N = 0: binary (default), N > 0: plaintext
-// - gc=N (heap profile): N > 0: run a garbage collection cycle before profiling
-// - seconds=N (allocs, block, goroutine, heap, mutex, threadcreate profiles): return a delta profile
-// - seconds=N (cpu (profile), trace profiles): profile for the given duration
-//
-// # Usage examples
-//
-// Use the pprof tool to look at the heap profile:
-//
-// go tool pprof http://localhost:6060/debug/pprof/heap
-//
-// Or to look at a 30-second CPU profile:
-//
-// go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
-//
-// Or to look at the goroutine blocking profile, after calling
-// [runtime.SetBlockProfileRate] in your program:
-//
-// go tool pprof http://localhost:6060/debug/pprof/block
-//
-// Or to look at the holders of contended mutexes, after calling
-// [runtime.SetMutexProfileFraction] in your program:
-//
-// go tool pprof http://localhost:6060/debug/pprof/mutex
-//
-// The package also exports a handler that serves execution trace data
-// for the "go tool trace" command. To collect a 5-second execution trace:
-//
-// curl -o trace.out http://localhost:6060/debug/pprof/trace?seconds=5
-// go tool trace trace.out
-//
-// To view all available profiles, open http://localhost:6060/debug/pprof/
-// in your browser.
-//
-// For a study of the facility in action, visit
-// https://blog.golang.org/2011/06/profiling-go-programs.html.
-package pprof
-
-import (
- "bufio"
- "bytes"
- "context"
- "fmt"
- "html"
- "internal/profile"
- "io"
- "log"
- "net/http"
- "net/url"
- "os"
- "runtime"
- "runtime/pprof"
- "runtime/trace"
- "sort"
- "strconv"
- "strings"
- "time"
-)
-
-func init() {
- http.HandleFunc("/debug/pprof/", Index)
- http.HandleFunc("/debug/pprof/cmdline", Cmdline)
- http.HandleFunc("/debug/pprof/profile", Profile)
- http.HandleFunc("/debug/pprof/symbol", Symbol)
- http.HandleFunc("/debug/pprof/trace", Trace)
-}
-
-// Cmdline responds with the running program's
-// command line, with arguments separated by NUL bytes.
-// The package initialization registers it as /debug/pprof/cmdline.
-func Cmdline(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("X-Content-Type-Options", "nosniff")
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
- fmt.Fprint(w, strings.Join(os.Args, "\x00"))
-}
-
-func sleep(r *http.Request, d time.Duration) {
- select {
- case <-time.After(d):
- case <-r.Context().Done():
- }
-}
-
-func durationExceedsWriteTimeout(r *http.Request, seconds float64) bool {
- srv, ok := r.Context().Value(http.ServerContextKey).(*http.Server)
- return ok && srv.WriteTimeout != 0 && seconds >= srv.WriteTimeout.Seconds()
-}
-
-func serveError(w http.ResponseWriter, status int, txt string) {
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
- w.Header().Set("X-Go-Pprof", "1")
- w.Header().Del("Content-Disposition")
- w.WriteHeader(status)
- fmt.Fprintln(w, txt)
-}
-
-// Profile responds with the pprof-formatted cpu profile.
-// Profiling lasts for duration specified in seconds GET parameter, or for 30 seconds if not specified.
-// The package initialization registers it as /debug/pprof/profile.
-func Profile(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("X-Content-Type-Options", "nosniff")
- sec, err := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
- if sec <= 0 || err != nil {
- sec = 30
- }
-
- if durationExceedsWriteTimeout(r, float64(sec)) {
- serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
- return
- }
-
- // Set Content Type assuming StartCPUProfile will work,
- // because if it does it starts writing.
- w.Header().Set("Content-Type", "application/octet-stream")
- w.Header().Set("Content-Disposition", `attachment; filename="profile"`)
- if err := pprof.StartCPUProfile(w); err != nil {
- // StartCPUProfile failed, so no writes yet.
- serveError(w, http.StatusInternalServerError,
- fmt.Sprintf("Could not enable CPU profiling: %s", err))
- return
- }
- sleep(r, time.Duration(sec)*time.Second)
- pprof.StopCPUProfile()
-}
-
-// Trace responds with the execution trace in binary form.
-// Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified.
-// The package initialization registers it as /debug/pprof/trace.
-func Trace(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("X-Content-Type-Options", "nosniff")
- sec, err := strconv.ParseFloat(r.FormValue("seconds"), 64)
- if sec <= 0 || err != nil {
- sec = 1
- }
-
- if durationExceedsWriteTimeout(r, sec) {
- serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
- return
- }
-
- // Set Content Type assuming trace.Start will work,
- // because if it does it starts writing.
- w.Header().Set("Content-Type", "application/octet-stream")
- w.Header().Set("Content-Disposition", `attachment; filename="trace"`)
- if err := trace.Start(w); err != nil {
- // trace.Start failed, so no writes yet.
- serveError(w, http.StatusInternalServerError,
- fmt.Sprintf("Could not enable tracing: %s", err))
- return
- }
- sleep(r, time.Duration(sec*float64(time.Second)))
- trace.Stop()
-}
-
-// Symbol looks up the program counters listed in the request,
-// responding with a table mapping program counters to function names.
-// The package initialization registers it as /debug/pprof/symbol.
-func Symbol(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("X-Content-Type-Options", "nosniff")
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-
- // We have to read the whole POST body before
- // writing any output. Buffer the output here.
- var buf bytes.Buffer
-
- // We don't know how many symbols we have, but we
- // do have symbol information. Pprof only cares whether
- // this number is 0 (no symbols available) or > 0.
- fmt.Fprintf(&buf, "num_symbols: 1\n")
-
- var b *bufio.Reader
- if r.Method == "POST" {
- b = bufio.NewReader(r.Body)
- } else {
- b = bufio.NewReader(strings.NewReader(r.URL.RawQuery))
- }
-
- for {
- word, err := b.ReadSlice('+')
- if err == nil {
- word = word[0 : len(word)-1] // trim +
- }
- pc, _ := strconv.ParseUint(string(word), 0, 64)
- if pc != 0 {
- f := runtime.FuncForPC(uintptr(pc))
- if f != nil {
- fmt.Fprintf(&buf, "%#x %s\n", pc, f.Name())
- }
- }
-
- // Wait until here to check for err; the last
- // symbol will have an err because it doesn't end in +.
- if err != nil {
- if err != io.EOF {
- fmt.Fprintf(&buf, "reading request: %v\n", err)
- }
- break
- }
- }
-
- w.Write(buf.Bytes())
-}
-
-// Handler returns an HTTP handler that serves the named profile.
-// Available profiles can be found in [runtime/pprof.Profile].
-func Handler(name string) http.Handler {
- return handler(name)
-}
-
-type handler string
-
-func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("X-Content-Type-Options", "nosniff")
- p := pprof.Lookup(string(name))
- if p == nil {
- serveError(w, http.StatusNotFound, "Unknown profile")
- return
- }
- if sec := r.FormValue("seconds"); sec != "" {
- name.serveDeltaProfile(w, r, p, sec)
- return
- }
- gc, _ := strconv.Atoi(r.FormValue("gc"))
- if name == "heap" && gc > 0 {
- runtime.GC()
- }
- debug, _ := strconv.Atoi(r.FormValue("debug"))
- if debug != 0 {
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
- } else {
- w.Header().Set("Content-Type", "application/octet-stream")
- w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name))
- }
- p.WriteTo(w, debug)
-}
-
-func (name handler) serveDeltaProfile(w http.ResponseWriter, r *http.Request, p *pprof.Profile, secStr string) {
- sec, err := strconv.ParseInt(secStr, 10, 64)
- if err != nil || sec <= 0 {
- serveError(w, http.StatusBadRequest, `invalid value for "seconds" - must be a positive integer`)
- return
- }
- if !profileSupportsDelta[name] {
- serveError(w, http.StatusBadRequest, `"seconds" parameter is not supported for this profile type`)
- return
- }
- // 'name' should be a key in profileSupportsDelta.
- if durationExceedsWriteTimeout(r, float64(sec)) {
- serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
- return
- }
- debug, _ := strconv.Atoi(r.FormValue("debug"))
- if debug != 0 {
- serveError(w, http.StatusBadRequest, "seconds and debug params are incompatible")
- return
- }
- p0, err := collectProfile(p)
- if err != nil {
- serveError(w, http.StatusInternalServerError, "failed to collect profile")
- return
- }
-
- t := time.NewTimer(time.Duration(sec) * time.Second)
- defer t.Stop()
-
- select {
- case <-r.Context().Done():
- err := r.Context().Err()
- if err == context.DeadlineExceeded {
- serveError(w, http.StatusRequestTimeout, err.Error())
- } else { // TODO: what's a good status code for canceled requests? 400?
- serveError(w, http.StatusInternalServerError, err.Error())
- }
- return
- case <-t.C:
- }
-
- p1, err := collectProfile(p)
- if err != nil {
- serveError(w, http.StatusInternalServerError, "failed to collect profile")
- return
- }
- ts := p1.TimeNanos
- dur := p1.TimeNanos - p0.TimeNanos
-
- p0.Scale(-1)
-
- p1, err = profile.Merge([]*profile.Profile{p0, p1})
- if err != nil {
- serveError(w, http.StatusInternalServerError, "failed to compute delta")
- return
- }
-
- p1.TimeNanos = ts // set since we don't know what profile.Merge set for TimeNanos.
- p1.DurationNanos = dur
-
- w.Header().Set("Content-Type", "application/octet-stream")
- w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s-delta"`, name))
- p1.Write(w)
-}
-
-func collectProfile(p *pprof.Profile) (*profile.Profile, error) {
- var buf bytes.Buffer
- if err := p.WriteTo(&buf, 0); err != nil {
- return nil, err
- }
- ts := time.Now().UnixNano()
- p0, err := profile.Parse(&buf)
- if err != nil {
- return nil, err
- }
- p0.TimeNanos = ts
- return p0, nil
-}
-
-var profileSupportsDelta = map[handler]bool{
- "allocs": true,
- "block": true,
- "goroutine": true,
- "heap": true,
- "mutex": true,
- "threadcreate": true,
-}
-
-var profileDescriptions = map[string]string{
- "allocs": "A sampling of all past memory allocations",
- "block": "Stack traces that led to blocking on synchronization primitives",
- "cmdline": "The command line invocation of the current program",
- "goroutine": "Stack traces of all current goroutines. Use debug=2 as a query parameter to export in the same format as an unrecovered panic.",
- "heap": "A sampling of memory allocations of live objects. You can specify the gc GET parameter to run GC before taking the heap sample.",
- "mutex": "Stack traces of holders of contended mutexes",
- "profile": "CPU profile. You can specify the duration in the seconds GET parameter. After you get the profile file, use the go tool pprof command to investigate the profile.",
- "threadcreate": "Stack traces that led to the creation of new OS threads",
- "trace": "A trace of execution of the current program. You can specify the duration in the seconds GET parameter. After you get the trace file, use the go tool trace command to investigate the trace.",
-}
-
-type profileEntry struct {
- Name string
- Href string
- Desc string
- Count int
-}
-
-// Index responds with the pprof-formatted profile named by the request.
-// For example, "/debug/pprof/heap" serves the "heap" profile.
-// Index responds to a request for "/debug/pprof/" with an HTML page
-// listing the available profiles.
-func Index(w http.ResponseWriter, r *http.Request) {
- if name, found := strings.CutPrefix(r.URL.Path, "/debug/pprof/"); found {
- if name != "" {
- handler(name).ServeHTTP(w, r)
- return
- }
- }
-
- w.Header().Set("X-Content-Type-Options", "nosniff")
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
-
- var profiles []profileEntry
- for _, p := range pprof.Profiles() {
- profiles = append(profiles, profileEntry{
- Name: p.Name(),
- Href: p.Name(),
- Desc: profileDescriptions[p.Name()],
- Count: p.Count(),
- })
- }
-
- // Adding other profiles exposed from within this package
- for _, p := range []string{"cmdline", "profile", "trace"} {
- profiles = append(profiles, profileEntry{
- Name: p,
- Href: p,
- Desc: profileDescriptions[p],
- })
- }
-
- sort.Slice(profiles, func(i, j int) bool {
- return profiles[i].Name < profiles[j].Name
- })
-
- if err := indexTmplExecute(w, profiles); err != nil {
- log.Print(err)
- }
-}
-
-func indexTmplExecute(w io.Writer, profiles []profileEntry) error {
- var b bytes.Buffer
- b.WriteString(`
-
-/debug/pprof/
-
-
-
-/debug/pprof/
-
-Set debug=1 as a query parameter to export in legacy text format
-
-Types of profiles available:
-
-Count | Profile |
-`)
-
- for _, profile := range profiles {
- link := &url.URL{Path: profile.Href, RawQuery: "debug=1"}
- fmt.Fprintf(&b, "%d | %s |
\n", profile.Count, link, html.EscapeString(profile.Name))
- }
-
- b.WriteString(`
-full goroutine stack dump
-
-
-Profile Descriptions:
-
-`)
- for _, profile := range profiles {
- fmt.Fprintf(&b, "%s:
%s \n", html.EscapeString(profile.Name), html.EscapeString(profile.Desc))
- }
- b.WriteString(`
-
-
-`)
-
- _, err := w.Write(b.Bytes())
- return err
-}
diff --git a/contrib/go/_std_1.22/src/net/http/roundtrip.go b/contrib/go/_std_1.22/src/net/http/roundtrip.go
deleted file mode 100644
index 08c270179afb..000000000000
--- a/contrib/go/_std_1.22/src/net/http/roundtrip.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 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.
-
-//go:build !js
-
-package http
-
-// RoundTrip implements the [RoundTripper] interface.
-//
-// For higher-level HTTP client support (such as handling of cookies
-// and redirects), see [Get], [Post], and the [Client] type.
-//
-// Like the RoundTripper interface, the error types returned
-// by RoundTrip are unspecified.
-func (t *Transport) RoundTrip(req *Request) (*Response, error) {
- return t.roundTrip(req)
-}
diff --git a/contrib/go/_std_1.22/src/net/http/server.go b/contrib/go/_std_1.22/src/net/http/server.go
deleted file mode 100644
index 23a603a83dd7..000000000000
--- a/contrib/go/_std_1.22/src/net/http/server.go
+++ /dev/null
@@ -1,3848 +0,0 @@
-// Copyright 2009 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.
-
-// HTTP server. See RFC 7230 through 7235.
-
-package http
-
-import (
- "bufio"
- "bytes"
- "context"
- "crypto/tls"
- "errors"
- "fmt"
- "internal/godebug"
- "io"
- "log"
- "math/rand"
- "net"
- "net/textproto"
- "net/url"
- urlpkg "net/url"
- "path"
- "runtime"
- "sort"
- "strconv"
- "strings"
- "sync"
- "sync/atomic"
- "time"
-
- "golang.org/x/net/http/httpguts"
-)
-
-// Errors used by the HTTP server.
-var (
- // ErrBodyNotAllowed is returned by ResponseWriter.Write calls
- // when the HTTP method or response code does not permit a
- // body.
- ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body")
-
- // ErrHijacked is returned by ResponseWriter.Write calls when
- // the underlying connection has been hijacked using the
- // Hijacker interface. A zero-byte write on a hijacked
- // connection will return ErrHijacked without any other side
- // effects.
- ErrHijacked = errors.New("http: connection has been hijacked")
-
- // ErrContentLength is returned by ResponseWriter.Write calls
- // when a Handler set a Content-Length response header with a
- // declared size and then attempted to write more bytes than
- // declared.
- ErrContentLength = errors.New("http: wrote more than the declared Content-Length")
-
- // Deprecated: ErrWriteAfterFlush is no longer returned by
- // anything in the net/http package. Callers should not
- // compare errors against this variable.
- ErrWriteAfterFlush = errors.New("unused")
-)
-
-// A Handler responds to an HTTP request.
-//
-// [Handler.ServeHTTP] should write reply headers and data to the [ResponseWriter]
-// and then return. Returning signals that the request is finished; it
-// is not valid to use the [ResponseWriter] or read from the
-// [Request.Body] after or concurrently with the completion of the
-// ServeHTTP call.
-//
-// Depending on the HTTP client software, HTTP protocol version, and
-// any intermediaries between the client and the Go server, it may not
-// be possible to read from the [Request.Body] after writing to the
-// [ResponseWriter]. Cautious handlers should read the [Request.Body]
-// first, and then reply.
-//
-// Except for reading the body, handlers should not modify the
-// provided Request.
-//
-// If ServeHTTP panics, the server (the caller of ServeHTTP) assumes
-// that the effect of the panic was isolated to the active request.
-// It recovers the panic, logs a stack trace to the server error log,
-// and either closes the network connection or sends an HTTP/2
-// RST_STREAM, depending on the HTTP protocol. To abort a handler so
-// the client sees an interrupted response but the server doesn't log
-// an error, panic with the value [ErrAbortHandler].
-type Handler interface {
- ServeHTTP(ResponseWriter, *Request)
-}
-
-// A ResponseWriter interface is used by an HTTP handler to
-// construct an HTTP response.
-//
-// A ResponseWriter may not be used after [Handler.ServeHTTP] has returned.
-type ResponseWriter interface {
- // Header returns the header map that will be sent by
- // [ResponseWriter.WriteHeader]. The [Header] map also is the mechanism with which
- // [Handler] implementations can set HTTP trailers.
- //
- // Changing the header map after a call to [ResponseWriter.WriteHeader] (or
- // [ResponseWriter.Write]) has no effect unless the HTTP status code was of the
- // 1xx class or the modified headers are trailers.
- //
- // There are two ways to set Trailers. The preferred way is to
- // predeclare in the headers which trailers you will later
- // send by setting the "Trailer" header to the names of the
- // trailer keys which will come later. In this case, those
- // keys of the Header map are treated as if they were
- // trailers. See the example. The second way, for trailer
- // keys not known to the [Handler] until after the first [ResponseWriter.Write],
- // is to prefix the [Header] map keys with the [TrailerPrefix]
- // constant value.
- //
- // To suppress automatic response headers (such as "Date"), set
- // their value to nil.
- Header() Header
-
- // Write writes the data to the connection as part of an HTTP reply.
- //
- // If [ResponseWriter.WriteHeader] has not yet been called, Write calls
- // WriteHeader(http.StatusOK) before writing the data. If the Header
- // does not contain a Content-Type line, Write adds a Content-Type set
- // to the result of passing the initial 512 bytes of written data to
- // [DetectContentType]. Additionally, if the total size of all written
- // data is under a few KB and there are no Flush calls, the
- // Content-Length header is added automatically.
- //
- // Depending on the HTTP protocol version and the client, calling
- // Write or WriteHeader may prevent future reads on the
- // Request.Body. For HTTP/1.x requests, handlers should read any
- // needed request body data before writing the response. Once the
- // headers have been flushed (due to either an explicit Flusher.Flush
- // call or writing enough data to trigger a flush), the request body
- // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
- // handlers to continue to read the request body while concurrently
- // writing the response. However, such behavior may not be supported
- // by all HTTP/2 clients. Handlers should read before writing if
- // possible to maximize compatibility.
- Write([]byte) (int, error)
-
- // WriteHeader sends an HTTP response header with the provided
- // status code.
- //
- // If WriteHeader is not called explicitly, the first call to Write
- // will trigger an implicit WriteHeader(http.StatusOK).
- // Thus explicit calls to WriteHeader are mainly used to
- // send error codes or 1xx informational responses.
- //
- // The provided code must be a valid HTTP 1xx-5xx status code.
- // Any number of 1xx headers may be written, followed by at most
- // one 2xx-5xx header. 1xx headers are sent immediately, but 2xx-5xx
- // headers may be buffered. Use the Flusher interface to send
- // buffered data. The header map is cleared when 2xx-5xx headers are
- // sent, but not with 1xx headers.
- //
- // The server will automatically send a 100 (Continue) header
- // on the first read from the request body if the request has
- // an "Expect: 100-continue" header.
- WriteHeader(statusCode int)
-}
-
-// The Flusher interface is implemented by ResponseWriters that allow
-// an HTTP handler to flush buffered data to the client.
-//
-// The default HTTP/1.x and HTTP/2 [ResponseWriter] implementations
-// support [Flusher], but ResponseWriter wrappers may not. Handlers
-// should always test for this ability at runtime.
-//
-// Note that even for ResponseWriters that support Flush,
-// if the client is connected through an HTTP proxy,
-// the buffered data may not reach the client until the response
-// completes.
-type Flusher interface {
- // Flush sends any buffered data to the client.
- Flush()
-}
-
-// The Hijacker interface is implemented by ResponseWriters that allow
-// an HTTP handler to take over the connection.
-//
-// The default [ResponseWriter] for HTTP/1.x connections supports
-// Hijacker, but HTTP/2 connections intentionally do not.
-// ResponseWriter wrappers may also not support Hijacker. Handlers
-// should always test for this ability at runtime.
-type Hijacker interface {
- // Hijack lets the caller take over the connection.
- // After a call to Hijack the HTTP server library
- // will not do anything else with the connection.
- //
- // It becomes the caller's responsibility to manage
- // and close the connection.
- //
- // The returned net.Conn may have read or write deadlines
- // already set, depending on the configuration of the
- // Server. It is the caller's responsibility to set
- // or clear those deadlines as needed.
- //
- // The returned bufio.Reader may contain unprocessed buffered
- // data from the client.
- //
- // After a call to Hijack, the original Request.Body must not
- // be used. The original Request's Context remains valid and
- // is not canceled until the Request's ServeHTTP method
- // returns.
- Hijack() (net.Conn, *bufio.ReadWriter, error)
-}
-
-// The CloseNotifier interface is implemented by ResponseWriters which
-// allow detecting when the underlying connection has gone away.
-//
-// This mechanism can be used to cancel long operations on the server
-// if the client has disconnected before the response is ready.
-//
-// Deprecated: the CloseNotifier interface predates Go's context package.
-// New code should use [Request.Context] instead.
-type CloseNotifier interface {
- // CloseNotify returns a channel that receives at most a
- // single value (true) when the client connection has gone
- // away.
- //
- // CloseNotify may wait to notify until Request.Body has been
- // fully read.
- //
- // After the Handler has returned, there is no guarantee
- // that the channel receives a value.
- //
- // If the protocol is HTTP/1.1 and CloseNotify is called while
- // processing an idempotent request (such a GET) while
- // HTTP/1.1 pipelining is in use, the arrival of a subsequent
- // pipelined request may cause a value to be sent on the
- // returned channel. In practice HTTP/1.1 pipelining is not
- // enabled in browsers and not seen often in the wild. If this
- // is a problem, use HTTP/2 or only use CloseNotify on methods
- // such as POST.
- CloseNotify() <-chan bool
-}
-
-var (
- // ServerContextKey is a context key. It can be used in HTTP
- // handlers with Context.Value to access the server that
- // started the handler. The associated value will be of
- // type *Server.
- ServerContextKey = &contextKey{"http-server"}
-
- // LocalAddrContextKey is a context key. It can be used in
- // HTTP handlers with Context.Value to access the local
- // address the connection arrived on.
- // The associated value will be of type net.Addr.
- LocalAddrContextKey = &contextKey{"local-addr"}
-)
-
-// A conn represents the server side of an HTTP connection.
-type conn struct {
- // server is the server on which the connection arrived.
- // Immutable; never nil.
- server *Server
-
- // cancelCtx cancels the connection-level context.
- cancelCtx context.CancelFunc
-
- // rwc is the underlying network connection.
- // This is never wrapped by other types and is the value given out
- // to CloseNotifier callers. It is usually of type *net.TCPConn or
- // *tls.Conn.
- rwc net.Conn
-
- // remoteAddr is rwc.RemoteAddr().String(). It is not populated synchronously
- // inside the Listener's Accept goroutine, as some implementations block.
- // It is populated immediately inside the (*conn).serve goroutine.
- // This is the value of a Handler's (*Request).RemoteAddr.
- remoteAddr string
-
- // tlsState is the TLS connection state when using TLS.
- // nil means not TLS.
- tlsState *tls.ConnectionState
-
- // werr is set to the first write error to rwc.
- // It is set via checkConnErrorWriter{w}, where bufw writes.
- werr error
-
- // r is bufr's read source. It's a wrapper around rwc that provides
- // io.LimitedReader-style limiting (while reading request headers)
- // and functionality to support CloseNotifier. See *connReader docs.
- r *connReader
-
- // bufr reads from r.
- bufr *bufio.Reader
-
- // bufw writes to checkConnErrorWriter{c}, which populates werr on error.
- bufw *bufio.Writer
-
- // lastMethod is the method of the most recent request
- // on this connection, if any.
- lastMethod string
-
- curReq atomic.Pointer[response] // (which has a Request in it)
-
- curState atomic.Uint64 // packed (unixtime<<8|uint8(ConnState))
-
- // mu guards hijackedv
- mu sync.Mutex
-
- // hijackedv is whether this connection has been hijacked
- // by a Handler with the Hijacker interface.
- // It is guarded by mu.
- hijackedv bool
-}
-
-func (c *conn) hijacked() bool {
- c.mu.Lock()
- defer c.mu.Unlock()
- return c.hijackedv
-}
-
-// c.mu must be held.
-func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
- if c.hijackedv {
- return nil, nil, ErrHijacked
- }
- c.r.abortPendingRead()
-
- c.hijackedv = true
- rwc = c.rwc
- rwc.SetDeadline(time.Time{})
-
- buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc))
- if c.r.hasByte {
- if _, err := c.bufr.Peek(c.bufr.Buffered() + 1); err != nil {
- return nil, nil, fmt.Errorf("unexpected Peek failure reading buffered byte: %v", err)
- }
- }
- c.setState(rwc, StateHijacked, runHooks)
- return
-}
-
-// This should be >= 512 bytes for DetectContentType,
-// but otherwise it's somewhat arbitrary.
-const bufferBeforeChunkingSize = 2048
-
-// chunkWriter writes to a response's conn buffer, and is the writer
-// wrapped by the response.w buffered writer.
-//
-// chunkWriter also is responsible for finalizing the Header, including
-// conditionally setting the Content-Type and setting a Content-Length
-// in cases where the handler's final output is smaller than the buffer
-// size. It also conditionally adds chunk headers, when in chunking mode.
-//
-// See the comment above (*response).Write for the entire write flow.
-type chunkWriter struct {
- res *response
-
- // header is either nil or a deep clone of res.handlerHeader
- // at the time of res.writeHeader, if res.writeHeader is
- // called and extra buffering is being done to calculate
- // Content-Type and/or Content-Length.
- header Header
-
- // wroteHeader tells whether the header's been written to "the
- // wire" (or rather: w.conn.buf). this is unlike
- // (*response).wroteHeader, which tells only whether it was
- // logically written.
- wroteHeader bool
-
- // set by the writeHeader method:
- chunking bool // using chunked transfer encoding for reply body
-}
-
-var (
- crlf = []byte("\r\n")
- colonSpace = []byte(": ")
-)
-
-func (cw *chunkWriter) Write(p []byte) (n int, err error) {
- if !cw.wroteHeader {
- cw.writeHeader(p)
- }
- if cw.res.req.Method == "HEAD" {
- // Eat writes.
- return len(p), nil
- }
- if cw.chunking {
- _, err = fmt.Fprintf(cw.res.conn.bufw, "%x\r\n", len(p))
- if err != nil {
- cw.res.conn.rwc.Close()
- return
- }
- }
- n, err = cw.res.conn.bufw.Write(p)
- if cw.chunking && err == nil {
- _, err = cw.res.conn.bufw.Write(crlf)
- }
- if err != nil {
- cw.res.conn.rwc.Close()
- }
- return
-}
-
-func (cw *chunkWriter) flush() error {
- if !cw.wroteHeader {
- cw.writeHeader(nil)
- }
- return cw.res.conn.bufw.Flush()
-}
-
-func (cw *chunkWriter) close() {
- if !cw.wroteHeader {
- cw.writeHeader(nil)
- }
- if cw.chunking {
- bw := cw.res.conn.bufw // conn's bufio writer
- // zero chunk to mark EOF
- bw.WriteString("0\r\n")
- if trailers := cw.res.finalTrailers(); trailers != nil {
- trailers.Write(bw) // the writer handles noting errors
- }
- // final blank line after the trailers (whether
- // present or not)
- bw.WriteString("\r\n")
- }
-}
-
-// A response represents the server side of an HTTP response.
-type response struct {
- conn *conn
- req *Request // request for this response
- reqBody io.ReadCloser
- cancelCtx context.CancelFunc // when ServeHTTP exits
- wroteHeader bool // a non-1xx header has been (logically) written
- wroteContinue bool // 100 Continue response was written
- wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive"
- wantsClose bool // HTTP request has Connection "close"
-
- // canWriteContinue is an atomic boolean that says whether or
- // not a 100 Continue header can be written to the
- // connection.
- // writeContinueMu must be held while writing the header.
- // These two fields together synchronize the body reader (the
- // expectContinueReader, which wants to write 100 Continue)
- // against the main writer.
- canWriteContinue atomic.Bool
- writeContinueMu sync.Mutex
-
- w *bufio.Writer // buffers output in chunks to chunkWriter
- cw chunkWriter
-
- // handlerHeader is the Header that Handlers get access to,
- // which may be retained and mutated even after WriteHeader.
- // handlerHeader is copied into cw.header at WriteHeader
- // time, and privately mutated thereafter.
- handlerHeader Header
- calledHeader bool // handler accessed handlerHeader via Header
-
- written int64 // number of bytes written in body
- contentLength int64 // explicitly-declared Content-Length; or -1
- status int // status code passed to WriteHeader
-
- // close connection after this reply. set on request and
- // updated after response from handler if there's a
- // "Connection: keep-alive" response header and a
- // Content-Length.
- closeAfterReply bool
-
- // When fullDuplex is false (the default), we consume any remaining
- // request body before starting to write a response.
- fullDuplex bool
-
- // requestBodyLimitHit is set by requestTooLarge when
- // maxBytesReader hits its max size. It is checked in
- // WriteHeader, to make sure we don't consume the
- // remaining request body to try to advance to the next HTTP
- // request. Instead, when this is set, we stop reading
- // subsequent requests on this connection and stop reading
- // input from it.
- requestBodyLimitHit bool
-
- // trailers are the headers to be sent after the handler
- // finishes writing the body. This field is initialized from
- // the Trailer response header when the response header is
- // written.
- trailers []string
-
- handlerDone atomic.Bool // set true when the handler exits
-
- // Buffers for Date, Content-Length, and status code
- dateBuf [len(TimeFormat)]byte
- clenBuf [10]byte
- statusBuf [3]byte
-
- // closeNotifyCh is the channel returned by CloseNotify.
- // TODO(bradfitz): this is currently (for Go 1.8) always
- // non-nil. Make this lazily-created again as it used to be?
- closeNotifyCh chan bool
- didCloseNotify atomic.Bool // atomic (only false->true winner should send)
-}
-
-func (c *response) SetReadDeadline(deadline time.Time) error {
- return c.conn.rwc.SetReadDeadline(deadline)
-}
-
-func (c *response) SetWriteDeadline(deadline time.Time) error {
- return c.conn.rwc.SetWriteDeadline(deadline)
-}
-
-func (c *response) EnableFullDuplex() error {
- c.fullDuplex = true
- return nil
-}
-
-// TrailerPrefix is a magic prefix for [ResponseWriter.Header] map keys
-// that, if present, signals that the map entry is actually for
-// the response trailers, and not the response headers. The prefix
-// is stripped after the ServeHTTP call finishes and the values are
-// sent in the trailers.
-//
-// This mechanism is intended only for trailers that are not known
-// prior to the headers being written. If the set of trailers is fixed
-// or known before the header is written, the normal Go trailers mechanism
-// is preferred:
-//
-// https://pkg.go.dev/net/http#ResponseWriter
-// https://pkg.go.dev/net/http#example-ResponseWriter-Trailers
-const TrailerPrefix = "Trailer:"
-
-// finalTrailers is called after the Handler exits and returns a non-nil
-// value if the Handler set any trailers.
-func (w *response) finalTrailers() Header {
- var t Header
- for k, vv := range w.handlerHeader {
- if kk, found := strings.CutPrefix(k, TrailerPrefix); found {
- if t == nil {
- t = make(Header)
- }
- t[kk] = vv
- }
- }
- for _, k := range w.trailers {
- if t == nil {
- t = make(Header)
- }
- for _, v := range w.handlerHeader[k] {
- t.Add(k, v)
- }
- }
- return t
-}
-
-// declareTrailer is called for each Trailer header when the
-// response header is written. It notes that a header will need to be
-// written in the trailers at the end of the response.
-func (w *response) declareTrailer(k string) {
- k = CanonicalHeaderKey(k)
- if !httpguts.ValidTrailerHeader(k) {
- // Forbidden by RFC 7230, section 4.1.2
- return
- }
- w.trailers = append(w.trailers, k)
-}
-
-// requestTooLarge is called by maxBytesReader when too much input has
-// been read from the client.
-func (w *response) requestTooLarge() {
- w.closeAfterReply = true
- w.requestBodyLimitHit = true
- if !w.wroteHeader {
- w.Header().Set("Connection", "close")
- }
-}
-
-// writerOnly hides an io.Writer value's optional ReadFrom method
-// from io.Copy.
-type writerOnly struct {
- io.Writer
-}
-
-// ReadFrom is here to optimize copying from an [*os.File] regular file
-// to a [*net.TCPConn] with sendfile, or from a supported src type such
-// as a *net.TCPConn on Linux with splice.
-func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
- buf := getCopyBuf()
- defer putCopyBuf(buf)
-
- // Our underlying w.conn.rwc is usually a *TCPConn (with its
- // own ReadFrom method). If not, just fall back to the normal
- // copy method.
- rf, ok := w.conn.rwc.(io.ReaderFrom)
- if !ok {
- return io.CopyBuffer(writerOnly{w}, src, buf)
- }
-
- // Copy the first sniffLen bytes before switching to ReadFrom.
- // This ensures we don't start writing the response before the
- // source is available (see golang.org/issue/5660) and provides
- // enough bytes to perform Content-Type sniffing when required.
- if !w.cw.wroteHeader {
- n0, err := io.CopyBuffer(writerOnly{w}, io.LimitReader(src, sniffLen), buf)
- n += n0
- if err != nil || n0 < sniffLen {
- return n, err
- }
- }
-
- w.w.Flush() // get rid of any previous writes
- w.cw.flush() // make sure Header is written; flush data to rwc
-
- // Now that cw has been flushed, its chunking field is guaranteed initialized.
- if !w.cw.chunking && w.bodyAllowed() {
- n0, err := rf.ReadFrom(src)
- n += n0
- w.written += n0
- return n, err
- }
-
- n0, err := io.CopyBuffer(writerOnly{w}, src, buf)
- n += n0
- return n, err
-}
-
-// debugServerConnections controls whether all server connections are wrapped
-// with a verbose logging wrapper.
-const debugServerConnections = false
-
-// Create new connection from rwc.
-func (srv *Server) newConn(rwc net.Conn) *conn {
- c := &conn{
- server: srv,
- rwc: rwc,
- }
- if debugServerConnections {
- c.rwc = newLoggingConn("server", c.rwc)
- }
- return c
-}
-
-type readResult struct {
- _ incomparable
- n int
- err error
- b byte // byte read, if n == 1
-}
-
-// connReader is the io.Reader wrapper used by *conn. It combines a
-// selectively-activated io.LimitedReader (to bound request header
-// read sizes) with support for selectively keeping an io.Reader.Read
-// call blocked in a background goroutine to wait for activity and
-// trigger a CloseNotifier channel.
-type connReader struct {
- conn *conn
-
- mu sync.Mutex // guards following
- hasByte bool
- byteBuf [1]byte
- cond *sync.Cond
- inRead bool
- aborted bool // set true before conn.rwc deadline is set to past
- remain int64 // bytes remaining
-}
-
-func (cr *connReader) lock() {
- cr.mu.Lock()
- if cr.cond == nil {
- cr.cond = sync.NewCond(&cr.mu)
- }
-}
-
-func (cr *connReader) unlock() { cr.mu.Unlock() }
-
-func (cr *connReader) startBackgroundRead() {
- cr.lock()
- defer cr.unlock()
- if cr.inRead {
- panic("invalid concurrent Body.Read call")
- }
- if cr.hasByte {
- return
- }
- cr.inRead = true
- cr.conn.rwc.SetReadDeadline(time.Time{})
- go cr.backgroundRead()
-}
-
-func (cr *connReader) backgroundRead() {
- n, err := cr.conn.rwc.Read(cr.byteBuf[:])
- cr.lock()
- if n == 1 {
- cr.hasByte = true
- // We were past the end of the previous request's body already
- // (since we wouldn't be in a background read otherwise), so
- // this is a pipelined HTTP request. Prior to Go 1.11 we used to
- // send on the CloseNotify channel and cancel the context here,
- // but the behavior was documented as only "may", and we only
- // did that because that's how CloseNotify accidentally behaved
- // in very early Go releases prior to context support. Once we
- // added context support, people used a Handler's
- // Request.Context() and passed it along. Having that context
- // cancel on pipelined HTTP requests caused problems.
- // Fortunately, almost nothing uses HTTP/1.x pipelining.
- // Unfortunately, apt-get does, or sometimes does.
- // New Go 1.11 behavior: don't fire CloseNotify or cancel
- // contexts on pipelined requests. Shouldn't affect people, but
- // fixes cases like Issue 23921. This does mean that a client
- // closing their TCP connection after sending a pipelined
- // request won't cancel the context, but we'll catch that on any
- // write failure (in checkConnErrorWriter.Write).
- // If the server never writes, yes, there are still contrived
- // server & client behaviors where this fails to ever cancel the
- // context, but that's kinda why HTTP/1.x pipelining died
- // anyway.
- }
- if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() {
- // Ignore this error. It's the expected error from
- // another goroutine calling abortPendingRead.
- } else if err != nil {
- cr.handleReadError(err)
- }
- cr.aborted = false
- cr.inRead = false
- cr.unlock()
- cr.cond.Broadcast()
-}
-
-func (cr *connReader) abortPendingRead() {
- cr.lock()
- defer cr.unlock()
- if !cr.inRead {
- return
- }
- cr.aborted = true
- cr.conn.rwc.SetReadDeadline(aLongTimeAgo)
- for cr.inRead {
- cr.cond.Wait()
- }
- cr.conn.rwc.SetReadDeadline(time.Time{})
-}
-
-func (cr *connReader) setReadLimit(remain int64) { cr.remain = remain }
-func (cr *connReader) setInfiniteReadLimit() { cr.remain = maxInt64 }
-func (cr *connReader) hitReadLimit() bool { return cr.remain <= 0 }
-
-// handleReadError is called whenever a Read from the client returns a
-// non-nil error.
-//
-// The provided non-nil err is almost always io.EOF or a "use of
-// closed network connection". In any case, the error is not
-// particularly interesting, except perhaps for debugging during
-// development. Any error means the connection is dead and we should
-// down its context.
-//
-// It may be called from multiple goroutines.
-func (cr *connReader) handleReadError(_ error) {
- cr.conn.cancelCtx()
- cr.closeNotify()
-}
-
-// may be called from multiple goroutines.
-func (cr *connReader) closeNotify() {
- res := cr.conn.curReq.Load()
- if res != nil && !res.didCloseNotify.Swap(true) {
- res.closeNotifyCh <- true
- }
-}
-
-func (cr *connReader) Read(p []byte) (n int, err error) {
- cr.lock()
- if cr.inRead {
- cr.unlock()
- if cr.conn.hijacked() {
- panic("invalid Body.Read call. After hijacked, the original Request must not be used")
- }
- panic("invalid concurrent Body.Read call")
- }
- if cr.hitReadLimit() {
- cr.unlock()
- return 0, io.EOF
- }
- if len(p) == 0 {
- cr.unlock()
- return 0, nil
- }
- if int64(len(p)) > cr.remain {
- p = p[:cr.remain]
- }
- if cr.hasByte {
- p[0] = cr.byteBuf[0]
- cr.hasByte = false
- cr.unlock()
- return 1, nil
- }
- cr.inRead = true
- cr.unlock()
- n, err = cr.conn.rwc.Read(p)
-
- cr.lock()
- cr.inRead = false
- if err != nil {
- cr.handleReadError(err)
- }
- cr.remain -= int64(n)
- cr.unlock()
-
- cr.cond.Broadcast()
- return n, err
-}
-
-var (
- bufioReaderPool sync.Pool
- bufioWriter2kPool sync.Pool
- bufioWriter4kPool sync.Pool
-)
-
-const copyBufPoolSize = 32 * 1024
-
-var copyBufPool = sync.Pool{New: func() any { return new([copyBufPoolSize]byte) }}
-
-func getCopyBuf() []byte {
- return copyBufPool.Get().(*[copyBufPoolSize]byte)[:]
-}
-func putCopyBuf(b []byte) {
- if len(b) != copyBufPoolSize {
- panic("trying to put back buffer of the wrong size in the copyBufPool")
- }
- copyBufPool.Put((*[copyBufPoolSize]byte)(b))
-}
-
-func bufioWriterPool(size int) *sync.Pool {
- switch size {
- case 2 << 10:
- return &bufioWriter2kPool
- case 4 << 10:
- return &bufioWriter4kPool
- }
- return nil
-}
-
-func newBufioReader(r io.Reader) *bufio.Reader {
- if v := bufioReaderPool.Get(); v != nil {
- br := v.(*bufio.Reader)
- br.Reset(r)
- return br
- }
- // Note: if this reader size is ever changed, update
- // TestHandlerBodyClose's assumptions.
- return bufio.NewReader(r)
-}
-
-func putBufioReader(br *bufio.Reader) {
- br.Reset(nil)
- bufioReaderPool.Put(br)
-}
-
-func newBufioWriterSize(w io.Writer, size int) *bufio.Writer {
- pool := bufioWriterPool(size)
- if pool != nil {
- if v := pool.Get(); v != nil {
- bw := v.(*bufio.Writer)
- bw.Reset(w)
- return bw
- }
- }
- return bufio.NewWriterSize(w, size)
-}
-
-func putBufioWriter(bw *bufio.Writer) {
- bw.Reset(nil)
- if pool := bufioWriterPool(bw.Available()); pool != nil {
- pool.Put(bw)
- }
-}
-
-// DefaultMaxHeaderBytes is the maximum permitted size of the headers
-// in an HTTP request.
-// This can be overridden by setting [Server.MaxHeaderBytes].
-const DefaultMaxHeaderBytes = 1 << 20 // 1 MB
-
-func (srv *Server) maxHeaderBytes() int {
- if srv.MaxHeaderBytes > 0 {
- return srv.MaxHeaderBytes
- }
- return DefaultMaxHeaderBytes
-}
-
-func (srv *Server) initialReadLimitSize() int64 {
- return int64(srv.maxHeaderBytes()) + 4096 // bufio slop
-}
-
-// tlsHandshakeTimeout returns the time limit permitted for the TLS
-// handshake, or zero for unlimited.
-//
-// It returns the minimum of any positive ReadHeaderTimeout,
-// ReadTimeout, or WriteTimeout.
-func (srv *Server) tlsHandshakeTimeout() time.Duration {
- var ret time.Duration
- for _, v := range [...]time.Duration{
- srv.ReadHeaderTimeout,
- srv.ReadTimeout,
- srv.WriteTimeout,
- } {
- if v <= 0 {
- continue
- }
- if ret == 0 || v < ret {
- ret = v
- }
- }
- return ret
-}
-
-// wrapper around io.ReadCloser which on first read, sends an
-// HTTP/1.1 100 Continue header
-type expectContinueReader struct {
- resp *response
- readCloser io.ReadCloser
- closed atomic.Bool
- sawEOF atomic.Bool
-}
-
-func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
- if ecr.closed.Load() {
- return 0, ErrBodyReadAfterClose
- }
- w := ecr.resp
- if !w.wroteContinue && w.canWriteContinue.Load() && !w.conn.hijacked() {
- w.wroteContinue = true
- w.writeContinueMu.Lock()
- if w.canWriteContinue.Load() {
- w.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
- w.conn.bufw.Flush()
- w.canWriteContinue.Store(false)
- }
- w.writeContinueMu.Unlock()
- }
- n, err = ecr.readCloser.Read(p)
- if err == io.EOF {
- ecr.sawEOF.Store(true)
- }
- return
-}
-
-func (ecr *expectContinueReader) Close() error {
- ecr.closed.Store(true)
- return ecr.readCloser.Close()
-}
-
-// TimeFormat is the time format to use when generating times in HTTP
-// headers. It is like [time.RFC1123] but hard-codes GMT as the time
-// zone. The time being formatted must be in UTC for Format to
-// generate the correct format.
-//
-// For parsing this time format, see [ParseTime].
-const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
-
-// appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat))
-func appendTime(b []byte, t time.Time) []byte {
- const days = "SunMonTueWedThuFriSat"
- const months = "JanFebMarAprMayJunJulAugSepOctNovDec"
-
- t = t.UTC()
- yy, mm, dd := t.Date()
- hh, mn, ss := t.Clock()
- day := days[3*t.Weekday():]
- mon := months[3*(mm-1):]
-
- return append(b,
- day[0], day[1], day[2], ',', ' ',
- byte('0'+dd/10), byte('0'+dd%10), ' ',
- mon[0], mon[1], mon[2], ' ',
- byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ',
- byte('0'+hh/10), byte('0'+hh%10), ':',
- byte('0'+mn/10), byte('0'+mn%10), ':',
- byte('0'+ss/10), byte('0'+ss%10), ' ',
- 'G', 'M', 'T')
-}
-
-var errTooLarge = errors.New("http: request too large")
-
-// Read next request from connection.
-func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
- if c.hijacked() {
- return nil, ErrHijacked
- }
-
- var (
- wholeReqDeadline time.Time // or zero if none
- hdrDeadline time.Time // or zero if none
- )
- t0 := time.Now()
- if d := c.server.readHeaderTimeout(); d > 0 {
- hdrDeadline = t0.Add(d)
- }
- if d := c.server.ReadTimeout; d > 0 {
- wholeReqDeadline = t0.Add(d)
- }
- c.rwc.SetReadDeadline(hdrDeadline)
- if d := c.server.WriteTimeout; d > 0 {
- defer func() {
- c.rwc.SetWriteDeadline(time.Now().Add(d))
- }()
- }
-
- c.r.setReadLimit(c.server.initialReadLimitSize())
- if c.lastMethod == "POST" {
- // RFC 7230 section 3 tolerance for old buggy clients.
- peek, _ := c.bufr.Peek(4) // ReadRequest will get err below
- c.bufr.Discard(numLeadingCRorLF(peek))
- }
- req, err := readRequest(c.bufr)
- if err != nil {
- if c.r.hitReadLimit() {
- return nil, errTooLarge
- }
- return nil, err
- }
-
- if !http1ServerSupportsRequest(req) {
- return nil, statusError{StatusHTTPVersionNotSupported, "unsupported protocol version"}
- }
-
- c.lastMethod = req.Method
- c.r.setInfiniteReadLimit()
-
- hosts, haveHost := req.Header["Host"]
- isH2Upgrade := req.isH2Upgrade()
- if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" {
- return nil, badRequestError("missing required Host header")
- }
- if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) {
- return nil, badRequestError("malformed Host header")
- }
- for k, vv := range req.Header {
- if !httpguts.ValidHeaderFieldName(k) {
- return nil, badRequestError("invalid header name")
- }
- for _, v := range vv {
- if !httpguts.ValidHeaderFieldValue(v) {
- return nil, badRequestError("invalid header value")
- }
- }
- }
- delete(req.Header, "Host")
-
- ctx, cancelCtx := context.WithCancel(ctx)
- req.ctx = ctx
- req.RemoteAddr = c.remoteAddr
- req.TLS = c.tlsState
- if body, ok := req.Body.(*body); ok {
- body.doEarlyClose = true
- }
-
- // Adjust the read deadline if necessary.
- if !hdrDeadline.Equal(wholeReqDeadline) {
- c.rwc.SetReadDeadline(wholeReqDeadline)
- }
-
- w = &response{
- conn: c,
- cancelCtx: cancelCtx,
- req: req,
- reqBody: req.Body,
- handlerHeader: make(Header),
- contentLength: -1,
- closeNotifyCh: make(chan bool, 1),
-
- // We populate these ahead of time so we're not
- // reading from req.Header after their Handler starts
- // and maybe mutates it (Issue 14940)
- wants10KeepAlive: req.wantsHttp10KeepAlive(),
- wantsClose: req.wantsClose(),
- }
- if isH2Upgrade {
- w.closeAfterReply = true
- }
- w.cw.res = w
- w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
- return w, nil
-}
-
-// http1ServerSupportsRequest reports whether Go's HTTP/1.x server
-// supports the given request.
-func http1ServerSupportsRequest(req *Request) bool {
- if req.ProtoMajor == 1 {
- return true
- }
- // Accept "PRI * HTTP/2.0" upgrade requests, so Handlers can
- // wire up their own HTTP/2 upgrades.
- if req.ProtoMajor == 2 && req.ProtoMinor == 0 &&
- req.Method == "PRI" && req.RequestURI == "*" {
- return true
- }
- // Reject HTTP/0.x, and all other HTTP/2+ requests (which
- // aren't encoded in ASCII anyway).
- return false
-}
-
-func (w *response) Header() Header {
- if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader {
- // Accessing the header between logically writing it
- // and physically writing it means we need to allocate
- // a clone to snapshot the logically written state.
- w.cw.header = w.handlerHeader.Clone()
- }
- w.calledHeader = true
- return w.handlerHeader
-}
-
-// maxPostHandlerReadBytes is the max number of Request.Body bytes not
-// consumed by a handler that the server will read from the client
-// in order to keep a connection alive. If there are more bytes than
-// this then the server to be paranoid instead sends a "Connection:
-// close" response.
-//
-// This number is approximately what a typical machine's TCP buffer
-// size is anyway. (if we have the bytes on the machine, we might as
-// well read them)
-const maxPostHandlerReadBytes = 256 << 10
-
-func checkWriteHeaderCode(code int) {
- // Issue 22880: require valid WriteHeader status codes.
- // For now we only enforce that it's three digits.
- // In the future we might block things over 599 (600 and above aren't defined
- // at https://httpwg.org/specs/rfc7231.html#status.codes).
- // But for now any three digits.
- //
- // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
- // no equivalent bogus thing we can realistically send in HTTP/2,
- // so we'll consistently panic instead and help people find their bugs
- // early. (We can't return an error from WriteHeader even if we wanted to.)
- if code < 100 || code > 999 {
- panic(fmt.Sprintf("invalid WriteHeader code %v", code))
- }
-}
-
-// relevantCaller searches the call stack for the first function outside of net/http.
-// The purpose of this function is to provide more helpful error messages.
-func relevantCaller() runtime.Frame {
- pc := make([]uintptr, 16)
- n := runtime.Callers(1, pc)
- frames := runtime.CallersFrames(pc[:n])
- var frame runtime.Frame
- for {
- frame, more := frames.Next()
- if !strings.HasPrefix(frame.Function, "net/http.") {
- return frame
- }
- if !more {
- break
- }
- }
- return frame
-}
-
-func (w *response) WriteHeader(code int) {
- if w.conn.hijacked() {
- caller := relevantCaller()
- w.conn.server.logf("http: response.WriteHeader on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
- return
- }
- if w.wroteHeader {
- caller := relevantCaller()
- w.conn.server.logf("http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
- return
- }
- checkWriteHeaderCode(code)
-
- // Handle informational headers.
- //
- // We shouldn't send any further headers after 101 Switching Protocols,
- // so it takes the non-informational path.
- if code >= 100 && code <= 199 && code != StatusSwitchingProtocols {
- // Prevent a potential race with an automatically-sent 100 Continue triggered by Request.Body.Read()
- if code == 100 && w.canWriteContinue.Load() {
- w.writeContinueMu.Lock()
- w.canWriteContinue.Store(false)
- w.writeContinueMu.Unlock()
- }
-
- writeStatusLine(w.conn.bufw, w.req.ProtoAtLeast(1, 1), code, w.statusBuf[:])
-
- // Per RFC 8297 we must not clear the current header map
- w.handlerHeader.WriteSubset(w.conn.bufw, excludedHeadersNoBody)
- w.conn.bufw.Write(crlf)
- w.conn.bufw.Flush()
-
- return
- }
-
- w.wroteHeader = true
- w.status = code
-
- if w.calledHeader && w.cw.header == nil {
- w.cw.header = w.handlerHeader.Clone()
- }
-
- if cl := w.handlerHeader.get("Content-Length"); cl != "" {
- v, err := strconv.ParseInt(cl, 10, 64)
- if err == nil && v >= 0 {
- w.contentLength = v
- } else {
- w.conn.server.logf("http: invalid Content-Length of %q", cl)
- w.handlerHeader.Del("Content-Length")
- }
- }
-}
-
-// extraHeader is the set of headers sometimes added by chunkWriter.writeHeader.
-// This type is used to avoid extra allocations from cloning and/or populating
-// the response Header map and all its 1-element slices.
-type extraHeader struct {
- contentType string
- connection string
- transferEncoding string
- date []byte // written if not nil
- contentLength []byte // written if not nil
-}
-
-// Sorted the same as extraHeader.Write's loop.
-var extraHeaderKeys = [][]byte{
- []byte("Content-Type"),
- []byte("Connection"),
- []byte("Transfer-Encoding"),
-}
-
-var (
- headerContentLength = []byte("Content-Length: ")
- headerDate = []byte("Date: ")
-)
-
-// Write writes the headers described in h to w.
-//
-// This method has a value receiver, despite the somewhat large size
-// of h, because it prevents an allocation. The escape analysis isn't
-// smart enough to realize this function doesn't mutate h.
-func (h extraHeader) Write(w *bufio.Writer) {
- if h.date != nil {
- w.Write(headerDate)
- w.Write(h.date)
- w.Write(crlf)
- }
- if h.contentLength != nil {
- w.Write(headerContentLength)
- w.Write(h.contentLength)
- w.Write(crlf)
- }
- for i, v := range []string{h.contentType, h.connection, h.transferEncoding} {
- if v != "" {
- w.Write(extraHeaderKeys[i])
- w.Write(colonSpace)
- w.WriteString(v)
- w.Write(crlf)
- }
- }
-}
-
-// writeHeader finalizes the header sent to the client and writes it
-// to cw.res.conn.bufw.
-//
-// p is not written by writeHeader, but is the first chunk of the body
-// that will be written. It is sniffed for a Content-Type if none is
-// set explicitly. It's also used to set the Content-Length, if the
-// total body size was small and the handler has already finished
-// running.
-func (cw *chunkWriter) writeHeader(p []byte) {
- if cw.wroteHeader {
- return
- }
- cw.wroteHeader = true
-
- w := cw.res
- keepAlivesEnabled := w.conn.server.doKeepAlives()
- isHEAD := w.req.Method == "HEAD"
-
- // header is written out to w.conn.buf below. Depending on the
- // state of the handler, we either own the map or not. If we
- // don't own it, the exclude map is created lazily for
- // WriteSubset to remove headers. The setHeader struct holds
- // headers we need to add.
- header := cw.header
- owned := header != nil
- if !owned {
- header = w.handlerHeader
- }
- var excludeHeader map[string]bool
- delHeader := func(key string) {
- if owned {
- header.Del(key)
- return
- }
- if _, ok := header[key]; !ok {
- return
- }
- if excludeHeader == nil {
- excludeHeader = make(map[string]bool)
- }
- excludeHeader[key] = true
- }
- var setHeader extraHeader
-
- // Don't write out the fake "Trailer:foo" keys. See TrailerPrefix.
- trailers := false
- for k := range cw.header {
- if strings.HasPrefix(k, TrailerPrefix) {
- if excludeHeader == nil {
- excludeHeader = make(map[string]bool)
- }
- excludeHeader[k] = true
- trailers = true
- }
- }
- for _, v := range cw.header["Trailer"] {
- trailers = true
- foreachHeaderElement(v, cw.res.declareTrailer)
- }
-
- te := header.get("Transfer-Encoding")
- hasTE := te != ""
-
- // If the handler is done but never sent a Content-Length
- // response header and this is our first (and last) write, set
- // it, even to zero. This helps HTTP/1.0 clients keep their
- // "keep-alive" connections alive.
- // Exceptions: 304/204/1xx responses never get Content-Length, and if
- // it was a HEAD request, we don't know the difference between
- // 0 actual bytes and 0 bytes because the handler noticed it
- // was a HEAD request and chose not to write anything. So for
- // HEAD, the handler should either write the Content-Length or
- // write non-zero bytes. If it's actually 0 bytes and the
- // handler never looked at the Request.Method, we just don't
- // send a Content-Length header.
- // Further, we don't send an automatic Content-Length if they
- // set a Transfer-Encoding, because they're generally incompatible.
- if w.handlerDone.Load() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && !header.has("Content-Length") && (!isHEAD || len(p) > 0) {
- w.contentLength = int64(len(p))
- setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
- }
-
- // If this was an HTTP/1.0 request with keep-alive and we sent a
- // Content-Length back, we can make this a keep-alive response ...
- if w.wants10KeepAlive && keepAlivesEnabled {
- sentLength := header.get("Content-Length") != ""
- if sentLength && header.get("Connection") == "keep-alive" {
- w.closeAfterReply = false
- }
- }
-
- // Check for an explicit (and valid) Content-Length header.
- hasCL := w.contentLength != -1
-
- if w.wants10KeepAlive && (isHEAD || hasCL || !bodyAllowedForStatus(w.status)) {
- _, connectionHeaderSet := header["Connection"]
- if !connectionHeaderSet {
- setHeader.connection = "keep-alive"
- }
- } else if !w.req.ProtoAtLeast(1, 1) || w.wantsClose {
- w.closeAfterReply = true
- }
-
- if header.get("Connection") == "close" || !keepAlivesEnabled {
- w.closeAfterReply = true
- }
-
- // If the client wanted a 100-continue but we never sent it to
- // them (or, more strictly: we never finished reading their
- // request body), don't reuse this connection.
- //
- // This behavior was first added on the theory that we don't know
- // if the next bytes on the wire are going to be the remainder of
- // the request body or the subsequent request (see issue 11549),
- // but that's not correct: If we keep using the connection,
- // the client is required to send the request body whether we
- // asked for it or not.
- //
- // We probably do want to skip reusing the connection in most cases,
- // however. If the client is offering a large request body that we
- // don't intend to use, then it's better to close the connection
- // than to read the body. For now, assume that if we're sending
- // headers, the handler is done reading the body and we should
- // drop the connection if we haven't seen EOF.
- if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.Load() {
- w.closeAfterReply = true
- }
-
- // We do this by default because there are a number of clients that
- // send a full request before starting to read the response, and they
- // can deadlock if we start writing the response with unconsumed body
- // remaining. See Issue 15527 for some history.
- //
- // If full duplex mode has been enabled with ResponseController.EnableFullDuplex,
- // then leave the request body alone.
- if w.req.ContentLength != 0 && !w.closeAfterReply && !w.fullDuplex {
- var discard, tooBig bool
-
- switch bdy := w.req.Body.(type) {
- case *expectContinueReader:
- if bdy.resp.wroteContinue {
- discard = true
- }
- case *body:
- bdy.mu.Lock()
- switch {
- case bdy.closed:
- if !bdy.sawEOF {
- // Body was closed in handler with non-EOF error.
- w.closeAfterReply = true
- }
- case bdy.unreadDataSizeLocked() >= maxPostHandlerReadBytes:
- tooBig = true
- default:
- discard = true
- }
- bdy.mu.Unlock()
- default:
- discard = true
- }
-
- if discard {
- _, err := io.CopyN(io.Discard, w.reqBody, maxPostHandlerReadBytes+1)
- switch err {
- case nil:
- // There must be even more data left over.
- tooBig = true
- case ErrBodyReadAfterClose:
- // Body was already consumed and closed.
- case io.EOF:
- // The remaining body was just consumed, close it.
- err = w.reqBody.Close()
- if err != nil {
- w.closeAfterReply = true
- }
- default:
- // Some other kind of error occurred, like a read timeout, or
- // corrupt chunked encoding. In any case, whatever remains
- // on the wire must not be parsed as another HTTP request.
- w.closeAfterReply = true
- }
- }
-
- if tooBig {
- w.requestTooLarge()
- delHeader("Connection")
- setHeader.connection = "close"
- }
- }
-
- code := w.status
- if bodyAllowedForStatus(code) {
- // If no content type, apply sniffing algorithm to body.
- _, haveType := header["Content-Type"]
-
- // If the Content-Encoding was set and is non-blank,
- // we shouldn't sniff the body. See Issue 31753.
- ce := header.Get("Content-Encoding")
- hasCE := len(ce) > 0
- if !hasCE && !haveType && !hasTE && len(p) > 0 {
- setHeader.contentType = DetectContentType(p)
- }
- } else {
- for _, k := range suppressedHeaders(code) {
- delHeader(k)
- }
- }
-
- if !header.has("Date") {
- setHeader.date = appendTime(cw.res.dateBuf[:0], time.Now())
- }
-
- if hasCL && hasTE && te != "identity" {
- // TODO: return an error if WriteHeader gets a return parameter
- // For now just ignore the Content-Length.
- w.conn.server.logf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
- te, w.contentLength)
- delHeader("Content-Length")
- hasCL = false
- }
-
- if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) || code == StatusNoContent {
- // Response has no body.
- delHeader("Transfer-Encoding")
- } else if hasCL {
- // Content-Length has been provided, so no chunking is to be done.
- delHeader("Transfer-Encoding")
- } else if w.req.ProtoAtLeast(1, 1) {
- // HTTP/1.1 or greater: Transfer-Encoding has been set to identity, and no
- // content-length has been provided. The connection must be closed after the
- // reply is written, and no chunking is to be done. This is the setup
- // recommended in the Server-Sent Events candidate recommendation 11,
- // section 8.
- if hasTE && te == "identity" {
- cw.chunking = false
- w.closeAfterReply = true
- delHeader("Transfer-Encoding")
- } else {
- // HTTP/1.1 or greater: use chunked transfer encoding
- // to avoid closing the connection at EOF.
- cw.chunking = true
- setHeader.transferEncoding = "chunked"
- if hasTE && te == "chunked" {
- // We will send the chunked Transfer-Encoding header later.
- delHeader("Transfer-Encoding")
- }
- }
- } else {
- // HTTP version < 1.1: cannot do chunked transfer
- // encoding and we don't know the Content-Length so
- // signal EOF by closing connection.
- w.closeAfterReply = true
- delHeader("Transfer-Encoding") // in case already set
- }
-
- // Cannot use Content-Length with non-identity Transfer-Encoding.
- if cw.chunking {
- delHeader("Content-Length")
- }
- if !w.req.ProtoAtLeast(1, 0) {
- return
- }
-
- // Only override the Connection header if it is not a successful
- // protocol switch response and if KeepAlives are not enabled.
- // See https://golang.org/issue/36381.
- delConnectionHeader := w.closeAfterReply &&
- (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) &&
- !isProtocolSwitchResponse(w.status, header)
- if delConnectionHeader {
- delHeader("Connection")
- if w.req.ProtoAtLeast(1, 1) {
- setHeader.connection = "close"
- }
- }
-
- writeStatusLine(w.conn.bufw, w.req.ProtoAtLeast(1, 1), code, w.statusBuf[:])
- cw.header.WriteSubset(w.conn.bufw, excludeHeader)
- setHeader.Write(w.conn.bufw)
- w.conn.bufw.Write(crlf)
-}
-
-// foreachHeaderElement splits v according to the "#rule" construction
-// in RFC 7230 section 7 and calls fn for each non-empty element.
-func foreachHeaderElement(v string, fn func(string)) {
- v = textproto.TrimString(v)
- if v == "" {
- return
- }
- if !strings.Contains(v, ",") {
- fn(v)
- return
- }
- for _, f := range strings.Split(v, ",") {
- if f = textproto.TrimString(f); f != "" {
- fn(f)
- }
- }
-}
-
-// writeStatusLine writes an HTTP/1.x Status-Line (RFC 7230 Section 3.1.2)
-// to bw. is11 is whether the HTTP request is HTTP/1.1. false means HTTP/1.0.
-// code is the response status code.
-// scratch is an optional scratch buffer. If it has at least capacity 3, it's used.
-func writeStatusLine(bw *bufio.Writer, is11 bool, code int, scratch []byte) {
- if is11 {
- bw.WriteString("HTTP/1.1 ")
- } else {
- bw.WriteString("HTTP/1.0 ")
- }
- if text := StatusText(code); text != "" {
- bw.Write(strconv.AppendInt(scratch[:0], int64(code), 10))
- bw.WriteByte(' ')
- bw.WriteString(text)
- bw.WriteString("\r\n")
- } else {
- // don't worry about performance
- fmt.Fprintf(bw, "%03d status code %d\r\n", code, code)
- }
-}
-
-// bodyAllowed reports whether a Write is allowed for this response type.
-// It's illegal to call this before the header has been flushed.
-func (w *response) bodyAllowed() bool {
- if !w.wroteHeader {
- panic("")
- }
- return bodyAllowedForStatus(w.status)
-}
-
-// The Life Of A Write is like this:
-//
-// Handler starts. No header has been sent. The handler can either
-// write a header, or just start writing. Writing before sending a header
-// sends an implicitly empty 200 OK header.
-//
-// If the handler didn't declare a Content-Length up front, we either
-// go into chunking mode or, if the handler finishes running before
-// the chunking buffer size, we compute a Content-Length and send that
-// in the header instead.
-//
-// Likewise, if the handler didn't set a Content-Type, we sniff that
-// from the initial chunk of output.
-//
-// The Writers are wired together like:
-//
-// 1. *response (the ResponseWriter) ->
-// 2. (*response).w, a [*bufio.Writer] of bufferBeforeChunkingSize bytes ->
-// 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type)
-// and which writes the chunk headers, if needed ->
-// 4. conn.bufw, a *bufio.Writer of default (4kB) bytes, writing to ->
-// 5. checkConnErrorWriter{c}, which notes any non-nil error on Write
-// and populates c.werr with it if so, but otherwise writes to ->
-// 6. the rwc, the [net.Conn].
-//
-// TODO(bradfitz): short-circuit some of the buffering when the
-// initial header contains both a Content-Type and Content-Length.
-// Also short-circuit in (1) when the header's been sent and not in
-// chunking mode, writing directly to (4) instead, if (2) has no
-// buffered data. More generally, we could short-circuit from (1) to
-// (3) even in chunking mode if the write size from (1) is over some
-// threshold and nothing is in (2). The answer might be mostly making
-// bufferBeforeChunkingSize smaller and having bufio's fast-paths deal
-// with this instead.
-func (w *response) Write(data []byte) (n int, err error) {
- return w.write(len(data), data, "")
-}
-
-func (w *response) WriteString(data string) (n int, err error) {
- return w.write(len(data), nil, data)
-}
-
-// either dataB or dataS is non-zero.
-func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
- if w.conn.hijacked() {
- if lenData > 0 {
- caller := relevantCaller()
- w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
- }
- return 0, ErrHijacked
- }
-
- if w.canWriteContinue.Load() {
- // Body reader wants to write 100 Continue but hasn't yet.
- // Tell it not to. The store must be done while holding the lock
- // because the lock makes sure that there is not an active write
- // this very moment.
- w.writeContinueMu.Lock()
- w.canWriteContinue.Store(false)
- w.writeContinueMu.Unlock()
- }
-
- if !w.wroteHeader {
- w.WriteHeader(StatusOK)
- }
- if lenData == 0 {
- return 0, nil
- }
- if !w.bodyAllowed() {
- return 0, ErrBodyNotAllowed
- }
-
- w.written += int64(lenData) // ignoring errors, for errorKludge
- if w.contentLength != -1 && w.written > w.contentLength {
- return 0, ErrContentLength
- }
- if dataB != nil {
- return w.w.Write(dataB)
- } else {
- return w.w.WriteString(dataS)
- }
-}
-
-func (w *response) finishRequest() {
- w.handlerDone.Store(true)
-
- if !w.wroteHeader {
- w.WriteHeader(StatusOK)
- }
-
- w.w.Flush()
- putBufioWriter(w.w)
- w.cw.close()
- w.conn.bufw.Flush()
-
- w.conn.r.abortPendingRead()
-
- // Close the body (regardless of w.closeAfterReply) so we can
- // re-use its bufio.Reader later safely.
- w.reqBody.Close()
-
- if w.req.MultipartForm != nil {
- w.req.MultipartForm.RemoveAll()
- }
-}
-
-// shouldReuseConnection reports whether the underlying TCP connection can be reused.
-// It must only be called after the handler is done executing.
-func (w *response) shouldReuseConnection() bool {
- if w.closeAfterReply {
- // The request or something set while executing the
- // handler indicated we shouldn't reuse this
- // connection.
- return false
- }
-
- if w.req.Method != "HEAD" && w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
- // Did not write enough. Avoid getting out of sync.
- return false
- }
-
- // There was some error writing to the underlying connection
- // during the request, so don't re-use this conn.
- if w.conn.werr != nil {
- return false
- }
-
- if w.closedRequestBodyEarly() {
- return false
- }
-
- return true
-}
-
-func (w *response) closedRequestBodyEarly() bool {
- body, ok := w.req.Body.(*body)
- return ok && body.didEarlyClose()
-}
-
-func (w *response) Flush() {
- w.FlushError()
-}
-
-func (w *response) FlushError() error {
- if !w.wroteHeader {
- w.WriteHeader(StatusOK)
- }
- err := w.w.Flush()
- e2 := w.cw.flush()
- if err == nil {
- err = e2
- }
- return err
-}
-
-func (c *conn) finalFlush() {
- if c.bufr != nil {
- // Steal the bufio.Reader (~4KB worth of memory) and its associated
- // reader for a future connection.
- putBufioReader(c.bufr)
- c.bufr = nil
- }
-
- if c.bufw != nil {
- c.bufw.Flush()
- // Steal the bufio.Writer (~4KB worth of memory) and its associated
- // writer for a future connection.
- putBufioWriter(c.bufw)
- c.bufw = nil
- }
-}
-
-// Close the connection.
-func (c *conn) close() {
- c.finalFlush()
- c.rwc.Close()
-}
-
-// rstAvoidanceDelay is the amount of time we sleep after closing the
-// write side of a TCP connection before closing the entire socket.
-// By sleeping, we increase the chances that the client sees our FIN
-// and processes its final data before they process the subsequent RST
-// from closing a connection with known unread data.
-// This RST seems to occur mostly on BSD systems. (And Windows?)
-// This timeout is somewhat arbitrary (~latency around the planet),
-// and may be modified by tests.
-//
-// TODO(bcmills): This should arguably be a server configuration parameter,
-// not a hard-coded value.
-var rstAvoidanceDelay = 500 * time.Millisecond
-
-type closeWriter interface {
- CloseWrite() error
-}
-
-var _ closeWriter = (*net.TCPConn)(nil)
-
-// closeWriteAndWait flushes any outstanding data and sends a FIN packet (if
-// client is connected via TCP), signaling that we're done. We then
-// pause for a bit, hoping the client processes it before any
-// subsequent RST.
-//
-// See https://golang.org/issue/3595
-func (c *conn) closeWriteAndWait() {
- c.finalFlush()
- if tcp, ok := c.rwc.(closeWriter); ok {
- tcp.CloseWrite()
- }
-
- // When we return from closeWriteAndWait, the caller will fully close the
- // connection. If client is still writing to the connection, this will cause
- // the write to fail with ECONNRESET or similar. Unfortunately, many TCP
- // implementations will also drop unread packets from the client's read buffer
- // when a write fails, causing our final response to be truncated away too.
- //
- // As a result, https://www.rfc-editor.org/rfc/rfc7230#section-6.6 recommends
- // that “[t]he server … continues to read from the connection until it
- // receives a corresponding close by the client, or until the server is
- // reasonably certain that its own TCP stack has received the client's
- // acknowledgement of the packet(s) containing the server's last response.”
- //
- // Unfortunately, we have no straightforward way to be “reasonably certain”
- // that we have received the client's ACK, and at any rate we don't want to
- // allow a misbehaving client to soak up server connections indefinitely by
- // withholding an ACK, nor do we want to go through the complexity or overhead
- // of using low-level APIs to figure out when a TCP round-trip has completed.
- //
- // Instead, we declare that we are “reasonably certain” that we received the
- // ACK if maxRSTAvoidanceDelay has elapsed.
- time.Sleep(rstAvoidanceDelay)
-}
-
-// validNextProto reports whether the proto is a valid ALPN protocol name.
-// Everything is valid except the empty string and built-in protocol types,
-// so that those can't be overridden with alternate implementations.
-func validNextProto(proto string) bool {
- switch proto {
- case "", "http/1.1", "http/1.0":
- return false
- }
- return true
-}
-
-const (
- runHooks = true
- skipHooks = false
-)
-
-func (c *conn) setState(nc net.Conn, state ConnState, runHook bool) {
- srv := c.server
- switch state {
- case StateNew:
- srv.trackConn(c, true)
- case StateHijacked, StateClosed:
- srv.trackConn(c, false)
- }
- if state > 0xff || state < 0 {
- panic("internal error")
- }
- packedState := uint64(time.Now().Unix()<<8) | uint64(state)
- c.curState.Store(packedState)
- if !runHook {
- return
- }
- if hook := srv.ConnState; hook != nil {
- hook(nc, state)
- }
-}
-
-func (c *conn) getState() (state ConnState, unixSec int64) {
- packedState := c.curState.Load()
- return ConnState(packedState & 0xff), int64(packedState >> 8)
-}
-
-// badRequestError is a literal string (used by in the server in HTML,
-// unescaped) to tell the user why their request was bad. It should
-// be plain text without user info or other embedded errors.
-func badRequestError(e string) error { return statusError{StatusBadRequest, e} }
-
-// statusError is an error used to respond to a request with an HTTP status.
-// The text should be plain text without user info or other embedded errors.
-type statusError struct {
- code int
- text string
-}
-
-func (e statusError) Error() string { return StatusText(e.code) + ": " + e.text }
-
-// ErrAbortHandler is a sentinel panic value to abort a handler.
-// While any panic from ServeHTTP aborts the response to the client,
-// panicking with ErrAbortHandler also suppresses logging of a stack
-// trace to the server's error log.
-var ErrAbortHandler = errors.New("net/http: abort Handler")
-
-// isCommonNetReadError reports whether err is a common error
-// encountered during reading a request off the network when the
-// client has gone away or had its read fail somehow. This is used to
-// determine which logs are interesting enough to log about.
-func isCommonNetReadError(err error) bool {
- if err == io.EOF {
- return true
- }
- if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
- return true
- }
- if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
- return true
- }
- return false
-}
-
-// Serve a new connection.
-func (c *conn) serve(ctx context.Context) {
- if ra := c.rwc.RemoteAddr(); ra != nil {
- c.remoteAddr = ra.String()
- }
- ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
- var inFlightResponse *response
- defer func() {
- if err := recover(); err != nil && err != ErrAbortHandler {
- const size = 64 << 10
- buf := make([]byte, size)
- buf = buf[:runtime.Stack(buf, false)]
- c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
- }
- if inFlightResponse != nil {
- inFlightResponse.cancelCtx()
- }
- if !c.hijacked() {
- if inFlightResponse != nil {
- inFlightResponse.conn.r.abortPendingRead()
- inFlightResponse.reqBody.Close()
- }
- c.close()
- c.setState(c.rwc, StateClosed, runHooks)
- }
- }()
-
- if tlsConn, ok := c.rwc.(*tls.Conn); ok {
- tlsTO := c.server.tlsHandshakeTimeout()
- if tlsTO > 0 {
- dl := time.Now().Add(tlsTO)
- c.rwc.SetReadDeadline(dl)
- c.rwc.SetWriteDeadline(dl)
- }
- if err := tlsConn.HandshakeContext(ctx); err != nil {
- // If the handshake failed due to the client not speaking
- // TLS, assume they're speaking plaintext HTTP and write a
- // 400 response on the TLS conn's underlying net.Conn.
- if re, ok := err.(tls.RecordHeaderError); ok && re.Conn != nil && tlsRecordHeaderLooksLikeHTTP(re.RecordHeader) {
- io.WriteString(re.Conn, "HTTP/1.0 400 Bad Request\r\n\r\nClient sent an HTTP request to an HTTPS server.\n")
- re.Conn.Close()
- return
- }
- c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
- return
- }
- // Restore Conn-level deadlines.
- if tlsTO > 0 {
- c.rwc.SetReadDeadline(time.Time{})
- c.rwc.SetWriteDeadline(time.Time{})
- }
- c.tlsState = new(tls.ConnectionState)
- *c.tlsState = tlsConn.ConnectionState()
- if proto := c.tlsState.NegotiatedProtocol; validNextProto(proto) {
- if fn := c.server.TLSNextProto[proto]; fn != nil {
- h := initALPNRequest{ctx, tlsConn, serverHandler{c.server}}
- // Mark freshly created HTTP/2 as active and prevent any server state hooks
- // from being run on these connections. This prevents closeIdleConns from
- // closing such connections. See issue https://golang.org/issue/39776.
- c.setState(c.rwc, StateActive, skipHooks)
- fn(c.server, tlsConn, h)
- }
- return
- }
- }
-
- // HTTP/1.x from here on.
-
- ctx, cancelCtx := context.WithCancel(ctx)
- c.cancelCtx = cancelCtx
- defer cancelCtx()
-
- c.r = &connReader{conn: c}
- c.bufr = newBufioReader(c.r)
- c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
-
- for {
- w, err := c.readRequest(ctx)
- if c.r.remain != c.server.initialReadLimitSize() {
- // If we read any bytes off the wire, we're active.
- c.setState(c.rwc, StateActive, runHooks)
- }
- if err != nil {
- const errorHeaders = "\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\n"
-
- switch {
- case err == errTooLarge:
- // Their HTTP client may or may not be
- // able to read this if we're
- // responding to them and hanging up
- // while they're still writing their
- // request. Undefined behavior.
- const publicErr = "431 Request Header Fields Too Large"
- fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
- c.closeWriteAndWait()
- return
-
- case isUnsupportedTEError(err):
- // Respond as per RFC 7230 Section 3.3.1 which says,
- // A server that receives a request message with a
- // transfer coding it does not understand SHOULD
- // respond with 501 (Unimplemented).
- code := StatusNotImplemented
-
- // We purposefully aren't echoing back the transfer-encoding's value,
- // so as to mitigate the risk of cross side scripting by an attacker.
- fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s%sUnsupported transfer encoding", code, StatusText(code), errorHeaders)
- return
-
- case isCommonNetReadError(err):
- return // don't reply
-
- default:
- if v, ok := err.(statusError); ok {
- fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s: %s%s%d %s: %s", v.code, StatusText(v.code), v.text, errorHeaders, v.code, StatusText(v.code), v.text)
- return
- }
- const publicErr = "400 Bad Request"
- fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
- return
- }
- }
-
- // Expect 100 Continue support
- req := w.req
- if req.expectsContinue() {
- if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
- // Wrap the Body reader with one that replies on the connection
- req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
- w.canWriteContinue.Store(true)
- }
- } else if req.Header.get("Expect") != "" {
- w.sendExpectationFailed()
- return
- }
-
- c.curReq.Store(w)
-
- if requestBodyRemains(req.Body) {
- registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
- } else {
- w.conn.r.startBackgroundRead()
- }
-
- // HTTP cannot have multiple simultaneous active requests.[*]
- // Until the server replies to this request, it can't read another,
- // so we might as well run the handler in this goroutine.
- // [*] Not strictly true: HTTP pipelining. We could let them all process
- // in parallel even if their responses need to be serialized.
- // But we're not going to implement HTTP pipelining because it
- // was never deployed in the wild and the answer is HTTP/2.
- inFlightResponse = w
- serverHandler{c.server}.ServeHTTP(w, w.req)
- inFlightResponse = nil
- w.cancelCtx()
- if c.hijacked() {
- return
- }
- w.finishRequest()
- c.rwc.SetWriteDeadline(time.Time{})
- if !w.shouldReuseConnection() {
- if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
- c.closeWriteAndWait()
- }
- return
- }
- c.setState(c.rwc, StateIdle, runHooks)
- c.curReq.Store(nil)
-
- if !w.conn.server.doKeepAlives() {
- // We're in shutdown mode. We might've replied
- // to the user without "Connection: close" and
- // they might think they can send another
- // request, but such is life with HTTP/1.1.
- return
- }
-
- if d := c.server.idleTimeout(); d != 0 {
- c.rwc.SetReadDeadline(time.Now().Add(d))
- } else {
- c.rwc.SetReadDeadline(time.Time{})
- }
-
- // Wait for the connection to become readable again before trying to
- // read the next request. This prevents a ReadHeaderTimeout or
- // ReadTimeout from starting until the first bytes of the next request
- // have been received.
- if _, err := c.bufr.Peek(4); err != nil {
- return
- }
-
- c.rwc.SetReadDeadline(time.Time{})
- }
-}
-
-func (w *response) sendExpectationFailed() {
- // TODO(bradfitz): let ServeHTTP handlers handle
- // requests with non-standard expectation[s]? Seems
- // theoretical at best, and doesn't fit into the
- // current ServeHTTP model anyway. We'd need to
- // make the ResponseWriter an optional
- // "ExpectReplier" interface or something.
- //
- // For now we'll just obey RFC 7231 5.1.1 which says
- // "A server that receives an Expect field-value other
- // than 100-continue MAY respond with a 417 (Expectation
- // Failed) status code to indicate that the unexpected
- // expectation cannot be met."
- w.Header().Set("Connection", "close")
- w.WriteHeader(StatusExpectationFailed)
- w.finishRequest()
-}
-
-// Hijack implements the [Hijacker.Hijack] method. Our response is both a [ResponseWriter]
-// and a [Hijacker].
-func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
- if w.handlerDone.Load() {
- panic("net/http: Hijack called after ServeHTTP finished")
- }
- if w.wroteHeader {
- w.cw.flush()
- }
-
- c := w.conn
- c.mu.Lock()
- defer c.mu.Unlock()
-
- // Release the bufioWriter that writes to the chunk writer, it is not
- // used after a connection has been hijacked.
- rwc, buf, err = c.hijackLocked()
- if err == nil {
- putBufioWriter(w.w)
- w.w = nil
- }
- return rwc, buf, err
-}
-
-func (w *response) CloseNotify() <-chan bool {
- if w.handlerDone.Load() {
- panic("net/http: CloseNotify called after ServeHTTP finished")
- }
- return w.closeNotifyCh
-}
-
-func registerOnHitEOF(rc io.ReadCloser, fn func()) {
- switch v := rc.(type) {
- case *expectContinueReader:
- registerOnHitEOF(v.readCloser, fn)
- case *body:
- v.registerOnHitEOF(fn)
- default:
- panic("unexpected type " + fmt.Sprintf("%T", rc))
- }
-}
-
-// requestBodyRemains reports whether future calls to Read
-// on rc might yield more data.
-func requestBodyRemains(rc io.ReadCloser) bool {
- if rc == NoBody {
- return false
- }
- switch v := rc.(type) {
- case *expectContinueReader:
- return requestBodyRemains(v.readCloser)
- case *body:
- return v.bodyRemains()
- default:
- panic("unexpected type " + fmt.Sprintf("%T", rc))
- }
-}
-
-// The HandlerFunc type is an adapter to allow the use of
-// ordinary functions as HTTP handlers. If f is a function
-// with the appropriate signature, HandlerFunc(f) is a
-// [Handler] that calls f.
-type HandlerFunc func(ResponseWriter, *Request)
-
-// ServeHTTP calls f(w, r).
-func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
- f(w, r)
-}
-
-// Helper handlers
-
-// Error replies to the request with the specified error message and HTTP code.
-// It does not otherwise end the request; the caller should ensure no further
-// writes are done to w.
-// The error message should be plain text.
-func Error(w ResponseWriter, error string, code int) {
- w.Header().Set("Content-Type", "text/plain; charset=utf-8")
- w.Header().Set("X-Content-Type-Options", "nosniff")
- w.WriteHeader(code)
- fmt.Fprintln(w, error)
-}
-
-// NotFound replies to the request with an HTTP 404 not found error.
-func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
-
-// NotFoundHandler returns a simple request handler
-// that replies to each request with a “404 page not found” reply.
-func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
-
-// StripPrefix returns a handler that serves HTTP requests by removing the
-// given prefix from the request URL's Path (and RawPath if set) and invoking
-// the handler h. StripPrefix handles a request for a path that doesn't begin
-// with prefix by replying with an HTTP 404 not found error. The prefix must
-// match exactly: if the prefix in the request contains escaped characters
-// the reply is also an HTTP 404 not found error.
-func StripPrefix(prefix string, h Handler) Handler {
- if prefix == "" {
- return h
- }
- return HandlerFunc(func(w ResponseWriter, r *Request) {
- p := strings.TrimPrefix(r.URL.Path, prefix)
- rp := strings.TrimPrefix(r.URL.RawPath, prefix)
- if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
- r2 := new(Request)
- *r2 = *r
- r2.URL = new(url.URL)
- *r2.URL = *r.URL
- r2.URL.Path = p
- r2.URL.RawPath = rp
- h.ServeHTTP(w, r2)
- } else {
- NotFound(w, r)
- }
- })
-}
-
-// Redirect replies to the request with a redirect to url,
-// which may be a path relative to the request path.
-//
-// The provided code should be in the 3xx range and is usually
-// [StatusMovedPermanently], [StatusFound] or [StatusSeeOther].
-//
-// If the Content-Type header has not been set, [Redirect] sets it
-// to "text/html; charset=utf-8" and writes a small HTML body.
-// Setting the Content-Type header to any value, including nil,
-// disables that behavior.
-func Redirect(w ResponseWriter, r *Request, url string, code int) {
- if u, err := urlpkg.Parse(url); err == nil {
- // If url was relative, make its path absolute by
- // combining with request path.
- // The client would probably do this for us,
- // but doing it ourselves is more reliable.
- // See RFC 7231, section 7.1.2
- if u.Scheme == "" && u.Host == "" {
- oldpath := r.URL.Path
- if oldpath == "" { // should not happen, but avoid a crash if it does
- oldpath = "/"
- }
-
- // no leading http://server
- if url == "" || url[0] != '/' {
- // make relative path absolute
- olddir, _ := path.Split(oldpath)
- url = olddir + url
- }
-
- var query string
- if i := strings.Index(url, "?"); i != -1 {
- url, query = url[:i], url[i:]
- }
-
- // clean up but preserve trailing slash
- trailing := strings.HasSuffix(url, "/")
- url = path.Clean(url)
- if trailing && !strings.HasSuffix(url, "/") {
- url += "/"
- }
- url += query
- }
- }
-
- h := w.Header()
-
- // RFC 7231 notes that a short HTML body is usually included in
- // the response because older user agents may not understand 301/307.
- // Do it only if the request didn't already have a Content-Type header.
- _, hadCT := h["Content-Type"]
-
- h.Set("Location", hexEscapeNonASCII(url))
- if !hadCT && (r.Method == "GET" || r.Method == "HEAD") {
- h.Set("Content-Type", "text/html; charset=utf-8")
- }
- w.WriteHeader(code)
-
- // Shouldn't send the body for POST or HEAD; that leaves GET.
- if !hadCT && r.Method == "GET" {
- body := "" + StatusText(code) + ".\n"
- fmt.Fprintln(w, body)
- }
-}
-
-var htmlReplacer = strings.NewReplacer(
- "&", "&",
- "<", "<",
- ">", ">",
- // """ is shorter than """.
- `"`, """,
- // "'" is shorter than "'" and apos was not in HTML until HTML5.
- "'", "'",
-)
-
-func htmlEscape(s string) string {
- return htmlReplacer.Replace(s)
-}
-
-// Redirect to a fixed URL
-type redirectHandler struct {
- url string
- code int
-}
-
-func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
- Redirect(w, r, rh.url, rh.code)
-}
-
-// RedirectHandler returns a request handler that redirects
-// each request it receives to the given url using the given
-// status code.
-//
-// The provided code should be in the 3xx range and is usually
-// [StatusMovedPermanently], [StatusFound] or [StatusSeeOther].
-func RedirectHandler(url string, code int) Handler {
- return &redirectHandler{url, code}
-}
-
-// ServeMux is an HTTP request multiplexer.
-// It matches the URL of each incoming request against a list of registered
-// patterns and calls the handler for the pattern that
-// most closely matches the URL.
-//
-// # Patterns
-//
-// Patterns can match the method, host and path of a request.
-// Some examples:
-//
-// - "/index.html" matches the path "/index.html" for any host and method.
-// - "GET /static/" matches a GET request whose path begins with "/static/".
-// - "example.com/" matches any request to the host "example.com".
-// - "example.com/{$}" matches requests with host "example.com" and path "/".
-// - "/b/{bucket}/o/{objectname...}" matches paths whose first segment is "b"
-// and whose third segment is "o". The name "bucket" denotes the second
-// segment and "objectname" denotes the remainder of the path.
-//
-// In general, a pattern looks like
-//
-// [METHOD ][HOST]/[PATH]
-//
-// All three parts are optional; "/" is a valid pattern.
-// If METHOD is present, it must be followed by a single space.
-//
-// Literal (that is, non-wildcard) parts of a pattern match
-// the corresponding parts of a request case-sensitively.
-//
-// A pattern with no method matches every method. A pattern
-// with the method GET matches both GET and HEAD requests.
-// Otherwise, the method must match exactly.
-//
-// A pattern with no host matches every host.
-// A pattern with a host matches URLs on that host only.
-//
-// A path can include wildcard segments of the form {NAME} or {NAME...}.
-// For example, "/b/{bucket}/o/{objectname...}".
-// The wildcard name must be a valid Go identifier.
-// Wildcards must be full path segments: they must be preceded by a slash and followed by
-// either a slash or the end of the string.
-// For example, "/b_{bucket}" is not a valid pattern.
-//
-// Normally a wildcard matches only a single path segment,
-// ending at the next literal slash (not %2F) in the request URL.
-// But if the "..." is present, then the wildcard matches the remainder of the URL path, including slashes.
-// (Therefore it is invalid for a "..." wildcard to appear anywhere but at the end of a pattern.)
-// The match for a wildcard can be obtained by calling [Request.PathValue] with the wildcard's name.
-// A trailing slash in a path acts as an anonymous "..." wildcard.
-//
-// The special wildcard {$} matches only the end of the URL.
-// For example, the pattern "/{$}" matches only the path "/",
-// whereas the pattern "/" matches every path.
-//
-// For matching, both pattern paths and incoming request paths are unescaped segment by segment.
-// So, for example, the path "/a%2Fb/100%25" is treated as having two segments, "a/b" and "100%".
-// The pattern "/a%2fb/" matches it, but the pattern "/a/b/" does not.
-//
-// # Precedence
-//
-// If two or more patterns match a request, then the most specific pattern takes precedence.
-// A pattern P1 is more specific than P2 if P1 matches a strict subset of P2’s requests;
-// that is, if P2 matches all the requests of P1 and more.
-// If neither is more specific, then the patterns conflict.
-// There is one exception to this rule, for backwards compatibility:
-// if two patterns would otherwise conflict and one has a host while the other does not,
-// then the pattern with the host takes precedence.
-// If a pattern passed [ServeMux.Handle] or [ServeMux.HandleFunc] conflicts with
-// another pattern that is already registered, those functions panic.
-//
-// As an example of the general rule, "/images/thumbnails/" is more specific than "/images/",
-// so both can be registered.
-// The former matches paths beginning with "/images/thumbnails/"
-// and the latter will match any other path in the "/images/" subtree.
-//
-// As another example, consider the patterns "GET /" and "/index.html":
-// both match a GET request for "/index.html", but the former pattern
-// matches all other GET and HEAD requests, while the latter matches any
-// request for "/index.html" that uses a different method.
-// The patterns conflict.
-//
-// # Trailing-slash redirection
-//
-// Consider a [ServeMux] with a handler for a subtree, registered using a trailing slash or "..." wildcard.
-// If the ServeMux receives a request for the subtree root without a trailing slash,
-// it redirects the request by adding the trailing slash.
-// This behavior can be overridden with a separate registration for the path without
-// the trailing slash or "..." wildcard. For example, registering "/images/" causes ServeMux
-// to redirect a request for "/images" to "/images/", unless "/images" has
-// been registered separately.
-//
-// # Request sanitizing
-//
-// ServeMux also takes care of sanitizing the URL request path and the Host
-// header, stripping the port number and redirecting any request containing . or
-// .. segments or repeated slashes to an equivalent, cleaner URL.
-//
-// # Compatibility
-//
-// The pattern syntax and matching behavior of ServeMux changed significantly
-// in Go 1.22. To restore the old behavior, set the GODEBUG environment variable
-// to "httpmuxgo121=1". This setting is read once, at program startup; changes
-// during execution will be ignored.
-//
-// The backwards-incompatible changes include:
-// - Wildcards are just ordinary literal path segments in 1.21.
-// For example, the pattern "/{x}" will match only that path in 1.21,
-// but will match any one-segment path in 1.22.
-// - In 1.21, no pattern was rejected, unless it was empty or conflicted with an existing pattern.
-// In 1.22, syntactically invalid patterns will cause [ServeMux.Handle] and [ServeMux.HandleFunc] to panic.
-// For example, in 1.21, the patterns "/{" and "/a{x}" match themselves,
-// but in 1.22 they are invalid and will cause a panic when registered.
-// - In 1.22, each segment of a pattern is unescaped; this was not done in 1.21.
-// For example, in 1.22 the pattern "/%61" matches the path "/a" ("%61" being the URL escape sequence for "a"),
-// but in 1.21 it would match only the path "/%2561" (where "%25" is the escape for the percent sign).
-// - When matching patterns to paths, in 1.22 each segment of the path is unescaped; in 1.21, the entire path is unescaped.
-// This change mostly affects how paths with %2F escapes adjacent to slashes are treated.
-// See https://go.dev/issue/21955 for details.
-type ServeMux struct {
- mu sync.RWMutex
- tree routingNode
- index routingIndex
- patterns []*pattern // TODO(jba): remove if possible
- mux121 serveMux121 // used only when GODEBUG=httpmuxgo121=1
-}
-
-// NewServeMux allocates and returns a new [ServeMux].
-func NewServeMux() *ServeMux {
- return &ServeMux{}
-}
-
-// DefaultServeMux is the default [ServeMux] used by [Serve].
-var DefaultServeMux = &defaultServeMux
-
-var defaultServeMux ServeMux
-
-// cleanPath returns the canonical path for p, eliminating . and .. elements.
-func cleanPath(p string) string {
- if p == "" {
- return "/"
- }
- if p[0] != '/' {
- p = "/" + p
- }
- np := path.Clean(p)
- // path.Clean removes trailing slash except for root;
- // put the trailing slash back if necessary.
- if p[len(p)-1] == '/' && np != "/" {
- // Fast path for common case of p being the string we want:
- if len(p) == len(np)+1 && strings.HasPrefix(p, np) {
- np = p
- } else {
- np += "/"
- }
- }
- return np
-}
-
-// stripHostPort returns h without any trailing ":".
-func stripHostPort(h string) string {
- // If no port on host, return unchanged
- if !strings.Contains(h, ":") {
- return h
- }
- host, _, err := net.SplitHostPort(h)
- if err != nil {
- return h // on error, return unchanged
- }
- return host
-}
-
-// Handler returns the handler to use for the given request,
-// consulting r.Method, r.Host, and r.URL.Path. It always returns
-// a non-nil handler. If the path is not in its canonical form, the
-// handler will be an internally-generated handler that redirects
-// to the canonical path. If the host contains a port, it is ignored
-// when matching handlers.
-//
-// The path and host are used unchanged for CONNECT requests.
-//
-// Handler also returns the registered pattern that matches the
-// request or, in the case of internally-generated redirects,
-// the path that will match after following the redirect.
-//
-// If there is no registered handler that applies to the request,
-// Handler returns a “page not found” handler and an empty pattern.
-func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
- if use121 {
- return mux.mux121.findHandler(r)
- }
- h, p, _, _ := mux.findHandler(r)
- return h, p
-}
-
-// findHandler finds a handler for a request.
-// If there is a matching handler, it returns it and the pattern that matched.
-// Otherwise it returns a Redirect or NotFound handler with the path that would match
-// after the redirect.
-func (mux *ServeMux) findHandler(r *Request) (h Handler, patStr string, _ *pattern, matches []string) {
- var n *routingNode
- host := r.URL.Host
- escapedPath := r.URL.EscapedPath()
- path := escapedPath
- // CONNECT requests are not canonicalized.
- if r.Method == "CONNECT" {
- // If r.URL.Path is /tree and its handler is not registered,
- // the /tree -> /tree/ redirect applies to CONNECT requests
- // but the path canonicalization does not.
- _, _, u := mux.matchOrRedirect(host, r.Method, path, r.URL)
- if u != nil {
- return RedirectHandler(u.String(), StatusMovedPermanently), u.Path, nil, nil
- }
- // Redo the match, this time with r.Host instead of r.URL.Host.
- // Pass a nil URL to skip the trailing-slash redirect logic.
- n, matches, _ = mux.matchOrRedirect(r.Host, r.Method, path, nil)
- } else {
- // All other requests have any port stripped and path cleaned
- // before passing to mux.handler.
- host = stripHostPort(r.Host)
- path = cleanPath(path)
-
- // If the given path is /tree and its handler is not registered,
- // redirect for /tree/.
- var u *url.URL
- n, matches, u = mux.matchOrRedirect(host, r.Method, path, r.URL)
- if u != nil {
- return RedirectHandler(u.String(), StatusMovedPermanently), u.Path, nil, nil
- }
- if path != escapedPath {
- // Redirect to cleaned path.
- patStr := ""
- if n != nil {
- patStr = n.pattern.String()
- }
- u := &url.URL{Path: path, RawQuery: r.URL.RawQuery}
- return RedirectHandler(u.String(), StatusMovedPermanently), patStr, nil, nil
- }
- }
- if n == nil {
- // We didn't find a match with the request method. To distinguish between
- // Not Found and Method Not Allowed, see if there is another pattern that
- // matches except for the method.
- allowedMethods := mux.matchingMethods(host, path)
- if len(allowedMethods) > 0 {
- return HandlerFunc(func(w ResponseWriter, r *Request) {
- w.Header().Set("Allow", strings.Join(allowedMethods, ", "))
- Error(w, StatusText(StatusMethodNotAllowed), StatusMethodNotAllowed)
- }), "", nil, nil
- }
- return NotFoundHandler(), "", nil, nil
- }
- return n.handler, n.pattern.String(), n.pattern, matches
-}
-
-// matchOrRedirect looks up a node in the tree that matches the host, method and path.
-//
-// If the url argument is non-nil, handler also deals with trailing-slash
-// redirection: when a path doesn't match exactly, the match is tried again
-// after appending "/" to the path. If that second match succeeds, the last
-// return value is the URL to redirect to.
-func (mux *ServeMux) matchOrRedirect(host, method, path string, u *url.URL) (_ *routingNode, matches []string, redirectTo *url.URL) {
- mux.mu.RLock()
- defer mux.mu.RUnlock()
-
- n, matches := mux.tree.match(host, method, path)
- // If we have an exact match, or we were asked not to try trailing-slash redirection,
- // then we're done.
- if !exactMatch(n, path) && u != nil {
- // If there is an exact match with a trailing slash, then redirect.
- path += "/"
- n2, _ := mux.tree.match(host, method, path)
- if exactMatch(n2, path) {
- return nil, nil, &url.URL{Path: cleanPath(u.Path) + "/", RawQuery: u.RawQuery}
- }
- }
- return n, matches, nil
-}
-
-// exactMatch reports whether the node's pattern exactly matches the path.
-// As a special case, if the node is nil, exactMatch return false.
-//
-// Before wildcards were introduced, it was clear that an exact match meant
-// that the pattern and path were the same string. The only other possibility
-// was that a trailing-slash pattern, like "/", matched a path longer than
-// it, like "/a".
-//
-// With wildcards, we define an inexact match as any one where a multi wildcard
-// matches a non-empty string. All other matches are exact.
-// For example, these are all exact matches:
-//
-// pattern path
-// /a /a
-// /{x} /a
-// /a/{$} /a/
-// /a/ /a/
-//
-// The last case has a multi wildcard (implicitly), but the match is exact because
-// the wildcard matches the empty string.
-//
-// Examples of matches that are not exact:
-//
-// pattern path
-// / /a
-// /a/{x...} /a/b
-func exactMatch(n *routingNode, path string) bool {
- if n == nil {
- return false
- }
- // We can't directly implement the definition (empty match for multi
- // wildcard) because we don't record a match for anonymous multis.
-
- // If there is no multi, the match is exact.
- if !n.pattern.lastSegment().multi {
- return true
- }
-
- // If the path doesn't end in a trailing slash, then the multi match
- // is non-empty.
- if len(path) > 0 && path[len(path)-1] != '/' {
- return false
- }
- // Only patterns ending in {$} or a multi wildcard can
- // match a path with a trailing slash.
- // For the match to be exact, the number of pattern
- // segments should be the same as the number of slashes in the path.
- // E.g. "/a/b/{$}" and "/a/b/{...}" exactly match "/a/b/", but "/a/" does not.
- return len(n.pattern.segments) == strings.Count(path, "/")
-}
-
-// matchingMethods return a sorted list of all methods that would match with the given host and path.
-func (mux *ServeMux) matchingMethods(host, path string) []string {
- // Hold the read lock for the entire method so that the two matches are done
- // on the same set of registered patterns.
- mux.mu.RLock()
- defer mux.mu.RUnlock()
- ms := map[string]bool{}
- mux.tree.matchingMethods(host, path, ms)
- // matchOrRedirect will try appending a trailing slash if there is no match.
- mux.tree.matchingMethods(host, path+"/", ms)
- methods := mapKeys(ms)
- sort.Strings(methods)
- return methods
-}
-
-// TODO(jba): replace with maps.Keys when it is defined.
-func mapKeys[K comparable, V any](m map[K]V) []K {
- var ks []K
- for k := range m {
- ks = append(ks, k)
- }
- return ks
-}
-
-// ServeHTTP dispatches the request to the handler whose
-// pattern most closely matches the request URL.
-func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
- if r.RequestURI == "*" {
- if r.ProtoAtLeast(1, 1) {
- w.Header().Set("Connection", "close")
- }
- w.WriteHeader(StatusBadRequest)
- return
- }
- var h Handler
- if use121 {
- h, _ = mux.mux121.findHandler(r)
- } else {
- h, _, r.pat, r.matches = mux.findHandler(r)
- }
- h.ServeHTTP(w, r)
-}
-
-// The four functions below all call ServeMux.register so that callerLocation
-// always refers to user code.
-
-// Handle registers the handler for the given pattern.
-// If the given pattern conflicts, with one that is already registered, Handle
-// panics.
-func (mux *ServeMux) Handle(pattern string, handler Handler) {
- if use121 {
- mux.mux121.handle(pattern, handler)
- } else {
- mux.register(pattern, handler)
- }
-}
-
-// HandleFunc registers the handler function for the given pattern.
-// If the given pattern conflicts, with one that is already registered, HandleFunc
-// panics.
-func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
- if use121 {
- mux.mux121.handleFunc(pattern, handler)
- } else {
- mux.register(pattern, HandlerFunc(handler))
- }
-}
-
-// Handle registers the handler for the given pattern in [DefaultServeMux].
-// The documentation for [ServeMux] explains how patterns are matched.
-func Handle(pattern string, handler Handler) {
- if use121 {
- DefaultServeMux.mux121.handle(pattern, handler)
- } else {
- DefaultServeMux.register(pattern, handler)
- }
-}
-
-// HandleFunc registers the handler function for the given pattern in [DefaultServeMux].
-// The documentation for [ServeMux] explains how patterns are matched.
-func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
- if use121 {
- DefaultServeMux.mux121.handleFunc(pattern, handler)
- } else {
- DefaultServeMux.register(pattern, HandlerFunc(handler))
- }
-}
-
-func (mux *ServeMux) register(pattern string, handler Handler) {
- if err := mux.registerErr(pattern, handler); err != nil {
- panic(err)
- }
-}
-
-func (mux *ServeMux) registerErr(patstr string, handler Handler) error {
- if patstr == "" {
- return errors.New("http: invalid pattern")
- }
- if handler == nil {
- return errors.New("http: nil handler")
- }
- if f, ok := handler.(HandlerFunc); ok && f == nil {
- return errors.New("http: nil handler")
- }
-
- pat, err := parsePattern(patstr)
- if err != nil {
- return fmt.Errorf("parsing %q: %w", patstr, err)
- }
-
- // Get the caller's location, for better conflict error messages.
- // Skip register and whatever calls it.
- _, file, line, ok := runtime.Caller(3)
- if !ok {
- pat.loc = "unknown location"
- } else {
- pat.loc = fmt.Sprintf("%s:%d", file, line)
- }
-
- mux.mu.Lock()
- defer mux.mu.Unlock()
- // Check for conflict.
- if err := mux.index.possiblyConflictingPatterns(pat, func(pat2 *pattern) error {
- if pat.conflictsWith(pat2) {
- d := describeConflict(pat, pat2)
- return fmt.Errorf("pattern %q (registered at %s) conflicts with pattern %q (registered at %s):\n%s",
- pat, pat.loc, pat2, pat2.loc, d)
- }
- return nil
- }); err != nil {
- return err
- }
- mux.tree.addPattern(pat, handler)
- mux.index.addPattern(pat)
- mux.patterns = append(mux.patterns, pat)
- return nil
-}
-
-// Serve accepts incoming HTTP connections on the listener l,
-// creating a new service goroutine for each. The service goroutines
-// read requests and then call handler to reply to them.
-//
-// The handler is typically nil, in which case [DefaultServeMux] is used.
-//
-// HTTP/2 support is only enabled if the Listener returns [*tls.Conn]
-// connections and they were configured with "h2" in the TLS
-// Config.NextProtos.
-//
-// Serve always returns a non-nil error.
-func Serve(l net.Listener, handler Handler) error {
- srv := &Server{Handler: handler}
- return srv.Serve(l)
-}
-
-// ServeTLS accepts incoming HTTPS connections on the listener l,
-// creating a new service goroutine for each. The service goroutines
-// read requests and then call handler to reply to them.
-//
-// The handler is typically nil, in which case [DefaultServeMux] is used.
-//
-// Additionally, files containing a certificate and matching private key
-// for the server must be provided. If the certificate is signed by a
-// certificate authority, the certFile should be the concatenation
-// of the server's certificate, any intermediates, and the CA's certificate.
-//
-// ServeTLS always returns a non-nil error.
-func ServeTLS(l net.Listener, handler Handler, certFile, keyFile string) error {
- srv := &Server{Handler: handler}
- return srv.ServeTLS(l, certFile, keyFile)
-}
-
-// A Server defines parameters for running an HTTP server.
-// The zero value for Server is a valid configuration.
-type Server struct {
- // Addr optionally specifies the TCP address for the server to listen on,
- // in the form "host:port". If empty, ":http" (port 80) is used.
- // The service names are defined in RFC 6335 and assigned by IANA.
- // See net.Dial for details of the address format.
- Addr string
-
- Handler Handler // handler to invoke, http.DefaultServeMux if nil
-
- // DisableGeneralOptionsHandler, if true, passes "OPTIONS *" requests to the Handler,
- // otherwise responds with 200 OK and Content-Length: 0.
- DisableGeneralOptionsHandler bool
-
- // TLSConfig optionally provides a TLS configuration for use
- // by ServeTLS and ListenAndServeTLS. Note that this value is
- // cloned by ServeTLS and ListenAndServeTLS, so it's not
- // possible to modify the configuration with methods like
- // tls.Config.SetSessionTicketKeys. To use
- // SetSessionTicketKeys, use Server.Serve with a TLS Listener
- // instead.
- TLSConfig *tls.Config
-
- // ReadTimeout is the maximum duration for reading the entire
- // request, including the body. A zero or negative value means
- // there will be no timeout.
- //
- // Because ReadTimeout does not let Handlers make per-request
- // decisions on each request body's acceptable deadline or
- // upload rate, most users will prefer to use
- // ReadHeaderTimeout. It is valid to use them both.
- ReadTimeout time.Duration
-
- // ReadHeaderTimeout is the amount of time allowed to read
- // request headers. The connection's read deadline is reset
- // after reading the headers and the Handler can decide what
- // is considered too slow for the body. If ReadHeaderTimeout
- // is zero, the value of ReadTimeout is used. If both are
- // zero, there is no timeout.
- ReadHeaderTimeout time.Duration
-
- // WriteTimeout is the maximum duration before timing out
- // writes of the response. It is reset whenever a new
- // request's header is read. Like ReadTimeout, it does not
- // let Handlers make decisions on a per-request basis.
- // A zero or negative value means there will be no timeout.
- WriteTimeout time.Duration
-
- // IdleTimeout is the maximum amount of time to wait for the
- // next request when keep-alives are enabled. If IdleTimeout
- // is zero, the value of ReadTimeout is used. If both are
- // zero, there is no timeout.
- IdleTimeout time.Duration
-
- // MaxHeaderBytes controls the maximum number of bytes the
- // server will read parsing the request header's keys and
- // values, including the request line. It does not limit the
- // size of the request body.
- // If zero, DefaultMaxHeaderBytes is used.
- MaxHeaderBytes int
-
- // TLSNextProto optionally specifies a function to take over
- // ownership of the provided TLS connection when an ALPN
- // protocol upgrade has occurred. The map key is the protocol
- // name negotiated. The Handler argument should be used to
- // handle HTTP requests and will initialize the Request's TLS
- // and RemoteAddr if not already set. The connection is
- // automatically closed when the function returns.
- // If TLSNextProto is not nil, HTTP/2 support is not enabled
- // automatically.
- TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
-
- // ConnState specifies an optional callback function that is
- // called when a client connection changes state. See the
- // ConnState type and associated constants for details.
- ConnState func(net.Conn, ConnState)
-
- // ErrorLog specifies an optional logger for errors accepting
- // connections, unexpected behavior from handlers, and
- // underlying FileSystem errors.
- // If nil, logging is done via the log package's standard logger.
- ErrorLog *log.Logger
-
- // BaseContext optionally specifies a function that returns
- // the base context for incoming requests on this server.
- // The provided Listener is the specific Listener that's
- // about to start accepting requests.
- // If BaseContext is nil, the default is context.Background().
- // If non-nil, it must return a non-nil context.
- BaseContext func(net.Listener) context.Context
-
- // ConnContext optionally specifies a function that modifies
- // the context used for a new connection c. The provided ctx
- // is derived from the base context and has a ServerContextKey
- // value.
- ConnContext func(ctx context.Context, c net.Conn) context.Context
-
- inShutdown atomic.Bool // true when server is in shutdown
-
- disableKeepAlives atomic.Bool
- nextProtoOnce sync.Once // guards setupHTTP2_* init
- nextProtoErr error // result of http2.ConfigureServer if used
-
- mu sync.Mutex
- listeners map[*net.Listener]struct{}
- activeConn map[*conn]struct{}
- onShutdown []func()
-
- listenerGroup sync.WaitGroup
-}
-
-// Close immediately closes all active net.Listeners and any
-// connections in state [StateNew], [StateActive], or [StateIdle]. For a
-// graceful shutdown, use [Server.Shutdown].
-//
-// Close does not attempt to close (and does not even know about)
-// any hijacked connections, such as WebSockets.
-//
-// Close returns any error returned from closing the [Server]'s
-// underlying Listener(s).
-func (srv *Server) Close() error {
- srv.inShutdown.Store(true)
- srv.mu.Lock()
- defer srv.mu.Unlock()
- err := srv.closeListenersLocked()
-
- // Unlock srv.mu while waiting for listenerGroup.
- // The group Add and Done calls are made with srv.mu held,
- // to avoid adding a new listener in the window between
- // us setting inShutdown above and waiting here.
- srv.mu.Unlock()
- srv.listenerGroup.Wait()
- srv.mu.Lock()
-
- for c := range srv.activeConn {
- c.rwc.Close()
- delete(srv.activeConn, c)
- }
- return err
-}
-
-// shutdownPollIntervalMax is the max polling interval when checking
-// quiescence during Server.Shutdown. Polling starts with a small
-// interval and backs off to the max.
-// Ideally we could find a solution that doesn't involve polling,
-// but which also doesn't have a high runtime cost (and doesn't
-// involve any contentious mutexes), but that is left as an
-// exercise for the reader.
-const shutdownPollIntervalMax = 500 * time.Millisecond
-
-// Shutdown gracefully shuts down the server without interrupting any
-// active connections. Shutdown works by first closing all open
-// listeners, then closing all idle connections, and then waiting
-// indefinitely for connections to return to idle and then shut down.
-// If the provided context expires before the shutdown is complete,
-// Shutdown returns the context's error, otherwise it returns any
-// error returned from closing the [Server]'s underlying Listener(s).
-//
-// When Shutdown is called, [Serve], [ListenAndServe], and
-// [ListenAndServeTLS] immediately return [ErrServerClosed]. Make sure the
-// program doesn't exit and waits instead for Shutdown to return.
-//
-// Shutdown does not attempt to close nor wait for hijacked
-// connections such as WebSockets. The caller of Shutdown should
-// separately notify such long-lived connections of shutdown and wait
-// for them to close, if desired. See [Server.RegisterOnShutdown] for a way to
-// register shutdown notification functions.
-//
-// Once Shutdown has been called on a server, it may not be reused;
-// future calls to methods such as Serve will return ErrServerClosed.
-func (srv *Server) Shutdown(ctx context.Context) error {
- srv.inShutdown.Store(true)
-
- srv.mu.Lock()
- lnerr := srv.closeListenersLocked()
- for _, f := range srv.onShutdown {
- go f()
- }
- srv.mu.Unlock()
- srv.listenerGroup.Wait()
-
- pollIntervalBase := time.Millisecond
- nextPollInterval := func() time.Duration {
- // Add 10% jitter.
- interval := pollIntervalBase + time.Duration(rand.Intn(int(pollIntervalBase/10)))
- // Double and clamp for next time.
- pollIntervalBase *= 2
- if pollIntervalBase > shutdownPollIntervalMax {
- pollIntervalBase = shutdownPollIntervalMax
- }
- return interval
- }
-
- timer := time.NewTimer(nextPollInterval())
- defer timer.Stop()
- for {
- if srv.closeIdleConns() {
- return lnerr
- }
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-timer.C:
- timer.Reset(nextPollInterval())
- }
- }
-}
-
-// RegisterOnShutdown registers a function to call on [Server.Shutdown].
-// This can be used to gracefully shutdown connections that have
-// undergone ALPN protocol upgrade or that have been hijacked.
-// This function should start protocol-specific graceful shutdown,
-// but should not wait for shutdown to complete.
-func (srv *Server) RegisterOnShutdown(f func()) {
- srv.mu.Lock()
- srv.onShutdown = append(srv.onShutdown, f)
- srv.mu.Unlock()
-}
-
-// closeIdleConns closes all idle connections and reports whether the
-// server is quiescent.
-func (s *Server) closeIdleConns() bool {
- s.mu.Lock()
- defer s.mu.Unlock()
- quiescent := true
- for c := range s.activeConn {
- st, unixSec := c.getState()
- // Issue 22682: treat StateNew connections as if
- // they're idle if we haven't read the first request's
- // header in over 5 seconds.
- if st == StateNew && unixSec < time.Now().Unix()-5 {
- st = StateIdle
- }
- if st != StateIdle || unixSec == 0 {
- // Assume unixSec == 0 means it's a very new
- // connection, without state set yet.
- quiescent = false
- continue
- }
- c.rwc.Close()
- delete(s.activeConn, c)
- }
- return quiescent
-}
-
-func (s *Server) closeListenersLocked() error {
- var err error
- for ln := range s.listeners {
- if cerr := (*ln).Close(); cerr != nil && err == nil {
- err = cerr
- }
- }
- return err
-}
-
-// A ConnState represents the state of a client connection to a server.
-// It's used by the optional [Server.ConnState] hook.
-type ConnState int
-
-const (
- // StateNew represents a new connection that is expected to
- // send a request immediately. Connections begin at this
- // state and then transition to either StateActive or
- // StateClosed.
- StateNew ConnState = iota
-
- // StateActive represents a connection that has read 1 or more
- // bytes of a request. The Server.ConnState hook for
- // StateActive fires before the request has entered a handler
- // and doesn't fire again until the request has been
- // handled. After the request is handled, the state
- // transitions to StateClosed, StateHijacked, or StateIdle.
- // For HTTP/2, StateActive fires on the transition from zero
- // to one active request, and only transitions away once all
- // active requests are complete. That means that ConnState
- // cannot be used to do per-request work; ConnState only notes
- // the overall state of the connection.
- StateActive
-
- // StateIdle represents a connection that has finished
- // handling a request and is in the keep-alive state, waiting
- // for a new request. Connections transition from StateIdle
- // to either StateActive or StateClosed.
- StateIdle
-
- // StateHijacked represents a hijacked connection.
- // This is a terminal state. It does not transition to StateClosed.
- StateHijacked
-
- // StateClosed represents a closed connection.
- // This is a terminal state. Hijacked connections do not
- // transition to StateClosed.
- StateClosed
-)
-
-var stateName = map[ConnState]string{
- StateNew: "new",
- StateActive: "active",
- StateIdle: "idle",
- StateHijacked: "hijacked",
- StateClosed: "closed",
-}
-
-func (c ConnState) String() string {
- return stateName[c]
-}
-
-// serverHandler delegates to either the server's Handler or
-// DefaultServeMux and also handles "OPTIONS *" requests.
-type serverHandler struct {
- srv *Server
-}
-
-func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
- handler := sh.srv.Handler
- if handler == nil {
- handler = DefaultServeMux
- }
- if !sh.srv.DisableGeneralOptionsHandler && req.RequestURI == "*" && req.Method == "OPTIONS" {
- handler = globalOptionsHandler{}
- }
-
- handler.ServeHTTP(rw, req)
-}
-
-// AllowQuerySemicolons returns a handler that serves requests by converting any
-// unescaped semicolons in the URL query to ampersands, and invoking the handler h.
-//
-// This restores the pre-Go 1.17 behavior of splitting query parameters on both
-// semicolons and ampersands. (See golang.org/issue/25192). Note that this
-// behavior doesn't match that of many proxies, and the mismatch can lead to
-// security issues.
-//
-// AllowQuerySemicolons should be invoked before [Request.ParseForm] is called.
-func AllowQuerySemicolons(h Handler) Handler {
- return HandlerFunc(func(w ResponseWriter, r *Request) {
- if strings.Contains(r.URL.RawQuery, ";") {
- r2 := new(Request)
- *r2 = *r
- r2.URL = new(url.URL)
- *r2.URL = *r.URL
- r2.URL.RawQuery = strings.ReplaceAll(r.URL.RawQuery, ";", "&")
- h.ServeHTTP(w, r2)
- } else {
- h.ServeHTTP(w, r)
- }
- })
-}
-
-// ListenAndServe listens on the TCP network address srv.Addr and then
-// calls [Serve] to handle requests on incoming connections.
-// Accepted connections are configured to enable TCP keep-alives.
-//
-// If srv.Addr is blank, ":http" is used.
-//
-// ListenAndServe always returns a non-nil error. After [Server.Shutdown] or [Server.Close],
-// the returned error is [ErrServerClosed].
-func (srv *Server) ListenAndServe() error {
- if srv.shuttingDown() {
- return ErrServerClosed
- }
- addr := srv.Addr
- if addr == "" {
- addr = ":http"
- }
- ln, err := net.Listen("tcp", addr)
- if err != nil {
- return err
- }
- return srv.Serve(ln)
-}
-
-var testHookServerServe func(*Server, net.Listener) // used if non-nil
-
-// shouldConfigureHTTP2ForServe reports whether Server.Serve should configure
-// automatic HTTP/2. (which sets up the srv.TLSNextProto map)
-func (srv *Server) shouldConfigureHTTP2ForServe() bool {
- if srv.TLSConfig == nil {
- // Compatibility with Go 1.6:
- // If there's no TLSConfig, it's possible that the user just
- // didn't set it on the http.Server, but did pass it to
- // tls.NewListener and passed that listener to Serve.
- // So we should configure HTTP/2 (to set up srv.TLSNextProto)
- // in case the listener returns an "h2" *tls.Conn.
- return true
- }
- // The user specified a TLSConfig on their http.Server.
- // In this, case, only configure HTTP/2 if their tls.Config
- // explicitly mentions "h2". Otherwise http2.ConfigureServer
- // would modify the tls.Config to add it, but they probably already
- // passed this tls.Config to tls.NewListener. And if they did,
- // it's too late anyway to fix it. It would only be potentially racy.
- // See Issue 15908.
- return strSliceContains(srv.TLSConfig.NextProtos, http2NextProtoTLS)
-}
-
-// ErrServerClosed is returned by the [Server.Serve], [ServeTLS], [ListenAndServe],
-// and [ListenAndServeTLS] methods after a call to [Server.Shutdown] or [Server.Close].
-var ErrServerClosed = errors.New("http: Server closed")
-
-// Serve accepts incoming connections on the Listener l, creating a
-// new service goroutine for each. The service goroutines read requests and
-// then call srv.Handler to reply to them.
-//
-// HTTP/2 support is only enabled if the Listener returns [*tls.Conn]
-// connections and they were configured with "h2" in the TLS
-// Config.NextProtos.
-//
-// Serve always returns a non-nil error and closes l.
-// After [Server.Shutdown] or [Server.Close], the returned error is [ErrServerClosed].
-func (srv *Server) Serve(l net.Listener) error {
- if fn := testHookServerServe; fn != nil {
- fn(srv, l) // call hook with unwrapped listener
- }
-
- origListener := l
- l = &onceCloseListener{Listener: l}
- defer l.Close()
-
- if err := srv.setupHTTP2_Serve(); err != nil {
- return err
- }
-
- if !srv.trackListener(&l, true) {
- return ErrServerClosed
- }
- defer srv.trackListener(&l, false)
-
- baseCtx := context.Background()
- if srv.BaseContext != nil {
- baseCtx = srv.BaseContext(origListener)
- if baseCtx == nil {
- panic("BaseContext returned a nil context")
- }
- }
-
- var tempDelay time.Duration // how long to sleep on accept failure
-
- ctx := context.WithValue(baseCtx, ServerContextKey, srv)
- for {
- rw, err := l.Accept()
- if err != nil {
- if srv.shuttingDown() {
- return ErrServerClosed
- }
- if ne, ok := err.(net.Error); ok && ne.Temporary() {
- if tempDelay == 0 {
- tempDelay = 5 * time.Millisecond
- } else {
- tempDelay *= 2
- }
- if max := 1 * time.Second; tempDelay > max {
- tempDelay = max
- }
- srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
- time.Sleep(tempDelay)
- continue
- }
- return err
- }
- connCtx := ctx
- if cc := srv.ConnContext; cc != nil {
- connCtx = cc(connCtx, rw)
- if connCtx == nil {
- panic("ConnContext returned nil")
- }
- }
- tempDelay = 0
- c := srv.newConn(rw)
- c.setState(c.rwc, StateNew, runHooks) // before Serve can return
- go c.serve(connCtx)
- }
-}
-
-// ServeTLS accepts incoming connections on the Listener l, creating a
-// new service goroutine for each. The service goroutines perform TLS
-// setup and then read requests, calling srv.Handler to reply to them.
-//
-// Files containing a certificate and matching private key for the
-// server must be provided if neither the [Server]'s
-// TLSConfig.Certificates nor TLSConfig.GetCertificate are populated.
-// If the certificate is signed by a certificate authority, the
-// certFile should be the concatenation of the server's certificate,
-// any intermediates, and the CA's certificate.
-//
-// ServeTLS always returns a non-nil error. After [Server.Shutdown] or [Server.Close], the
-// returned error is [ErrServerClosed].
-func (srv *Server) ServeTLS(l net.Listener, certFile, keyFile string) error {
- // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig
- // before we clone it and create the TLS Listener.
- if err := srv.setupHTTP2_ServeTLS(); err != nil {
- return err
- }
-
- config := cloneTLSConfig(srv.TLSConfig)
- if !strSliceContains(config.NextProtos, "http/1.1") {
- config.NextProtos = append(config.NextProtos, "http/1.1")
- }
-
- configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil
- if !configHasCert || certFile != "" || keyFile != "" {
- var err error
- config.Certificates = make([]tls.Certificate, 1)
- config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
- if err != nil {
- return err
- }
- }
-
- tlsListener := tls.NewListener(l, config)
- return srv.Serve(tlsListener)
-}
-
-// trackListener adds or removes a net.Listener to the set of tracked
-// listeners.
-//
-// We store a pointer to interface in the map set, in case the
-// net.Listener is not comparable. This is safe because we only call
-// trackListener via Serve and can track+defer untrack the same
-// pointer to local variable there. We never need to compare a
-// Listener from another caller.
-//
-// It reports whether the server is still up (not Shutdown or Closed).
-func (s *Server) trackListener(ln *net.Listener, add bool) bool {
- s.mu.Lock()
- defer s.mu.Unlock()
- if s.listeners == nil {
- s.listeners = make(map[*net.Listener]struct{})
- }
- if add {
- if s.shuttingDown() {
- return false
- }
- s.listeners[ln] = struct{}{}
- s.listenerGroup.Add(1)
- } else {
- delete(s.listeners, ln)
- s.listenerGroup.Done()
- }
- return true
-}
-
-func (s *Server) trackConn(c *conn, add bool) {
- s.mu.Lock()
- defer s.mu.Unlock()
- if s.activeConn == nil {
- s.activeConn = make(map[*conn]struct{})
- }
- if add {
- s.activeConn[c] = struct{}{}
- } else {
- delete(s.activeConn, c)
- }
-}
-
-func (s *Server) idleTimeout() time.Duration {
- if s.IdleTimeout != 0 {
- return s.IdleTimeout
- }
- return s.ReadTimeout
-}
-
-func (s *Server) readHeaderTimeout() time.Duration {
- if s.ReadHeaderTimeout != 0 {
- return s.ReadHeaderTimeout
- }
- return s.ReadTimeout
-}
-
-func (s *Server) doKeepAlives() bool {
- return !s.disableKeepAlives.Load() && !s.shuttingDown()
-}
-
-func (s *Server) shuttingDown() bool {
- return s.inShutdown.Load()
-}
-
-// SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled.
-// By default, keep-alives are always enabled. Only very
-// resource-constrained environments or servers in the process of
-// shutting down should disable them.
-func (srv *Server) SetKeepAlivesEnabled(v bool) {
- if v {
- srv.disableKeepAlives.Store(false)
- return
- }
- srv.disableKeepAlives.Store(true)
-
- // Close idle HTTP/1 conns:
- srv.closeIdleConns()
-
- // TODO: Issue 26303: close HTTP/2 conns as soon as they become idle.
-}
-
-func (s *Server) logf(format string, args ...any) {
- if s.ErrorLog != nil {
- s.ErrorLog.Printf(format, args...)
- } else {
- log.Printf(format, args...)
- }
-}
-
-// logf prints to the ErrorLog of the *Server associated with request r
-// via ServerContextKey. If there's no associated server, or if ErrorLog
-// is nil, logging is done via the log package's standard logger.
-func logf(r *Request, format string, args ...any) {
- s, _ := r.Context().Value(ServerContextKey).(*Server)
- if s != nil && s.ErrorLog != nil {
- s.ErrorLog.Printf(format, args...)
- } else {
- log.Printf(format, args...)
- }
-}
-
-// ListenAndServe listens on the TCP network address addr and then calls
-// [Serve] with handler to handle requests on incoming connections.
-// Accepted connections are configured to enable TCP keep-alives.
-//
-// The handler is typically nil, in which case [DefaultServeMux] is used.
-//
-// ListenAndServe always returns a non-nil error.
-func ListenAndServe(addr string, handler Handler) error {
- server := &Server{Addr: addr, Handler: handler}
- return server.ListenAndServe()
-}
-
-// ListenAndServeTLS acts identically to [ListenAndServe], except that it
-// expects HTTPS connections. Additionally, files containing a certificate and
-// matching private key for the server must be provided. If the certificate
-// is signed by a certificate authority, the certFile should be the concatenation
-// of the server's certificate, any intermediates, and the CA's certificate.
-func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
- server := &Server{Addr: addr, Handler: handler}
- return server.ListenAndServeTLS(certFile, keyFile)
-}
-
-// ListenAndServeTLS listens on the TCP network address srv.Addr and
-// then calls [ServeTLS] to handle requests on incoming TLS connections.
-// Accepted connections are configured to enable TCP keep-alives.
-//
-// Filenames containing a certificate and matching private key for the
-// server must be provided if neither the [Server]'s TLSConfig.Certificates
-// nor TLSConfig.GetCertificate are populated. If the certificate is
-// signed by a certificate authority, the certFile should be the
-// concatenation of the server's certificate, any intermediates, and
-// the CA's certificate.
-//
-// If srv.Addr is blank, ":https" is used.
-//
-// ListenAndServeTLS always returns a non-nil error. After [Server.Shutdown] or
-// [Server.Close], the returned error is [ErrServerClosed].
-func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
- if srv.shuttingDown() {
- return ErrServerClosed
- }
- addr := srv.Addr
- if addr == "" {
- addr = ":https"
- }
-
- ln, err := net.Listen("tcp", addr)
- if err != nil {
- return err
- }
-
- defer ln.Close()
-
- return srv.ServeTLS(ln, certFile, keyFile)
-}
-
-// setupHTTP2_ServeTLS conditionally configures HTTP/2 on
-// srv and reports whether there was an error setting it up. If it is
-// not configured for policy reasons, nil is returned.
-func (srv *Server) setupHTTP2_ServeTLS() error {
- srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults)
- return srv.nextProtoErr
-}
-
-// setupHTTP2_Serve is called from (*Server).Serve and conditionally
-// configures HTTP/2 on srv using a more conservative policy than
-// setupHTTP2_ServeTLS because Serve is called after tls.Listen,
-// and may be called concurrently. See shouldConfigureHTTP2ForServe.
-//
-// The tests named TestTransportAutomaticHTTP2* and
-// TestConcurrentServerServe in server_test.go demonstrate some
-// of the supported use cases and motivations.
-func (srv *Server) setupHTTP2_Serve() error {
- srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults_Serve)
- return srv.nextProtoErr
-}
-
-func (srv *Server) onceSetNextProtoDefaults_Serve() {
- if srv.shouldConfigureHTTP2ForServe() {
- srv.onceSetNextProtoDefaults()
- }
-}
-
-var http2server = godebug.New("http2server")
-
-// onceSetNextProtoDefaults configures HTTP/2, if the user hasn't
-// configured otherwise. (by setting srv.TLSNextProto non-nil)
-// It must only be called via srv.nextProtoOnce (use srv.setupHTTP2_*).
-func (srv *Server) onceSetNextProtoDefaults() {
- if omitBundledHTTP2 {
- return
- }
- if http2server.Value() == "0" {
- http2server.IncNonDefault()
- return
- }
- // Enable HTTP/2 by default if the user hasn't otherwise
- // configured their TLSNextProto map.
- if srv.TLSNextProto == nil {
- conf := &http2Server{
- NewWriteScheduler: func() http2WriteScheduler { return http2NewPriorityWriteScheduler(nil) },
- }
- srv.nextProtoErr = http2ConfigureServer(srv, conf)
- }
-}
-
-// TimeoutHandler returns a [Handler] that runs h with the given time limit.
-//
-// The new Handler calls h.ServeHTTP to handle each request, but if a
-// call runs for longer than its time limit, the handler responds with
-// a 503 Service Unavailable error and the given message in its body.
-// (If msg is empty, a suitable default message will be sent.)
-// After such a timeout, writes by h to its [ResponseWriter] will return
-// [ErrHandlerTimeout].
-//
-// TimeoutHandler supports the [Pusher] interface but does not support
-// the [Hijacker] or [Flusher] interfaces.
-func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
- return &timeoutHandler{
- handler: h,
- body: msg,
- dt: dt,
- }
-}
-
-// ErrHandlerTimeout is returned on [ResponseWriter] Write calls
-// in handlers which have timed out.
-var ErrHandlerTimeout = errors.New("http: Handler timeout")
-
-type timeoutHandler struct {
- handler Handler
- body string
- dt time.Duration
-
- // When set, no context will be created and this context will
- // be used instead.
- testContext context.Context
-}
-
-func (h *timeoutHandler) errorBody() string {
- if h.body != "" {
- return h.body
- }
- return "TimeoutTimeout
"
-}
-
-func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
- ctx := h.testContext
- if ctx == nil {
- var cancelCtx context.CancelFunc
- ctx, cancelCtx = context.WithTimeout(r.Context(), h.dt)
- defer cancelCtx()
- }
- r = r.WithContext(ctx)
- done := make(chan struct{})
- tw := &timeoutWriter{
- w: w,
- h: make(Header),
- req: r,
- }
- panicChan := make(chan any, 1)
- go func() {
- defer func() {
- if p := recover(); p != nil {
- panicChan <- p
- }
- }()
- h.handler.ServeHTTP(tw, r)
- close(done)
- }()
- select {
- case p := <-panicChan:
- panic(p)
- case <-done:
- tw.mu.Lock()
- defer tw.mu.Unlock()
- dst := w.Header()
- for k, vv := range tw.h {
- dst[k] = vv
- }
- if !tw.wroteHeader {
- tw.code = StatusOK
- }
- w.WriteHeader(tw.code)
- w.Write(tw.wbuf.Bytes())
- case <-ctx.Done():
- tw.mu.Lock()
- defer tw.mu.Unlock()
- switch err := ctx.Err(); err {
- case context.DeadlineExceeded:
- w.WriteHeader(StatusServiceUnavailable)
- io.WriteString(w, h.errorBody())
- tw.err = ErrHandlerTimeout
- default:
- w.WriteHeader(StatusServiceUnavailable)
- tw.err = err
- }
- }
-}
-
-type timeoutWriter struct {
- w ResponseWriter
- h Header
- wbuf bytes.Buffer
- req *Request
-
- mu sync.Mutex
- err error
- wroteHeader bool
- code int
-}
-
-var _ Pusher = (*timeoutWriter)(nil)
-
-// Push implements the [Pusher] interface.
-func (tw *timeoutWriter) Push(target string, opts *PushOptions) error {
- if pusher, ok := tw.w.(Pusher); ok {
- return pusher.Push(target, opts)
- }
- return ErrNotSupported
-}
-
-func (tw *timeoutWriter) Header() Header { return tw.h }
-
-func (tw *timeoutWriter) Write(p []byte) (int, error) {
- tw.mu.Lock()
- defer tw.mu.Unlock()
- if tw.err != nil {
- return 0, tw.err
- }
- if !tw.wroteHeader {
- tw.writeHeaderLocked(StatusOK)
- }
- return tw.wbuf.Write(p)
-}
-
-func (tw *timeoutWriter) writeHeaderLocked(code int) {
- checkWriteHeaderCode(code)
-
- switch {
- case tw.err != nil:
- return
- case tw.wroteHeader:
- if tw.req != nil {
- caller := relevantCaller()
- logf(tw.req, "http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
- }
- default:
- tw.wroteHeader = true
- tw.code = code
- }
-}
-
-func (tw *timeoutWriter) WriteHeader(code int) {
- tw.mu.Lock()
- defer tw.mu.Unlock()
- tw.writeHeaderLocked(code)
-}
-
-// onceCloseListener wraps a net.Listener, protecting it from
-// multiple Close calls.
-type onceCloseListener struct {
- net.Listener
- once sync.Once
- closeErr error
-}
-
-func (oc *onceCloseListener) Close() error {
- oc.once.Do(oc.close)
- return oc.closeErr
-}
-
-func (oc *onceCloseListener) close() { oc.closeErr = oc.Listener.Close() }
-
-// globalOptionsHandler responds to "OPTIONS *" requests.
-type globalOptionsHandler struct{}
-
-func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
- w.Header().Set("Content-Length", "0")
- if r.ContentLength != 0 {
- // Read up to 4KB of OPTIONS body (as mentioned in the
- // spec as being reserved for future use), but anything
- // over that is considered a waste of server resources
- // (or an attack) and we abort and close the connection,
- // courtesy of MaxBytesReader's EOF behavior.
- mb := MaxBytesReader(w, r.Body, 4<<10)
- io.Copy(io.Discard, mb)
- }
-}
-
-// initALPNRequest is an HTTP handler that initializes certain
-// uninitialized fields in its *Request. Such partially-initialized
-// Requests come from ALPN protocol handlers.
-type initALPNRequest struct {
- ctx context.Context
- c *tls.Conn
- h serverHandler
-}
-
-// BaseContext is an exported but unadvertised [http.Handler] method
-// recognized by x/net/http2 to pass down a context; the TLSNextProto
-// API predates context support so we shoehorn through the only
-// interface we have available.
-func (h initALPNRequest) BaseContext() context.Context { return h.ctx }
-
-func (h initALPNRequest) ServeHTTP(rw ResponseWriter, req *Request) {
- if req.TLS == nil {
- req.TLS = &tls.ConnectionState{}
- *req.TLS = h.c.ConnectionState()
- }
- if req.Body == nil {
- req.Body = NoBody
- }
- if req.RemoteAddr == "" {
- req.RemoteAddr = h.c.RemoteAddr().String()
- }
- h.h.ServeHTTP(rw, req)
-}
-
-// loggingConn is used for debugging.
-type loggingConn struct {
- name string
- net.Conn
-}
-
-var (
- uniqNameMu sync.Mutex
- uniqNameNext = make(map[string]int)
-)
-
-func newLoggingConn(baseName string, c net.Conn) net.Conn {
- uniqNameMu.Lock()
- defer uniqNameMu.Unlock()
- uniqNameNext[baseName]++
- return &loggingConn{
- name: fmt.Sprintf("%s-%d", baseName, uniqNameNext[baseName]),
- Conn: c,
- }
-}
-
-func (c *loggingConn) Write(p []byte) (n int, err error) {
- log.Printf("%s.Write(%d) = ....", c.name, len(p))
- n, err = c.Conn.Write(p)
- log.Printf("%s.Write(%d) = %d, %v", c.name, len(p), n, err)
- return
-}
-
-func (c *loggingConn) Read(p []byte) (n int, err error) {
- log.Printf("%s.Read(%d) = ....", c.name, len(p))
- n, err = c.Conn.Read(p)
- log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err)
- return
-}
-
-func (c *loggingConn) Close() (err error) {
- log.Printf("%s.Close() = ...", c.name)
- err = c.Conn.Close()
- log.Printf("%s.Close() = %v", c.name, err)
- return
-}
-
-// checkConnErrorWriter writes to c.rwc and records any write errors to c.werr.
-// It only contains one field (and a pointer field at that), so it
-// fits in an interface value without an extra allocation.
-type checkConnErrorWriter struct {
- c *conn
-}
-
-func (w checkConnErrorWriter) Write(p []byte) (n int, err error) {
- n, err = w.c.rwc.Write(p)
- if err != nil && w.c.werr == nil {
- w.c.werr = err
- w.c.cancelCtx()
- }
- return
-}
-
-func numLeadingCRorLF(v []byte) (n int) {
- for _, b := range v {
- if b == '\r' || b == '\n' {
- n++
- continue
- }
- break
- }
- return
-}
-
-func strSliceContains(ss []string, s string) bool {
- for _, v := range ss {
- if v == s {
- return true
- }
- }
- return false
-}
-
-// tlsRecordHeaderLooksLikeHTTP reports whether a TLS record header
-// looks like it might've been a misdirected plaintext HTTP request.
-func tlsRecordHeaderLooksLikeHTTP(hdr [5]byte) bool {
- switch string(hdr[:]) {
- case "GET /", "HEAD ", "POST ", "PUT /", "OPTIO":
- return true
- }
- return false
-}
-
-// MaxBytesHandler returns a [Handler] that runs h with its [ResponseWriter] and [Request.Body] wrapped by a MaxBytesReader.
-func MaxBytesHandler(h Handler, n int64) Handler {
- return HandlerFunc(func(w ResponseWriter, r *Request) {
- r2 := *r
- r2.Body = MaxBytesReader(w, r.Body, n)
- h.ServeHTTP(w, &r2)
- })
-}
diff --git a/contrib/go/_std_1.22/src/net/internal/socktest/ya.make b/contrib/go/_std_1.22/src/net/internal/socktest/ya.make
deleted file mode 100644
index b83fe4f8d545..000000000000
--- a/contrib/go/_std_1.22/src/net/internal/socktest/ya.make
+++ /dev/null
@@ -1,27 +0,0 @@
-SUBSCRIBER(g:contrib)
-
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- switch.go
- switch_posix.go
- switch_unix.go
- sys_unix.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- switch.go
- switch_posix.go
- switch_unix.go
- sys_cloexec.go
- sys_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- switch.go
- switch_posix.go
- switch_windows.go
- sys_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/net/lookup.go b/contrib/go/_std_1.22/src/net/lookup.go
deleted file mode 100644
index 3ec266078609..000000000000
--- a/contrib/go/_std_1.22/src/net/lookup.go
+++ /dev/null
@@ -1,920 +0,0 @@
-// 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.
-
-package net
-
-import (
- "context"
- "errors"
- "internal/nettrace"
- "internal/singleflight"
- "net/netip"
- "sync"
-
- "golang.org/x/net/dns/dnsmessage"
-)
-
-// protocols contains minimal mappings between internet protocol
-// names and numbers for platforms that don't have a complete list of
-// protocol numbers.
-//
-// See https://www.iana.org/assignments/protocol-numbers
-//
-// On Unix, this map is augmented by readProtocols via lookupProtocol.
-var protocols = map[string]int{
- "icmp": 1,
- "igmp": 2,
- "tcp": 6,
- "udp": 17,
- "ipv6-icmp": 58,
-}
-
-// services contains minimal mappings between services names and port
-// numbers for platforms that don't have a complete list of port numbers.
-//
-// See https://www.iana.org/assignments/service-names-port-numbers
-//
-// On Unix, this map is augmented by readServices via goLookupPort.
-var services = map[string]map[string]int{
- "udp": {
- "domain": 53,
- },
- "tcp": {
- "ftp": 21,
- "ftps": 990,
- "gopher": 70, // ʕ◔ϖ◔ʔ
- "http": 80,
- "https": 443,
- "imap2": 143,
- "imap3": 220,
- "imaps": 993,
- "pop3": 110,
- "pop3s": 995,
- "smtp": 25,
- "submissions": 465,
- "ssh": 22,
- "telnet": 23,
- },
-}
-
-// dnsWaitGroup can be used by tests to wait for all DNS goroutines to
-// complete. This avoids races on the test hooks.
-var dnsWaitGroup sync.WaitGroup
-
-const maxProtoLength = len("RSVP-E2E-IGNORE") + 10 // with room to grow
-
-func lookupProtocolMap(name string) (int, error) {
- var lowerProtocol [maxProtoLength]byte
- n := copy(lowerProtocol[:], name)
- lowerASCIIBytes(lowerProtocol[:n])
- proto, found := protocols[string(lowerProtocol[:n])]
- if !found || n != len(name) {
- return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name}
- }
- return proto, nil
-}
-
-// maxPortBufSize is the longest reasonable name of a service
-// (non-numeric port).
-// Currently the longest known IANA-unregistered name is
-// "mobility-header", so we use that length, plus some slop in case
-// something longer is added in the future.
-const maxPortBufSize = len("mobility-header") + 10
-
-func lookupPortMap(network, service string) (port int, error error) {
- switch network {
- case "ip": // no hints
- if p, err := lookupPortMapWithNetwork("tcp", "ip", service); err == nil {
- return p, nil
- }
- return lookupPortMapWithNetwork("udp", "ip", service)
- case "tcp", "tcp4", "tcp6":
- return lookupPortMapWithNetwork("tcp", "tcp", service)
- case "udp", "udp4", "udp6":
- return lookupPortMapWithNetwork("udp", "udp", service)
- }
- return 0, &DNSError{Err: "unknown network", Name: network + "/" + service}
-}
-
-func lookupPortMapWithNetwork(network, errNetwork, service string) (port int, error error) {
- if m, ok := services[network]; ok {
- var lowerService [maxPortBufSize]byte
- n := copy(lowerService[:], service)
- lowerASCIIBytes(lowerService[:n])
- if port, ok := m[string(lowerService[:n])]; ok && n == len(service) {
- return port, nil
- }
- return 0, &DNSError{Err: "unknown port", Name: errNetwork + "/" + service, IsNotFound: true}
- }
- return 0, &DNSError{Err: "unknown network", Name: errNetwork + "/" + service}
-}
-
-// ipVersion returns the provided network's IP version: '4', '6' or 0
-// if network does not end in a '4' or '6' byte.
-func ipVersion(network string) byte {
- if network == "" {
- return 0
- }
- n := network[len(network)-1]
- if n != '4' && n != '6' {
- n = 0
- }
- return n
-}
-
-// DefaultResolver is the resolver used by the package-level Lookup
-// functions and by Dialers without a specified Resolver.
-var DefaultResolver = &Resolver{}
-
-// A Resolver looks up names and numbers.
-//
-// A nil *Resolver is equivalent to a zero Resolver.
-type Resolver struct {
- // PreferGo controls whether Go's built-in DNS resolver is preferred
- // on platforms where it's available. It is equivalent to setting
- // GODEBUG=netdns=go, but scoped to just this resolver.
- PreferGo bool
-
- // StrictErrors controls the behavior of temporary errors
- // (including timeout, socket errors, and SERVFAIL) when using
- // Go's built-in resolver. For a query composed of multiple
- // sub-queries (such as an A+AAAA address lookup, or walking the
- // DNS search list), this option causes such errors to abort the
- // whole query instead of returning a partial result. This is
- // not enabled by default because it may affect compatibility
- // with resolvers that process AAAA queries incorrectly.
- StrictErrors bool
-
- // Dial optionally specifies an alternate dialer for use by
- // Go's built-in DNS resolver to make TCP and UDP connections
- // to DNS services. The host in the address parameter will
- // always be a literal IP address and not a host name, and the
- // port in the address parameter will be a literal port number
- // and not a service name.
- // If the Conn returned is also a PacketConn, sent and received DNS
- // messages must adhere to RFC 1035 section 4.2.1, "UDP usage".
- // Otherwise, DNS messages transmitted over Conn must adhere
- // to RFC 7766 section 5, "Transport Protocol Selection".
- // If nil, the default dialer is used.
- Dial func(ctx context.Context, network, address string) (Conn, error)
-
- // lookupGroup merges LookupIPAddr calls together for lookups for the same
- // host. The lookupGroup key is the LookupIPAddr.host argument.
- // The return values are ([]IPAddr, error).
- lookupGroup singleflight.Group
-
- // TODO(bradfitz): optional interface impl override hook
- // TODO(bradfitz): Timeout time.Duration?
-}
-
-func (r *Resolver) preferGo() bool { return r != nil && r.PreferGo }
-func (r *Resolver) strictErrors() bool { return r != nil && r.StrictErrors }
-
-func (r *Resolver) getLookupGroup() *singleflight.Group {
- if r == nil {
- return &DefaultResolver.lookupGroup
- }
- return &r.lookupGroup
-}
-
-// LookupHost looks up the given host using the local resolver.
-// It returns a slice of that host's addresses.
-//
-// LookupHost uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupHost].
-func LookupHost(host string) (addrs []string, err error) {
- return DefaultResolver.LookupHost(context.Background(), host)
-}
-
-// LookupHost looks up the given host using the local resolver.
-// It returns a slice of that host's addresses.
-func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) {
- // Make sure that no matter what we do later, host=="" is rejected.
- if host == "" {
- return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
- }
- if _, err := netip.ParseAddr(host); err == nil {
- return []string{host}, nil
- }
- return r.lookupHost(ctx, host)
-}
-
-// LookupIP looks up host using the local resolver.
-// It returns a slice of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) ([]IP, error) {
- addrs, err := DefaultResolver.LookupIPAddr(context.Background(), host)
- if err != nil {
- return nil, err
- }
- ips := make([]IP, len(addrs))
- for i, ia := range addrs {
- ips[i] = ia.IP
- }
- return ips, nil
-}
-
-// LookupIPAddr looks up host using the local resolver.
-// It returns a slice of that host's IPv4 and IPv6 addresses.
-func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, error) {
- return r.lookupIPAddr(ctx, "ip", host)
-}
-
-// LookupIP looks up host for the given network using the local resolver.
-// It returns a slice of that host's IP addresses of the type specified by
-// network.
-// network must be one of "ip", "ip4" or "ip6".
-func (r *Resolver) LookupIP(ctx context.Context, network, host string) ([]IP, error) {
- afnet, _, err := parseNetwork(ctx, network, false)
- if err != nil {
- return nil, err
- }
- switch afnet {
- case "ip", "ip4", "ip6":
- default:
- return nil, UnknownNetworkError(network)
- }
-
- if host == "" {
- return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
- }
- addrs, err := r.internetAddrList(ctx, afnet, host)
- if err != nil {
- return nil, err
- }
-
- ips := make([]IP, 0, len(addrs))
- for _, addr := range addrs {
- ips = append(ips, addr.(*IPAddr).IP)
- }
- return ips, nil
-}
-
-// LookupNetIP looks up host using the local resolver.
-// It returns a slice of that host's IP addresses of the type specified by
-// network.
-// The network must be one of "ip", "ip4" or "ip6".
-func (r *Resolver) LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error) {
- // TODO(bradfitz): make this efficient, making the internal net package
- // type throughout be netip.Addr and only converting to the net.IP slice
- // version at the edge. But for now (2021-10-20), this is a wrapper around
- // the old way.
- ips, err := r.LookupIP(ctx, network, host)
- if err != nil {
- return nil, err
- }
- ret := make([]netip.Addr, 0, len(ips))
- for _, ip := range ips {
- if a, ok := netip.AddrFromSlice(ip); ok {
- ret = append(ret, a)
- }
- }
- return ret, nil
-}
-
-// onlyValuesCtx is a context that uses an underlying context
-// for value lookup if the underlying context hasn't yet expired.
-type onlyValuesCtx struct {
- context.Context
- lookupValues context.Context
-}
-
-var _ context.Context = (*onlyValuesCtx)(nil)
-
-// Value performs a lookup if the original context hasn't expired.
-func (ovc *onlyValuesCtx) Value(key any) any {
- select {
- case <-ovc.lookupValues.Done():
- return nil
- default:
- return ovc.lookupValues.Value(key)
- }
-}
-
-// withUnexpiredValuesPreserved returns a context.Context that only uses lookupCtx
-// for its values, otherwise it is never canceled and has no deadline.
-// If the lookup context expires, any looked up values will return nil.
-// See Issue 28600.
-func withUnexpiredValuesPreserved(lookupCtx context.Context) context.Context {
- return &onlyValuesCtx{Context: context.Background(), lookupValues: lookupCtx}
-}
-
-// lookupIPAddr looks up host using the local resolver and particular network.
-// It returns a slice of that host's IPv4 and IPv6 addresses.
-func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IPAddr, error) {
- // Make sure that no matter what we do later, host=="" is rejected.
- if host == "" {
- return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
- }
- if ip, err := netip.ParseAddr(host); err == nil {
- return []IPAddr{{IP: IP(ip.AsSlice()).To16(), Zone: ip.Zone()}}, nil
- }
- trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
- if trace != nil && trace.DNSStart != nil {
- trace.DNSStart(host)
- }
- // The underlying resolver func is lookupIP by default but it
- // can be overridden by tests. This is needed by net/http, so it
- // uses a context key instead of unexported variables.
- resolverFunc := r.lookupIP
- if alt, _ := ctx.Value(nettrace.LookupIPAltResolverKey{}).(func(context.Context, string, string) ([]IPAddr, error)); alt != nil {
- resolverFunc = alt
- }
-
- // We don't want a cancellation of ctx to affect the
- // lookupGroup operation. Otherwise if our context gets
- // canceled it might cause an error to be returned to a lookup
- // using a completely different context. However we need to preserve
- // only the values in context. See Issue 28600.
- lookupGroupCtx, lookupGroupCancel := context.WithCancel(withUnexpiredValuesPreserved(ctx))
-
- lookupKey := network + "\000" + host
- dnsWaitGroup.Add(1)
- ch := r.getLookupGroup().DoChan(lookupKey, func() (any, error) {
- return testHookLookupIP(lookupGroupCtx, resolverFunc, network, host)
- })
-
- dnsWaitGroupDone := func(ch <-chan singleflight.Result, cancelFn context.CancelFunc) {
- <-ch
- dnsWaitGroup.Done()
- cancelFn()
- }
- select {
- case <-ctx.Done():
- // Our context was canceled. If we are the only
- // goroutine looking up this key, then drop the key
- // from the lookupGroup and cancel the lookup.
- // If there are other goroutines looking up this key,
- // let the lookup continue uncanceled, and let later
- // lookups with the same key share the result.
- // See issues 8602, 20703, 22724.
- if r.getLookupGroup().ForgetUnshared(lookupKey) {
- lookupGroupCancel()
- go dnsWaitGroupDone(ch, func() {})
- } else {
- go dnsWaitGroupDone(ch, lookupGroupCancel)
- }
- ctxErr := ctx.Err()
- err := &DNSError{
- Err: mapErr(ctxErr).Error(),
- Name: host,
- IsTimeout: ctxErr == context.DeadlineExceeded,
- }
- if trace != nil && trace.DNSDone != nil {
- trace.DNSDone(nil, false, err)
- }
- return nil, err
- case r := <-ch:
- dnsWaitGroup.Done()
- lookupGroupCancel()
- err := r.Err
- if err != nil {
- if _, ok := err.(*DNSError); !ok {
- isTimeout := false
- if err == context.DeadlineExceeded {
- isTimeout = true
- } else if terr, ok := err.(timeout); ok {
- isTimeout = terr.Timeout()
- }
- err = &DNSError{
- Err: err.Error(),
- Name: host,
- IsTimeout: isTimeout,
- }
- }
- }
- if trace != nil && trace.DNSDone != nil {
- addrs, _ := r.Val.([]IPAddr)
- trace.DNSDone(ipAddrsEface(addrs), r.Shared, err)
- }
- return lookupIPReturn(r.Val, err, r.Shared)
- }
-}
-
-// lookupIPReturn turns the return values from singleflight.Do into
-// the return values from LookupIP.
-func lookupIPReturn(addrsi any, err error, shared bool) ([]IPAddr, error) {
- if err != nil {
- return nil, err
- }
- addrs := addrsi.([]IPAddr)
- if shared {
- clone := make([]IPAddr, len(addrs))
- copy(clone, addrs)
- addrs = clone
- }
- return addrs, nil
-}
-
-// ipAddrsEface returns an empty interface slice of addrs.
-func ipAddrsEface(addrs []IPAddr) []any {
- s := make([]any, len(addrs))
- for i, v := range addrs {
- s[i] = v
- }
- return s
-}
-
-// LookupPort looks up the port for the given network and service.
-//
-// LookupPort uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupPort].
-func LookupPort(network, service string) (port int, err error) {
- return DefaultResolver.LookupPort(context.Background(), network, service)
-}
-
-// LookupPort looks up the port for the given network and service.
-//
-// The network must be one of "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6" or "ip".
-func (r *Resolver) LookupPort(ctx context.Context, network, service string) (port int, err error) {
- port, needsLookup := parsePort(service)
- if needsLookup {
- switch network {
- case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip":
- case "": // a hint wildcard for Go 1.0 undocumented behavior
- network = "ip"
- default:
- return 0, &AddrError{Err: "unknown network", Addr: network}
- }
- port, err = r.lookupPort(ctx, network, service)
- if err != nil {
- return 0, err
- }
- }
- if 0 > port || port > 65535 {
- return 0, &AddrError{Err: "invalid port", Addr: service}
- }
- return port, nil
-}
-
-// LookupCNAME returns the canonical name for the given host.
-// Callers that do not care about the canonical name can call
-// [LookupHost] or [LookupIP] directly; both take care of resolving
-// the canonical name as part of the lookup.
-//
-// A canonical name is the final name after following zero
-// or more CNAME records.
-// LookupCNAME does not return an error if host does not
-// contain DNS "CNAME" records, as long as host resolves to
-// address records.
-//
-// The returned canonical name is validated to be a properly
-// formatted presentation-format domain name.
-//
-// LookupCNAME uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupCNAME].
-func LookupCNAME(host string) (cname string, err error) {
- return DefaultResolver.LookupCNAME(context.Background(), host)
-}
-
-// LookupCNAME returns the canonical name for the given host.
-// Callers that do not care about the canonical name can call
-// [LookupHost] or [LookupIP] directly; both take care of resolving
-// the canonical name as part of the lookup.
-//
-// A canonical name is the final name after following zero
-// or more CNAME records.
-// LookupCNAME does not return an error if host does not
-// contain DNS "CNAME" records, as long as host resolves to
-// address records.
-//
-// The returned canonical name is validated to be a properly
-// formatted presentation-format domain name.
-func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) {
- cname, err := r.lookupCNAME(ctx, host)
- if err != nil {
- return "", err
- }
- if !isDomainName(cname) {
- return "", &DNSError{Err: errMalformedDNSRecordsDetail, Name: host}
- }
- return cname, nil
-}
-
-// LookupSRV tries to resolve an [SRV] query of the given service,
-// protocol, and domain name. The proto is "tcp" or "udp".
-// The returned records are sorted by priority and randomized
-// by weight within a priority.
-//
-// LookupSRV constructs the DNS name to look up following RFC 2782.
-// That is, it looks up _service._proto.name. To accommodate services
-// publishing SRV records under non-standard names, if both service
-// and proto are empty strings, LookupSRV looks up name directly.
-//
-// The returned service names are validated to be properly
-// formatted presentation-format domain names. If the response contains
-// invalid names, those records are filtered out and an error
-// will be returned alongside the remaining results, if any.
-func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
- return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
-}
-
-// LookupSRV tries to resolve an [SRV] query of the given service,
-// protocol, and domain name. The proto is "tcp" or "udp".
-// The returned records are sorted by priority and randomized
-// by weight within a priority.
-//
-// LookupSRV constructs the DNS name to look up following RFC 2782.
-// That is, it looks up _service._proto.name. To accommodate services
-// publishing SRV records under non-standard names, if both service
-// and proto are empty strings, LookupSRV looks up name directly.
-//
-// The returned service names are validated to be properly
-// formatted presentation-format domain names. If the response contains
-// invalid names, those records are filtered out and an error
-// will be returned alongside the remaining results, if any.
-func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
- cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
- if err != nil {
- return "", nil, err
- }
- if cname != "" && !isDomainName(cname) {
- return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
- }
- filteredAddrs := make([]*SRV, 0, len(addrs))
- for _, addr := range addrs {
- if addr == nil {
- continue
- }
- if !isDomainName(addr.Target) {
- continue
- }
- filteredAddrs = append(filteredAddrs, addr)
- }
- if len(addrs) != len(filteredAddrs) {
- return cname, filteredAddrs, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
- }
- return cname, filteredAddrs, nil
-}
-
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-//
-// The returned mail server names are validated to be properly
-// formatted presentation-format domain names. If the response contains
-// invalid names, those records are filtered out and an error
-// will be returned alongside the remaining results, if any.
-//
-// LookupMX uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupMX].
-func LookupMX(name string) ([]*MX, error) {
- return DefaultResolver.LookupMX(context.Background(), name)
-}
-
-// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-//
-// The returned mail server names are validated to be properly
-// formatted presentation-format domain names. If the response contains
-// invalid names, those records are filtered out and an error
-// will be returned alongside the remaining results, if any.
-func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
- records, err := r.lookupMX(ctx, name)
- if err != nil {
- return nil, err
- }
- filteredMX := make([]*MX, 0, len(records))
- for _, mx := range records {
- if mx == nil {
- continue
- }
- if !isDomainName(mx.Host) {
- continue
- }
- filteredMX = append(filteredMX, mx)
- }
- if len(records) != len(filteredMX) {
- return filteredMX, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
- }
- return filteredMX, nil
-}
-
-// LookupNS returns the DNS NS records for the given domain name.
-//
-// The returned name server names are validated to be properly
-// formatted presentation-format domain names. If the response contains
-// invalid names, those records are filtered out and an error
-// will be returned alongside the remaining results, if any.
-//
-// LookupNS uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupNS].
-func LookupNS(name string) ([]*NS, error) {
- return DefaultResolver.LookupNS(context.Background(), name)
-}
-
-// LookupNS returns the DNS NS records for the given domain name.
-//
-// The returned name server names are validated to be properly
-// formatted presentation-format domain names. If the response contains
-// invalid names, those records are filtered out and an error
-// will be returned alongside the remaining results, if any.
-func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
- records, err := r.lookupNS(ctx, name)
- if err != nil {
- return nil, err
- }
- filteredNS := make([]*NS, 0, len(records))
- for _, ns := range records {
- if ns == nil {
- continue
- }
- if !isDomainName(ns.Host) {
- continue
- }
- filteredNS = append(filteredNS, ns)
- }
- if len(records) != len(filteredNS) {
- return filteredNS, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
- }
- return filteredNS, nil
-}
-
-// LookupTXT returns the DNS TXT records for the given domain name.
-//
-// LookupTXT uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupTXT].
-func LookupTXT(name string) ([]string, error) {
- return DefaultResolver.lookupTXT(context.Background(), name)
-}
-
-// LookupTXT returns the DNS TXT records for the given domain name.
-func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
- return r.lookupTXT(ctx, name)
-}
-
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-//
-// The returned names are validated to be properly formatted presentation-format
-// domain names. If the response contains invalid names, those records are filtered
-// out and an error will be returned alongside the remaining results, if any.
-//
-// When using the host C library resolver, at most one result will be
-// returned. To bypass the host resolver, use a custom [Resolver].
-//
-// LookupAddr uses [context.Background] internally; to specify the context, use
-// [Resolver.LookupAddr].
-func LookupAddr(addr string) (names []string, err error) {
- return DefaultResolver.LookupAddr(context.Background(), addr)
-}
-
-// LookupAddr performs a reverse lookup for the given address, returning a list
-// of names mapping to that address.
-//
-// The returned names are validated to be properly formatted presentation-format
-// domain names. If the response contains invalid names, those records are filtered
-// out and an error will be returned alongside the remaining results, if any.
-func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
- names, err := r.lookupAddr(ctx, addr)
- if err != nil {
- return nil, err
- }
- filteredNames := make([]string, 0, len(names))
- for _, name := range names {
- if isDomainName(name) {
- filteredNames = append(filteredNames, name)
- }
- }
- if len(names) != len(filteredNames) {
- return filteredNames, &DNSError{Err: errMalformedDNSRecordsDetail, Name: addr}
- }
- return filteredNames, nil
-}
-
-// errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup...
-// method receives DNS records which contain invalid DNS names. This may be returned alongside
-// results which have had the malformed records filtered out.
-var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names"
-
-// dial makes a new connection to the provided server (which must be
-// an IP address) with the provided network type, using either r.Dial
-// (if both r and r.Dial are non-nil) or else Dialer.DialContext.
-func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) {
- // Calling Dial here is scary -- we have to be sure not to
- // dial a name that will require a DNS lookup, or Dial will
- // call back here to translate it. The DNS config parser has
- // already checked that all the cfg.servers are IP
- // addresses, which Dial will use without a DNS lookup.
- var c Conn
- var err error
- if r != nil && r.Dial != nil {
- c, err = r.Dial(ctx, network, server)
- } else {
- var d Dialer
- c, err = d.DialContext(ctx, network, server)
- }
- if err != nil {
- return nil, mapErr(err)
- }
- return c, nil
-}
-
-// goLookupSRV returns the SRV records for a target name, built either
-// from its component service ("sip"), protocol ("tcp"), and name
-// ("example.com."), or from name directly (if service and proto are
-// both empty).
-//
-// In either case, the returned target name ("_sip._tcp.example.com.")
-// is also returned on success.
-//
-// The records are sorted by weight.
-func (r *Resolver) goLookupSRV(ctx context.Context, service, proto, name string) (target string, srvs []*SRV, err error) {
- if service == "" && proto == "" {
- target = name
- } else {
- target = "_" + service + "._" + proto + "." + name
- }
- p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV, nil)
- if err != nil {
- return "", nil, err
- }
- var cname dnsmessage.Name
- for {
- h, err := p.AnswerHeader()
- if err == dnsmessage.ErrSectionDone {
- break
- }
- if err != nil {
- return "", nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- if h.Type != dnsmessage.TypeSRV {
- if err := p.SkipAnswer(); err != nil {
- return "", nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- continue
- }
- if cname.Length == 0 && h.Name.Length != 0 {
- cname = h.Name
- }
- srv, err := p.SRVResource()
- if err != nil {
- return "", nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight})
- }
- byPriorityWeight(srvs).sort()
- return cname.String(), srvs, nil
-}
-
-// goLookupMX returns the MX records for name.
-func (r *Resolver) goLookupMX(ctx context.Context, name string) ([]*MX, error) {
- p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX, nil)
- if err != nil {
- return nil, err
- }
- var mxs []*MX
- for {
- h, err := p.AnswerHeader()
- if err == dnsmessage.ErrSectionDone {
- break
- }
- if err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- if h.Type != dnsmessage.TypeMX {
- if err := p.SkipAnswer(); err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- continue
- }
- mx, err := p.MXResource()
- if err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref})
-
- }
- byPref(mxs).sort()
- return mxs, nil
-}
-
-// goLookupNS returns the NS records for name.
-func (r *Resolver) goLookupNS(ctx context.Context, name string) ([]*NS, error) {
- p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS, nil)
- if err != nil {
- return nil, err
- }
- var nss []*NS
- for {
- h, err := p.AnswerHeader()
- if err == dnsmessage.ErrSectionDone {
- break
- }
- if err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- if h.Type != dnsmessage.TypeNS {
- if err := p.SkipAnswer(); err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- continue
- }
- ns, err := p.NSResource()
- if err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- nss = append(nss, &NS{Host: ns.NS.String()})
- }
- return nss, nil
-}
-
-// goLookupTXT returns the TXT records from name.
-func (r *Resolver) goLookupTXT(ctx context.Context, name string) ([]string, error) {
- p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT, nil)
- if err != nil {
- return nil, err
- }
- var txts []string
- for {
- h, err := p.AnswerHeader()
- if err == dnsmessage.ErrSectionDone {
- break
- }
- if err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- if h.Type != dnsmessage.TypeTXT {
- if err := p.SkipAnswer(); err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- continue
- }
- txt, err := p.TXTResource()
- if err != nil {
- return nil, &DNSError{
- Err: "cannot unmarshal DNS message",
- Name: name,
- Server: server,
- }
- }
- // Multiple strings in one TXT record need to be
- // concatenated without separator to be consistent
- // with previous Go resolver.
- n := 0
- for _, s := range txt.TXT {
- n += len(s)
- }
- txtJoin := make([]byte, 0, n)
- for _, s := range txt.TXT {
- txtJoin = append(txtJoin, s...)
- }
- if len(txts) == 0 {
- txts = make([]string, 0, 1)
- }
- txts = append(txts, string(txtJoin))
- }
- return txts, nil
-}
-
-func parseCNAMEFromResources(resources []dnsmessage.Resource) (string, error) {
- if len(resources) == 0 {
- return "", errors.New("no CNAME record received")
- }
- c, ok := resources[0].Body.(*dnsmessage.CNAMEResource)
- if !ok {
- return "", errors.New("could not parse CNAME record")
- }
- return c.CNAME.String(), nil
-}
diff --git a/contrib/go/_std_1.22/src/net/mail/message.go b/contrib/go/_std_1.22/src/net/mail/message.go
deleted file mode 100644
index fc2a9e46f811..000000000000
--- a/contrib/go/_std_1.22/src/net/mail/message.go
+++ /dev/null
@@ -1,915 +0,0 @@
-// Copyright 2011 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.
-
-/*
-Package mail implements parsing of mail messages.
-
-For the most part, this package follows the syntax as specified by RFC 5322 and
-extended by RFC 6532.
-Notable divergences:
- - Obsolete address formats are not parsed, including addresses with
- embedded route information.
- - The full range of spacing (the CFWS syntax element) is not supported,
- such as breaking addresses across lines.
- - No unicode normalization is performed.
- - The special characters ()[]:;@\, are allowed to appear unquoted in names.
- - A leading From line is permitted, as in mbox format (RFC 4155).
-*/
-package mail
-
-import (
- "bufio"
- "errors"
- "fmt"
- "io"
- "log"
- "mime"
- "net/textproto"
- "strings"
- "sync"
- "time"
- "unicode/utf8"
-)
-
-var debug = debugT(false)
-
-type debugT bool
-
-func (d debugT) Printf(format string, args ...any) {
- if d {
- log.Printf(format, args...)
- }
-}
-
-// A Message represents a parsed mail message.
-type Message struct {
- Header Header
- Body io.Reader
-}
-
-// ReadMessage reads a message from r.
-// The headers are parsed, and the body of the message will be available
-// for reading from msg.Body.
-func ReadMessage(r io.Reader) (msg *Message, err error) {
- tp := textproto.NewReader(bufio.NewReader(r))
-
- hdr, err := readHeader(tp)
- if err != nil && (err != io.EOF || len(hdr) == 0) {
- return nil, err
- }
-
- return &Message{
- Header: Header(hdr),
- Body: tp.R,
- }, nil
-}
-
-// readHeader reads the message headers from r.
-// This is like textproto.ReadMIMEHeader, but doesn't validate.
-// The fix for issue #53188 tightened up net/textproto to enforce
-// restrictions of RFC 7230.
-// This package implements RFC 5322, which does not have those restrictions.
-// This function copies the relevant code from net/textproto,
-// simplified for RFC 5322.
-func readHeader(r *textproto.Reader) (map[string][]string, error) {
- m := make(map[string][]string)
-
- // The first line cannot start with a leading space.
- if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
- line, err := r.ReadLine()
- if err != nil {
- return m, err
- }
- return m, errors.New("malformed initial line: " + line)
- }
-
- for {
- kv, err := r.ReadContinuedLine()
- if kv == "" {
- return m, err
- }
-
- // Key ends at first colon.
- k, v, ok := strings.Cut(kv, ":")
- if !ok {
- return m, errors.New("malformed header line: " + kv)
- }
- key := textproto.CanonicalMIMEHeaderKey(k)
-
- // Permit empty key, because that is what we did in the past.
- if key == "" {
- continue
- }
-
- // Skip initial spaces in value.
- value := strings.TrimLeft(v, " \t")
-
- m[key] = append(m[key], value)
-
- if err != nil {
- return m, err
- }
- }
-}
-
-// Layouts suitable for passing to time.Parse.
-// These are tried in order.
-var (
- dateLayoutsBuildOnce sync.Once
- dateLayouts []string
-)
-
-func buildDateLayouts() {
- // Generate layouts based on RFC 5322, section 3.3.
-
- dows := [...]string{"", "Mon, "} // day-of-week
- days := [...]string{"2", "02"} // day = 1*2DIGIT
- years := [...]string{"2006", "06"} // year = 4*DIGIT / 2*DIGIT
- seconds := [...]string{":05", ""} // second
- // "-0700 (MST)" is not in RFC 5322, but is common.
- zones := [...]string{"-0700", "MST", "UT"} // zone = (("+" / "-") 4DIGIT) / "UT" / "GMT" / ...
-
- for _, dow := range dows {
- for _, day := range days {
- for _, year := range years {
- for _, second := range seconds {
- for _, zone := range zones {
- s := dow + day + " Jan " + year + " 15:04" + second + " " + zone
- dateLayouts = append(dateLayouts, s)
- }
- }
- }
- }
- }
-}
-
-// ParseDate parses an RFC 5322 date string.
-func ParseDate(date string) (time.Time, error) {
- dateLayoutsBuildOnce.Do(buildDateLayouts)
- // CR and LF must match and are tolerated anywhere in the date field.
- date = strings.ReplaceAll(date, "\r\n", "")
- if strings.Contains(date, "\r") {
- return time.Time{}, errors.New("mail: header has a CR without LF")
- }
- // Re-using some addrParser methods which support obsolete text, i.e. non-printable ASCII
- p := addrParser{date, nil}
- p.skipSpace()
-
- // RFC 5322: zone = (FWS ( "+" / "-" ) 4DIGIT) / obs-zone
- // zone length is always 5 chars unless obsolete (obs-zone)
- if ind := strings.IndexAny(p.s, "+-"); ind != -1 && len(p.s) >= ind+5 {
- date = p.s[:ind+5]
- p.s = p.s[ind+5:]
- } else {
- ind := strings.Index(p.s, "T")
- if ind == 0 {
- // In this case we have the following date formats:
- // * Thu, 20 Nov 1997 09:55:06 MDT
- // * Thu, 20 Nov 1997 09:55:06 MDT (MDT)
- // * Thu, 20 Nov 1997 09:55:06 MDT (This comment)
- ind = strings.Index(p.s[1:], "T")
- if ind != -1 {
- ind++
- }
- }
-
- if ind != -1 && len(p.s) >= ind+5 {
- // The last letter T of the obsolete time zone is checked when no standard time zone is found.
- // If T is misplaced, the date to parse is garbage.
- date = p.s[:ind+1]
- p.s = p.s[ind+1:]
- }
- }
- if !p.skipCFWS() {
- return time.Time{}, errors.New("mail: misformatted parenthetical comment")
- }
- for _, layout := range dateLayouts {
- t, err := time.Parse(layout, date)
- if err == nil {
- return t, nil
- }
- }
- return time.Time{}, errors.New("mail: header could not be parsed")
-}
-
-// A Header represents the key-value pairs in a mail message header.
-type Header map[string][]string
-
-// Get gets the first value associated with the given key.
-// It is case insensitive; CanonicalMIMEHeaderKey is used
-// to canonicalize the provided key.
-// If there are no values associated with the key, Get returns "".
-// To access multiple values of a key, or to use non-canonical keys,
-// access the map directly.
-func (h Header) Get(key string) string {
- return textproto.MIMEHeader(h).Get(key)
-}
-
-var ErrHeaderNotPresent = errors.New("mail: header not in message")
-
-// Date parses the Date header field.
-func (h Header) Date() (time.Time, error) {
- hdr := h.Get("Date")
- if hdr == "" {
- return time.Time{}, ErrHeaderNotPresent
- }
- return ParseDate(hdr)
-}
-
-// AddressList parses the named header field as a list of addresses.
-func (h Header) AddressList(key string) ([]*Address, error) {
- hdr := h.Get(key)
- if hdr == "" {
- return nil, ErrHeaderNotPresent
- }
- return ParseAddressList(hdr)
-}
-
-// Address represents a single mail address.
-// An address such as "Barry Gibbs " is represented
-// as Address{Name: "Barry Gibbs", Address: "bg@example.com"}.
-type Address struct {
- Name string // Proper name; may be empty.
- Address string // user@domain
-}
-
-// ParseAddress parses a single RFC 5322 address, e.g. "Barry Gibbs "
-func ParseAddress(address string) (*Address, error) {
- return (&addrParser{s: address}).parseSingleAddress()
-}
-
-// ParseAddressList parses the given string as a list of addresses.
-func ParseAddressList(list string) ([]*Address, error) {
- return (&addrParser{s: list}).parseAddressList()
-}
-
-// An AddressParser is an RFC 5322 address parser.
-type AddressParser struct {
- // WordDecoder optionally specifies a decoder for RFC 2047 encoded-words.
- WordDecoder *mime.WordDecoder
-}
-
-// Parse parses a single RFC 5322 address of the
-// form "Gogh Fir " or "foo@example.com".
-func (p *AddressParser) Parse(address string) (*Address, error) {
- return (&addrParser{s: address, dec: p.WordDecoder}).parseSingleAddress()
-}
-
-// ParseList parses the given string as a list of comma-separated addresses
-// of the form "Gogh Fir " or "foo@example.com".
-func (p *AddressParser) ParseList(list string) ([]*Address, error) {
- return (&addrParser{s: list, dec: p.WordDecoder}).parseAddressList()
-}
-
-// String formats the address as a valid RFC 5322 address.
-// If the address's name contains non-ASCII characters
-// the name will be rendered according to RFC 2047.
-func (a *Address) String() string {
- // Format address local@domain
- at := strings.LastIndex(a.Address, "@")
- var local, domain string
- if at < 0 {
- // This is a malformed address ("@" is required in addr-spec);
- // treat the whole address as local-part.
- local = a.Address
- } else {
- local, domain = a.Address[:at], a.Address[at+1:]
- }
-
- // Add quotes if needed
- quoteLocal := false
- for i, r := range local {
- if isAtext(r, false) {
- continue
- }
- if r == '.' {
- // Dots are okay if they are surrounded by atext.
- // We only need to check that the previous byte is
- // not a dot, and this isn't the end of the string.
- if i > 0 && local[i-1] != '.' && i < len(local)-1 {
- continue
- }
- }
- quoteLocal = true
- break
- }
- if quoteLocal {
- local = quoteString(local)
-
- }
-
- s := "<" + local + "@" + domain + ">"
-
- if a.Name == "" {
- return s
- }
-
- // If every character is printable ASCII, quoting is simple.
- allPrintable := true
- for _, r := range a.Name {
- // isWSP here should actually be isFWS,
- // but we don't support folding yet.
- if !isVchar(r) && !isWSP(r) || isMultibyte(r) {
- allPrintable = false
- break
- }
- }
- if allPrintable {
- return quoteString(a.Name) + " " + s
- }
-
- // Text in an encoded-word in a display-name must not contain certain
- // characters like quotes or parentheses (see RFC 2047 section 5.3).
- // When this is the case encode the name using base64 encoding.
- if strings.ContainsAny(a.Name, "\"#$%&'(),.:;<>@[]^`{|}~") {
- return mime.BEncoding.Encode("utf-8", a.Name) + " " + s
- }
- return mime.QEncoding.Encode("utf-8", a.Name) + " " + s
-}
-
-type addrParser struct {
- s string
- dec *mime.WordDecoder // may be nil
-}
-
-func (p *addrParser) parseAddressList() ([]*Address, error) {
- var list []*Address
- for {
- p.skipSpace()
-
- // allow skipping empty entries (RFC5322 obs-addr-list)
- if p.consume(',') {
- continue
- }
-
- addrs, err := p.parseAddress(true)
- if err != nil {
- return nil, err
- }
- list = append(list, addrs...)
-
- if !p.skipCFWS() {
- return nil, errors.New("mail: misformatted parenthetical comment")
- }
- if p.empty() {
- break
- }
- if p.peek() != ',' {
- return nil, errors.New("mail: expected comma")
- }
-
- // Skip empty entries for obs-addr-list.
- for p.consume(',') {
- p.skipSpace()
- }
- if p.empty() {
- break
- }
- }
- return list, nil
-}
-
-func (p *addrParser) parseSingleAddress() (*Address, error) {
- addrs, err := p.parseAddress(true)
- if err != nil {
- return nil, err
- }
- if !p.skipCFWS() {
- return nil, errors.New("mail: misformatted parenthetical comment")
- }
- if !p.empty() {
- return nil, fmt.Errorf("mail: expected single address, got %q", p.s)
- }
- if len(addrs) == 0 {
- return nil, errors.New("mail: empty group")
- }
- if len(addrs) > 1 {
- return nil, errors.New("mail: group with multiple addresses")
- }
- return addrs[0], nil
-}
-
-// parseAddress parses a single RFC 5322 address at the start of p.
-func (p *addrParser) parseAddress(handleGroup bool) ([]*Address, error) {
- debug.Printf("parseAddress: %q", p.s)
- p.skipSpace()
- if p.empty() {
- return nil, errors.New("mail: no address")
- }
-
- // address = mailbox / group
- // mailbox = name-addr / addr-spec
- // group = display-name ":" [group-list] ";" [CFWS]
-
- // addr-spec has a more restricted grammar than name-addr,
- // so try parsing it first, and fallback to name-addr.
- // TODO(dsymonds): Is this really correct?
- spec, err := p.consumeAddrSpec()
- if err == nil {
- var displayName string
- p.skipSpace()
- if !p.empty() && p.peek() == '(' {
- displayName, err = p.consumeDisplayNameComment()
- if err != nil {
- return nil, err
- }
- }
-
- return []*Address{{
- Name: displayName,
- Address: spec,
- }}, err
- }
- debug.Printf("parseAddress: not an addr-spec: %v", err)
- debug.Printf("parseAddress: state is now %q", p.s)
-
- // display-name
- var displayName string
- if p.peek() != '<' {
- displayName, err = p.consumePhrase()
- if err != nil {
- return nil, err
- }
- }
- debug.Printf("parseAddress: displayName=%q", displayName)
-
- p.skipSpace()
- if handleGroup {
- if p.consume(':') {
- return p.consumeGroupList()
- }
- }
- // angle-addr = "<" addr-spec ">"
- if !p.consume('<') {
- atext := true
- for _, r := range displayName {
- if !isAtext(r, true) {
- atext = false
- break
- }
- }
- if atext {
- // The input is like "foo.bar"; it's possible the input
- // meant to be "foo.bar@domain", or "foo.bar <...>".
- return nil, errors.New("mail: missing '@' or angle-addr")
- }
- // The input is like "Full Name", which couldn't possibly be a
- // valid email address if followed by "@domain"; the input
- // likely meant to be "Full Name <...>".
- return nil, errors.New("mail: no angle-addr")
- }
- spec, err = p.consumeAddrSpec()
- if err != nil {
- return nil, err
- }
- if !p.consume('>') {
- return nil, errors.New("mail: unclosed angle-addr")
- }
- debug.Printf("parseAddress: spec=%q", spec)
-
- return []*Address{{
- Name: displayName,
- Address: spec,
- }}, nil
-}
-
-func (p *addrParser) consumeGroupList() ([]*Address, error) {
- var group []*Address
- // handle empty group.
- p.skipSpace()
- if p.consume(';') {
- if !p.skipCFWS() {
- return nil, errors.New("mail: misformatted parenthetical comment")
- }
- return group, nil
- }
-
- for {
- p.skipSpace()
- // embedded groups not allowed.
- addrs, err := p.parseAddress(false)
- if err != nil {
- return nil, err
- }
- group = append(group, addrs...)
-
- if !p.skipCFWS() {
- return nil, errors.New("mail: misformatted parenthetical comment")
- }
- if p.consume(';') {
- if !p.skipCFWS() {
- return nil, errors.New("mail: misformatted parenthetical comment")
- }
- break
- }
- if !p.consume(',') {
- return nil, errors.New("mail: expected comma")
- }
- }
- return group, nil
-}
-
-// consumeAddrSpec parses a single RFC 5322 addr-spec at the start of p.
-func (p *addrParser) consumeAddrSpec() (spec string, err error) {
- debug.Printf("consumeAddrSpec: %q", p.s)
-
- orig := *p
- defer func() {
- if err != nil {
- *p = orig
- }
- }()
-
- // local-part = dot-atom / quoted-string
- var localPart string
- p.skipSpace()
- if p.empty() {
- return "", errors.New("mail: no addr-spec")
- }
- if p.peek() == '"' {
- // quoted-string
- debug.Printf("consumeAddrSpec: parsing quoted-string")
- localPart, err = p.consumeQuotedString()
- if localPart == "" {
- err = errors.New("mail: empty quoted string in addr-spec")
- }
- } else {
- // dot-atom
- debug.Printf("consumeAddrSpec: parsing dot-atom")
- localPart, err = p.consumeAtom(true, false)
- }
- if err != nil {
- debug.Printf("consumeAddrSpec: failed: %v", err)
- return "", err
- }
-
- if !p.consume('@') {
- return "", errors.New("mail: missing @ in addr-spec")
- }
-
- // domain = dot-atom / domain-literal
- var domain string
- p.skipSpace()
- if p.empty() {
- return "", errors.New("mail: no domain in addr-spec")
- }
- // TODO(dsymonds): Handle domain-literal
- domain, err = p.consumeAtom(true, false)
- if err != nil {
- return "", err
- }
-
- return localPart + "@" + domain, nil
-}
-
-// consumePhrase parses the RFC 5322 phrase at the start of p.
-func (p *addrParser) consumePhrase() (phrase string, err error) {
- debug.Printf("consumePhrase: [%s]", p.s)
- // phrase = 1*word
- var words []string
- var isPrevEncoded bool
- for {
- // obs-phrase allows CFWS after one word
- if len(words) > 0 {
- if !p.skipCFWS() {
- return "", errors.New("mail: misformatted parenthetical comment")
- }
- }
- // word = atom / quoted-string
- var word string
- p.skipSpace()
- if p.empty() {
- break
- }
- isEncoded := false
- if p.peek() == '"' {
- // quoted-string
- word, err = p.consumeQuotedString()
- } else {
- // atom
- // We actually parse dot-atom here to be more permissive
- // than what RFC 5322 specifies.
- word, err = p.consumeAtom(true, true)
- if err == nil {
- word, isEncoded, err = p.decodeRFC2047Word(word)
- }
- }
-
- if err != nil {
- break
- }
- debug.Printf("consumePhrase: consumed %q", word)
- if isPrevEncoded && isEncoded {
- words[len(words)-1] += word
- } else {
- words = append(words, word)
- }
- isPrevEncoded = isEncoded
- }
- // Ignore any error if we got at least one word.
- if err != nil && len(words) == 0 {
- debug.Printf("consumePhrase: hit err: %v", err)
- return "", fmt.Errorf("mail: missing word in phrase: %v", err)
- }
- phrase = strings.Join(words, " ")
- return phrase, nil
-}
-
-// consumeQuotedString parses the quoted string at the start of p.
-func (p *addrParser) consumeQuotedString() (qs string, err error) {
- // Assume first byte is '"'.
- i := 1
- qsb := make([]rune, 0, 10)
-
- escaped := false
-
-Loop:
- for {
- r, size := utf8.DecodeRuneInString(p.s[i:])
-
- switch {
- case size == 0:
- return "", errors.New("mail: unclosed quoted-string")
-
- case size == 1 && r == utf8.RuneError:
- return "", fmt.Errorf("mail: invalid utf-8 in quoted-string: %q", p.s)
-
- case escaped:
- // quoted-pair = ("\" (VCHAR / WSP))
-
- if !isVchar(r) && !isWSP(r) {
- return "", fmt.Errorf("mail: bad character in quoted-string: %q", r)
- }
-
- qsb = append(qsb, r)
- escaped = false
-
- case isQtext(r) || isWSP(r):
- // qtext (printable US-ASCII excluding " and \), or
- // FWS (almost; we're ignoring CRLF)
- qsb = append(qsb, r)
-
- case r == '"':
- break Loop
-
- case r == '\\':
- escaped = true
-
- default:
- return "", fmt.Errorf("mail: bad character in quoted-string: %q", r)
-
- }
-
- i += size
- }
- p.s = p.s[i+1:]
- return string(qsb), nil
-}
-
-// consumeAtom parses an RFC 5322 atom at the start of p.
-// If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
-// If permissive is true, consumeAtom will not fail on:
-// - leading/trailing/double dots in the atom (see golang.org/issue/4938)
-func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) {
- i := 0
-
-Loop:
- for {
- r, size := utf8.DecodeRuneInString(p.s[i:])
- switch {
- case size == 1 && r == utf8.RuneError:
- return "", fmt.Errorf("mail: invalid utf-8 in address: %q", p.s)
-
- case size == 0 || !isAtext(r, dot):
- break Loop
-
- default:
- i += size
-
- }
- }
-
- if i == 0 {
- return "", errors.New("mail: invalid string")
- }
- atom, p.s = p.s[:i], p.s[i:]
- if !permissive {
- if strings.HasPrefix(atom, ".") {
- return "", errors.New("mail: leading dot in atom")
- }
- if strings.Contains(atom, "..") {
- return "", errors.New("mail: double dot in atom")
- }
- if strings.HasSuffix(atom, ".") {
- return "", errors.New("mail: trailing dot in atom")
- }
- }
- return atom, nil
-}
-
-func (p *addrParser) consumeDisplayNameComment() (string, error) {
- if !p.consume('(') {
- return "", errors.New("mail: comment does not start with (")
- }
- comment, ok := p.consumeComment()
- if !ok {
- return "", errors.New("mail: misformatted parenthetical comment")
- }
-
- // TODO(stapelberg): parse quoted-string within comment
- words := strings.FieldsFunc(comment, func(r rune) bool { return r == ' ' || r == '\t' })
- for idx, word := range words {
- decoded, isEncoded, err := p.decodeRFC2047Word(word)
- if err != nil {
- return "", err
- }
- if isEncoded {
- words[idx] = decoded
- }
- }
-
- return strings.Join(words, " "), nil
-}
-
-func (p *addrParser) consume(c byte) bool {
- if p.empty() || p.peek() != c {
- return false
- }
- p.s = p.s[1:]
- return true
-}
-
-// skipSpace skips the leading space and tab characters.
-func (p *addrParser) skipSpace() {
- p.s = strings.TrimLeft(p.s, " \t")
-}
-
-func (p *addrParser) peek() byte {
- return p.s[0]
-}
-
-func (p *addrParser) empty() bool {
- return p.len() == 0
-}
-
-func (p *addrParser) len() int {
- return len(p.s)
-}
-
-// skipCFWS skips CFWS as defined in RFC5322.
-func (p *addrParser) skipCFWS() bool {
- p.skipSpace()
-
- for {
- if !p.consume('(') {
- break
- }
-
- if _, ok := p.consumeComment(); !ok {
- return false
- }
-
- p.skipSpace()
- }
-
- return true
-}
-
-func (p *addrParser) consumeComment() (string, bool) {
- // '(' already consumed.
- depth := 1
-
- var comment string
- for {
- if p.empty() || depth == 0 {
- break
- }
-
- if p.peek() == '\\' && p.len() > 1 {
- p.s = p.s[1:]
- } else if p.peek() == '(' {
- depth++
- } else if p.peek() == ')' {
- depth--
- }
- if depth > 0 {
- comment += p.s[:1]
- }
- p.s = p.s[1:]
- }
-
- return comment, depth == 0
-}
-
-func (p *addrParser) decodeRFC2047Word(s string) (word string, isEncoded bool, err error) {
- dec := p.dec
- if dec == nil {
- dec = &rfc2047Decoder
- }
-
- // Substitute our own CharsetReader function so that we can tell
- // whether an error from the Decode method was due to the
- // CharsetReader (meaning the charset is invalid).
- // We used to look for the charsetError type in the error result,
- // but that behaves badly with CharsetReaders other than the
- // one in rfc2047Decoder.
- adec := *dec
- charsetReaderError := false
- adec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
- if dec.CharsetReader == nil {
- charsetReaderError = true
- return nil, charsetError(charset)
- }
- r, err := dec.CharsetReader(charset, input)
- if err != nil {
- charsetReaderError = true
- }
- return r, err
- }
- word, err = adec.Decode(s)
- if err == nil {
- return word, true, nil
- }
-
- // If the error came from the character set reader
- // (meaning the character set itself is invalid
- // but the decoding worked fine until then),
- // return the original text and the error,
- // with isEncoded=true.
- if charsetReaderError {
- return s, true, err
- }
-
- // Ignore invalid RFC 2047 encoded-word errors.
- return s, false, nil
-}
-
-var rfc2047Decoder = mime.WordDecoder{
- CharsetReader: func(charset string, input io.Reader) (io.Reader, error) {
- return nil, charsetError(charset)
- },
-}
-
-type charsetError string
-
-func (e charsetError) Error() string {
- return fmt.Sprintf("charset not supported: %q", string(e))
-}
-
-// isAtext reports whether r is an RFC 5322 atext character.
-// If dot is true, period is included.
-func isAtext(r rune, dot bool) bool {
- switch r {
- case '.':
- return dot
-
- // RFC 5322 3.2.3. specials
- case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '"': // RFC 5322 3.2.3. specials
- return false
- }
- return isVchar(r)
-}
-
-// isQtext reports whether r is an RFC 5322 qtext character.
-func isQtext(r rune) bool {
- // Printable US-ASCII, excluding backslash or quote.
- if r == '\\' || r == '"' {
- return false
- }
- return isVchar(r)
-}
-
-// quoteString renders a string as an RFC 5322 quoted-string.
-func quoteString(s string) string {
- var b strings.Builder
- b.WriteByte('"')
- for _, r := range s {
- if isQtext(r) || isWSP(r) {
- b.WriteRune(r)
- } else if isVchar(r) {
- b.WriteByte('\\')
- b.WriteRune(r)
- }
- }
- b.WriteByte('"')
- return b.String()
-}
-
-// isVchar reports whether r is an RFC 5322 VCHAR character.
-func isVchar(r rune) bool {
- // Visible (printing) characters.
- return '!' <= r && r <= '~' || isMultibyte(r)
-}
-
-// isMultibyte reports whether r is a multi-byte UTF-8 character
-// as supported by RFC 6532.
-func isMultibyte(r rune) bool {
- return r >= utf8.RuneSelf
-}
-
-// isWSP reports whether r is a WSP (white space).
-// WSP is a space or horizontal tab (RFC 5234 Appendix B).
-func isWSP(r rune) bool {
- return r == ' ' || r == '\t'
-}
diff --git a/contrib/go/_std_1.22/src/net/netip/leaf_alts.go b/contrib/go/_std_1.22/src/net/netip/leaf_alts.go
deleted file mode 100644
index d887bed62733..000000000000
--- a/contrib/go/_std_1.22/src/net/netip/leaf_alts.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021 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.
-
-// Stuff that exists in std, but we can't use due to being a dependency
-// of net, for go/build deps_test policy reasons.
-
-package netip
-
-func beUint64(b []byte) uint64 {
- _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
- return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
- uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
-}
-
-func bePutUint64(b []byte, v uint64) {
- _ = b[7] // early bounds check to guarantee safety of writes below
- b[0] = byte(v >> 56)
- b[1] = byte(v >> 48)
- b[2] = byte(v >> 40)
- b[3] = byte(v >> 32)
- b[4] = byte(v >> 24)
- b[5] = byte(v >> 16)
- b[6] = byte(v >> 8)
- b[7] = byte(v)
-}
-
-func bePutUint32(b []byte, v uint32) {
- _ = b[3] // early bounds check to guarantee safety of writes below
- b[0] = byte(v >> 24)
- b[1] = byte(v >> 16)
- b[2] = byte(v >> 8)
- b[3] = byte(v)
-}
-
-func leUint16(b []byte) uint16 {
- _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
- return uint16(b[0]) | uint16(b[1])<<8
-}
-
-func lePutUint16(b []byte, v uint16) {
- _ = b[1] // early bounds check to guarantee safety of writes below
- b[0] = byte(v)
- b[1] = byte(v >> 8)
-}
diff --git a/contrib/go/_std_1.22/src/net/netip/ya.make b/contrib/go/_std_1.22/src/net/netip/ya.make
deleted file mode 100644
index 644b119e6d34..000000000000
--- a/contrib/go/_std_1.22/src/net/netip/ya.make
+++ /dev/null
@@ -1,9 +0,0 @@
-GO_LIBRARY()
-IF (TRUE)
- SRCS(
- leaf_alts.go
- netip.go
- uint128.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/net/parse.go b/contrib/go/_std_1.22/src/net/parse.go
deleted file mode 100644
index 29dffad43cf4..000000000000
--- a/contrib/go/_std_1.22/src/net/parse.go
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright 2009 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.
-
-// Simple file i/o and string manipulation, to avoid
-// depending on strconv and bufio and strings.
-
-package net
-
-import (
- "internal/bytealg"
- "io"
- "os"
- "time"
-)
-
-type file struct {
- file *os.File
- data []byte
- atEOF bool
-}
-
-func (f *file) close() { f.file.Close() }
-
-func (f *file) getLineFromData() (s string, ok bool) {
- data := f.data
- i := 0
- for i = 0; i < len(data); i++ {
- if data[i] == '\n' {
- s = string(data[0:i])
- ok = true
- // move data
- i++
- n := len(data) - i
- copy(data[0:], data[i:])
- f.data = data[0:n]
- return
- }
- }
- if f.atEOF && len(f.data) > 0 {
- // EOF, return all we have
- s = string(data)
- f.data = f.data[0:0]
- ok = true
- }
- return
-}
-
-func (f *file) readLine() (s string, ok bool) {
- if s, ok = f.getLineFromData(); ok {
- return
- }
- if len(f.data) < cap(f.data) {
- ln := len(f.data)
- n, err := io.ReadFull(f.file, f.data[ln:cap(f.data)])
- if n >= 0 {
- f.data = f.data[0 : ln+n]
- }
- if err == io.EOF || err == io.ErrUnexpectedEOF {
- f.atEOF = true
- }
- }
- s, ok = f.getLineFromData()
- return
-}
-
-func (f *file) stat() (mtime time.Time, size int64, err error) {
- st, err := f.file.Stat()
- if err != nil {
- return time.Time{}, 0, err
- }
- return st.ModTime(), st.Size(), nil
-}
-
-func open(name string) (*file, error) {
- fd, err := os.Open(name)
- if err != nil {
- return nil, err
- }
- return &file{fd, make([]byte, 0, 64*1024), false}, nil
-}
-
-func stat(name string) (mtime time.Time, size int64, err error) {
- st, err := os.Stat(name)
- if err != nil {
- return time.Time{}, 0, err
- }
- return st.ModTime(), st.Size(), nil
-}
-
-// Count occurrences in s of any bytes in t.
-func countAnyByte(s string, t string) int {
- n := 0
- for i := 0; i < len(s); i++ {
- if bytealg.IndexByteString(t, s[i]) >= 0 {
- n++
- }
- }
- return n
-}
-
-// Split s at any bytes in t.
-func splitAtBytes(s string, t string) []string {
- a := make([]string, 1+countAnyByte(s, t))
- n := 0
- last := 0
- for i := 0; i < len(s); i++ {
- if bytealg.IndexByteString(t, s[i]) >= 0 {
- if last < i {
- a[n] = s[last:i]
- n++
- }
- last = i + 1
- }
- }
- if last < len(s) {
- a[n] = s[last:]
- n++
- }
- return a[0:n]
-}
-
-func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
-
-// Bigger than we need, not too big to worry about overflow
-const big = 0xFFFFFF
-
-// Decimal to integer.
-// Returns number, characters consumed, success.
-func dtoi(s string) (n int, i int, ok bool) {
- n = 0
- for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
- n = n*10 + int(s[i]-'0')
- if n >= big {
- return big, i, false
- }
- }
- if i == 0 {
- return 0, 0, false
- }
- return n, i, true
-}
-
-// Hexadecimal to integer.
-// Returns number, characters consumed, success.
-func xtoi(s string) (n int, i int, ok bool) {
- n = 0
- for i = 0; i < len(s); i++ {
- if '0' <= s[i] && s[i] <= '9' {
- n *= 16
- n += int(s[i] - '0')
- } else if 'a' <= s[i] && s[i] <= 'f' {
- n *= 16
- n += int(s[i]-'a') + 10
- } else if 'A' <= s[i] && s[i] <= 'F' {
- n *= 16
- n += int(s[i]-'A') + 10
- } else {
- break
- }
- if n >= big {
- return 0, i, false
- }
- }
- if i == 0 {
- return 0, i, false
- }
- return n, i, true
-}
-
-// xtoi2 converts the next two hex digits of s into a byte.
-// If s is longer than 2 bytes then the third byte must be e.
-// If the first two bytes of s are not hex digits or the third byte
-// does not match e, false is returned.
-func xtoi2(s string, e byte) (byte, bool) {
- if len(s) > 2 && s[2] != e {
- return 0, false
- }
- n, ei, ok := xtoi(s[:2])
- return byte(n), ok && ei == 2
-}
-
-// hasUpperCase tells whether the given string contains at least one upper-case.
-func hasUpperCase(s string) bool {
- for i := range s {
- if 'A' <= s[i] && s[i] <= 'Z' {
- return true
- }
- }
- return false
-}
-
-// lowerASCIIBytes makes x ASCII lowercase in-place.
-func lowerASCIIBytes(x []byte) {
- for i, b := range x {
- if 'A' <= b && b <= 'Z' {
- x[i] += 'a' - 'A'
- }
- }
-}
-
-// lowerASCII returns the ASCII lowercase version of b.
-func lowerASCII(b byte) byte {
- if 'A' <= b && b <= 'Z' {
- return b + ('a' - 'A')
- }
- return b
-}
-
-// trimSpace returns x without any leading or trailing ASCII whitespace.
-func trimSpace(x string) string {
- for len(x) > 0 && isSpace(x[0]) {
- x = x[1:]
- }
- for len(x) > 0 && isSpace(x[len(x)-1]) {
- x = x[:len(x)-1]
- }
- return x
-}
-
-// isSpace reports whether b is an ASCII space character.
-func isSpace(b byte) bool {
- return b == ' ' || b == '\t' || b == '\n' || b == '\r'
-}
-
-// removeComment returns line, removing any '#' byte and any following
-// bytes.
-func removeComment(line string) string {
- if i := bytealg.IndexByteString(line, '#'); i != -1 {
- return line[:i]
- }
- return line
-}
-
-// foreachField runs fn on each non-empty run of non-space bytes in x.
-// It returns the first non-nil error returned by fn.
-func foreachField(x string, fn func(field string) error) error {
- x = trimSpace(x)
- for len(x) > 0 {
- sp := bytealg.IndexByteString(x, ' ')
- if sp == -1 {
- return fn(x)
- }
- if field := trimSpace(x[:sp]); len(field) > 0 {
- if err := fn(field); err != nil {
- return err
- }
- }
- x = trimSpace(x[sp+1:])
- }
- return nil
-}
-
-// stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
-// suffix.
-func stringsHasSuffix(s, suffix string) bool {
- return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
-}
-
-// stringsHasSuffixFold reports whether s ends in suffix,
-// ASCII-case-insensitively.
-func stringsHasSuffixFold(s, suffix string) bool {
- return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix)
-}
-
-// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
-func stringsHasPrefix(s, prefix string) bool {
- return len(s) >= len(prefix) && s[:len(prefix)] == prefix
-}
-
-// stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
-// are equal, ASCII-case-insensitively.
-func stringsEqualFold(s, t string) bool {
- if len(s) != len(t) {
- return false
- }
- for i := 0; i < len(s); i++ {
- if lowerASCII(s[i]) != lowerASCII(t[i]) {
- return false
- }
- }
- return true
-}
diff --git a/contrib/go/_std_1.22/src/net/rpc/debug.go b/contrib/go/_std_1.22/src/net/rpc/debug.go
deleted file mode 100644
index 9e499fd984de..000000000000
--- a/contrib/go/_std_1.22/src/net/rpc/debug.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2009 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.
-
-package rpc
-
-/*
- Some HTML presented at http://machine:port/debug/rpc
- Lists services, their methods, and some statistics, still rudimentary.
-*/
-
-import (
- "fmt"
- "html/template"
- "net/http"
- "sort"
-)
-
-const debugText = `
-
- Services
- {{range .}}
-
- Service {{.Name}}
-
-
- Method | Calls |
- {{range .Method}}
-
- {{.Name}}({{.Type.ArgType}}, {{.Type.ReplyType}}) error |
- {{.Type.NumCalls}} |
-
- {{end}}
-
- {{end}}
-
- `
-
-var debug = template.Must(template.New("RPC debug").Parse(debugText))
-
-// If set, print log statements for internal and I/O errors.
-var debugLog = false
-
-type debugMethod struct {
- Type *methodType
- Name string
-}
-
-type methodArray []debugMethod
-
-type debugService struct {
- Service *service
- Name string
- Method methodArray
-}
-
-type serviceArray []debugService
-
-func (s serviceArray) Len() int { return len(s) }
-func (s serviceArray) Less(i, j int) bool { return s[i].Name < s[j].Name }
-func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
-func (m methodArray) Len() int { return len(m) }
-func (m methodArray) Less(i, j int) bool { return m[i].Name < m[j].Name }
-func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
-
-type debugHTTP struct {
- *Server
-}
-
-// Runs at /debug/rpc
-func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- // Build a sorted version of the data.
- var services serviceArray
- server.serviceMap.Range(func(snamei, svci any) bool {
- svc := svci.(*service)
- ds := debugService{svc, snamei.(string), make(methodArray, 0, len(svc.method))}
- for mname, method := range svc.method {
- ds.Method = append(ds.Method, debugMethod{method, mname})
- }
- sort.Sort(ds.Method)
- services = append(services, ds)
- return true
- })
- sort.Sort(services)
- err := debug.Execute(w, services)
- if err != nil {
- fmt.Fprintln(w, "rpc: error executing template:", err.Error())
- }
-}
diff --git a/contrib/go/_std_1.22/src/net/sendfile_linux.go b/contrib/go/_std_1.22/src/net/sendfile_linux.go
deleted file mode 100644
index 9a7d0058032f..000000000000
--- a/contrib/go/_std_1.22/src/net/sendfile_linux.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2011 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.
-
-package net
-
-import (
- "internal/poll"
- "io"
- "os"
-)
-
-// sendFile copies the contents of r to c using the sendfile
-// system call to minimize copies.
-//
-// if handled == true, sendFile returns the number (potentially zero) of bytes
-// copied and any non-EOF error.
-//
-// if handled == false, sendFile performed no work.
-func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
- var remain int64 = 1<<63 - 1 // by default, copy until EOF
-
- lr, ok := r.(*io.LimitedReader)
- if ok {
- remain, r = lr.N, lr.R
- if remain <= 0 {
- return 0, nil, true
- }
- }
- f, ok := r.(*os.File)
- if !ok {
- return 0, nil, false
- }
-
- sc, err := f.SyscallConn()
- if err != nil {
- return 0, nil, false
- }
-
- var werr error
- err = sc.Read(func(fd uintptr) bool {
- written, werr, handled = poll.SendFile(&c.pfd, int(fd), remain)
- return true
- })
- if err == nil {
- err = werr
- }
-
- if lr != nil {
- lr.N = remain - written
- }
- return written, wrapSyscallError("sendfile", err), handled
-}
diff --git a/contrib/go/_std_1.22/src/net/sendfile_stub.go b/contrib/go/_std_1.22/src/net/sendfile_stub.go
deleted file mode 100644
index a4fdd99ffec2..000000000000
--- a/contrib/go/_std_1.22/src/net/sendfile_stub.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2011 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.
-
-//go:build aix || js || netbsd || openbsd || ios || wasip1
-
-package net
-
-import "io"
-
-func sendFile(c *netFD, r io.Reader) (n int64, err error, handled bool) {
- return 0, nil, false
-}
diff --git a/contrib/go/_std_1.22/src/net/sendfile_windows.go b/contrib/go/_std_1.22/src/net/sendfile_windows.go
deleted file mode 100644
index 59b1b0d5c1dd..000000000000
--- a/contrib/go/_std_1.22/src/net/sendfile_windows.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2011 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.
-
-package net
-
-import (
- "internal/poll"
- "io"
- "os"
- "syscall"
-)
-
-// sendFile copies the contents of r to c using the TransmitFile
-// system call to minimize copies.
-//
-// if handled == true, sendFile returns the number of bytes copied and any
-// non-EOF error.
-//
-// if handled == false, sendFile performed no work.
-func sendFile(fd *netFD, r io.Reader) (written int64, err error, handled bool) {
- var n int64 = 0 // by default, copy until EOF.
-
- lr, ok := r.(*io.LimitedReader)
- if ok {
- n, r = lr.N, lr.R
- if n <= 0 {
- return 0, nil, true
- }
- }
-
- f, ok := r.(*os.File)
- if !ok {
- return 0, nil, false
- }
-
- written, err = poll.SendFile(&fd.pfd, syscall.Handle(f.Fd()), n)
- if err != nil {
- err = wrapSyscallError("transmitfile", err)
- }
-
- // If any byte was copied, regardless of any error
- // encountered mid-way, handled must be set to true.
- handled = written > 0
-
- return
-}
diff --git a/contrib/go/_std_1.22/src/net/sock_cloexec.go b/contrib/go/_std_1.22/src/net/sock_cloexec.go
deleted file mode 100644
index 9eeb89746b9e..000000000000
--- a/contrib/go/_std_1.22/src/net/sock_cloexec.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 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.
-
-// This file implements sysSocket for platforms that provide a fast path for
-// setting SetNonblock and CloseOnExec.
-
-//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris
-
-package net
-
-import (
- "internal/poll"
- "os"
- "syscall"
-)
-
-// Wrapper around the socket system call that marks the returned file
-// descriptor as nonblocking and close-on-exec.
-func sysSocket(family, sotype, proto int) (int, error) {
- s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto)
- // TODO: We can remove the fallback on Linux and *BSD,
- // as currently supported versions all support accept4
- // with SOCK_CLOEXEC, but Solaris does not. See issue #59359.
- switch err {
- case nil:
- return s, nil
- default:
- return -1, os.NewSyscallError("socket", err)
- case syscall.EPROTONOSUPPORT, syscall.EINVAL:
- }
-
- // See ../syscall/exec_unix.go for description of ForkLock.
- syscall.ForkLock.RLock()
- s, err = socketFunc(family, sotype, proto)
- if err == nil {
- syscall.CloseOnExec(s)
- }
- syscall.ForkLock.RUnlock()
- if err != nil {
- return -1, os.NewSyscallError("socket", err)
- }
- if err = syscall.SetNonblock(s, true); err != nil {
- poll.CloseFunc(s)
- return -1, os.NewSyscallError("setnonblock", err)
- }
- return s, nil
-}
diff --git a/contrib/go/_std_1.22/src/net/splice_linux.go b/contrib/go/_std_1.22/src/net/splice_linux.go
deleted file mode 100644
index bdafcb59ab84..000000000000
--- a/contrib/go/_std_1.22/src/net/splice_linux.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2018 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.
-
-package net
-
-import (
- "internal/poll"
- "io"
-)
-
-// spliceFrom transfers data from r to c using the splice system call to minimize
-// copies from and to userspace. c must be a TCP connection.
-// Currently, spliceFrom is only enabled if r is a TCP or a stream-oriented Unix connection.
-//
-// If spliceFrom returns handled == false, it has performed no work.
-func spliceFrom(c *netFD, r io.Reader) (written int64, err error, handled bool) {
- var remain int64 = 1<<63 - 1 // by default, copy until EOF
- lr, ok := r.(*io.LimitedReader)
- if ok {
- remain, r = lr.N, lr.R
- if remain <= 0 {
- return 0, nil, true
- }
- }
-
- var s *netFD
- switch v := r.(type) {
- case *TCPConn:
- s = v.fd
- case tcpConnWithoutWriteTo:
- s = v.fd
- case *UnixConn:
- if v.fd.net != "unix" {
- return 0, nil, false
- }
- s = v.fd
- default:
- return 0, nil, false
- }
-
- written, handled, sc, err := poll.Splice(&c.pfd, &s.pfd, remain)
- if lr != nil {
- lr.N -= written
- }
- return written, wrapSyscallError(sc, err), handled
-}
-
-// spliceTo transfers data from c to w using the splice system call to minimize
-// copies from and to userspace. c must be a TCP connection.
-// Currently, spliceTo is only enabled if w is a stream-oriented Unix connection.
-//
-// If spliceTo returns handled == false, it has performed no work.
-func spliceTo(w io.Writer, c *netFD) (written int64, err error, handled bool) {
- uc, ok := w.(*UnixConn)
- if !ok || uc.fd.net != "unix" {
- return
- }
-
- written, handled, sc, err := poll.Splice(&uc.fd.pfd, &c.pfd, 1<<63-1)
- return written, wrapSyscallError(sc, err), handled
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_darwin.go b/contrib/go/_std_1.22/src/net/tcpsockopt_darwin.go
deleted file mode 100644
index 53c6756e33e0..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_darwin.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2009 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.
-
-package net
-
-import (
- "runtime"
- "syscall"
- "time"
-)
-
-// syscall.TCP_KEEPINTVL is missing on some darwin architectures.
-const sysTCP_KEEPINTVL = 0x101
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- // The kernel expects seconds so round to next highest second.
- secs := int(roundDurationUp(d, time.Second))
- if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err != nil {
- return wrapSyscallError("setsockopt", err)
- }
- err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs)
- runtime.KeepAlive(fd)
- return wrapSyscallError("setsockopt", err)
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_dragonfly.go b/contrib/go/_std_1.22/src/net/tcpsockopt_dragonfly.go
deleted file mode 100644
index b473c02b6867..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_dragonfly.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2009 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.
-
-package net
-
-import (
- "runtime"
- "syscall"
- "time"
-)
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- // The kernel expects milliseconds so round to next highest
- // millisecond.
- msecs := int(roundDurationUp(d, time.Millisecond))
- if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, msecs); err != nil {
- return wrapSyscallError("setsockopt", err)
- }
- err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, msecs)
- runtime.KeepAlive(fd)
- return wrapSyscallError("setsockopt", err)
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_openbsd.go b/contrib/go/_std_1.22/src/net/tcpsockopt_openbsd.go
deleted file mode 100644
index 10e1bef3e5aa..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_openbsd.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 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.
-
-package net
-
-import (
- "syscall"
- "time"
-)
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- // OpenBSD has no user-settable per-socket TCP keepalive
- // options.
- return syscall.ENOPROTOOPT
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_plan9.go b/contrib/go/_std_1.22/src/net/tcpsockopt_plan9.go
deleted file mode 100644
index 264359dcf3da..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_plan9.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 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.
-
-// TCP socket options for plan9
-
-package net
-
-import (
- "internal/itoa"
- "syscall"
- "time"
-)
-
-func setNoDelay(fd *netFD, noDelay bool) error {
- return syscall.EPLAN9
-}
-
-// Set keep alive period.
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- cmd := "keepalive " + itoa.Itoa(int(d/time.Millisecond))
- _, e := fd.ctl.WriteAt([]byte(cmd), 0)
- return e
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_solaris.go b/contrib/go/_std_1.22/src/net/tcpsockopt_solaris.go
deleted file mode 100644
index f15e589dc058..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_solaris.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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.
-
-package net
-
-import (
- "runtime"
- "syscall"
- "time"
-)
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- // The kernel expects milliseconds so round to next highest
- // millisecond.
- msecs := int(roundDurationUp(d, time.Millisecond))
-
- // Normally we'd do
- // syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs)
- // here, but we can't because Solaris does not have TCP_KEEPINTVL.
- // Solaris has TCP_KEEPALIVE_ABORT_THRESHOLD, but it's not the same
- // thing, it refers to the total time until aborting (not between
- // probes), and it uses an exponential backoff algorithm instead of
- // waiting the same time between probes. We can't hope for the best
- // and do it anyway, like on Darwin, because Solaris might eventually
- // allocate a constant with a different meaning for the value of
- // TCP_KEEPINTVL on illumos.
-
- err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE_THRESHOLD, msecs)
- runtime.KeepAlive(fd)
- return wrapSyscallError("setsockopt", err)
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_stub.go b/contrib/go/_std_1.22/src/net/tcpsockopt_stub.go
deleted file mode 100644
index cef07cd6484e..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_stub.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 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.
-
-//go:build js || wasip1
-
-package net
-
-import (
- "syscall"
- "time"
-)
-
-func setNoDelay(fd *netFD, noDelay bool) error {
- return syscall.ENOPROTOOPT
-}
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- return syscall.ENOPROTOOPT
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_unix.go b/contrib/go/_std_1.22/src/net/tcpsockopt_unix.go
deleted file mode 100644
index bdcdc4023983..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_unix.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2009 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.
-
-//go:build aix || freebsd || linux || netbsd
-
-package net
-
-import (
- "runtime"
- "syscall"
- "time"
-)
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- // The kernel expects seconds so round to next highest second.
- secs := int(roundDurationUp(d, time.Second))
- if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs); err != nil {
- return wrapSyscallError("setsockopt", err)
- }
- err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs)
- runtime.KeepAlive(fd)
- return wrapSyscallError("setsockopt", err)
-}
diff --git a/contrib/go/_std_1.22/src/net/tcpsockopt_windows.go b/contrib/go/_std_1.22/src/net/tcpsockopt_windows.go
deleted file mode 100644
index 4a0b09465eea..000000000000
--- a/contrib/go/_std_1.22/src/net/tcpsockopt_windows.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2009 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.
-
-package net
-
-import (
- "os"
- "runtime"
- "syscall"
- "time"
- "unsafe"
-)
-
-func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
- // The kernel expects milliseconds so round to next highest
- // millisecond.
- msecs := uint32(roundDurationUp(d, time.Millisecond))
- ka := syscall.TCPKeepalive{
- OnOff: 1,
- Time: msecs,
- Interval: msecs,
- }
- ret := uint32(0)
- size := uint32(unsafe.Sizeof(ka))
- err := fd.pfd.WSAIoctl(syscall.SIO_KEEPALIVE_VALS, (*byte)(unsafe.Pointer(&ka)), size, nil, 0, &ret, nil, 0)
- runtime.KeepAlive(fd)
- return os.NewSyscallError("wsaioctl", err)
-}
diff --git a/contrib/go/_std_1.22/src/net/textproto/reader.go b/contrib/go/_std_1.22/src/net/textproto/reader.go
deleted file mode 100644
index 793021101b30..000000000000
--- a/contrib/go/_std_1.22/src/net/textproto/reader.go
+++ /dev/null
@@ -1,840 +0,0 @@
-// Copyright 2010 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.
-
-package textproto
-
-import (
- "bufio"
- "bytes"
- "errors"
- "fmt"
- "io"
- "math"
- "strconv"
- "strings"
- "sync"
-)
-
-// TODO: This should be a distinguishable error (ErrMessageTooLarge)
-// to allow mime/multipart to detect it.
-var errMessageTooLarge = errors.New("message too large")
-
-// A Reader implements convenience methods for reading requests
-// or responses from a text protocol network connection.
-type Reader struct {
- R *bufio.Reader
- dot *dotReader
- buf []byte // a re-usable buffer for readContinuedLineSlice
-}
-
-// NewReader returns a new [Reader] reading from r.
-//
-// To avoid denial of service attacks, the provided [bufio.Reader]
-// should be reading from an [io.LimitReader] or similar Reader to bound
-// the size of responses.
-func NewReader(r *bufio.Reader) *Reader {
- return &Reader{R: r}
-}
-
-// ReadLine reads a single line from r,
-// eliding the final \n or \r\n from the returned string.
-func (r *Reader) ReadLine() (string, error) {
- line, err := r.readLineSlice(-1)
- return string(line), err
-}
-
-// ReadLineBytes is like [Reader.ReadLine] but returns a []byte instead of a string.
-func (r *Reader) ReadLineBytes() ([]byte, error) {
- line, err := r.readLineSlice(-1)
- if line != nil {
- line = bytes.Clone(line)
- }
- return line, err
-}
-
-// readLineSlice reads a single line from r,
-// up to lim bytes long (or unlimited if lim is less than 0),
-// eliding the final \r or \r\n from the returned string.
-func (r *Reader) readLineSlice(lim int64) ([]byte, error) {
- r.closeDot()
- var line []byte
- for {
- l, more, err := r.R.ReadLine()
- if err != nil {
- return nil, err
- }
- if lim >= 0 && int64(len(line))+int64(len(l)) > lim {
- return nil, errMessageTooLarge
- }
- // Avoid the copy if the first call produced a full line.
- if line == nil && !more {
- return l, nil
- }
- line = append(line, l...)
- if !more {
- break
- }
- }
- return line, nil
-}
-
-// ReadContinuedLine reads a possibly continued line from r,
-// eliding the final trailing ASCII white space.
-// Lines after the first are considered continuations if they
-// begin with a space or tab character. In the returned data,
-// continuation lines are separated from the previous line
-// only by a single space: the newline and leading white space
-// are removed.
-//
-// For example, consider this input:
-//
-// Line 1
-// continued...
-// Line 2
-//
-// The first call to ReadContinuedLine will return "Line 1 continued..."
-// and the second will return "Line 2".
-//
-// Empty lines are never continued.
-func (r *Reader) ReadContinuedLine() (string, error) {
- line, err := r.readContinuedLineSlice(-1, noValidation)
- return string(line), err
-}
-
-// trim returns s with leading and trailing spaces and tabs removed.
-// It does not assume Unicode or UTF-8.
-func trim(s []byte) []byte {
- i := 0
- for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
- i++
- }
- n := len(s)
- for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
- n--
- }
- return s[i:n]
-}
-
-// ReadContinuedLineBytes is like [Reader.ReadContinuedLine] but
-// returns a []byte instead of a string.
-func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
- line, err := r.readContinuedLineSlice(-1, noValidation)
- if line != nil {
- line = bytes.Clone(line)
- }
- return line, err
-}
-
-// readContinuedLineSlice reads continued lines from the reader buffer,
-// returning a byte slice with all lines. The validateFirstLine function
-// is run on the first read line, and if it returns an error then this
-// error is returned from readContinuedLineSlice.
-// It reads up to lim bytes of data (or unlimited if lim is less than 0).
-func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
- if validateFirstLine == nil {
- return nil, fmt.Errorf("missing validateFirstLine func")
- }
-
- // Read the first line.
- line, err := r.readLineSlice(lim)
- if err != nil {
- return nil, err
- }
- if len(line) == 0 { // blank line - no continuation
- return line, nil
- }
-
- if err := validateFirstLine(line); err != nil {
- return nil, err
- }
-
- // Optimistically assume that we have started to buffer the next line
- // and it starts with an ASCII letter (the next header key), or a blank
- // line, so we can avoid copying that buffered data around in memory
- // and skipping over non-existent whitespace.
- if r.R.Buffered() > 1 {
- peek, _ := r.R.Peek(2)
- if len(peek) > 0 && (isASCIILetter(peek[0]) || peek[0] == '\n') ||
- len(peek) == 2 && peek[0] == '\r' && peek[1] == '\n' {
- return trim(line), nil
- }
- }
-
- // ReadByte or the next readLineSlice will flush the read buffer;
- // copy the slice into buf.
- r.buf = append(r.buf[:0], trim(line)...)
-
- if lim < 0 {
- lim = math.MaxInt64
- }
- lim -= int64(len(r.buf))
-
- // Read continuation lines.
- for r.skipSpace() > 0 {
- r.buf = append(r.buf, ' ')
- if int64(len(r.buf)) >= lim {
- return nil, errMessageTooLarge
- }
- line, err := r.readLineSlice(lim - int64(len(r.buf)))
- if err != nil {
- break
- }
- r.buf = append(r.buf, trim(line)...)
- }
- return r.buf, nil
-}
-
-// skipSpace skips R over all spaces and returns the number of bytes skipped.
-func (r *Reader) skipSpace() int {
- n := 0
- for {
- c, err := r.R.ReadByte()
- if err != nil {
- // Bufio will keep err until next read.
- break
- }
- if c != ' ' && c != '\t' {
- r.R.UnreadByte()
- break
- }
- n++
- }
- return n
-}
-
-func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err error) {
- line, err := r.ReadLine()
- if err != nil {
- return
- }
- return parseCodeLine(line, expectCode)
-}
-
-func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err error) {
- if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
- err = ProtocolError("short response: " + line)
- return
- }
- continued = line[3] == '-'
- code, err = strconv.Atoi(line[0:3])
- if err != nil || code < 100 {
- err = ProtocolError("invalid response code: " + line)
- return
- }
- message = line[4:]
- if 1 <= expectCode && expectCode < 10 && code/100 != expectCode ||
- 10 <= expectCode && expectCode < 100 && code/10 != expectCode ||
- 100 <= expectCode && expectCode < 1000 && code != expectCode {
- err = &Error{code, message}
- }
- return
-}
-
-// ReadCodeLine reads a response code line of the form
-//
-// code message
-//
-// where code is a three-digit status code and the message
-// extends to the rest of the line. An example of such a line is:
-//
-// 220 plan9.bell-labs.com ESMTP
-//
-// If the prefix of the status does not match the digits in expectCode,
-// ReadCodeLine returns with err set to &Error{code, message}.
-// For example, if expectCode is 31, an error will be returned if
-// the status is not in the range [310,319].
-//
-// If the response is multi-line, ReadCodeLine returns an error.
-//
-// An expectCode <= 0 disables the check of the status code.
-func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err error) {
- code, continued, message, err := r.readCodeLine(expectCode)
- if err == nil && continued {
- err = ProtocolError("unexpected multi-line response: " + message)
- }
- return
-}
-
-// ReadResponse reads a multi-line response of the form:
-//
-// code-message line 1
-// code-message line 2
-// ...
-// code message line n
-//
-// where code is a three-digit status code. The first line starts with the
-// code and a hyphen. The response is terminated by a line that starts
-// with the same code followed by a space. Each line in message is
-// separated by a newline (\n).
-//
-// See page 36 of RFC 959 (https://www.ietf.org/rfc/rfc959.txt) for
-// details of another form of response accepted:
-//
-// code-message line 1
-// message line 2
-// ...
-// code message line n
-//
-// If the prefix of the status does not match the digits in expectCode,
-// ReadResponse returns with err set to &Error{code, message}.
-// For example, if expectCode is 31, an error will be returned if
-// the status is not in the range [310,319].
-//
-// An expectCode <= 0 disables the check of the status code.
-func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
- code, continued, message, err := r.readCodeLine(expectCode)
- multi := continued
- for continued {
- line, err := r.ReadLine()
- if err != nil {
- return 0, "", err
- }
-
- var code2 int
- var moreMessage string
- code2, continued, moreMessage, err = parseCodeLine(line, 0)
- if err != nil || code2 != code {
- message += "\n" + strings.TrimRight(line, "\r\n")
- continued = true
- continue
- }
- message += "\n" + moreMessage
- }
- if err != nil && multi && message != "" {
- // replace one line error message with all lines (full message)
- err = &Error{code, message}
- }
- return
-}
-
-// DotReader returns a new [Reader] that satisfies Reads using the
-// decoded text of a dot-encoded block read from r.
-// The returned Reader is only valid until the next call
-// to a method on r.
-//
-// Dot encoding is a common framing used for data blocks
-// in text protocols such as SMTP. The data consists of a sequence
-// of lines, each of which ends in "\r\n". The sequence itself
-// ends at a line containing just a dot: ".\r\n". Lines beginning
-// with a dot are escaped with an additional dot to avoid
-// looking like the end of the sequence.
-//
-// The decoded form returned by the Reader's Read method
-// rewrites the "\r\n" line endings into the simpler "\n",
-// removes leading dot escapes if present, and stops with error [io.EOF]
-// after consuming (and discarding) the end-of-sequence line.
-func (r *Reader) DotReader() io.Reader {
- r.closeDot()
- r.dot = &dotReader{r: r}
- return r.dot
-}
-
-type dotReader struct {
- r *Reader
- state int
-}
-
-// Read satisfies reads by decoding dot-encoded data read from d.r.
-func (d *dotReader) Read(b []byte) (n int, err error) {
- // Run data through a simple state machine to
- // elide leading dots, rewrite trailing \r\n into \n,
- // and detect ending .\r\n line.
- const (
- stateBeginLine = iota // beginning of line; initial state; must be zero
- stateDot // read . at beginning of line
- stateDotCR // read .\r at beginning of line
- stateCR // read \r (possibly at end of line)
- stateData // reading data in middle of line
- stateEOF // reached .\r\n end marker line
- )
- br := d.r.R
- for n < len(b) && d.state != stateEOF {
- var c byte
- c, err = br.ReadByte()
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- break
- }
- switch d.state {
- case stateBeginLine:
- if c == '.' {
- d.state = stateDot
- continue
- }
- if c == '\r' {
- d.state = stateCR
- continue
- }
- d.state = stateData
-
- case stateDot:
- if c == '\r' {
- d.state = stateDotCR
- continue
- }
- if c == '\n' {
- d.state = stateEOF
- continue
- }
- d.state = stateData
-
- case stateDotCR:
- if c == '\n' {
- d.state = stateEOF
- continue
- }
- // Not part of .\r\n.
- // Consume leading dot and emit saved \r.
- br.UnreadByte()
- c = '\r'
- d.state = stateData
-
- case stateCR:
- if c == '\n' {
- d.state = stateBeginLine
- break
- }
- // Not part of \r\n. Emit saved \r
- br.UnreadByte()
- c = '\r'
- d.state = stateData
-
- case stateData:
- if c == '\r' {
- d.state = stateCR
- continue
- }
- if c == '\n' {
- d.state = stateBeginLine
- }
- }
- b[n] = c
- n++
- }
- if err == nil && d.state == stateEOF {
- err = io.EOF
- }
- if err != nil && d.r.dot == d {
- d.r.dot = nil
- }
- return
-}
-
-// closeDot drains the current DotReader if any,
-// making sure that it reads until the ending dot line.
-func (r *Reader) closeDot() {
- if r.dot == nil {
- return
- }
- buf := make([]byte, 128)
- for r.dot != nil {
- // When Read reaches EOF or an error,
- // it will set r.dot == nil.
- r.dot.Read(buf)
- }
-}
-
-// ReadDotBytes reads a dot-encoding and returns the decoded data.
-//
-// See the documentation for the [Reader.DotReader] method for details about dot-encoding.
-func (r *Reader) ReadDotBytes() ([]byte, error) {
- return io.ReadAll(r.DotReader())
-}
-
-// ReadDotLines reads a dot-encoding and returns a slice
-// containing the decoded lines, with the final \r\n or \n elided from each.
-//
-// See the documentation for the [Reader.DotReader] method for details about dot-encoding.
-func (r *Reader) ReadDotLines() ([]string, error) {
- // We could use ReadDotBytes and then Split it,
- // but reading a line at a time avoids needing a
- // large contiguous block of memory and is simpler.
- var v []string
- var err error
- for {
- var line string
- line, err = r.ReadLine()
- if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- break
- }
-
- // Dot by itself marks end; otherwise cut one dot.
- if len(line) > 0 && line[0] == '.' {
- if len(line) == 1 {
- break
- }
- line = line[1:]
- }
- v = append(v, line)
- }
- return v, err
-}
-
-var colon = []byte(":")
-
-// ReadMIMEHeader reads a MIME-style header from r.
-// The header is a sequence of possibly continued Key: Value lines
-// ending in a blank line.
-// The returned map m maps [CanonicalMIMEHeaderKey](key) to a
-// sequence of values in the same order encountered in the input.
-//
-// For example, consider this input:
-//
-// My-Key: Value 1
-// Long-Key: Even
-// Longer Value
-// My-Key: Value 2
-//
-// Given that input, ReadMIMEHeader returns the map:
-//
-// map[string][]string{
-// "My-Key": {"Value 1", "Value 2"},
-// "Long-Key": {"Even Longer Value"},
-// }
-func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
- return readMIMEHeader(r, math.MaxInt64, math.MaxInt64)
-}
-
-// readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
-// It is called by the mime/multipart package.
-func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) {
- // Avoid lots of small slice allocations later by allocating one
- // large one ahead of time which we'll cut up into smaller
- // slices. If this isn't big enough later, we allocate small ones.
- var strs []string
- hint := r.upcomingHeaderKeys()
- if hint > 0 {
- if hint > 1000 {
- hint = 1000 // set a cap to avoid overallocation
- }
- strs = make([]string, hint)
- }
-
- m := make(MIMEHeader, hint)
-
- // Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes per entry.
- // Benchmarking map creation as of go1.20, a one-entry MIMEHeader is 416 bytes and large
- // MIMEHeaders average about 200 bytes per entry.
- maxMemory -= 400
- const mapEntryOverhead = 200
-
- // The first line cannot start with a leading space.
- if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
- const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
- line, err := r.readLineSlice(errorLimit)
- if err != nil {
- return m, err
- }
- return m, ProtocolError("malformed MIME header initial line: " + string(line))
- }
-
- for {
- kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon)
- if len(kv) == 0 {
- return m, err
- }
-
- // Key ends at first colon.
- k, v, ok := bytes.Cut(kv, colon)
- if !ok {
- return m, ProtocolError("malformed MIME header line: " + string(kv))
- }
- key, ok := canonicalMIMEHeaderKey(k)
- if !ok {
- return m, ProtocolError("malformed MIME header line: " + string(kv))
- }
- for _, c := range v {
- if !validHeaderValueByte(c) {
- return m, ProtocolError("malformed MIME header line: " + string(kv))
- }
- }
-
- // As per RFC 7230 field-name is a token, tokens consist of one or more chars.
- // We could return a ProtocolError here, but better to be liberal in what we
- // accept, so if we get an empty key, skip it.
- if key == "" {
- continue
- }
-
- maxHeaders--
- if maxHeaders < 0 {
- return nil, errMessageTooLarge
- }
-
- // Skip initial spaces in value.
- value := string(bytes.TrimLeft(v, " \t"))
-
- vv := m[key]
- if vv == nil {
- maxMemory -= int64(len(key))
- maxMemory -= mapEntryOverhead
- }
- maxMemory -= int64(len(value))
- if maxMemory < 0 {
- return m, errMessageTooLarge
- }
- if vv == nil && len(strs) > 0 {
- // More than likely this will be a single-element key.
- // Most headers aren't multi-valued.
- // Set the capacity on strs[0] to 1, so any future append
- // won't extend the slice into the other strings.
- vv, strs = strs[:1:1], strs[1:]
- vv[0] = value
- m[key] = vv
- } else {
- m[key] = append(vv, value)
- }
-
- if err != nil {
- return m, err
- }
- }
-}
-
-// noValidation is a no-op validation func for readContinuedLineSlice
-// that permits any lines.
-func noValidation(_ []byte) error { return nil }
-
-// mustHaveFieldNameColon ensures that, per RFC 7230, the
-// field-name is on a single line, so the first line must
-// contain a colon.
-func mustHaveFieldNameColon(line []byte) error {
- if bytes.IndexByte(line, ':') < 0 {
- return ProtocolError(fmt.Sprintf("malformed MIME header: missing colon: %q", line))
- }
- return nil
-}
-
-var nl = []byte("\n")
-
-// upcomingHeaderKeys returns an approximation of the number of keys
-// that will be in this header. If it gets confused, it returns 0.
-func (r *Reader) upcomingHeaderKeys() (n int) {
- // Try to determine the 'hint' size.
- r.R.Peek(1) // force a buffer load if empty
- s := r.R.Buffered()
- if s == 0 {
- return
- }
- peek, _ := r.R.Peek(s)
- for len(peek) > 0 && n < 1000 {
- var line []byte
- line, peek, _ = bytes.Cut(peek, nl)
- if len(line) == 0 || (len(line) == 1 && line[0] == '\r') {
- // Blank line separating headers from the body.
- break
- }
- if line[0] == ' ' || line[0] == '\t' {
- // Folded continuation of the previous line.
- continue
- }
- n++
- }
- return n
-}
-
-// CanonicalMIMEHeaderKey returns the canonical format of the
-// MIME header key s. The canonicalization converts the first
-// letter and any letter following a hyphen to upper case;
-// the rest are converted to lowercase. For example, the
-// canonical key for "accept-encoding" is "Accept-Encoding".
-// MIME header keys are assumed to be ASCII only.
-// If s contains a space or invalid header field bytes, it is
-// returned without modifications.
-func CanonicalMIMEHeaderKey(s string) string {
- // Quick check for canonical encoding.
- upper := true
- for i := 0; i < len(s); i++ {
- c := s[i]
- if !validHeaderFieldByte(c) {
- return s
- }
- if upper && 'a' <= c && c <= 'z' {
- s, _ = canonicalMIMEHeaderKey([]byte(s))
- return s
- }
- if !upper && 'A' <= c && c <= 'Z' {
- s, _ = canonicalMIMEHeaderKey([]byte(s))
- return s
- }
- upper = c == '-'
- }
- return s
-}
-
-const toLower = 'a' - 'A'
-
-// validHeaderFieldByte reports whether c is a valid byte in a header
-// field name. RFC 7230 says:
-//
-// header-field = field-name ":" OWS field-value OWS
-// field-name = token
-// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
-// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
-// token = 1*tchar
-func validHeaderFieldByte(c byte) bool {
- // mask is a 128-bit bitmap with 1s for allowed bytes,
- // so that the byte c can be tested with a shift and an and.
- // If c >= 128, then 1<>64)) != 0
-}
-
-// validHeaderValueByte reports whether c is a valid byte in a header
-// field value. RFC 7230 says:
-//
-// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
-// field-vchar = VCHAR / obs-text
-// obs-text = %x80-FF
-//
-// RFC 5234 says:
-//
-// HTAB = %x09
-// SP = %x20
-// VCHAR = %x21-7E
-func validHeaderValueByte(c byte) bool {
- // mask is a 128-bit bitmap with 1s for allowed bytes,
- // so that the byte c can be tested with a shift and an and.
- // If c >= 128, then 1<>64)) == 0
-}
-
-// canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
-// allowed to mutate the provided byte slice before returning the
-// string.
-//
-// For invalid inputs (if a contains spaces or non-token bytes), a
-// is unchanged and a string copy is returned.
-//
-// ok is true if the header key contains only valid characters and spaces.
-// ReadMIMEHeader accepts header keys containing spaces, but does not
-// canonicalize them.
-func canonicalMIMEHeaderKey(a []byte) (_ string, ok bool) {
- // See if a looks like a header key. If not, return it unchanged.
- noCanon := false
- for _, c := range a {
- if validHeaderFieldByte(c) {
- continue
- }
- // Don't canonicalize.
- if c == ' ' {
- // We accept invalid headers with a space before the
- // colon, but must not canonicalize them.
- // See https://go.dev/issue/34540.
- noCanon = true
- continue
- }
- return string(a), false
- }
- if noCanon {
- return string(a), true
- }
-
- upper := true
- for i, c := range a {
- // Canonicalize: first letter upper case
- // and upper case after each dash.
- // (Host, User-Agent, If-Modified-Since).
- // MIME headers are ASCII only, so no Unicode issues.
- if upper && 'a' <= c && c <= 'z' {
- c -= toLower
- } else if !upper && 'A' <= c && c <= 'Z' {
- c += toLower
- }
- a[i] = c
- upper = c == '-' // for next time
- }
- commonHeaderOnce.Do(initCommonHeader)
- // The compiler recognizes m[string(byteSlice)] as a special
- // case, so a copy of a's bytes into a new string does not
- // happen in this map lookup:
- if v := commonHeader[string(a)]; v != "" {
- return v, true
- }
- return string(a), true
-}
-
-// commonHeader interns common header strings.
-var commonHeader map[string]string
-
-var commonHeaderOnce sync.Once
-
-func initCommonHeader() {
- commonHeader = make(map[string]string)
- for _, v := range []string{
- "Accept",
- "Accept-Charset",
- "Accept-Encoding",
- "Accept-Language",
- "Accept-Ranges",
- "Cache-Control",
- "Cc",
- "Connection",
- "Content-Id",
- "Content-Language",
- "Content-Length",
- "Content-Transfer-Encoding",
- "Content-Type",
- "Cookie",
- "Date",
- "Dkim-Signature",
- "Etag",
- "Expires",
- "From",
- "Host",
- "If-Modified-Since",
- "If-None-Match",
- "In-Reply-To",
- "Last-Modified",
- "Location",
- "Message-Id",
- "Mime-Version",
- "Pragma",
- "Received",
- "Return-Path",
- "Server",
- "Set-Cookie",
- "Subject",
- "To",
- "User-Agent",
- "Via",
- "X-Forwarded-For",
- "X-Imforwards",
- "X-Powered-By",
- } {
- commonHeader[v] = v
- }
-}
diff --git a/contrib/go/_std_1.22/src/net/ya.make b/contrib/go/_std_1.22/src/net/ya.make
deleted file mode 100644
index a6cdbd8d6caf..000000000000
--- a/contrib/go/_std_1.22/src/net/ya.make
+++ /dev/null
@@ -1,325 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED)
- SRCS(
- addrselect.go
- cgo_darwin.go
- cgo_unix.go
- cgo_unix_syscall.go
- conf.go
- dial.go
- dnsclient.go
- dnsclient_unix.go
- dnsconfig.go
- dnsconfig_unix.go
- error_posix.go
- error_unix.go
- fd_posix.go
- fd_unix.go
- file.go
- file_unix.go
- hook.go
- hook_unix.go
- hosts.go
- interface.go
- interface_bsd.go
- interface_darwin.go
- ip.go
- iprawsock.go
- iprawsock_posix.go
- ipsock.go
- ipsock_posix.go
- lookup.go
- lookup_unix.go
- mac.go
- mptcpsock_stub.go
- net.go
- netcgo_off.go
- netgo_off.go
- nss.go
- parse.go
- pipe.go
- port.go
- port_unix.go
- rawconn.go
- rlimit_unix.go
- sendfile_unix_alt.go
- sock_bsd.go
- sock_posix.go
- sockaddr_posix.go
- sockopt_bsd.go
- sockopt_posix.go
- sockoptip_bsdvar.go
- sockoptip_posix.go
- splice_stub.go
- sys_cloexec.go
- tcpsock.go
- tcpsock_posix.go
- tcpsockopt_darwin.go
- tcpsockopt_posix.go
- udpsock.go
- udpsock_posix.go
- unixsock.go
- unixsock_posix.go
- unixsock_readmsg_cloexec.go
- writev_unix.go
- )
-
-IF (CGO_ENABLED)
- CGO_SRCS(
- cgo_unix_cgo_darwin.go
- )
-ENDIF()
-ELSEIF (OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- addrselect.go
- cgo_darwin.go
- cgo_unix.go
- cgo_unix_syscall.go
- conf.go
- dial.go
- dnsclient.go
- dnsclient_unix.go
- dnsconfig.go
- dnsconfig_unix.go
- error_posix.go
- error_unix.go
- fd_posix.go
- fd_unix.go
- file.go
- file_unix.go
- hook.go
- hook_unix.go
- hosts.go
- interface.go
- interface_bsd.go
- interface_darwin.go
- ip.go
- iprawsock.go
- iprawsock_posix.go
- ipsock.go
- ipsock_posix.go
- lookup.go
- lookup_unix.go
- mac.go
- mptcpsock_stub.go
- net.go
- netcgo_off.go
- netgo_off.go
- nss.go
- parse.go
- pipe.go
- port.go
- port_unix.go
- rawconn.go
- rlimit_unix.go
- sendfile_unix_alt.go
- sock_bsd.go
- sock_posix.go
- sockaddr_posix.go
- sockopt_bsd.go
- sockopt_posix.go
- sockoptip_bsdvar.go
- sockoptip_posix.go
- splice_stub.go
- sys_cloexec.go
- tcpsock.go
- tcpsock_posix.go
- tcpsockopt_darwin.go
- tcpsockopt_posix.go
- udpsock.go
- udpsock_posix.go
- unixsock.go
- unixsock_posix.go
- unixsock_readmsg_cloexec.go
- writev_unix.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED)
- SRCS(
- addrselect.go
- cgo_unix.go
- conf.go
- dial.go
- dnsclient.go
- dnsclient_unix.go
- dnsconfig.go
- dnsconfig_unix.go
- error_posix.go
- error_unix.go
- fd_posix.go
- fd_unix.go
- file.go
- file_unix.go
- hook.go
- hook_unix.go
- hosts.go
- interface.go
- interface_linux.go
- ip.go
- iprawsock.go
- iprawsock_posix.go
- ipsock.go
- ipsock_posix.go
- lookup.go
- lookup_unix.go
- mac.go
- mptcpsock_linux.go
- net.go
- netcgo_off.go
- netgo_off.go
- nss.go
- parse.go
- pipe.go
- port.go
- port_unix.go
- rawconn.go
- rlimit_unix.go
- sendfile_linux.go
- sock_cloexec.go
- sock_linux.go
- sock_posix.go
- sockaddr_posix.go
- sockopt_linux.go
- sockopt_posix.go
- sockoptip_linux.go
- sockoptip_posix.go
- splice_linux.go
- tcpsock.go
- tcpsock_posix.go
- tcpsockopt_posix.go
- tcpsockopt_unix.go
- udpsock.go
- udpsock_posix.go
- unixsock.go
- unixsock_posix.go
- unixsock_readmsg_cmsg_cloexec.go
- writev_unix.go
- )
-
-IF (CGO_ENABLED)
- CGO_SRCS(
- cgo_linux.go
- cgo_resnew.go
- cgo_socknew.go
- cgo_unix_cgo.go
- cgo_unix_cgo_res.go
- )
-ENDIF()
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- addrselect.go
- cgo_stub.go
- conf.go
- dial.go
- dnsclient.go
- dnsclient_unix.go
- dnsconfig.go
- dnsconfig_unix.go
- error_posix.go
- error_unix.go
- fd_posix.go
- fd_unix.go
- file.go
- file_unix.go
- hook.go
- hook_unix.go
- hosts.go
- interface.go
- interface_linux.go
- ip.go
- iprawsock.go
- iprawsock_posix.go
- ipsock.go
- ipsock_posix.go
- lookup.go
- lookup_unix.go
- mac.go
- mptcpsock_linux.go
- net.go
- netcgo_off.go
- netgo_off.go
- nss.go
- parse.go
- pipe.go
- port.go
- port_unix.go
- rawconn.go
- rlimit_unix.go
- sendfile_linux.go
- sock_cloexec.go
- sock_linux.go
- sock_posix.go
- sockaddr_posix.go
- sockopt_linux.go
- sockopt_posix.go
- sockoptip_linux.go
- sockoptip_posix.go
- splice_linux.go
- tcpsock.go
- tcpsock_posix.go
- tcpsockopt_posix.go
- tcpsockopt_unix.go
- udpsock.go
- udpsock_posix.go
- unixsock.go
- unixsock_posix.go
- unixsock_readmsg_cmsg_cloexec.go
- writev_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- addrselect.go
- conf.go
- dial.go
- dnsclient.go
- dnsclient_unix.go
- dnsconfig.go
- dnsconfig_windows.go
- error_posix.go
- error_windows.go
- fd_posix.go
- fd_windows.go
- file.go
- file_windows.go
- hook.go
- hook_windows.go
- hosts.go
- interface.go
- interface_windows.go
- ip.go
- iprawsock.go
- iprawsock_posix.go
- ipsock.go
- ipsock_posix.go
- lookup.go
- lookup_windows.go
- mac.go
- mptcpsock_stub.go
- net.go
- netcgo_off.go
- netgo_off.go
- nss.go
- parse.go
- pipe.go
- port.go
- rawconn.go
- sendfile_windows.go
- sock_posix.go
- sock_windows.go
- sockaddr_posix.go
- sockopt_posix.go
- sockopt_windows.go
- sockoptip_posix.go
- sockoptip_windows.go
- splice_stub.go
- tcpsock.go
- tcpsock_posix.go
- tcpsockopt_posix.go
- tcpsockopt_windows.go
- udpsock.go
- udpsock_posix.go
- unixsock.go
- unixsock_posix.go
- unixsock_readmsg_other.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/os/dir.go b/contrib/go/_std_1.22/src/os/dir.go
deleted file mode 100644
index 5306bcb3ba7c..000000000000
--- a/contrib/go/_std_1.22/src/os/dir.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2016 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.
-
-package os
-
-import (
- "io/fs"
- "sort"
-)
-
-type readdirMode int
-
-const (
- readdirName readdirMode = iota
- readdirDirEntry
- readdirFileInfo
-)
-
-// Readdir reads the contents of the directory associated with file and
-// returns a slice of up to n FileInfo values, as would be returned
-// by Lstat, in directory order. Subsequent calls on the same file will yield
-// further FileInfos.
-//
-// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
-// Readdir returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is io.EOF.
-//
-// If n <= 0, Readdir returns all the FileInfo from the directory in
-// a single slice. In this case, if Readdir succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil error. If it encounters an error before the end of the
-// directory, Readdir returns the FileInfo read until that point
-// and a non-nil error.
-//
-// Most clients are better served by the more efficient ReadDir method.
-func (f *File) Readdir(n int) ([]FileInfo, error) {
- if f == nil {
- return nil, ErrInvalid
- }
- _, _, infos, err := f.readdir(n, readdirFileInfo)
- if infos == nil {
- // Readdir has historically always returned a non-nil empty slice, never nil,
- // even on error (except misuse with nil receiver above).
- // Keep it that way to avoid breaking overly sensitive callers.
- infos = []FileInfo{}
- }
- return infos, err
-}
-
-// Readdirnames reads the contents of the directory associated with file
-// and returns a slice of up to n names of files in the directory,
-// in directory order. Subsequent calls on the same file will yield
-// further names.
-//
-// If n > 0, Readdirnames returns at most n names. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is io.EOF.
-//
-// If n <= 0, Readdirnames returns all the names from the directory in
-// a single slice. In this case, if Readdirnames succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil error. If it encounters an error before the end of the
-// directory, Readdirnames returns the names read until that point and
-// a non-nil error.
-func (f *File) Readdirnames(n int) (names []string, err error) {
- if f == nil {
- return nil, ErrInvalid
- }
- names, _, _, err = f.readdir(n, readdirName)
- if names == nil {
- // Readdirnames has historically always returned a non-nil empty slice, never nil,
- // even on error (except misuse with nil receiver above).
- // Keep it that way to avoid breaking overly sensitive callers.
- names = []string{}
- }
- return names, err
-}
-
-// A DirEntry is an entry read from a directory
-// (using the ReadDir function or a File's ReadDir method).
-type DirEntry = fs.DirEntry
-
-// ReadDir reads the contents of the directory associated with the file f
-// and returns a slice of DirEntry values in directory order.
-// Subsequent calls on the same file will yield later DirEntry records in the directory.
-//
-// If n > 0, ReadDir returns at most n DirEntry records.
-// In this case, if ReadDir returns an empty slice, it will return an error explaining why.
-// At the end of a directory, the error is io.EOF.
-//
-// If n <= 0, ReadDir returns all the DirEntry records remaining in the directory.
-// When it succeeds, it returns a nil error (not io.EOF).
-func (f *File) ReadDir(n int) ([]DirEntry, error) {
- if f == nil {
- return nil, ErrInvalid
- }
- _, dirents, _, err := f.readdir(n, readdirDirEntry)
- if dirents == nil {
- // Match Readdir and Readdirnames: don't return nil slices.
- dirents = []DirEntry{}
- }
- return dirents, err
-}
-
-// testingForceReadDirLstat forces ReadDir to call Lstat, for testing that code path.
-// This can be difficult to provoke on some Unix systems otherwise.
-var testingForceReadDirLstat bool
-
-// ReadDir reads the named directory,
-// returning all its directory entries sorted by filename.
-// If an error occurs reading the directory,
-// ReadDir returns the entries it was able to read before the error,
-// along with the error.
-func ReadDir(name string) ([]DirEntry, error) {
- f, err := Open(name)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- dirs, err := f.ReadDir(-1)
- sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })
- return dirs, err
-}
diff --git a/contrib/go/_std_1.22/src/os/dir_plan9.go b/contrib/go/_std_1.22/src/os/dir_plan9.go
deleted file mode 100644
index 6ea5940e71df..000000000000
--- a/contrib/go/_std_1.22/src/os/dir_plan9.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "io"
- "io/fs"
- "syscall"
-)
-
-func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {
- // If this file has no dirinfo, create one.
- if file.dirinfo == nil {
- file.dirinfo = new(dirInfo)
- }
- d := file.dirinfo
- size := n
- if size <= 0 {
- size = 100
- n = -1
- }
- for n != 0 {
- // Refill the buffer if necessary.
- if d.bufp >= d.nbuf {
- nb, err := file.Read(d.buf[:])
-
- // Update the buffer state before checking for errors.
- d.bufp, d.nbuf = 0, nb
-
- if err != nil {
- if err == io.EOF {
- break
- }
- return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err}
- }
- if nb < syscall.STATFIXLEN {
- return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat}
- }
- }
-
- // Get a record from the buffer.
- b := d.buf[d.bufp:]
- m := int(uint16(b[0])|uint16(b[1])<<8) + 2
- if m < syscall.STATFIXLEN {
- return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat}
- }
-
- dir, err := syscall.UnmarshalDir(b[:m])
- if err != nil {
- return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err}
- }
-
- if mode == readdirName {
- names = append(names, dir.Name)
- } else {
- f := fileInfoFromStat(dir)
- if mode == readdirDirEntry {
- dirents = append(dirents, dirEntry{f})
- } else {
- infos = append(infos, f)
- }
- }
- d.bufp += m
- n--
- }
-
- if n > 0 && len(names)+len(dirents)+len(infos) == 0 {
- return nil, nil, nil, io.EOF
- }
- return names, dirents, infos, nil
-}
-
-type dirEntry struct {
- fs *fileStat
-}
-
-func (de dirEntry) Name() string { return de.fs.Name() }
-func (de dirEntry) IsDir() bool { return de.fs.IsDir() }
-func (de dirEntry) Type() FileMode { return de.fs.Mode().Type() }
-func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil }
-
-func (de dirEntry) String() string {
- return fs.FormatDirEntry(de)
-}
diff --git a/contrib/go/_std_1.22/src/os/dir_windows.go b/contrib/go/_std_1.22/src/os/dir_windows.go
deleted file mode 100644
index 4485dffdb184..000000000000
--- a/contrib/go/_std_1.22/src/os/dir_windows.go
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "internal/syscall/windows"
- "io"
- "io/fs"
- "runtime"
- "sync"
- "syscall"
- "unsafe"
-)
-
-// Auxiliary information if the File describes a directory
-type dirInfo struct {
- // buf is a slice pointer so the slice header
- // does not escape to the heap when returning
- // buf to dirBufPool.
- buf *[]byte // buffer for directory I/O
- bufp int // location of next record in buf
- vol uint32
- class uint32 // type of entries in buf
- path string // absolute directory path, empty if the file system supports FILE_ID_BOTH_DIR_INFO
-}
-
-const (
- // dirBufSize is the size of the dirInfo buffer.
- // The buffer must be big enough to hold at least a single entry.
- // The filename alone can be 512 bytes (MAX_PATH*2), and the fixed part of
- // the FILE_ID_BOTH_DIR_INFO structure is 105 bytes, so dirBufSize
- // should not be set below 1024 bytes (512+105+safety buffer).
- // Windows 8.1 and earlier only works with buffer sizes up to 64 kB.
- dirBufSize = 64 * 1024 // 64kB
-)
-
-var dirBufPool = sync.Pool{
- New: func() any {
- // The buffer must be at least a block long.
- buf := make([]byte, dirBufSize)
- return &buf
- },
-}
-
-func (d *dirInfo) close() {
- if d.buf != nil {
- dirBufPool.Put(d.buf)
- d.buf = nil
- }
-}
-
-// allowReadDirFileID indicates whether File.readdir should try to use FILE_ID_BOTH_DIR_INFO
-// if the underlying file system supports it.
-// Useful for testing purposes.
-var allowReadDirFileID = true
-
-func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) {
- // If this file has no dirinfo, create one.
- if file.dirinfo == nil {
- // vol is used by os.SameFile.
- // It is safe to query it once and reuse the value.
- // Hard links are not allowed to reference files in other volumes.
- // Junctions and symbolic links can reference files and directories in other volumes,
- // but the reparse point should still live in the parent volume.
- var vol, flags uint32
- err = windows.GetVolumeInformationByHandle(file.pfd.Sysfd, nil, 0, &vol, nil, &flags, nil, 0)
- runtime.KeepAlive(file)
- if err != nil {
- err = &PathError{Op: "readdir", Path: file.name, Err: err}
- return
- }
- file.dirinfo = new(dirInfo)
- file.dirinfo.buf = dirBufPool.Get().(*[]byte)
- file.dirinfo.vol = vol
- if allowReadDirFileID && flags&windows.FILE_SUPPORTS_OPEN_BY_FILE_ID != 0 {
- file.dirinfo.class = windows.FileIdBothDirectoryRestartInfo
- } else {
- file.dirinfo.class = windows.FileFullDirectoryRestartInfo
- // Set the directory path for use by os.SameFile, as it is possible that
- // the file system supports retrieving the file ID using GetFileInformationByHandle.
- file.dirinfo.path = file.name
- if !isAbs(file.dirinfo.path) {
- // If the path is relative, we need to convert it to an absolute path
- // in case the current directory changes between this call and a
- // call to os.SameFile.
- file.dirinfo.path, err = syscall.FullPath(file.dirinfo.path)
- if err != nil {
- err = &PathError{Op: "readdir", Path: file.name, Err: err}
- return
- }
- }
- }
- }
- d := file.dirinfo
- wantAll := n <= 0
- if wantAll {
- n = -1
- }
- for n != 0 {
- // Refill the buffer if necessary
- if d.bufp == 0 {
- err = windows.GetFileInformationByHandleEx(file.pfd.Sysfd, d.class, (*byte)(unsafe.Pointer(&(*d.buf)[0])), uint32(len(*d.buf)))
- runtime.KeepAlive(file)
- if err != nil {
- if err == syscall.ERROR_NO_MORE_FILES {
- break
- }
- if err == syscall.ERROR_FILE_NOT_FOUND &&
- (d.class == windows.FileIdBothDirectoryRestartInfo || d.class == windows.FileFullDirectoryRestartInfo) {
- // GetFileInformationByHandleEx doesn't document the return error codes when the info class is FileIdBothDirectoryRestartInfo,
- // but MS-FSA 2.1.5.6.3 [1] specifies that the underlying file system driver should return STATUS_NO_SUCH_FILE when
- // reading an empty root directory, which is mapped to ERROR_FILE_NOT_FOUND by Windows.
- // Note that some file system drivers may never return this error code, as the spec allows to return the "." and ".."
- // entries in such cases, making the directory appear non-empty.
- // The chances of false positive are very low, as we know that the directory exists, else GetVolumeInformationByHandle
- // would have failed, and that the handle is still valid, as we haven't closed it.
- // See go.dev/issue/61159.
- // [1] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/fa8194e0-53ec-413b-8315-e8fa85396fd8
- break
- }
- if s, _ := file.Stat(); s != nil && !s.IsDir() {
- err = &PathError{Op: "readdir", Path: file.name, Err: syscall.ENOTDIR}
- } else {
- err = &PathError{Op: "GetFileInformationByHandleEx", Path: file.name, Err: err}
- }
- return
- }
- if d.class == windows.FileIdBothDirectoryRestartInfo {
- d.class = windows.FileIdBothDirectoryInfo
- } else if d.class == windows.FileFullDirectoryRestartInfo {
- d.class = windows.FileFullDirectoryInfo
- }
- }
- // Drain the buffer
- var islast bool
- for n != 0 && !islast {
- var nextEntryOffset uint32
- var nameslice []uint16
- entry := unsafe.Pointer(&(*d.buf)[d.bufp])
- if d.class == windows.FileIdBothDirectoryInfo {
- info := (*windows.FILE_ID_BOTH_DIR_INFO)(entry)
- nextEntryOffset = info.NextEntryOffset
- nameslice = unsafe.Slice(&info.FileName[0], info.FileNameLength/2)
- } else {
- info := (*windows.FILE_FULL_DIR_INFO)(entry)
- nextEntryOffset = info.NextEntryOffset
- nameslice = unsafe.Slice(&info.FileName[0], info.FileNameLength/2)
- }
- d.bufp += int(nextEntryOffset)
- islast = nextEntryOffset == 0
- if islast {
- d.bufp = 0
- }
- if (len(nameslice) == 1 && nameslice[0] == '.') ||
- (len(nameslice) == 2 && nameslice[0] == '.' && nameslice[1] == '.') {
- // Ignore "." and ".." and avoid allocating a string for them.
- continue
- }
- name := syscall.UTF16ToString(nameslice)
- if mode == readdirName {
- names = append(names, name)
- } else {
- var f *fileStat
- if d.class == windows.FileIdBothDirectoryInfo {
- f = newFileStatFromFileIDBothDirInfo((*windows.FILE_ID_BOTH_DIR_INFO)(entry))
- } else {
- f = newFileStatFromFileFullDirInfo((*windows.FILE_FULL_DIR_INFO)(entry))
- // Defer appending the entry name to the parent directory path until
- // it is really needed, to avoid allocating a string that may not be used.
- // It is currently only used in os.SameFile.
- f.appendNameToPath = true
- f.path = d.path
- }
- f.name = name
- f.vol = d.vol
- if mode == readdirDirEntry {
- dirents = append(dirents, dirEntry{f})
- } else {
- infos = append(infos, f)
- }
- }
- n--
- }
- }
- if !wantAll && len(names)+len(dirents)+len(infos) == 0 {
- return nil, nil, nil, io.EOF
- }
- return names, dirents, infos, nil
-}
-
-type dirEntry struct {
- fs *fileStat
-}
-
-func (de dirEntry) Name() string { return de.fs.Name() }
-func (de dirEntry) IsDir() bool { return de.fs.IsDir() }
-func (de dirEntry) Type() FileMode { return de.fs.Mode().Type() }
-func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil }
-
-func (de dirEntry) String() string {
- return fs.FormatDirEntry(de)
-}
diff --git a/contrib/go/_std_1.22/src/os/endian_big.go b/contrib/go/_std_1.22/src/os/endian_big.go
deleted file mode 100644
index 0375e533726e..000000000000
--- a/contrib/go/_std_1.22/src/os/endian_big.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2016 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.
-//
-//go:build ppc64 || s390x || mips || mips64
-
-package os
-
-const isBigEndian = true
diff --git a/contrib/go/_std_1.22/src/os/endian_little.go b/contrib/go/_std_1.22/src/os/endian_little.go
deleted file mode 100644
index a7cf1cdda8e4..000000000000
--- a/contrib/go/_std_1.22/src/os/endian_little.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2016 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.
-//
-//go:build 386 || amd64 || arm || arm64 || loong64 || ppc64le || mips64le || mipsle || riscv64 || wasm
-
-package os
-
-const isBigEndian = false
diff --git a/contrib/go/_std_1.22/src/os/error.go b/contrib/go/_std_1.22/src/os/error.go
deleted file mode 100644
index 62ede9ded3bc..000000000000
--- a/contrib/go/_std_1.22/src/os/error.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "internal/poll"
- "io/fs"
-)
-
-// Portable analogs of some common system call errors.
-//
-// Errors returned from this package may be tested against these errors
-// with errors.Is.
-var (
- // ErrInvalid indicates an invalid argument.
- // Methods on File will return this error when the receiver is nil.
- ErrInvalid = fs.ErrInvalid // "invalid argument"
-
- ErrPermission = fs.ErrPermission // "permission denied"
- ErrExist = fs.ErrExist // "file already exists"
- ErrNotExist = fs.ErrNotExist // "file does not exist"
- ErrClosed = fs.ErrClosed // "file already closed"
-
- ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
- ErrDeadlineExceeded = errDeadlineExceeded() // "i/o timeout"
-)
-
-func errNoDeadline() error { return poll.ErrNoDeadline }
-
-// errDeadlineExceeded returns the value for os.ErrDeadlineExceeded.
-// This error comes from the internal/poll package, which is also
-// used by package net. Doing it this way ensures that the net
-// package will return os.ErrDeadlineExceeded for an exceeded deadline,
-// as documented by net.Conn.SetDeadline, without requiring any extra
-// work in the net package and without requiring the internal/poll
-// package to import os (which it can't, because that would be circular).
-func errDeadlineExceeded() error { return poll.ErrDeadlineExceeded }
-
-type timeout interface {
- Timeout() bool
-}
-
-// PathError records an error and the operation and file path that caused it.
-type PathError = fs.PathError
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Err error
-}
-
-func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
-
-func (e *SyscallError) Unwrap() error { return e.Err }
-
-// Timeout reports whether this error represents a timeout.
-func (e *SyscallError) Timeout() bool {
- t, ok := e.Err.(timeout)
- return ok && t.Timeout()
-}
-
-// NewSyscallError returns, as an error, a new SyscallError
-// with the given system call name and error details.
-// As a convenience, if err is nil, NewSyscallError returns nil.
-func NewSyscallError(syscall string, err error) error {
- if err == nil {
- return nil
- }
- return &SyscallError{syscall, err}
-}
-
-// IsExist returns a boolean indicating whether the error is known to report
-// that a file or directory already exists. It is satisfied by ErrExist as
-// well as some syscall errors.
-//
-// This function predates errors.Is. It only supports errors returned by
-// the os package. New code should use errors.Is(err, fs.ErrExist).
-func IsExist(err error) bool {
- return underlyingErrorIs(err, ErrExist)
-}
-
-// IsNotExist returns a boolean indicating whether the error is known to
-// report that a file or directory does not exist. It is satisfied by
-// ErrNotExist as well as some syscall errors.
-//
-// This function predates errors.Is. It only supports errors returned by
-// the os package. New code should use errors.Is(err, fs.ErrNotExist).
-func IsNotExist(err error) bool {
- return underlyingErrorIs(err, ErrNotExist)
-}
-
-// IsPermission returns a boolean indicating whether the error is known to
-// report that permission is denied. It is satisfied by ErrPermission as well
-// as some syscall errors.
-//
-// This function predates errors.Is. It only supports errors returned by
-// the os package. New code should use errors.Is(err, fs.ErrPermission).
-func IsPermission(err error) bool {
- return underlyingErrorIs(err, ErrPermission)
-}
-
-// IsTimeout returns a boolean indicating whether the error is known
-// to report that a timeout occurred.
-//
-// This function predates errors.Is, and the notion of whether an
-// error indicates a timeout can be ambiguous. For example, the Unix
-// error EWOULDBLOCK sometimes indicates a timeout and sometimes does not.
-// New code should use errors.Is with a value appropriate to the call
-// returning the error, such as os.ErrDeadlineExceeded.
-func IsTimeout(err error) bool {
- terr, ok := underlyingError(err).(timeout)
- return ok && terr.Timeout()
-}
-
-func underlyingErrorIs(err, target error) bool {
- // Note that this function is not errors.Is:
- // underlyingError only unwraps the specific error-wrapping types
- // that it historically did, not all errors implementing Unwrap().
- err = underlyingError(err)
- if err == target {
- return true
- }
- // To preserve prior behavior, only examine syscall errors.
- e, ok := err.(syscallErrorType)
- return ok && e.Is(target)
-}
-
-// underlyingError returns the underlying error for known os error types.
-func underlyingError(err error) error {
- switch err := err.(type) {
- case *PathError:
- return err.Err
- case *LinkError:
- return err.Err
- case *SyscallError:
- return err.Err
- }
- return err
-}
diff --git a/contrib/go/_std_1.22/src/os/error_posix.go b/contrib/go/_std_1.22/src/os/error_posix.go
deleted file mode 100644
index b159c036c110..000000000000
--- a/contrib/go/_std_1.22/src/os/error_posix.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 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.
-
-//go:build unix || (js && wasm) || wasip1 || windows
-
-package os
-
-import "syscall"
-
-// wrapSyscallError takes an error and a syscall name. If the error is
-// a syscall.Errno, it wraps it in an os.SyscallError using the syscall name.
-func wrapSyscallError(name string, err error) error {
- if _, ok := err.(syscall.Errno); ok {
- err = NewSyscallError(name, err)
- }
- return err
-}
diff --git a/contrib/go/_std_1.22/src/os/exec.go b/contrib/go/_std_1.22/src/os/exec.go
deleted file mode 100644
index ed5a75c4d13f..000000000000
--- a/contrib/go/_std_1.22/src/os/exec.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "errors"
- "internal/testlog"
- "runtime"
- "sync"
- "sync/atomic"
- "syscall"
- "time"
-)
-
-// ErrProcessDone indicates a Process has finished.
-var ErrProcessDone = errors.New("os: process already finished")
-
-// Process stores the information about a process created by StartProcess.
-type Process struct {
- Pid int
- handle uintptr // handle is accessed atomically on Windows
- isdone atomic.Bool // process has been successfully waited on
- sigMu sync.RWMutex // avoid race between wait and signal
-}
-
-func newProcess(pid int, handle uintptr) *Process {
- p := &Process{Pid: pid, handle: handle}
- runtime.SetFinalizer(p, (*Process).Release)
- return p
-}
-
-func (p *Process) setDone() {
- p.isdone.Store(true)
-}
-
-func (p *Process) done() bool {
- return p.isdone.Load()
-}
-
-// ProcAttr holds the attributes that will be applied to a new process
-// started by StartProcess.
-type ProcAttr struct {
- // If Dir is non-empty, the child changes into the directory before
- // creating the process.
- Dir string
- // If Env is non-nil, it gives the environment variables for the
- // new process in the form returned by Environ.
- // If it is nil, the result of Environ will be used.
- Env []string
- // Files specifies the open files inherited by the new process. The
- // first three entries correspond to standard input, standard output, and
- // standard error. An implementation may support additional entries,
- // depending on the underlying operating system. A nil entry corresponds
- // to that file being closed when the process starts.
- // On Unix systems, StartProcess will change these File values
- // to blocking mode, which means that SetDeadline will stop working
- // and calling Close will not interrupt a Read or Write.
- Files []*File
-
- // Operating system-specific process creation attributes.
- // Note that setting this field means that your program
- // may not execute properly or even compile on some
- // operating systems.
- Sys *syscall.SysProcAttr
-}
-
-// A Signal represents an operating system signal.
-// The usual underlying implementation is operating system-dependent:
-// on Unix it is syscall.Signal.
-type Signal interface {
- String() string
- Signal() // to distinguish from other Stringers
-}
-
-// Getpid returns the process id of the caller.
-func Getpid() int { return syscall.Getpid() }
-
-// Getppid returns the process id of the caller's parent.
-func Getppid() int { return syscall.Getppid() }
-
-// FindProcess looks for a running process by its pid.
-//
-// The Process it returns can be used to obtain information
-// about the underlying operating system process.
-//
-// On Unix systems, FindProcess always succeeds and returns a Process
-// for the given pid, regardless of whether the process exists. To test whether
-// the process actually exists, see whether p.Signal(syscall.Signal(0)) reports
-// an error.
-func FindProcess(pid int) (*Process, error) {
- return findProcess(pid)
-}
-
-// StartProcess starts a new process with the program, arguments and attributes
-// specified by name, argv and attr. The argv slice will become os.Args in the
-// new process, so it normally starts with the program name.
-//
-// If the calling goroutine has locked the operating system thread
-// with runtime.LockOSThread and modified any inheritable OS-level
-// thread state (for example, Linux or Plan 9 name spaces), the new
-// process will inherit the caller's thread state.
-//
-// StartProcess is a low-level interface. The os/exec package provides
-// higher-level interfaces.
-//
-// If there is an error, it will be of type *PathError.
-func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
- testlog.Open(name)
- return startProcess(name, argv, attr)
-}
-
-// Release releases any resources associated with the Process p,
-// rendering it unusable in the future.
-// Release only needs to be called if Wait is not.
-func (p *Process) Release() error {
- return p.release()
-}
-
-// Kill causes the Process to exit immediately. Kill does not wait until
-// the Process has actually exited. This only kills the Process itself,
-// not any other processes it may have started.
-func (p *Process) Kill() error {
- return p.kill()
-}
-
-// Wait waits for the Process to exit, and then returns a
-// ProcessState describing its status and an error, if any.
-// Wait releases any resources associated with the Process.
-// On most operating systems, the Process must be a child
-// of the current process or an error will be returned.
-func (p *Process) Wait() (*ProcessState, error) {
- return p.wait()
-}
-
-// Signal sends a signal to the Process.
-// Sending Interrupt on Windows is not implemented.
-func (p *Process) Signal(sig Signal) error {
- return p.signal(sig)
-}
-
-// UserTime returns the user CPU time of the exited process and its children.
-func (p *ProcessState) UserTime() time.Duration {
- return p.userTime()
-}
-
-// SystemTime returns the system CPU time of the exited process and its children.
-func (p *ProcessState) SystemTime() time.Duration {
- return p.systemTime()
-}
-
-// Exited reports whether the program has exited.
-// On Unix systems this reports true if the program exited due to calling exit,
-// but false if the program terminated due to a signal.
-func (p *ProcessState) Exited() bool {
- return p.exited()
-}
-
-// Success reports whether the program exited successfully,
-// such as with exit status 0 on Unix.
-func (p *ProcessState) Success() bool {
- return p.success()
-}
-
-// Sys returns system-dependent exit information about
-// the process. Convert it to the appropriate underlying
-// type, such as syscall.WaitStatus on Unix, to access its contents.
-func (p *ProcessState) Sys() any {
- return p.sys()
-}
-
-// SysUsage returns system-dependent resource usage information about
-// the exited process. Convert it to the appropriate underlying
-// type, such as *syscall.Rusage on Unix, to access its contents.
-// (On Unix, *syscall.Rusage matches struct rusage as defined in the
-// getrusage(2) manual page.)
-func (p *ProcessState) SysUsage() any {
- return p.sysUsage()
-}
diff --git a/contrib/go/_std_1.22/src/os/exec/exec.go b/contrib/go/_std_1.22/src/os/exec/exec.go
deleted file mode 100644
index a52b75f69cde..000000000000
--- a/contrib/go/_std_1.22/src/os/exec/exec.go
+++ /dev/null
@@ -1,1307 +0,0 @@
-// Copyright 2009 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.
-
-// Package exec runs external commands. It wraps os.StartProcess to make it
-// easier to remap stdin and stdout, connect I/O with pipes, and do other
-// adjustments.
-//
-// Unlike the "system" library call from C and other languages, the
-// os/exec package intentionally does not invoke the system shell and
-// does not expand any glob patterns or handle other expansions,
-// pipelines, or redirections typically done by shells. The package
-// behaves more like C's "exec" family of functions. To expand glob
-// patterns, either call the shell directly, taking care to escape any
-// dangerous input, or use the path/filepath package's Glob function.
-// To expand environment variables, use package os's ExpandEnv.
-//
-// Note that the examples in this package assume a Unix system.
-// They may not run on Windows, and they do not run in the Go Playground
-// used by golang.org and godoc.org.
-//
-// # Executables in the current directory
-//
-// The functions Command and LookPath look for a program
-// in the directories listed in the current path, following the
-// conventions of the host operating system.
-// Operating systems have for decades included the current
-// directory in this search, sometimes implicitly and sometimes
-// configured explicitly that way by default.
-// Modern practice is that including the current directory
-// is usually unexpected and often leads to security problems.
-//
-// To avoid those security problems, as of Go 1.19, this package will not resolve a program
-// using an implicit or explicit path entry relative to the current directory.
-// That is, if you run exec.LookPath("go"), it will not successfully return
-// ./go on Unix nor .\go.exe on Windows, no matter how the path is configured.
-// Instead, if the usual path algorithms would result in that answer,
-// these functions return an error err satisfying errors.Is(err, ErrDot).
-//
-// For example, consider these two program snippets:
-//
-// path, err := exec.LookPath("prog")
-// if err != nil {
-// log.Fatal(err)
-// }
-// use(path)
-//
-// and
-//
-// cmd := exec.Command("prog")
-// if err := cmd.Run(); err != nil {
-// log.Fatal(err)
-// }
-//
-// These will not find and run ./prog or .\prog.exe,
-// no matter how the current path is configured.
-//
-// Code that always wants to run a program from the current directory
-// can be rewritten to say "./prog" instead of "prog".
-//
-// Code that insists on including results from relative path entries
-// can instead override the error using an errors.Is check:
-//
-// path, err := exec.LookPath("prog")
-// if errors.Is(err, exec.ErrDot) {
-// err = nil
-// }
-// if err != nil {
-// log.Fatal(err)
-// }
-// use(path)
-//
-// and
-//
-// cmd := exec.Command("prog")
-// if errors.Is(cmd.Err, exec.ErrDot) {
-// cmd.Err = nil
-// }
-// if err := cmd.Run(); err != nil {
-// log.Fatal(err)
-// }
-//
-// Setting the environment variable GODEBUG=execerrdot=0
-// disables generation of ErrDot entirely, temporarily restoring the pre-Go 1.19
-// behavior for programs that are unable to apply more targeted fixes.
-// A future version of Go may remove support for this variable.
-//
-// Before adding such overrides, make sure you understand the
-// security implications of doing so.
-// See https://go.dev/blog/path-security for more information.
-package exec
-
-import (
- "bytes"
- "context"
- "errors"
- "internal/godebug"
- "internal/syscall/execenv"
- "io"
- "os"
- "path/filepath"
- "runtime"
- "strconv"
- "strings"
- "syscall"
- "time"
-)
-
-// Error is returned by LookPath when it fails to classify a file as an
-// executable.
-type Error struct {
- // Name is the file name for which the error occurred.
- Name string
- // Err is the underlying error.
- Err error
-}
-
-func (e *Error) Error() string {
- return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error()
-}
-
-func (e *Error) Unwrap() error { return e.Err }
-
-// ErrWaitDelay is returned by (*Cmd).Wait if the process exits with a
-// successful status code but its output pipes are not closed before the
-// command's WaitDelay expires.
-var ErrWaitDelay = errors.New("exec: WaitDelay expired before I/O complete")
-
-// wrappedError wraps an error without relying on fmt.Errorf.
-type wrappedError struct {
- prefix string
- err error
-}
-
-func (w wrappedError) Error() string {
- return w.prefix + ": " + w.err.Error()
-}
-
-func (w wrappedError) Unwrap() error {
- return w.err
-}
-
-// Cmd represents an external command being prepared or run.
-//
-// A Cmd cannot be reused after calling its Run, Output or CombinedOutput
-// methods.
-type Cmd struct {
- // Path is the path of the command to run.
- //
- // This is the only field that must be set to a non-zero
- // value. If Path is relative, it is evaluated relative
- // to Dir.
- Path string
-
- // Args holds command line arguments, including the command as Args[0].
- // If the Args field is empty or nil, Run uses {Path}.
- //
- // In typical use, both Path and Args are set by calling Command.
- Args []string
-
- // Env specifies the environment of the process.
- // Each entry is of the form "key=value".
- // If Env is nil, the new process uses the current process's
- // environment.
- // If Env contains duplicate environment keys, only the last
- // value in the slice for each duplicate key is used.
- // As a special case on Windows, SYSTEMROOT is always added if
- // missing and not explicitly set to the empty string.
- Env []string
-
- // Dir specifies the working directory of the command.
- // If Dir is the empty string, Run runs the command in the
- // calling process's current directory.
- Dir string
-
- // Stdin specifies the process's standard input.
- //
- // If Stdin is nil, the process reads from the null device (os.DevNull).
- //
- // If Stdin is an *os.File, the process's standard input is connected
- // directly to that file.
- //
- // Otherwise, during the execution of the command a separate
- // goroutine reads from Stdin and delivers that data to the command
- // over a pipe. In this case, Wait does not complete until the goroutine
- // stops copying, either because it has reached the end of Stdin
- // (EOF or a read error), or because writing to the pipe returned an error,
- // or because a nonzero WaitDelay was set and expired.
- Stdin io.Reader
-
- // Stdout and Stderr specify the process's standard output and error.
- //
- // If either is nil, Run connects the corresponding file descriptor
- // to the null device (os.DevNull).
- //
- // If either is an *os.File, the corresponding output from the process
- // is connected directly to that file.
- //
- // Otherwise, during the execution of the command a separate goroutine
- // reads from the process over a pipe and delivers that data to the
- // corresponding Writer. In this case, Wait does not complete until the
- // goroutine reaches EOF or encounters an error or a nonzero WaitDelay
- // expires.
- //
- // If Stdout and Stderr are the same writer, and have a type that can
- // be compared with ==, at most one goroutine at a time will call Write.
- Stdout io.Writer
- Stderr io.Writer
-
- // ExtraFiles specifies additional open files to be inherited by the
- // new process. It does not include standard input, standard output, or
- // standard error. If non-nil, entry i becomes file descriptor 3+i.
- //
- // ExtraFiles is not supported on Windows.
- ExtraFiles []*os.File
-
- // SysProcAttr holds optional, operating system-specific attributes.
- // Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
- SysProcAttr *syscall.SysProcAttr
-
- // Process is the underlying process, once started.
- Process *os.Process
-
- // ProcessState contains information about an exited process.
- // If the process was started successfully, Wait or Run will
- // populate its ProcessState when the command completes.
- ProcessState *os.ProcessState
-
- // ctx is the context passed to CommandContext, if any.
- ctx context.Context
-
- Err error // LookPath error, if any.
-
- // If Cancel is non-nil, the command must have been created with
- // CommandContext and Cancel will be called when the command's
- // Context is done. By default, CommandContext sets Cancel to
- // call the Kill method on the command's Process.
- //
- // Typically a custom Cancel will send a signal to the command's
- // Process, but it may instead take other actions to initiate cancellation,
- // such as closing a stdin or stdout pipe or sending a shutdown request on a
- // network socket.
- //
- // If the command exits with a success status after Cancel is
- // called, and Cancel does not return an error equivalent to
- // os.ErrProcessDone, then Wait and similar methods will return a non-nil
- // error: either an error wrapping the one returned by Cancel,
- // or the error from the Context.
- // (If the command exits with a non-success status, or Cancel
- // returns an error that wraps os.ErrProcessDone, Wait and similar methods
- // continue to return the command's usual exit status.)
- //
- // If Cancel is set to nil, nothing will happen immediately when the command's
- // Context is done, but a nonzero WaitDelay will still take effect. That may
- // be useful, for example, to work around deadlocks in commands that do not
- // support shutdown signals but are expected to always finish quickly.
- //
- // Cancel will not be called if Start returns a non-nil error.
- Cancel func() error
-
- // If WaitDelay is non-zero, it bounds the time spent waiting on two sources
- // of unexpected delay in Wait: a child process that fails to exit after the
- // associated Context is canceled, and a child process that exits but leaves
- // its I/O pipes unclosed.
- //
- // The WaitDelay timer starts when either the associated Context is done or a
- // call to Wait observes that the child process has exited, whichever occurs
- // first. When the delay has elapsed, the command shuts down the child process
- // and/or its I/O pipes.
- //
- // If the child process has failed to exit — perhaps because it ignored or
- // failed to receive a shutdown signal from a Cancel function, or because no
- // Cancel function was set — then it will be terminated using os.Process.Kill.
- //
- // Then, if the I/O pipes communicating with the child process are still open,
- // those pipes are closed in order to unblock any goroutines currently blocked
- // on Read or Write calls.
- //
- // If pipes are closed due to WaitDelay, no Cancel call has occurred,
- // and the command has otherwise exited with a successful status, Wait and
- // similar methods will return ErrWaitDelay instead of nil.
- //
- // If WaitDelay is zero (the default), I/O pipes will be read until EOF,
- // which might not occur until orphaned subprocesses of the command have
- // also closed their descriptors for the pipes.
- WaitDelay time.Duration
-
- // childIOFiles holds closers for any of the child process's
- // stdin, stdout, and/or stderr files that were opened by the Cmd itself
- // (not supplied by the caller). These should be closed as soon as they
- // are inherited by the child process.
- childIOFiles []io.Closer
-
- // parentIOPipes holds closers for the parent's end of any pipes
- // connected to the child's stdin, stdout, and/or stderr streams
- // that were opened by the Cmd itself (not supplied by the caller).
- // These should be closed after Wait sees the command and copying
- // goroutines exit, or after WaitDelay has expired.
- parentIOPipes []io.Closer
-
- // goroutine holds a set of closures to execute to copy data
- // to and/or from the command's I/O pipes.
- goroutine []func() error
-
- // If goroutineErr is non-nil, it receives the first error from a copying
- // goroutine once all such goroutines have completed.
- // goroutineErr is set to nil once its error has been received.
- goroutineErr <-chan error
-
- // If ctxResult is non-nil, it receives the result of watchCtx exactly once.
- ctxResult <-chan ctxResult
-
- // The stack saved when the Command was created, if GODEBUG contains
- // execwait=2. Used for debugging leaks.
- createdByStack []byte
-
- // For a security release long ago, we created x/sys/execabs,
- // which manipulated the unexported lookPathErr error field
- // in this struct. For Go 1.19 we exported the field as Err error,
- // above, but we have to keep lookPathErr around for use by
- // old programs building against new toolchains.
- // The String and Start methods look for an error in lookPathErr
- // in preference to Err, to preserve the errors that execabs sets.
- //
- // In general we don't guarantee misuse of reflect like this,
- // but the misuse of reflect was by us, the best of various bad
- // options to fix the security problem, and people depend on
- // those old copies of execabs continuing to work.
- // The result is that we have to leave this variable around for the
- // rest of time, a compatibility scar.
- //
- // See https://go.dev/blog/path-security
- // and https://go.dev/issue/43724 for more context.
- lookPathErr error
-
- // cachedLookExtensions caches the result of calling lookExtensions.
- // This is only used on Windows.
- cachedLookExtensions string
-}
-
-// A ctxResult reports the result of watching the Context associated with a
-// running command (and sending corresponding signals if needed).
-type ctxResult struct {
- err error
-
- // If timer is non-nil, it expires after WaitDelay has elapsed after
- // the Context is done.
- //
- // (If timer is nil, that means that the Context was not done before the
- // command completed, or no WaitDelay was set, or the WaitDelay already
- // expired and its effect was already applied.)
- timer *time.Timer
-}
-
-var execwait = godebug.New("#execwait")
-var execerrdot = godebug.New("execerrdot")
-
-// Command returns the Cmd struct to execute the named program with
-// the given arguments.
-//
-// It sets only the Path and Args in the returned structure.
-//
-// If name contains no path separators, Command uses LookPath to
-// resolve name to a complete path if possible. Otherwise it uses name
-// directly as Path.
-//
-// The returned Cmd's Args field is constructed from the command name
-// followed by the elements of arg, so arg should not include the
-// command name itself. For example, Command("echo", "hello").
-// Args[0] is always name, not the possibly resolved Path.
-//
-// On Windows, processes receive the whole command line as a single string
-// and do their own parsing. Command combines and quotes Args into a command
-// line string with an algorithm compatible with applications using
-// CommandLineToArgvW (which is the most common way). Notable exceptions are
-// msiexec.exe and cmd.exe (and thus, all batch files), which have a different
-// unquoting algorithm. In these or other similar cases, you can do the
-// quoting yourself and provide the full command line in SysProcAttr.CmdLine,
-// leaving Args empty.
-func Command(name string, arg ...string) *Cmd {
- cmd := &Cmd{
- Path: name,
- Args: append([]string{name}, arg...),
- }
-
- if v := execwait.Value(); v != "" {
- if v == "2" {
- // Obtain the caller stack. (This is equivalent to runtime/debug.Stack,
- // copied to avoid importing the whole package.)
- stack := make([]byte, 1024)
- for {
- n := runtime.Stack(stack, false)
- if n < len(stack) {
- stack = stack[:n]
- break
- }
- stack = make([]byte, 2*len(stack))
- }
-
- if i := bytes.Index(stack, []byte("\nos/exec.Command(")); i >= 0 {
- stack = stack[i+1:]
- }
- cmd.createdByStack = stack
- }
-
- runtime.SetFinalizer(cmd, func(c *Cmd) {
- if c.Process != nil && c.ProcessState == nil {
- debugHint := ""
- if c.createdByStack == nil {
- debugHint = " (set GODEBUG=execwait=2 to capture stacks for debugging)"
- } else {
- os.Stderr.WriteString("GODEBUG=execwait=2 detected a leaked exec.Cmd created by:\n")
- os.Stderr.Write(c.createdByStack)
- os.Stderr.WriteString("\n")
- debugHint = ""
- }
- panic("exec: Cmd started a Process but leaked without a call to Wait" + debugHint)
- }
- })
- }
-
- if filepath.Base(name) == name {
- lp, err := LookPath(name)
- if lp != "" {
- // Update cmd.Path even if err is non-nil.
- // If err is ErrDot (especially on Windows), lp may include a resolved
- // extension (like .exe or .bat) that should be preserved.
- cmd.Path = lp
- }
- if err != nil {
- cmd.Err = err
- }
- } else if runtime.GOOS == "windows" && filepath.IsAbs(name) {
- // We may need to add a filename extension from PATHEXT
- // or verify an extension that is already present.
- // Since the path is absolute, its extension should be unambiguous
- // and independent of cmd.Dir, and we can go ahead and cache the lookup now.
- //
- // Note that we cannot add an extension here for relative paths, because
- // cmd.Dir may be set after we return from this function and that may cause
- // the command to resolve to a different extension.
- lp, err := lookExtensions(name, "")
- cmd.cachedLookExtensions = lp
- if err != nil {
- cmd.Err = err
- }
- }
- return cmd
-}
-
-// CommandContext is like Command but includes a context.
-//
-// The provided context is used to interrupt the process
-// (by calling cmd.Cancel or os.Process.Kill)
-// if the context becomes done before the command completes on its own.
-//
-// CommandContext sets the command's Cancel function to invoke the Kill method
-// on its Process, and leaves its WaitDelay unset. The caller may change the
-// cancellation behavior by modifying those fields before starting the command.
-func CommandContext(ctx context.Context, name string, arg ...string) *Cmd {
- if ctx == nil {
- panic("nil Context")
- }
- cmd := Command(name, arg...)
- cmd.ctx = ctx
- cmd.Cancel = func() error {
- return cmd.Process.Kill()
- }
- return cmd
-}
-
-// String returns a human-readable description of c.
-// It is intended only for debugging.
-// In particular, it is not suitable for use as input to a shell.
-// The output of String may vary across Go releases.
-func (c *Cmd) String() string {
- if c.Err != nil || c.lookPathErr != nil {
- // failed to resolve path; report the original requested path (plus args)
- return strings.Join(c.Args, " ")
- }
- // report the exact executable path (plus args)
- b := new(strings.Builder)
- b.WriteString(c.Path)
- for _, a := range c.Args[1:] {
- b.WriteByte(' ')
- b.WriteString(a)
- }
- return b.String()
-}
-
-// interfaceEqual protects against panics from doing equality tests on
-// two interfaces with non-comparable underlying types.
-func interfaceEqual(a, b any) bool {
- defer func() {
- recover()
- }()
- return a == b
-}
-
-func (c *Cmd) argv() []string {
- if len(c.Args) > 0 {
- return c.Args
- }
- return []string{c.Path}
-}
-
-func (c *Cmd) childStdin() (*os.File, error) {
- if c.Stdin == nil {
- f, err := os.Open(os.DevNull)
- if err != nil {
- return nil, err
- }
- c.childIOFiles = append(c.childIOFiles, f)
- return f, nil
- }
-
- if f, ok := c.Stdin.(*os.File); ok {
- return f, nil
- }
-
- pr, pw, err := os.Pipe()
- if err != nil {
- return nil, err
- }
-
- c.childIOFiles = append(c.childIOFiles, pr)
- c.parentIOPipes = append(c.parentIOPipes, pw)
- c.goroutine = append(c.goroutine, func() error {
- _, err := io.Copy(pw, c.Stdin)
- if skipStdinCopyError(err) {
- err = nil
- }
- if err1 := pw.Close(); err == nil {
- err = err1
- }
- return err
- })
- return pr, nil
-}
-
-func (c *Cmd) childStdout() (*os.File, error) {
- return c.writerDescriptor(c.Stdout)
-}
-
-func (c *Cmd) childStderr(childStdout *os.File) (*os.File, error) {
- if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) {
- return childStdout, nil
- }
- return c.writerDescriptor(c.Stderr)
-}
-
-// writerDescriptor returns an os.File to which the child process
-// can write to send data to w.
-//
-// If w is nil, writerDescriptor returns a File that writes to os.DevNull.
-func (c *Cmd) writerDescriptor(w io.Writer) (*os.File, error) {
- if w == nil {
- f, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0)
- if err != nil {
- return nil, err
- }
- c.childIOFiles = append(c.childIOFiles, f)
- return f, nil
- }
-
- if f, ok := w.(*os.File); ok {
- return f, nil
- }
-
- pr, pw, err := os.Pipe()
- if err != nil {
- return nil, err
- }
-
- c.childIOFiles = append(c.childIOFiles, pw)
- c.parentIOPipes = append(c.parentIOPipes, pr)
- c.goroutine = append(c.goroutine, func() error {
- _, err := io.Copy(w, pr)
- pr.Close() // in case io.Copy stopped due to write error
- return err
- })
- return pw, nil
-}
-
-func closeDescriptors(closers []io.Closer) {
- for _, fd := range closers {
- fd.Close()
- }
-}
-
-// Run starts the specified command and waits for it to complete.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command starts but does not complete successfully, the error is of
-// type *ExitError. Other error types may be returned for other situations.
-//
-// If the calling goroutine has locked the operating system thread
-// with runtime.LockOSThread and modified any inheritable OS-level
-// thread state (for example, Linux or Plan 9 name spaces), the new
-// process will inherit the caller's thread state.
-func (c *Cmd) Run() error {
- if err := c.Start(); err != nil {
- return err
- }
- return c.Wait()
-}
-
-// Start starts the specified command but does not wait for it to complete.
-//
-// If Start returns successfully, the c.Process field will be set.
-//
-// After a successful call to Start the Wait method must be called in
-// order to release associated system resources.
-func (c *Cmd) Start() error {
- // Check for doubled Start calls before we defer failure cleanup. If the prior
- // call to Start succeeded, we don't want to spuriously close its pipes.
- if c.Process != nil {
- return errors.New("exec: already started")
- }
-
- started := false
- defer func() {
- closeDescriptors(c.childIOFiles)
- c.childIOFiles = nil
-
- if !started {
- closeDescriptors(c.parentIOPipes)
- c.parentIOPipes = nil
- }
- }()
-
- if c.Path == "" && c.Err == nil && c.lookPathErr == nil {
- c.Err = errors.New("exec: no command")
- }
- if c.Err != nil || c.lookPathErr != nil {
- if c.lookPathErr != nil {
- return c.lookPathErr
- }
- return c.Err
- }
- lp := c.Path
- if c.cachedLookExtensions != "" {
- lp = c.cachedLookExtensions
- }
- if runtime.GOOS == "windows" && c.cachedLookExtensions == "" {
- // If c.Path is relative, we had to wait until now
- // to resolve it in case c.Dir was changed.
- // (If it is absolute, we already resolved its extension in Command
- // and shouldn't need to do so again.)
- //
- // Unfortunately, we cannot write the result back to c.Path because programs
- // may assume that they can call Start concurrently with reading the path.
- // (It is safe and non-racy to do so on Unix platforms, and users might not
- // test with the race detector on all platforms;
- // see https://go.dev/issue/62596.)
- //
- // So we will pass the fully resolved path to os.StartProcess, but leave
- // c.Path as is: missing a bit of logging information seems less harmful
- // than triggering a surprising data race, and if the user really cares
- // about that bit of logging they can always use LookPath to resolve it.
- var err error
- lp, err = lookExtensions(c.Path, c.Dir)
- if err != nil {
- return err
- }
- }
- if c.Cancel != nil && c.ctx == nil {
- return errors.New("exec: command with a non-nil Cancel was not created with CommandContext")
- }
- if c.ctx != nil {
- select {
- case <-c.ctx.Done():
- return c.ctx.Err()
- default:
- }
- }
-
- childFiles := make([]*os.File, 0, 3+len(c.ExtraFiles))
- stdin, err := c.childStdin()
- if err != nil {
- return err
- }
- childFiles = append(childFiles, stdin)
- stdout, err := c.childStdout()
- if err != nil {
- return err
- }
- childFiles = append(childFiles, stdout)
- stderr, err := c.childStderr(stdout)
- if err != nil {
- return err
- }
- childFiles = append(childFiles, stderr)
- childFiles = append(childFiles, c.ExtraFiles...)
-
- env, err := c.environ()
- if err != nil {
- return err
- }
-
- c.Process, err = os.StartProcess(lp, c.argv(), &os.ProcAttr{
- Dir: c.Dir,
- Files: childFiles,
- Env: env,
- Sys: c.SysProcAttr,
- })
- if err != nil {
- return err
- }
- started = true
-
- // Don't allocate the goroutineErr channel unless there are goroutines to start.
- if len(c.goroutine) > 0 {
- goroutineErr := make(chan error, 1)
- c.goroutineErr = goroutineErr
-
- type goroutineStatus struct {
- running int
- firstErr error
- }
- statusc := make(chan goroutineStatus, 1)
- statusc <- goroutineStatus{running: len(c.goroutine)}
- for _, fn := range c.goroutine {
- go func(fn func() error) {
- err := fn()
-
- status := <-statusc
- if status.firstErr == nil {
- status.firstErr = err
- }
- status.running--
- if status.running == 0 {
- goroutineErr <- status.firstErr
- } else {
- statusc <- status
- }
- }(fn)
- }
- c.goroutine = nil // Allow the goroutines' closures to be GC'd when they complete.
- }
-
- // If we have anything to do when the command's Context expires,
- // start a goroutine to watch for cancellation.
- //
- // (Even if the command was created by CommandContext, a helper library may
- // have explicitly set its Cancel field back to nil, indicating that it should
- // be allowed to continue running after cancellation after all.)
- if (c.Cancel != nil || c.WaitDelay != 0) && c.ctx != nil && c.ctx.Done() != nil {
- resultc := make(chan ctxResult)
- c.ctxResult = resultc
- go c.watchCtx(resultc)
- }
-
- return nil
-}
-
-// watchCtx watches c.ctx until it is able to send a result to resultc.
-//
-// If c.ctx is done before a result can be sent, watchCtx calls c.Cancel,
-// and/or kills cmd.Process it after c.WaitDelay has elapsed.
-//
-// watchCtx manipulates c.goroutineErr, so its result must be received before
-// c.awaitGoroutines is called.
-func (c *Cmd) watchCtx(resultc chan<- ctxResult) {
- select {
- case resultc <- ctxResult{}:
- return
- case <-c.ctx.Done():
- }
-
- var err error
- if c.Cancel != nil {
- if interruptErr := c.Cancel(); interruptErr == nil {
- // We appear to have successfully interrupted the command, so any
- // program behavior from this point may be due to ctx even if the
- // command exits with code 0.
- err = c.ctx.Err()
- } else if errors.Is(interruptErr, os.ErrProcessDone) {
- // The process already finished: we just didn't notice it yet.
- // (Perhaps c.Wait hadn't been called, or perhaps it happened to race with
- // c.ctx being cancelled.) Don't inject a needless error.
- } else {
- err = wrappedError{
- prefix: "exec: canceling Cmd",
- err: interruptErr,
- }
- }
- }
- if c.WaitDelay == 0 {
- resultc <- ctxResult{err: err}
- return
- }
-
- timer := time.NewTimer(c.WaitDelay)
- select {
- case resultc <- ctxResult{err: err, timer: timer}:
- // c.Process.Wait returned and we've handed the timer off to c.Wait.
- // It will take care of goroutine shutdown from here.
- return
- case <-timer.C:
- }
-
- killed := false
- if killErr := c.Process.Kill(); killErr == nil {
- // We appear to have killed the process. c.Process.Wait should return a
- // non-nil error to c.Wait unless the Kill signal races with a successful
- // exit, and if that does happen we shouldn't report a spurious error,
- // so don't set err to anything here.
- killed = true
- } else if !errors.Is(killErr, os.ErrProcessDone) {
- err = wrappedError{
- prefix: "exec: killing Cmd",
- err: killErr,
- }
- }
-
- if c.goroutineErr != nil {
- select {
- case goroutineErr := <-c.goroutineErr:
- // Forward goroutineErr only if we don't have reason to believe it was
- // caused by a call to Cancel or Kill above.
- if err == nil && !killed {
- err = goroutineErr
- }
- default:
- // Close the child process's I/O pipes, in case it abandoned some
- // subprocess that inherited them and is still holding them open
- // (see https://go.dev/issue/23019).
- //
- // We close the goroutine pipes only after we have sent any signals we're
- // going to send to the process (via Signal or Kill above): if we send
- // SIGKILL to the process, we would prefer for it to die of SIGKILL, not
- // SIGPIPE. (However, this may still cause any orphaned subprocesses to
- // terminate with SIGPIPE.)
- closeDescriptors(c.parentIOPipes)
- // Wait for the copying goroutines to finish, but report ErrWaitDelay for
- // the error: any other error here could result from closing the pipes.
- _ = <-c.goroutineErr
- if err == nil {
- err = ErrWaitDelay
- }
- }
-
- // Since we have already received the only result from c.goroutineErr,
- // set it to nil to prevent awaitGoroutines from blocking on it.
- c.goroutineErr = nil
- }
-
- resultc <- ctxResult{err: err}
-}
-
-// An ExitError reports an unsuccessful exit by a command.
-type ExitError struct {
- *os.ProcessState
-
- // Stderr holds a subset of the standard error output from the
- // Cmd.Output method if standard error was not otherwise being
- // collected.
- //
- // If the error output is long, Stderr may contain only a prefix
- // and suffix of the output, with the middle replaced with
- // text about the number of omitted bytes.
- //
- // Stderr is provided for debugging, for inclusion in error messages.
- // Users with other needs should redirect Cmd.Stderr as needed.
- Stderr []byte
-}
-
-func (e *ExitError) Error() string {
- return e.ProcessState.String()
-}
-
-// Wait waits for the command to exit and waits for any copying to
-// stdin or copying from stdout or stderr to complete.
-//
-// The command must have been started by Start.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *ExitError. Other error types may be
-// returned for I/O problems.
-//
-// If any of c.Stdin, c.Stdout or c.Stderr are not an *os.File, Wait also waits
-// for the respective I/O loop copying to or from the process to complete.
-//
-// Wait releases any resources associated with the Cmd.
-func (c *Cmd) Wait() error {
- if c.Process == nil {
- return errors.New("exec: not started")
- }
- if c.ProcessState != nil {
- return errors.New("exec: Wait was already called")
- }
-
- state, err := c.Process.Wait()
- if err == nil && !state.Success() {
- err = &ExitError{ProcessState: state}
- }
- c.ProcessState = state
-
- var timer *time.Timer
- if c.ctxResult != nil {
- watch := <-c.ctxResult
- timer = watch.timer
- // If c.Process.Wait returned an error, prefer that.
- // Otherwise, report any error from the watchCtx goroutine,
- // such as a Context cancellation or a WaitDelay overrun.
- if err == nil && watch.err != nil {
- err = watch.err
- }
- }
-
- if goroutineErr := c.awaitGoroutines(timer); err == nil {
- // Report an error from the copying goroutines only if the program otherwise
- // exited normally on its own. Otherwise, the copying error may be due to the
- // abnormal termination.
- err = goroutineErr
- }
- closeDescriptors(c.parentIOPipes)
- c.parentIOPipes = nil
-
- return err
-}
-
-// awaitGoroutines waits for the results of the goroutines copying data to or
-// from the command's I/O pipes.
-//
-// If c.WaitDelay elapses before the goroutines complete, awaitGoroutines
-// forcibly closes their pipes and returns ErrWaitDelay.
-//
-// If timer is non-nil, it must send to timer.C at the end of c.WaitDelay.
-func (c *Cmd) awaitGoroutines(timer *time.Timer) error {
- defer func() {
- if timer != nil {
- timer.Stop()
- }
- c.goroutineErr = nil
- }()
-
- if c.goroutineErr == nil {
- return nil // No running goroutines to await.
- }
-
- if timer == nil {
- if c.WaitDelay == 0 {
- return <-c.goroutineErr
- }
-
- select {
- case err := <-c.goroutineErr:
- // Avoid the overhead of starting a timer.
- return err
- default:
- }
-
- // No existing timer was started: either there is no Context associated with
- // the command, or c.Process.Wait completed before the Context was done.
- timer = time.NewTimer(c.WaitDelay)
- }
-
- select {
- case <-timer.C:
- closeDescriptors(c.parentIOPipes)
- // Wait for the copying goroutines to finish, but ignore any error
- // (since it was probably caused by closing the pipes).
- _ = <-c.goroutineErr
- return ErrWaitDelay
-
- case err := <-c.goroutineErr:
- return err
- }
-}
-
-// Output runs the command and returns its standard output.
-// Any returned error will usually be of type *ExitError.
-// If c.Stderr was nil, Output populates ExitError.Stderr.
-func (c *Cmd) Output() ([]byte, error) {
- if c.Stdout != nil {
- return nil, errors.New("exec: Stdout already set")
- }
- var stdout bytes.Buffer
- c.Stdout = &stdout
-
- captureErr := c.Stderr == nil
- if captureErr {
- c.Stderr = &prefixSuffixSaver{N: 32 << 10}
- }
-
- err := c.Run()
- if err != nil && captureErr {
- if ee, ok := err.(*ExitError); ok {
- ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes()
- }
- }
- return stdout.Bytes(), err
-}
-
-// CombinedOutput runs the command and returns its combined standard
-// output and standard error.
-func (c *Cmd) CombinedOutput() ([]byte, error) {
- if c.Stdout != nil {
- return nil, errors.New("exec: Stdout already set")
- }
- if c.Stderr != nil {
- return nil, errors.New("exec: Stderr already set")
- }
- var b bytes.Buffer
- c.Stdout = &b
- c.Stderr = &b
- err := c.Run()
- return b.Bytes(), err
-}
-
-// StdinPipe returns a pipe that will be connected to the command's
-// standard input when the command starts.
-// The pipe will be closed automatically after Wait sees the command exit.
-// A caller need only call Close to force the pipe to close sooner.
-// For example, if the command being run will not exit until standard input
-// is closed, the caller must close the pipe.
-func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
- if c.Stdin != nil {
- return nil, errors.New("exec: Stdin already set")
- }
- if c.Process != nil {
- return nil, errors.New("exec: StdinPipe after process started")
- }
- pr, pw, err := os.Pipe()
- if err != nil {
- return nil, err
- }
- c.Stdin = pr
- c.childIOFiles = append(c.childIOFiles, pr)
- c.parentIOPipes = append(c.parentIOPipes, pw)
- return pw, nil
-}
-
-// StdoutPipe returns a pipe that will be connected to the command's
-// standard output when the command starts.
-//
-// Wait will close the pipe after seeing the command exit, so most callers
-// need not close the pipe themselves. It is thus incorrect to call Wait
-// before all reads from the pipe have completed.
-// For the same reason, it is incorrect to call Run when using StdoutPipe.
-// See the example for idiomatic usage.
-func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
- if c.Stdout != nil {
- return nil, errors.New("exec: Stdout already set")
- }
- if c.Process != nil {
- return nil, errors.New("exec: StdoutPipe after process started")
- }
- pr, pw, err := os.Pipe()
- if err != nil {
- return nil, err
- }
- c.Stdout = pw
- c.childIOFiles = append(c.childIOFiles, pw)
- c.parentIOPipes = append(c.parentIOPipes, pr)
- return pr, nil
-}
-
-// StderrPipe returns a pipe that will be connected to the command's
-// standard error when the command starts.
-//
-// Wait will close the pipe after seeing the command exit, so most callers
-// need not close the pipe themselves. It is thus incorrect to call Wait
-// before all reads from the pipe have completed.
-// For the same reason, it is incorrect to use Run when using StderrPipe.
-// See the StdoutPipe example for idiomatic usage.
-func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
- if c.Stderr != nil {
- return nil, errors.New("exec: Stderr already set")
- }
- if c.Process != nil {
- return nil, errors.New("exec: StderrPipe after process started")
- }
- pr, pw, err := os.Pipe()
- if err != nil {
- return nil, err
- }
- c.Stderr = pw
- c.childIOFiles = append(c.childIOFiles, pw)
- c.parentIOPipes = append(c.parentIOPipes, pr)
- return pr, nil
-}
-
-// prefixSuffixSaver is an io.Writer which retains the first N bytes
-// and the last N bytes written to it. The Bytes() methods reconstructs
-// it with a pretty error message.
-type prefixSuffixSaver struct {
- N int // max size of prefix or suffix
- prefix []byte
- suffix []byte // ring buffer once len(suffix) == N
- suffixOff int // offset to write into suffix
- skipped int64
-
- // TODO(bradfitz): we could keep one large []byte and use part of it for
- // the prefix, reserve space for the '... Omitting N bytes ...' message,
- // then the ring buffer suffix, and just rearrange the ring buffer
- // suffix when Bytes() is called, but it doesn't seem worth it for
- // now just for error messages. It's only ~64KB anyway.
-}
-
-func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) {
- lenp := len(p)
- p = w.fill(&w.prefix, p)
-
- // Only keep the last w.N bytes of suffix data.
- if overage := len(p) - w.N; overage > 0 {
- p = p[overage:]
- w.skipped += int64(overage)
- }
- p = w.fill(&w.suffix, p)
-
- // w.suffix is full now if p is non-empty. Overwrite it in a circle.
- for len(p) > 0 { // 0, 1, or 2 iterations.
- n := copy(w.suffix[w.suffixOff:], p)
- p = p[n:]
- w.skipped += int64(n)
- w.suffixOff += n
- if w.suffixOff == w.N {
- w.suffixOff = 0
- }
- }
- return lenp, nil
-}
-
-// fill appends up to len(p) bytes of p to *dst, such that *dst does not
-// grow larger than w.N. It returns the un-appended suffix of p.
-func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) {
- if remain := w.N - len(*dst); remain > 0 {
- add := min(len(p), remain)
- *dst = append(*dst, p[:add]...)
- p = p[add:]
- }
- return p
-}
-
-func (w *prefixSuffixSaver) Bytes() []byte {
- if w.suffix == nil {
- return w.prefix
- }
- if w.skipped == 0 {
- return append(w.prefix, w.suffix...)
- }
- var buf bytes.Buffer
- buf.Grow(len(w.prefix) + len(w.suffix) + 50)
- buf.Write(w.prefix)
- buf.WriteString("\n... omitting ")
- buf.WriteString(strconv.FormatInt(w.skipped, 10))
- buf.WriteString(" bytes ...\n")
- buf.Write(w.suffix[w.suffixOff:])
- buf.Write(w.suffix[:w.suffixOff])
- return buf.Bytes()
-}
-
-// environ returns a best-effort copy of the environment in which the command
-// would be run as it is currently configured. If an error occurs in computing
-// the environment, it is returned alongside the best-effort copy.
-func (c *Cmd) environ() ([]string, error) {
- var err error
-
- env := c.Env
- if env == nil {
- env, err = execenv.Default(c.SysProcAttr)
- if err != nil {
- env = os.Environ()
- // Note that the non-nil err is preserved despite env being overridden.
- }
-
- if c.Dir != "" {
- switch runtime.GOOS {
- case "windows", "plan9":
- // Windows and Plan 9 do not use the PWD variable, so we don't need to
- // keep it accurate.
- default:
- // On POSIX platforms, PWD represents “an absolute pathname of the
- // current working directory.” Since we are changing the working
- // directory for the command, we should also update PWD to reflect that.
- //
- // Unfortunately, we didn't always do that, so (as proposed in
- // https://go.dev/issue/50599) to avoid unintended collateral damage we
- // only implicitly update PWD when Env is nil. That way, we're much
- // less likely to override an intentional change to the variable.
- if pwd, absErr := filepath.Abs(c.Dir); absErr == nil {
- env = append(env, "PWD="+pwd)
- } else if err == nil {
- err = absErr
- }
- }
- }
- }
-
- env, dedupErr := dedupEnv(env)
- if err == nil {
- err = dedupErr
- }
- return addCriticalEnv(env), err
-}
-
-// Environ returns a copy of the environment in which the command would be run
-// as it is currently configured.
-func (c *Cmd) Environ() []string {
- // Intentionally ignore errors: environ returns a best-effort environment no matter what.
- env, _ := c.environ()
- return env
-}
-
-// dedupEnv returns a copy of env with any duplicates removed, in favor of
-// later values.
-// Items not of the normal environment "key=value" form are preserved unchanged.
-// Except on Plan 9, items containing NUL characters are removed, and
-// an error is returned along with the remaining values.
-func dedupEnv(env []string) ([]string, error) {
- return dedupEnvCase(runtime.GOOS == "windows", runtime.GOOS == "plan9", env)
-}
-
-// dedupEnvCase is dedupEnv with a case option for testing.
-// If caseInsensitive is true, the case of keys is ignored.
-// If nulOK is false, items containing NUL characters are allowed.
-func dedupEnvCase(caseInsensitive, nulOK bool, env []string) ([]string, error) {
- // Construct the output in reverse order, to preserve the
- // last occurrence of each key.
- var err error
- out := make([]string, 0, len(env))
- saw := make(map[string]bool, len(env))
- for n := len(env); n > 0; n-- {
- kv := env[n-1]
-
- // Reject NUL in environment variables to prevent security issues (#56284);
- // except on Plan 9, which uses NUL as os.PathListSeparator (#56544).
- if !nulOK && strings.IndexByte(kv, 0) != -1 {
- err = errors.New("exec: environment variable contains NUL")
- continue
- }
-
- i := strings.Index(kv, "=")
- if i == 0 {
- // We observe in practice keys with a single leading "=" on Windows.
- // TODO(#49886): Should we consume only the first leading "=" as part
- // of the key, or parse through arbitrarily many of them until a non-"="?
- i = strings.Index(kv[1:], "=") + 1
- }
- if i < 0 {
- if kv != "" {
- // The entry is not of the form "key=value" (as it is required to be).
- // Leave it as-is for now.
- // TODO(#52436): should we strip or reject these bogus entries?
- out = append(out, kv)
- }
- continue
- }
- k := kv[:i]
- if caseInsensitive {
- k = strings.ToLower(k)
- }
- if saw[k] {
- continue
- }
-
- saw[k] = true
- out = append(out, kv)
- }
-
- // Now reverse the slice to restore the original order.
- for i := 0; i < len(out)/2; i++ {
- j := len(out) - i - 1
- out[i], out[j] = out[j], out[i]
- }
-
- return out, err
-}
-
-// addCriticalEnv adds any critical environment variables that are required
-// (or at least almost always required) on the operating system.
-// Currently this is only used for Windows.
-func addCriticalEnv(env []string) []string {
- if runtime.GOOS != "windows" {
- return env
- }
- for _, kv := range env {
- k, _, ok := strings.Cut(kv, "=")
- if !ok {
- continue
- }
- if strings.EqualFold(k, "SYSTEMROOT") {
- // We already have it.
- return env
- }
- }
- return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT"))
-}
-
-// ErrDot indicates that a path lookup resolved to an executable
-// in the current directory due to ‘.’ being in the path, either
-// implicitly or explicitly. See the package documentation for details.
-//
-// Note that functions in this package do not return ErrDot directly.
-// Code should use errors.Is(err, ErrDot), not err == ErrDot,
-// to test whether a returned error err is due to this condition.
-var ErrDot = errors.New("cannot run executable found relative to current directory")
diff --git a/contrib/go/_std_1.22/src/os/exec/internal/fdtest/ya.make b/contrib/go/_std_1.22/src/os/exec/internal/fdtest/ya.make
deleted file mode 100644
index 0bc55ff0acb7..000000000000
--- a/contrib/go/_std_1.22/src/os/exec/internal/fdtest/ya.make
+++ /dev/null
@@ -1,13 +0,0 @@
-SUBSCRIBER(g:contrib)
-
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- exists_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- exists_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/os/exec/ya.make b/contrib/go/_std_1.22/src/os/exec/ya.make
deleted file mode 100644
index 4cdcd7c290a1..000000000000
--- a/contrib/go/_std_1.22/src/os/exec/ya.make
+++ /dev/null
@@ -1,17 +0,0 @@
-SUBSCRIBER(g:contrib)
-
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- exec.go
- exec_unix.go
- lp_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- exec.go
- exec_windows.go
- lp_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/os/exec_plan9.go b/contrib/go/_std_1.22/src/os/exec_plan9.go
deleted file mode 100644
index 69714ff79830..000000000000
--- a/contrib/go/_std_1.22/src/os/exec_plan9.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "internal/itoa"
- "runtime"
- "syscall"
- "time"
-)
-
-// The only signal values guaranteed to be present in the os package
-// on all systems are Interrupt (send the process an interrupt) and
-// Kill (force the process to exit). Interrupt is not implemented on
-// Windows; using it with os.Process.Signal will return an error.
-var (
- Interrupt Signal = syscall.Note("interrupt")
- Kill Signal = syscall.Note("kill")
-)
-
-func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
- sysattr := &syscall.ProcAttr{
- Dir: attr.Dir,
- Env: attr.Env,
- Sys: attr.Sys,
- }
-
- sysattr.Files = make([]uintptr, 0, len(attr.Files))
- for _, f := range attr.Files {
- sysattr.Files = append(sysattr.Files, f.Fd())
- }
-
- pid, h, e := syscall.StartProcess(name, argv, sysattr)
- if e != nil {
- return nil, &PathError{Op: "fork/exec", Path: name, Err: e}
- }
-
- return newProcess(pid, h), nil
-}
-
-func (p *Process) writeProcFile(file string, data string) error {
- f, e := OpenFile("/proc/"+itoa.Itoa(p.Pid)+"/"+file, O_WRONLY, 0)
- if e != nil {
- return e
- }
- defer f.Close()
- _, e = f.Write([]byte(data))
- return e
-}
-
-func (p *Process) signal(sig Signal) error {
- if p.done() {
- return ErrProcessDone
- }
- if e := p.writeProcFile("note", sig.String()); e != nil {
- return NewSyscallError("signal", e)
- }
- return nil
-}
-
-func (p *Process) kill() error {
- return p.signal(Kill)
-}
-
-func (p *Process) wait() (ps *ProcessState, err error) {
- var waitmsg syscall.Waitmsg
-
- if p.Pid == -1 {
- return nil, ErrInvalid
- }
- err = syscall.WaitProcess(p.Pid, &waitmsg)
- if err != nil {
- return nil, NewSyscallError("wait", err)
- }
-
- p.setDone()
- ps = &ProcessState{
- pid: waitmsg.Pid,
- status: &waitmsg,
- }
- return ps, nil
-}
-
-func (p *Process) release() error {
- // NOOP for Plan 9.
- p.Pid = -1
- // no need for a finalizer anymore
- runtime.SetFinalizer(p, nil)
- return nil
-}
-
-func findProcess(pid int) (p *Process, err error) {
- // NOOP for Plan 9.
- return newProcess(pid, 0), nil
-}
-
-// ProcessState stores information about a process, as reported by Wait.
-type ProcessState struct {
- pid int // The process's id.
- status *syscall.Waitmsg // System-dependent status info.
-}
-
-// Pid returns the process id of the exited process.
-func (p *ProcessState) Pid() int {
- return p.pid
-}
-
-func (p *ProcessState) exited() bool {
- return p.status.Exited()
-}
-
-func (p *ProcessState) success() bool {
- return p.status.ExitStatus() == 0
-}
-
-func (p *ProcessState) sys() any {
- return p.status
-}
-
-func (p *ProcessState) sysUsage() any {
- return p.status
-}
-
-func (p *ProcessState) userTime() time.Duration {
- return time.Duration(p.status.Time[0]) * time.Millisecond
-}
-
-func (p *ProcessState) systemTime() time.Duration {
- return time.Duration(p.status.Time[1]) * time.Millisecond
-}
-
-func (p *ProcessState) String() string {
- if p == nil {
- return ""
- }
- return "exit status: " + p.status.Msg
-}
-
-// ExitCode returns the exit code of the exited process, or -1
-// if the process hasn't exited or was terminated by a signal.
-func (p *ProcessState) ExitCode() int {
- // return -1 if the process hasn't started.
- if p == nil {
- return -1
- }
- return p.status.ExitStatus()
-}
diff --git a/contrib/go/_std_1.22/src/os/exec_unix.go b/contrib/go/_std_1.22/src/os/exec_unix.go
deleted file mode 100644
index 36b320df1894..000000000000
--- a/contrib/go/_std_1.22/src/os/exec_unix.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2009 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.
-
-//go:build unix || (js && wasm) || wasip1
-
-package os
-
-import (
- "errors"
- "runtime"
- "syscall"
- "time"
-)
-
-func (p *Process) wait() (ps *ProcessState, err error) {
- if p.Pid == -1 {
- return nil, syscall.EINVAL
- }
-
- // If we can block until Wait4 will succeed immediately, do so.
- ready, err := p.blockUntilWaitable()
- if err != nil {
- return nil, err
- }
- if ready {
- // Mark the process done now, before the call to Wait4,
- // so that Process.signal will not send a signal.
- p.setDone()
- // Acquire a write lock on sigMu to wait for any
- // active call to the signal method to complete.
- p.sigMu.Lock()
- p.sigMu.Unlock()
- }
-
- var (
- status syscall.WaitStatus
- rusage syscall.Rusage
- pid1 int
- e error
- )
- for {
- pid1, e = syscall.Wait4(p.Pid, &status, 0, &rusage)
- if e != syscall.EINTR {
- break
- }
- }
- if e != nil {
- return nil, NewSyscallError("wait", e)
- }
- p.setDone()
- ps = &ProcessState{
- pid: pid1,
- status: status,
- rusage: &rusage,
- }
- return ps, nil
-}
-
-func (p *Process) signal(sig Signal) error {
- if p.Pid == -1 {
- return errors.New("os: process already released")
- }
- if p.Pid == 0 {
- return errors.New("os: process not initialized")
- }
- p.sigMu.RLock()
- defer p.sigMu.RUnlock()
- if p.done() {
- return ErrProcessDone
- }
- s, ok := sig.(syscall.Signal)
- if !ok {
- return errors.New("os: unsupported signal type")
- }
- if e := syscall.Kill(p.Pid, s); e != nil {
- if e == syscall.ESRCH {
- return ErrProcessDone
- }
- return e
- }
- return nil
-}
-
-func (p *Process) release() error {
- // NOOP for unix.
- p.Pid = -1
- // no need for a finalizer anymore
- runtime.SetFinalizer(p, nil)
- return nil
-}
-
-func findProcess(pid int) (p *Process, err error) {
- // NOOP for unix.
- return newProcess(pid, 0), nil
-}
-
-func (p *ProcessState) userTime() time.Duration {
- return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond
-}
-
-func (p *ProcessState) systemTime() time.Duration {
- return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond
-}
diff --git a/contrib/go/_std_1.22/src/os/executable_procfs.go b/contrib/go/_std_1.22/src/os/executable_procfs.go
deleted file mode 100644
index 94e674e36486..000000000000
--- a/contrib/go/_std_1.22/src/os/executable_procfs.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 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.
-
-//go:build linux || netbsd
-
-package os
-
-import (
- "errors"
- "runtime"
-)
-
-func executable() (string, error) {
- var procfn string
- switch runtime.GOOS {
- default:
- return "", errors.New("Executable not implemented for " + runtime.GOOS)
- case "linux", "android":
- procfn = "/proc/self/exe"
- case "netbsd":
- procfn = "/proc/curproc/exe"
- }
- path, err := Readlink(procfn)
-
- // When the executable has been deleted then Readlink returns a
- // path appended with " (deleted)".
- return stringsTrimSuffix(path, " (deleted)"), err
-}
-
-// stringsTrimSuffix is the same as strings.TrimSuffix.
-func stringsTrimSuffix(s, suffix string) string {
- if len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix {
- return s[:len(s)-len(suffix)]
- }
- return s
-}
diff --git a/contrib/go/_std_1.22/src/os/file_plan9.go b/contrib/go/_std_1.22/src/os/file_plan9.go
deleted file mode 100644
index c0ee6b33f9f9..000000000000
--- a/contrib/go/_std_1.22/src/os/file_plan9.go
+++ /dev/null
@@ -1,618 +0,0 @@
-// Copyright 2011 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.
-
-package os
-
-import (
- "internal/bytealg"
- "internal/poll"
- "io"
- "runtime"
- "syscall"
- "time"
-)
-
-// fixLongPath is a noop on non-Windows platforms.
-func fixLongPath(path string) string {
- return path
-}
-
-// file is the real representation of *File.
-// The extra level of indirection ensures that no clients of os
-// can overwrite this data, which could cause the finalizer
-// to close the wrong file descriptor.
-type file struct {
- fdmu poll.FDMutex
- fd int
- name string
- dirinfo *dirInfo // nil unless directory being read
- appendMode bool // whether file is opened for appending
-}
-
-// Fd returns the integer Plan 9 file descriptor referencing the open file.
-// If f is closed, the file descriptor becomes invalid.
-// If f is garbage collected, a finalizer may close the file descriptor,
-// making it invalid; see runtime.SetFinalizer for more information on when
-// a finalizer might be run. On Unix systems this will cause the SetDeadline
-// methods to stop working.
-//
-// As an alternative, see the f.SyscallConn method.
-func (f *File) Fd() uintptr {
- if f == nil {
- return ^(uintptr(0))
- }
- return uintptr(f.fd)
-}
-
-// NewFile returns a new File with the given file descriptor and
-// name. The returned value will be nil if fd is not a valid file
-// descriptor.
-func NewFile(fd uintptr, name string) *File {
- fdi := int(fd)
- if fdi < 0 {
- return nil
- }
- f := &File{&file{fd: fdi, name: name}}
- runtime.SetFinalizer(f.file, (*file).close)
- return f
-}
-
-// Auxiliary information if the File describes a directory
-type dirInfo struct {
- buf [syscall.STATMAX]byte // buffer for directory I/O
- nbuf int // length of buf; return value from Read
- bufp int // location of next record in buf.
-}
-
-func epipecheck(file *File, e error) {
-}
-
-// DevNull is the name of the operating system's “null device.”
-// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
-const DevNull = "/dev/null"
-
-// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
-func syscallMode(i FileMode) (o uint32) {
- o |= uint32(i.Perm())
- if i&ModeAppend != 0 {
- o |= syscall.DMAPPEND
- }
- if i&ModeExclusive != 0 {
- o |= syscall.DMEXCL
- }
- if i&ModeTemporary != 0 {
- o |= syscall.DMTMP
- }
- return
-}
-
-// openFileNolog is the Plan 9 implementation of OpenFile.
-func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
- var (
- fd int
- e error
- create bool
- excl bool
- trunc bool
- append bool
- )
-
- if flag&O_CREATE == O_CREATE {
- flag = flag & ^O_CREATE
- create = true
- }
- if flag&O_EXCL == O_EXCL {
- excl = true
- }
- if flag&O_TRUNC == O_TRUNC {
- trunc = true
- }
- // O_APPEND is emulated on Plan 9
- if flag&O_APPEND == O_APPEND {
- flag = flag &^ O_APPEND
- append = true
- }
-
- if (create && trunc) || excl {
- fd, e = syscall.Create(name, flag, syscallMode(perm))
- } else {
- fd, e = syscall.Open(name, flag)
- if IsNotExist(e) && create {
- fd, e = syscall.Create(name, flag, syscallMode(perm))
- if e != nil {
- return nil, &PathError{Op: "create", Path: name, Err: e}
- }
- }
- }
-
- if e != nil {
- return nil, &PathError{Op: "open", Path: name, Err: e}
- }
-
- if append {
- if _, e = syscall.Seek(fd, 0, io.SeekEnd); e != nil {
- return nil, &PathError{Op: "seek", Path: name, Err: e}
- }
- }
-
- return NewFile(uintptr(fd), name), nil
-}
-
-// Close closes the File, rendering it unusable for I/O.
-// On files that support SetDeadline, any pending I/O operations will
-// be canceled and return immediately with an ErrClosed error.
-// Close will return an error if it has already been called.
-func (f *File) Close() error {
- if f == nil {
- return ErrInvalid
- }
- return f.file.close()
-}
-
-func (file *file) close() error {
- if !file.fdmu.IncrefAndClose() {
- return &PathError{Op: "close", Path: file.name, Err: ErrClosed}
- }
-
- // At this point we should cancel any pending I/O.
- // How do we do that on Plan 9?
-
- err := file.decref()
-
- // no need for a finalizer anymore
- runtime.SetFinalizer(file, nil)
- return err
-}
-
-// destroy actually closes the descriptor. This is called when
-// there are no remaining references, by the decref, readUnlock,
-// and writeUnlock methods.
-func (file *file) destroy() error {
- var err error
- if e := syscall.Close(file.fd); e != nil {
- err = &PathError{Op: "close", Path: file.name, Err: e}
- }
- return err
-}
-
-// Stat returns the FileInfo structure describing file.
-// If there is an error, it will be of type *PathError.
-func (f *File) Stat() (FileInfo, error) {
- if f == nil {
- return nil, ErrInvalid
- }
- d, err := dirstat(f)
- if err != nil {
- return nil, err
- }
- return fileInfoFromStat(d), nil
-}
-
-// Truncate changes the size of the file.
-// It does not change the I/O offset.
-// If there is an error, it will be of type *PathError.
-func (f *File) Truncate(size int64) error {
- if f == nil {
- return ErrInvalid
- }
-
- var d syscall.Dir
- d.Null()
- d.Length = size
-
- var buf [syscall.STATFIXLEN]byte
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &PathError{Op: "truncate", Path: f.name, Err: err}
- }
-
- if err := f.incref("truncate"); err != nil {
- return err
- }
- defer f.decref()
-
- if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
- return &PathError{Op: "truncate", Path: f.name, Err: err}
- }
- return nil
-}
-
-const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
-
-func (f *File) chmod(mode FileMode) error {
- if f == nil {
- return ErrInvalid
- }
- var d syscall.Dir
-
- odir, e := dirstat(f)
- if e != nil {
- return &PathError{Op: "chmod", Path: f.name, Err: e}
- }
- d.Null()
- d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
-
- var buf [syscall.STATFIXLEN]byte
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &PathError{Op: "chmod", Path: f.name, Err: err}
- }
-
- if err := f.incref("chmod"); err != nil {
- return err
- }
- defer f.decref()
-
- if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
- return &PathError{Op: "chmod", Path: f.name, Err: err}
- }
- return nil
-}
-
-// Sync commits the current contents of the file to stable storage.
-// Typically, this means flushing the file system's in-memory copy
-// of recently written data to disk.
-func (f *File) Sync() error {
- if f == nil {
- return ErrInvalid
- }
- var d syscall.Dir
- d.Null()
-
- var buf [syscall.STATFIXLEN]byte
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &PathError{Op: "sync", Path: f.name, Err: err}
- }
-
- if err := f.incref("sync"); err != nil {
- return err
- }
- defer f.decref()
-
- if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
- return &PathError{Op: "sync", Path: f.name, Err: err}
- }
- return nil
-}
-
-// read reads up to len(b) bytes from the File.
-// It returns the number of bytes read and an error, if any.
-func (f *File) read(b []byte) (n int, err error) {
- if err := f.readLock(); err != nil {
- return 0, err
- }
- defer f.readUnlock()
- n, e := fixCount(syscall.Read(f.fd, b))
- if n == 0 && len(b) > 0 && e == nil {
- return 0, io.EOF
- }
- return n, e
-}
-
-// pread reads len(b) bytes from the File starting at byte offset off.
-// It returns the number of bytes read and the error, if any.
-// EOF is signaled by a zero count with err set to nil.
-func (f *File) pread(b []byte, off int64) (n int, err error) {
- if err := f.readLock(); err != nil {
- return 0, err
- }
- defer f.readUnlock()
- n, e := fixCount(syscall.Pread(f.fd, b, off))
- if n == 0 && len(b) > 0 && e == nil {
- return 0, io.EOF
- }
- return n, e
-}
-
-// write writes len(b) bytes to the File.
-// It returns the number of bytes written and an error, if any.
-// Since Plan 9 preserves message boundaries, never allow
-// a zero-byte write.
-func (f *File) write(b []byte) (n int, err error) {
- if err := f.writeLock(); err != nil {
- return 0, err
- }
- defer f.writeUnlock()
- if len(b) == 0 {
- return 0, nil
- }
- return fixCount(syscall.Write(f.fd, b))
-}
-
-// pwrite writes len(b) bytes to the File starting at byte offset off.
-// It returns the number of bytes written and an error, if any.
-// Since Plan 9 preserves message boundaries, never allow
-// a zero-byte write.
-func (f *File) pwrite(b []byte, off int64) (n int, err error) {
- if err := f.writeLock(); err != nil {
- return 0, err
- }
- defer f.writeUnlock()
- if len(b) == 0 {
- return 0, nil
- }
- return fixCount(syscall.Pwrite(f.fd, b, off))
-}
-
-// seek sets the offset for the next Read or Write on file to offset, interpreted
-// according to whence: 0 means relative to the origin of the file, 1 means
-// relative to the current offset, and 2 means relative to the end.
-// It returns the new offset and an error, if any.
-func (f *File) seek(offset int64, whence int) (ret int64, err error) {
- if err := f.incref(""); err != nil {
- return 0, err
- }
- defer f.decref()
- if f.dirinfo != nil {
- // Free cached dirinfo, so we allocate a new one if we
- // access this file as a directory again. See #35767 and #37161.
- f.dirinfo = nil
- }
- return syscall.Seek(f.fd, offset, whence)
-}
-
-// Truncate changes the size of the named file.
-// If the file is a symbolic link, it changes the size of the link's target.
-// If there is an error, it will be of type *PathError.
-func Truncate(name string, size int64) error {
- var d syscall.Dir
-
- d.Null()
- d.Length = size
-
- var buf [syscall.STATFIXLEN]byte
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &PathError{Op: "truncate", Path: name, Err: err}
- }
- if err = syscall.Wstat(name, buf[:n]); err != nil {
- return &PathError{Op: "truncate", Path: name, Err: err}
- }
- return nil
-}
-
-// Remove removes the named file or directory.
-// If there is an error, it will be of type *PathError.
-func Remove(name string) error {
- if e := syscall.Remove(name); e != nil {
- return &PathError{Op: "remove", Path: name, Err: e}
- }
- return nil
-}
-
-// hasPrefix from the strings package.
-func hasPrefix(s, prefix string) bool {
- return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
-}
-
-func rename(oldname, newname string) error {
- dirname := oldname[:bytealg.LastIndexByteString(oldname, '/')+1]
- if hasPrefix(newname, dirname) {
- newname = newname[len(dirname):]
- } else {
- return &LinkError{"rename", oldname, newname, ErrInvalid}
- }
-
- // If newname still contains slashes after removing the oldname
- // prefix, the rename is cross-directory and must be rejected.
- if bytealg.LastIndexByteString(newname, '/') >= 0 {
- return &LinkError{"rename", oldname, newname, ErrInvalid}
- }
-
- var d syscall.Dir
-
- d.Null()
- d.Name = newname
-
- buf := make([]byte, syscall.STATFIXLEN+len(d.Name))
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &LinkError{"rename", oldname, newname, err}
- }
-
- // If newname already exists and is not a directory, rename replaces it.
- f, err := Stat(dirname + newname)
- if err == nil && !f.IsDir() {
- Remove(dirname + newname)
- }
-
- if err = syscall.Wstat(oldname, buf[:n]); err != nil {
- return &LinkError{"rename", oldname, newname, err}
- }
- return nil
-}
-
-// See docs in file.go:Chmod.
-func chmod(name string, mode FileMode) error {
- var d syscall.Dir
-
- odir, e := dirstat(name)
- if e != nil {
- return &PathError{Op: "chmod", Path: name, Err: e}
- }
- d.Null()
- d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
-
- var buf [syscall.STATFIXLEN]byte
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &PathError{Op: "chmod", Path: name, Err: err}
- }
- if err = syscall.Wstat(name, buf[:n]); err != nil {
- return &PathError{Op: "chmod", Path: name, Err: err}
- }
- return nil
-}
-
-// Chtimes changes the access and modification times of the named
-// file, similar to the Unix utime() or utimes() functions.
-// A zero time.Time value will leave the corresponding file time unchanged.
-//
-// The underlying filesystem may truncate or round the values to a
-// less precise time unit.
-// If there is an error, it will be of type *PathError.
-func Chtimes(name string, atime time.Time, mtime time.Time) error {
- var d syscall.Dir
-
- d.Null()
- d.Atime = uint32(atime.Unix())
- d.Mtime = uint32(mtime.Unix())
- if atime.IsZero() {
- d.Atime = 0xFFFFFFFF
- }
- if mtime.IsZero() {
- d.Mtime = 0xFFFFFFFF
- }
-
- var buf [syscall.STATFIXLEN]byte
- n, err := d.Marshal(buf[:])
- if err != nil {
- return &PathError{Op: "chtimes", Path: name, Err: err}
- }
- if err = syscall.Wstat(name, buf[:n]); err != nil {
- return &PathError{Op: "chtimes", Path: name, Err: err}
- }
- return nil
-}
-
-// Pipe returns a connected pair of Files; reads from r return bytes
-// written to w. It returns the files and an error, if any.
-func Pipe() (r *File, w *File, err error) {
- var p [2]int
-
- if e := syscall.Pipe(p[0:]); e != nil {
- return nil, nil, NewSyscallError("pipe", e)
- }
-
- return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
-}
-
-// not supported on Plan 9
-
-// Link creates newname as a hard link to the oldname file.
-// If there is an error, it will be of type *LinkError.
-func Link(oldname, newname string) error {
- return &LinkError{"link", oldname, newname, syscall.EPLAN9}
-}
-
-// Symlink creates newname as a symbolic link to oldname.
-// On Windows, a symlink to a non-existent oldname creates a file symlink;
-// if oldname is later created as a directory the symlink will not work.
-// If there is an error, it will be of type *LinkError.
-func Symlink(oldname, newname string) error {
- return &LinkError{"symlink", oldname, newname, syscall.EPLAN9}
-}
-
-func readlink(name string) (string, error) {
- return "", &PathError{Op: "readlink", Path: name, Err: syscall.EPLAN9}
-}
-
-// Chown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link's target.
-// A uid or gid of -1 means to not change that value.
-// If there is an error, it will be of type *PathError.
-//
-// On Windows or Plan 9, Chown always returns the syscall.EWINDOWS or
-// EPLAN9 error, wrapped in *PathError.
-func Chown(name string, uid, gid int) error {
- return &PathError{Op: "chown", Path: name, Err: syscall.EPLAN9}
-}
-
-// Lchown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link itself.
-// If there is an error, it will be of type *PathError.
-func Lchown(name string, uid, gid int) error {
- return &PathError{Op: "lchown", Path: name, Err: syscall.EPLAN9}
-}
-
-// Chown changes the numeric uid and gid of the named file.
-// If there is an error, it will be of type *PathError.
-func (f *File) Chown(uid, gid int) error {
- if f == nil {
- return ErrInvalid
- }
- return &PathError{Op: "chown", Path: f.name, Err: syscall.EPLAN9}
-}
-
-func tempDir() string {
- dir := Getenv("TMPDIR")
- if dir == "" {
- dir = "/tmp"
- }
- return dir
-}
-
-// Chdir changes the current working directory to the file,
-// which must be a directory.
-// If there is an error, it will be of type *PathError.
-func (f *File) Chdir() error {
- if err := f.incref("chdir"); err != nil {
- return err
- }
- defer f.decref()
- if e := syscall.Fchdir(f.fd); e != nil {
- return &PathError{Op: "chdir", Path: f.name, Err: e}
- }
- return nil
-}
-
-// setDeadline sets the read and write deadline.
-func (f *File) setDeadline(time.Time) error {
- if err := f.checkValid("SetDeadline"); err != nil {
- return err
- }
- return poll.ErrNoDeadline
-}
-
-// setReadDeadline sets the read deadline.
-func (f *File) setReadDeadline(time.Time) error {
- if err := f.checkValid("SetReadDeadline"); err != nil {
- return err
- }
- return poll.ErrNoDeadline
-}
-
-// setWriteDeadline sets the write deadline.
-func (f *File) setWriteDeadline(time.Time) error {
- if err := f.checkValid("SetWriteDeadline"); err != nil {
- return err
- }
- return poll.ErrNoDeadline
-}
-
-// checkValid checks whether f is valid for use, but does not prepare
-// to actually use it. If f is not ready checkValid returns an appropriate
-// error, perhaps incorporating the operation name op.
-func (f *File) checkValid(op string) error {
- if f == nil {
- return ErrInvalid
- }
- if err := f.incref(op); err != nil {
- return err
- }
- return f.decref()
-}
-
-type rawConn struct{}
-
-func (c *rawConn) Control(f func(uintptr)) error {
- return syscall.EPLAN9
-}
-
-func (c *rawConn) Read(f func(uintptr) bool) error {
- return syscall.EPLAN9
-}
-
-func (c *rawConn) Write(f func(uintptr) bool) error {
- return syscall.EPLAN9
-}
-
-func newRawConn(file *File) (*rawConn, error) {
- return nil, syscall.EPLAN9
-}
-
-func ignoringEINTR(fn func() error) error {
- return fn()
-}
diff --git a/contrib/go/_std_1.22/src/os/file_unix.go b/contrib/go/_std_1.22/src/os/file_unix.go
deleted file mode 100644
index 649ec3ebb591..000000000000
--- a/contrib/go/_std_1.22/src/os/file_unix.go
+++ /dev/null
@@ -1,495 +0,0 @@
-// Copyright 2009 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.
-
-//go:build unix || (js && wasm) || wasip1
-
-package os
-
-import (
- "internal/poll"
- "internal/syscall/unix"
- "io/fs"
- "runtime"
- "syscall"
- _ "unsafe" // for go:linkname
-)
-
-const _UTIME_OMIT = unix.UTIME_OMIT
-
-// fixLongPath is a noop on non-Windows platforms.
-func fixLongPath(path string) string {
- return path
-}
-
-func rename(oldname, newname string) error {
- fi, err := Lstat(newname)
- if err == nil && fi.IsDir() {
- // There are two independent errors this function can return:
- // one for a bad oldname, and one for a bad newname.
- // At this point we've determined the newname is bad.
- // But just in case oldname is also bad, prioritize returning
- // the oldname error because that's what we did historically.
- // However, if the old name and new name are not the same, yet
- // they refer to the same file, it implies a case-only
- // rename on a case-insensitive filesystem, which is ok.
- if ofi, err := Lstat(oldname); err != nil {
- if pe, ok := err.(*PathError); ok {
- err = pe.Err
- }
- return &LinkError{"rename", oldname, newname, err}
- } else if newname == oldname || !SameFile(fi, ofi) {
- return &LinkError{"rename", oldname, newname, syscall.EEXIST}
- }
- }
- err = ignoringEINTR(func() error {
- return syscall.Rename(oldname, newname)
- })
- if err != nil {
- return &LinkError{"rename", oldname, newname, err}
- }
- return nil
-}
-
-// file is the real representation of *File.
-// The extra level of indirection ensures that no clients of os
-// can overwrite this data, which could cause the finalizer
-// to close the wrong file descriptor.
-type file struct {
- pfd poll.FD
- name string
- dirinfo *dirInfo // nil unless directory being read
- nonblock bool // whether we set nonblocking mode
- stdoutOrErr bool // whether this is stdout or stderr
- appendMode bool // whether file is opened for appending
-}
-
-// Fd returns the integer Unix file descriptor referencing the open file.
-// If f is closed, the file descriptor becomes invalid.
-// If f is garbage collected, a finalizer may close the file descriptor,
-// making it invalid; see runtime.SetFinalizer for more information on when
-// a finalizer might be run. On Unix systems this will cause the SetDeadline
-// methods to stop working.
-// Because file descriptors can be reused, the returned file descriptor may
-// only be closed through the Close method of f, or by its finalizer during
-// garbage collection. Otherwise, during garbage collection the finalizer
-// may close an unrelated file descriptor with the same (reused) number.
-//
-// As an alternative, see the f.SyscallConn method.
-func (f *File) Fd() uintptr {
- if f == nil {
- return ^(uintptr(0))
- }
-
- // If we put the file descriptor into nonblocking mode,
- // then set it to blocking mode before we return it,
- // because historically we have always returned a descriptor
- // opened in blocking mode. The File will continue to work,
- // but any blocking operation will tie up a thread.
- if f.nonblock {
- f.pfd.SetBlocking()
- }
-
- return uintptr(f.pfd.Sysfd)
-}
-
-// NewFile returns a new File with the given file descriptor and
-// name. The returned value will be nil if fd is not a valid file
-// descriptor. On Unix systems, if the file descriptor is in
-// non-blocking mode, NewFile will attempt to return a pollable File
-// (one for which the SetDeadline methods work).
-//
-// After passing it to NewFile, fd may become invalid under the same
-// conditions described in the comments of the Fd method, and the same
-// constraints apply.
-func NewFile(fd uintptr, name string) *File {
- fdi := int(fd)
- if fdi < 0 {
- return nil
- }
-
- kind := kindNewFile
- appendMode := false
- if flags, err := unix.Fcntl(fdi, syscall.F_GETFL, 0); err == nil {
- if unix.HasNonblockFlag(flags) {
- kind = kindNonBlock
- }
- appendMode = flags&syscall.O_APPEND != 0
- }
- f := newFile(fdi, name, kind)
- f.appendMode = appendMode
- return f
-}
-
-// net_newUnixFile is a hidden entry point called by net.conn.File.
-// This is used so that a nonblocking network connection will become
-// blocking if code calls the Fd method. We don't want that for direct
-// calls to NewFile: passing a nonblocking descriptor to NewFile should
-// remain nonblocking if you get it back using Fd. But for net.conn.File
-// the call to NewFile is hidden from the user. Historically in that case
-// the Fd method has returned a blocking descriptor, and we want to
-// retain that behavior because existing code expects it and depends on it.
-//
-//go:linkname net_newUnixFile net.newUnixFile
-func net_newUnixFile(fd int, name string) *File {
- if fd < 0 {
- panic("invalid FD")
- }
-
- f := newFile(fd, name, kindNonBlock)
- f.nonblock = true // tell Fd to return blocking descriptor
- return f
-}
-
-// newFileKind describes the kind of file to newFile.
-type newFileKind int
-
-const (
- // kindNewFile means that the descriptor was passed to us via NewFile.
- kindNewFile newFileKind = iota
- // kindOpenFile means that the descriptor was opened using
- // Open, Create, or OpenFile (without O_NONBLOCK).
- kindOpenFile
- // kindPipe means that the descriptor was opened using Pipe.
- kindPipe
- // kindNonBlock means that the descriptor is already in
- // non-blocking mode.
- kindNonBlock
- // kindNoPoll means that we should not put the descriptor into
- // non-blocking mode, because we know it is not a pipe or FIFO.
- // Used by openDirAt for directories.
- kindNoPoll
-)
-
-// newFile is like NewFile, but if called from OpenFile or Pipe
-// (as passed in the kind parameter) it tries to add the file to
-// the runtime poller.
-func newFile(fd int, name string, kind newFileKind) *File {
- f := &File{&file{
- pfd: poll.FD{
- Sysfd: fd,
- IsStream: true,
- ZeroReadIsEOF: true,
- },
- name: name,
- stdoutOrErr: fd == 1 || fd == 2,
- }}
-
- pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock
-
- // If the caller passed a non-blocking filedes (kindNonBlock),
- // we assume they know what they are doing so we allow it to be
- // used with kqueue.
- if kind == kindOpenFile {
- switch runtime.GOOS {
- case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd":
- var st syscall.Stat_t
- err := ignoringEINTR(func() error {
- return syscall.Fstat(fd, &st)
- })
- typ := st.Mode & syscall.S_IFMT
- // Don't try to use kqueue with regular files on *BSDs.
- // On FreeBSD a regular file is always
- // reported as ready for writing.
- // On Dragonfly, NetBSD and OpenBSD the fd is signaled
- // only once as ready (both read and write).
- // Issue 19093.
- // Also don't add directories to the netpoller.
- if err == nil && (typ == syscall.S_IFREG || typ == syscall.S_IFDIR) {
- pollable = false
- }
-
- // In addition to the behavior described above for regular files,
- // on Darwin, kqueue does not work properly with fifos:
- // closing the last writer does not cause a kqueue event
- // for any readers. See issue #24164.
- if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && typ == syscall.S_IFIFO {
- pollable = false
- }
- }
- }
-
- clearNonBlock := false
- if pollable {
- if kind == kindNonBlock {
- // The descriptor is already in non-blocking mode.
- // We only set f.nonblock if we put the file into
- // non-blocking mode.
- } else if err := syscall.SetNonblock(fd, true); err == nil {
- f.nonblock = true
- clearNonBlock = true
- } else {
- pollable = false
- }
- }
-
- // An error here indicates a failure to register
- // with the netpoll system. That can happen for
- // a file descriptor that is not supported by
- // epoll/kqueue; for example, disk files on
- // Linux systems. We assume that any real error
- // will show up in later I/O.
- // We do restore the blocking behavior if it was set by us.
- if pollErr := f.pfd.Init("file", pollable); pollErr != nil && clearNonBlock {
- if err := syscall.SetNonblock(fd, false); err == nil {
- f.nonblock = false
- }
- }
-
- runtime.SetFinalizer(f.file, (*file).close)
- return f
-}
-
-func sigpipe() // implemented in package runtime
-
-// epipecheck raises SIGPIPE if we get an EPIPE error on standard
-// output or standard error. See the SIGPIPE docs in os/signal, and
-// issue 11845.
-func epipecheck(file *File, e error) {
- if e == syscall.EPIPE && file.stdoutOrErr {
- sigpipe()
- }
-}
-
-// DevNull is the name of the operating system's “null device.”
-// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
-const DevNull = "/dev/null"
-
-// openFileNolog is the Unix implementation of OpenFile.
-// Changes here should be reflected in openDirAt, if relevant.
-func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
- setSticky := false
- if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
- if _, err := Stat(name); IsNotExist(err) {
- setSticky = true
- }
- }
-
- var r int
- var s poll.SysFile
- for {
- var e error
- r, s, e = open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
- if e == nil {
- break
- }
-
- // We have to check EINTR here, per issues 11180 and 39237.
- if e == syscall.EINTR {
- continue
- }
-
- return nil, &PathError{Op: "open", Path: name, Err: e}
- }
-
- // open(2) itself won't handle the sticky bit on *BSD and Solaris
- if setSticky {
- setStickyBit(name)
- }
-
- // There's a race here with fork/exec, which we are
- // content to live with. See ../syscall/exec_unix.go.
- if !supportsCloseOnExec {
- syscall.CloseOnExec(r)
- }
-
- kind := kindOpenFile
- if unix.HasNonblockFlag(flag) {
- kind = kindNonBlock
- }
-
- f := newFile(r, name, kind)
- f.pfd.SysFile = s
- return f, nil
-}
-
-func (file *file) close() error {
- if file == nil {
- return syscall.EINVAL
- }
- if file.dirinfo != nil {
- file.dirinfo.close()
- file.dirinfo = nil
- }
- var err error
- if e := file.pfd.Close(); e != nil {
- if e == poll.ErrFileClosing {
- e = ErrClosed
- }
- err = &PathError{Op: "close", Path: file.name, Err: e}
- }
-
- // no need for a finalizer anymore
- runtime.SetFinalizer(file, nil)
- return err
-}
-
-// seek sets the offset for the next Read or Write on file to offset, interpreted
-// according to whence: 0 means relative to the origin of the file, 1 means
-// relative to the current offset, and 2 means relative to the end.
-// It returns the new offset and an error, if any.
-func (f *File) seek(offset int64, whence int) (ret int64, err error) {
- if f.dirinfo != nil {
- // Free cached dirinfo, so we allocate a new one if we
- // access this file as a directory again. See #35767 and #37161.
- f.dirinfo.close()
- f.dirinfo = nil
- }
- ret, err = f.pfd.Seek(offset, whence)
- runtime.KeepAlive(f)
- return ret, err
-}
-
-// Truncate changes the size of the named file.
-// If the file is a symbolic link, it changes the size of the link's target.
-// If there is an error, it will be of type *PathError.
-func Truncate(name string, size int64) error {
- e := ignoringEINTR(func() error {
- return syscall.Truncate(name, size)
- })
- if e != nil {
- return &PathError{Op: "truncate", Path: name, Err: e}
- }
- return nil
-}
-
-// Remove removes the named file or (empty) directory.
-// If there is an error, it will be of type *PathError.
-func Remove(name string) error {
- // System call interface forces us to know
- // whether name is a file or directory.
- // Try both: it is cheaper on average than
- // doing a Stat plus the right one.
- e := ignoringEINTR(func() error {
- return syscall.Unlink(name)
- })
- if e == nil {
- return nil
- }
- e1 := ignoringEINTR(func() error {
- return syscall.Rmdir(name)
- })
- if e1 == nil {
- return nil
- }
-
- // Both failed: figure out which error to return.
- // OS X and Linux differ on whether unlink(dir)
- // returns EISDIR, so can't use that. However,
- // both agree that rmdir(file) returns ENOTDIR,
- // so we can use that to decide which error is real.
- // Rmdir might also return ENOTDIR if given a bad
- // file path, like /etc/passwd/foo, but in that case,
- // both errors will be ENOTDIR, so it's okay to
- // use the error from unlink.
- if e1 != syscall.ENOTDIR {
- e = e1
- }
- return &PathError{Op: "remove", Path: name, Err: e}
-}
-
-func tempDir() string {
- dir := Getenv("TMPDIR")
- if dir == "" {
- if runtime.GOOS == "android" {
- dir = "/data/local/tmp"
- } else {
- dir = "/tmp"
- }
- }
- return dir
-}
-
-// Link creates newname as a hard link to the oldname file.
-// If there is an error, it will be of type *LinkError.
-func Link(oldname, newname string) error {
- e := ignoringEINTR(func() error {
- return syscall.Link(oldname, newname)
- })
- if e != nil {
- return &LinkError{"link", oldname, newname, e}
- }
- return nil
-}
-
-// Symlink creates newname as a symbolic link to oldname.
-// On Windows, a symlink to a non-existent oldname creates a file symlink;
-// if oldname is later created as a directory the symlink will not work.
-// If there is an error, it will be of type *LinkError.
-func Symlink(oldname, newname string) error {
- e := ignoringEINTR(func() error {
- return syscall.Symlink(oldname, newname)
- })
- if e != nil {
- return &LinkError{"symlink", oldname, newname, e}
- }
- return nil
-}
-
-func readlink(name string) (string, error) {
- for len := 128; ; len *= 2 {
- b := make([]byte, len)
- var (
- n int
- e error
- )
- for {
- n, e = fixCount(syscall.Readlink(name, b))
- if e != syscall.EINTR {
- break
- }
- }
- // buffer too small
- if (runtime.GOOS == "aix" || runtime.GOOS == "wasip1") && e == syscall.ERANGE {
- continue
- }
- if e != nil {
- return "", &PathError{Op: "readlink", Path: name, Err: e}
- }
- if n < len {
- return string(b[0:n]), nil
- }
- }
-}
-
-type unixDirent struct {
- parent string
- name string
- typ FileMode
- info FileInfo
-}
-
-func (d *unixDirent) Name() string { return d.name }
-func (d *unixDirent) IsDir() bool { return d.typ.IsDir() }
-func (d *unixDirent) Type() FileMode { return d.typ }
-
-func (d *unixDirent) Info() (FileInfo, error) {
- if d.info != nil {
- return d.info, nil
- }
- return lstat(d.parent + "/" + d.name)
-}
-
-func (d *unixDirent) String() string {
- return fs.FormatDirEntry(d)
-}
-
-func newUnixDirent(parent, name string, typ FileMode) (DirEntry, error) {
- ude := &unixDirent{
- parent: parent,
- name: name,
- typ: typ,
- }
- if typ != ^FileMode(0) && !testingForceReadDirLstat {
- return ude, nil
- }
-
- info, err := lstat(parent + "/" + name)
- if err != nil {
- return nil, err
- }
-
- ude.typ = info.Mode().Type()
- ude.info = info
- return ude, nil
-}
diff --git a/contrib/go/_std_1.22/src/os/path.go b/contrib/go/_std_1.22/src/os/path.go
deleted file mode 100644
index 6ac4cbe20f78..000000000000
--- a/contrib/go/_std_1.22/src/os/path.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "syscall"
-)
-
-// MkdirAll creates a directory named path,
-// along with any necessary parents, and returns nil,
-// or else returns an error.
-// The permission bits perm (before umask) are used for all
-// directories that MkdirAll creates.
-// If path is already a directory, MkdirAll does nothing
-// and returns nil.
-func MkdirAll(path string, perm FileMode) error {
- // Fast path: if we can tell whether path is a directory or file, stop with success or error.
- dir, err := Stat(path)
- if err == nil {
- if dir.IsDir() {
- return nil
- }
- return &PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
- }
-
- // Slow path: make sure parent exists and then call Mkdir for path.
-
- // Extract the parent folder from path by first removing any trailing
- // path separator and then scanning backward until finding a path
- // separator or reaching the beginning of the string.
- i := len(path) - 1
- for i >= 0 && IsPathSeparator(path[i]) {
- i--
- }
- for i >= 0 && !IsPathSeparator(path[i]) {
- i--
- }
- if i < 0 {
- i = 0
- }
-
- // If there is a parent directory, and it is not the volume name,
- // recurse to ensure parent directory exists.
- if parent := path[:i]; len(parent) > len(volumeName(path)) {
- err = MkdirAll(parent, perm)
- if err != nil {
- return err
- }
- }
-
- // Parent now exists; invoke Mkdir and use its result.
- err = Mkdir(path, perm)
- if err != nil {
- // Handle arguments like "foo/." by
- // double-checking that directory doesn't exist.
- dir, err1 := Lstat(path)
- if err1 == nil && dir.IsDir() {
- return nil
- }
- return err
- }
- return nil
-}
-
-// RemoveAll removes path and any children it contains.
-// It removes everything it can but returns the first error
-// it encounters. If the path does not exist, RemoveAll
-// returns nil (no error).
-// If there is an error, it will be of type *PathError.
-func RemoveAll(path string) error {
- return removeAll(path)
-}
-
-// endsWithDot reports whether the final component of path is ".".
-func endsWithDot(path string) bool {
- if path == "." {
- return true
- }
- if len(path) >= 2 && path[len(path)-1] == '.' && IsPathSeparator(path[len(path)-2]) {
- return true
- }
- return false
-}
diff --git a/contrib/go/_std_1.22/src/os/path_plan9.go b/contrib/go/_std_1.22/src/os/path_plan9.go
deleted file mode 100644
index f1c9dbc048c1..000000000000
--- a/contrib/go/_std_1.22/src/os/path_plan9.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2011 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.
-
-package os
-
-const (
- PathSeparator = '/' // OS-specific path separator
- PathListSeparator = '\000' // OS-specific path list separator
-)
-
-// IsPathSeparator reports whether c is a directory separator character.
-func IsPathSeparator(c uint8) bool {
- return PathSeparator == c
-}
-
-func volumeName(p string) string {
- return ""
-}
diff --git a/contrib/go/_std_1.22/src/os/path_unix.go b/contrib/go/_std_1.22/src/os/path_unix.go
deleted file mode 100644
index 1c80fa91f8be..000000000000
--- a/contrib/go/_std_1.22/src/os/path_unix.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2011 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.
-
-//go:build unix || (js && wasm) || wasip1
-
-package os
-
-const (
- PathSeparator = '/' // OS-specific path separator
- PathListSeparator = ':' // OS-specific path list separator
-)
-
-// IsPathSeparator reports whether c is a directory separator character.
-func IsPathSeparator(c uint8) bool {
- return PathSeparator == c
-}
-
-// basename removes trailing slashes and the leading directory name from path name.
-func basename(name string) string {
- i := len(name) - 1
- // Remove trailing slashes
- for ; i > 0 && name[i] == '/'; i-- {
- name = name[:i]
- }
- // Remove leading directory name
- for i--; i >= 0; i-- {
- if name[i] == '/' {
- name = name[i+1:]
- break
- }
- }
-
- return name
-}
-
-// splitPath returns the base name and parent directory.
-func splitPath(path string) (string, string) {
- // if no better parent is found, the path is relative from "here"
- dirname := "."
-
- // Remove all but one leading slash.
- for len(path) > 1 && path[0] == '/' && path[1] == '/' {
- path = path[1:]
- }
-
- i := len(path) - 1
-
- // Remove trailing slashes.
- for ; i > 0 && path[i] == '/'; i-- {
- path = path[:i]
- }
-
- // if no slashes in path, base is path
- basename := path
-
- // Remove leading directory path
- for i--; i >= 0; i-- {
- if path[i] == '/' {
- if i == 0 {
- dirname = path[:1]
- } else {
- dirname = path[:i]
- }
- basename = path[i+1:]
- break
- }
- }
-
- return dirname, basename
-}
-
-func volumeName(p string) string {
- return ""
-}
diff --git a/contrib/go/_std_1.22/src/os/path_windows.go b/contrib/go/_std_1.22/src/os/path_windows.go
deleted file mode 100644
index 052202514825..000000000000
--- a/contrib/go/_std_1.22/src/os/path_windows.go
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2011 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.
-
-package os
-
-const (
- PathSeparator = '\\' // OS-specific path separator
- PathListSeparator = ';' // OS-specific path list separator
-)
-
-// IsPathSeparator reports whether c is a directory separator character.
-func IsPathSeparator(c uint8) bool {
- // NOTE: Windows accepts / as path separator.
- return c == '\\' || c == '/'
-}
-
-// basename removes trailing slashes and the leading
-// directory name and drive letter from path name.
-func basename(name string) string {
- // Remove drive letter
- if len(name) == 2 && name[1] == ':' {
- name = "."
- } else if len(name) > 2 && name[1] == ':' {
- name = name[2:]
- }
- i := len(name) - 1
- // Remove trailing slashes
- for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- {
- name = name[:i]
- }
- // Remove leading directory name
- for i--; i >= 0; i-- {
- if name[i] == '/' || name[i] == '\\' {
- name = name[i+1:]
- break
- }
- }
- return name
-}
-
-func isAbs(path string) (b bool) {
- v := volumeName(path)
- if v == "" {
- return false
- }
- path = path[len(v):]
- if path == "" {
- return false
- }
- return IsPathSeparator(path[0])
-}
-
-func volumeName(path string) (v string) {
- if len(path) < 2 {
- return ""
- }
- // with drive letter
- c := path[0]
- if path[1] == ':' &&
- ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
- 'A' <= c && c <= 'Z') {
- return path[:2]
- }
- // is it UNC
- if l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&
- !IsPathSeparator(path[2]) && path[2] != '.' {
- // first, leading `\\` and next shouldn't be `\`. its server name.
- for n := 3; n < l-1; n++ {
- // second, next '\' shouldn't be repeated.
- if IsPathSeparator(path[n]) {
- n++
- // third, following something characters. its share name.
- if !IsPathSeparator(path[n]) {
- if path[n] == '.' {
- break
- }
- for ; n < l; n++ {
- if IsPathSeparator(path[n]) {
- break
- }
- }
- return path[:n]
- }
- break
- }
- }
- }
- return ""
-}
-
-func fromSlash(path string) string {
- // Replace each '/' with '\\' if present
- var pathbuf []byte
- var lastSlash int
- for i, b := range path {
- if b == '/' {
- if pathbuf == nil {
- pathbuf = make([]byte, len(path))
- }
- copy(pathbuf[lastSlash:], path[lastSlash:i])
- pathbuf[i] = '\\'
- lastSlash = i + 1
- }
- }
- if pathbuf == nil {
- return path
- }
-
- copy(pathbuf[lastSlash:], path[lastSlash:])
- return string(pathbuf)
-}
-
-func dirname(path string) string {
- vol := volumeName(path)
- i := len(path) - 1
- for i >= len(vol) && !IsPathSeparator(path[i]) {
- i--
- }
- dir := path[len(vol) : i+1]
- last := len(dir) - 1
- if last > 0 && IsPathSeparator(dir[last]) {
- dir = dir[:last]
- }
- if dir == "" {
- dir = "."
- }
- return vol + dir
-}
-
-// This is set via go:linkname on runtime.canUseLongPaths, and is true when the OS
-// supports opting into proper long path handling without the need for fixups.
-var canUseLongPaths bool
-
-// fixLongPath returns the extended-length (\\?\-prefixed) form of
-// path when needed, in order to avoid the default 260 character file
-// path limit imposed by Windows. If path is not easily converted to
-// the extended-length form (for example, if path is a relative path
-// or contains .. elements), or is short enough, fixLongPath returns
-// path unmodified.
-//
-// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
-func fixLongPath(path string) string {
- if canUseLongPaths {
- return path
- }
- // Do nothing (and don't allocate) if the path is "short".
- // Empirically (at least on the Windows Server 2013 builder),
- // the kernel is arbitrarily okay with < 248 bytes. That
- // matches what the docs above say:
- // "When using an API to create a directory, the specified
- // path cannot be so long that you cannot append an 8.3 file
- // name (that is, the directory name cannot exceed MAX_PATH
- // minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
- //
- // The MSDN docs appear to say that a normal path that is 248 bytes long
- // will work; empirically the path must be less then 248 bytes long.
- if len(path) < 248 {
- // Don't fix. (This is how Go 1.7 and earlier worked,
- // not automatically generating the \\?\ form)
- return path
- }
-
- // The extended form begins with \\?\, as in
- // \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
- // The extended form disables evaluation of . and .. path
- // elements and disables the interpretation of / as equivalent
- // to \. The conversion here rewrites / to \ and elides
- // . elements as well as trailing or duplicate separators. For
- // simplicity it avoids the conversion entirely for relative
- // paths or paths containing .. elements. For now,
- // \\server\share paths are not converted to
- // \\?\UNC\server\share paths because the rules for doing so
- // are less well-specified.
- if len(path) >= 2 && path[:2] == `\\` {
- // Don't canonicalize UNC paths.
- return path
- }
- if !isAbs(path) {
- // Relative path
- return path
- }
-
- const prefix = `\\?`
-
- pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
- copy(pathbuf, prefix)
- n := len(path)
- r, w := 0, len(prefix)
- for r < n {
- switch {
- case IsPathSeparator(path[r]):
- // empty block
- r++
- case path[r] == '.' && (r+1 == n || IsPathSeparator(path[r+1])):
- // /./
- r++
- case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || IsPathSeparator(path[r+2])):
- // /../ is currently unhandled
- return path
- default:
- pathbuf[w] = '\\'
- w++
- for ; r < n && !IsPathSeparator(path[r]); r++ {
- pathbuf[w] = path[r]
- w++
- }
- }
- }
- // A drive's root directory needs a trailing \
- if w == len(`\\?\c:`) {
- pathbuf[w] = '\\'
- w++
- }
- return string(pathbuf[:w])
-}
diff --git a/contrib/go/_std_1.22/src/os/proc.go b/contrib/go/_std_1.22/src/os/proc.go
deleted file mode 100644
index 3aae5680eea5..000000000000
--- a/contrib/go/_std_1.22/src/os/proc.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2009 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.
-
-// Process etc.
-
-package os
-
-import (
- "internal/testlog"
- "runtime"
- "syscall"
-)
-
-// Args hold the command-line arguments, starting with the program name.
-var Args []string
-
-func init() {
- if runtime.GOOS == "windows" {
- // Initialized in exec_windows.go.
- return
- }
- Args = runtime_args()
-}
-
-func runtime_args() []string // in package runtime
-
-// Getuid returns the numeric user id of the caller.
-//
-// On Windows, it returns -1.
-func Getuid() int { return syscall.Getuid() }
-
-// Geteuid returns the numeric effective user id of the caller.
-//
-// On Windows, it returns -1.
-func Geteuid() int { return syscall.Geteuid() }
-
-// Getgid returns the numeric group id of the caller.
-//
-// On Windows, it returns -1.
-func Getgid() int { return syscall.Getgid() }
-
-// Getegid returns the numeric effective group id of the caller.
-//
-// On Windows, it returns -1.
-func Getegid() int { return syscall.Getegid() }
-
-// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
-//
-// On Windows, it returns syscall.EWINDOWS. See the os/user package
-// for a possible alternative.
-func Getgroups() ([]int, error) {
- gids, e := syscall.Getgroups()
- return gids, NewSyscallError("getgroups", e)
-}
-
-// Exit causes the current program to exit with the given status code.
-// Conventionally, code zero indicates success, non-zero an error.
-// The program terminates immediately; deferred functions are not run.
-//
-// For portability, the status code should be in the range [0, 125].
-func Exit(code int) {
- if code == 0 && testlog.PanicOnExit0() {
- // We were told to panic on calls to os.Exit(0).
- // This is used to fail tests that make an early
- // unexpected call to os.Exit(0).
- panic("unexpected call to os.Exit(0) during test")
- }
-
- // Inform the runtime that os.Exit is being called. If -race is
- // enabled, this will give race detector a chance to fail the
- // program (racy programs do not have the right to finish
- // successfully). If coverage is enabled, then this call will
- // enable us to write out a coverage data file.
- runtime_beforeExit(code)
-
- syscall.Exit(code)
-}
-
-func runtime_beforeExit(exitCode int) // implemented in runtime
diff --git a/contrib/go/_std_1.22/src/os/signal/doc.go b/contrib/go/_std_1.22/src/os/signal/doc.go
deleted file mode 100644
index a2a7525ef0ae..000000000000
--- a/contrib/go/_std_1.22/src/os/signal/doc.go
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2015 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.
-
-/*
-Package signal implements access to incoming signals.
-
-Signals are primarily used on Unix-like systems. For the use of this
-package on Windows and Plan 9, see below.
-
-# Types of signals
-
-The signals SIGKILL and SIGSTOP may not be caught by a program, and
-therefore cannot be affected by this package.
-
-Synchronous signals are signals triggered by errors in program
-execution: SIGBUS, SIGFPE, and SIGSEGV. These are only considered
-synchronous when caused by program execution, not when sent using
-[os.Process.Kill] or the kill program or some similar mechanism. In
-general, except as discussed below, Go programs will convert a
-synchronous signal into a run-time panic.
-
-The remaining signals are asynchronous signals. They are not
-triggered by program errors, but are instead sent from the kernel or
-from some other program.
-
-Of the asynchronous signals, the SIGHUP signal is sent when a program
-loses its controlling terminal. The SIGINT signal is sent when the
-user at the controlling terminal presses the interrupt character,
-which by default is ^C (Control-C). The SIGQUIT signal is sent when
-the user at the controlling terminal presses the quit character, which
-by default is ^\ (Control-Backslash). In general you can cause a
-program to simply exit by pressing ^C, and you can cause it to exit
-with a stack dump by pressing ^\.
-
-# Default behavior of signals in Go programs
-
-By default, a synchronous signal is converted into a run-time panic. A
-SIGHUP, SIGINT, or SIGTERM signal causes the program to exit. A
-SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGSTKFLT, SIGEMT, or SIGSYS signal
-causes the program to exit with a stack dump. A SIGTSTP, SIGTTIN, or
-SIGTTOU signal gets the system default behavior (these signals are
-used by the shell for job control). The SIGPROF signal is handled
-directly by the Go runtime to implement runtime.CPUProfile. Other
-signals will be caught but no action will be taken.
-
-If the Go program is started with either SIGHUP or SIGINT ignored
-(signal handler set to SIG_IGN), they will remain ignored.
-
-If the Go program is started with a non-empty signal mask, that will
-generally be honored. However, some signals are explicitly unblocked:
-the synchronous signals, SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF,
-and, on Linux, signals 32 (SIGCANCEL) and 33 (SIGSETXID)
-(SIGCANCEL and SIGSETXID are used internally by glibc). Subprocesses
-started by [os.Exec], or by [os/exec], will inherit the
-modified signal mask.
-
-# Changing the behavior of signals in Go programs
-
-The functions in this package allow a program to change the way Go
-programs handle signals.
-
-Notify disables the default behavior for a given set of asynchronous
-signals and instead delivers them over one or more registered
-channels. Specifically, it applies to the signals SIGHUP, SIGINT,
-SIGQUIT, SIGABRT, and SIGTERM. It also applies to the job control
-signals SIGTSTP, SIGTTIN, and SIGTTOU, in which case the system
-default behavior does not occur. It also applies to some signals that
-otherwise cause no action: SIGUSR1, SIGUSR2, SIGPIPE, SIGALRM,
-SIGCHLD, SIGCONT, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGWINCH,
-SIGIO, SIGPWR, SIGSYS, SIGINFO, SIGTHR, SIGWAITING, SIGLWP, SIGFREEZE,
-SIGTHAW, SIGLOST, SIGXRES, SIGJVM1, SIGJVM2, and any real time signals
-used on the system. Note that not all of these signals are available
-on all systems.
-
-If the program was started with SIGHUP or SIGINT ignored, and Notify
-is called for either signal, a signal handler will be installed for
-that signal and it will no longer be ignored. If, later, Reset or
-Ignore is called for that signal, or Stop is called on all channels
-passed to Notify for that signal, the signal will once again be
-ignored. Reset will restore the system default behavior for the
-signal, while Ignore will cause the system to ignore the signal
-entirely.
-
-If the program is started with a non-empty signal mask, some signals
-will be explicitly unblocked as described above. If Notify is called
-for a blocked signal, it will be unblocked. If, later, Reset is
-called for that signal, or Stop is called on all channels passed to
-Notify for that signal, the signal will once again be blocked.
-
-# SIGPIPE
-
-When a Go program writes to a broken pipe, the kernel will raise a
-SIGPIPE signal.
-
-If the program has not called Notify to receive SIGPIPE signals, then
-the behavior depends on the file descriptor number. A write to a
-broken pipe on file descriptors 1 or 2 (standard output or standard
-error) will cause the program to exit with a SIGPIPE signal. A write
-to a broken pipe on some other file descriptor will take no action on
-the SIGPIPE signal, and the write will fail with an EPIPE error.
-
-If the program has called Notify to receive SIGPIPE signals, the file
-descriptor number does not matter. The SIGPIPE signal will be
-delivered to the Notify channel, and the write will fail with an EPIPE
-error.
-
-This means that, by default, command line programs will behave like
-typical Unix command line programs, while other programs will not
-crash with SIGPIPE when writing to a closed network connection.
-
-# Go programs that use cgo or SWIG
-
-In a Go program that includes non-Go code, typically C/C++ code
-accessed using cgo or SWIG, Go's startup code normally runs first. It
-configures the signal handlers as expected by the Go runtime, before
-the non-Go startup code runs. If the non-Go startup code wishes to
-install its own signal handlers, it must take certain steps to keep Go
-working well. This section documents those steps and the overall
-effect changes to signal handler settings by the non-Go code can have
-on Go programs. In rare cases, the non-Go code may run before the Go
-code, in which case the next section also applies.
-
-If the non-Go code called by the Go program does not change any signal
-handlers or masks, then the behavior is the same as for a pure Go
-program.
-
-If the non-Go code installs any signal handlers, it must use the
-SA_ONSTACK flag with sigaction. Failing to do so is likely to cause
-the program to crash if the signal is received. Go programs routinely
-run with a limited stack, and therefore set up an alternate signal
-stack.
-
-If the non-Go code installs a signal handler for any of the
-synchronous signals (SIGBUS, SIGFPE, SIGSEGV), then it should record
-the existing Go signal handler. If those signals occur while
-executing Go code, it should invoke the Go signal handler (whether the
-signal occurs while executing Go code can be determined by looking at
-the PC passed to the signal handler). Otherwise some Go run-time
-panics will not occur as expected.
-
-If the non-Go code installs a signal handler for any of the
-asynchronous signals, it may invoke the Go signal handler or not as it
-chooses. Naturally, if it does not invoke the Go signal handler, the
-Go behavior described above will not occur. This can be an issue with
-the SIGPROF signal in particular.
-
-The non-Go code should not change the signal mask on any threads
-created by the Go runtime. If the non-Go code starts new threads of
-its own, it may set the signal mask as it pleases.
-
-If the non-Go code starts a new thread, changes the signal mask, and
-then invokes a Go function in that thread, the Go runtime will
-automatically unblock certain signals: the synchronous signals,
-SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF, SIGCANCEL, and
-SIGSETXID. When the Go function returns, the non-Go signal mask will
-be restored.
-
-If the Go signal handler is invoked on a non-Go thread not running Go
-code, the handler generally forwards the signal to the non-Go code, as
-follows. If the signal is SIGPROF, the Go handler does
-nothing. Otherwise, the Go handler removes itself, unblocks the
-signal, and raises it again, to invoke any non-Go handler or default
-system handler. If the program does not exit, the Go handler then
-reinstalls itself and continues execution of the program.
-
-If a SIGPIPE signal is received, the Go program will invoke the
-special handling described above if the SIGPIPE is received on a Go
-thread. If the SIGPIPE is received on a non-Go thread the signal will
-be forwarded to the non-Go handler, if any; if there is none the
-default system handler will cause the program to terminate.
-
-# Non-Go programs that call Go code
-
-When Go code is built with options like -buildmode=c-shared, it will
-be run as part of an existing non-Go program. The non-Go code may
-have already installed signal handlers when the Go code starts (that
-may also happen in unusual cases when using cgo or SWIG; in that case,
-the discussion here applies). For -buildmode=c-archive the Go runtime
-will initialize signals at global constructor time. For
--buildmode=c-shared the Go runtime will initialize signals when the
-shared library is loaded.
-
-If the Go runtime sees an existing signal handler for the SIGCANCEL or
-SIGSETXID signals (which are used only on Linux), it will turn on
-the SA_ONSTACK flag and otherwise keep the signal handler.
-
-For the synchronous signals and SIGPIPE, the Go runtime will install a
-signal handler. It will save any existing signal handler. If a
-synchronous signal arrives while executing non-Go code, the Go runtime
-will invoke the existing signal handler instead of the Go signal
-handler.
-
-Go code built with -buildmode=c-archive or -buildmode=c-shared will
-not install any other signal handlers by default. If there is an
-existing signal handler, the Go runtime will turn on the SA_ONSTACK
-flag and otherwise keep the signal handler. If Notify is called for an
-asynchronous signal, a Go signal handler will be installed for that
-signal. If, later, Reset is called for that signal, the original
-handling for that signal will be reinstalled, restoring the non-Go
-signal handler if any.
-
-Go code built without -buildmode=c-archive or -buildmode=c-shared will
-install a signal handler for the asynchronous signals listed above,
-and save any existing signal handler. If a signal is delivered to a
-non-Go thread, it will act as described above, except that if there is
-an existing non-Go signal handler, that handler will be installed
-before raising the signal.
-
-# Windows
-
-On Windows a ^C (Control-C) or ^BREAK (Control-Break) normally cause
-the program to exit. If Notify is called for [os.Interrupt], ^C or ^BREAK
-will cause [os.Interrupt] to be sent on the channel, and the program will
-not exit. If Reset is called, or Stop is called on all channels passed
-to Notify, then the default behavior will be restored.
-
-Additionally, if Notify is called, and Windows sends CTRL_CLOSE_EVENT,
-CTRL_LOGOFF_EVENT or CTRL_SHUTDOWN_EVENT to the process, Notify will
-return syscall.SIGTERM. Unlike Control-C and Control-Break, Notify does
-not change process behavior when either CTRL_CLOSE_EVENT,
-CTRL_LOGOFF_EVENT or CTRL_SHUTDOWN_EVENT is received - the process will
-still get terminated unless it exits. But receiving syscall.SIGTERM will
-give the process an opportunity to clean up before termination.
-
-# Plan 9
-
-On Plan 9, signals have type syscall.Note, which is a string. Calling
-Notify with a syscall.Note will cause that value to be sent on the
-channel when that string is posted as a note.
-*/
-package signal
diff --git a/contrib/go/_std_1.22/src/os/types.go b/contrib/go/_std_1.22/src/os/types.go
deleted file mode 100644
index d8edd98b68d7..000000000000
--- a/contrib/go/_std_1.22/src/os/types.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "io/fs"
- "syscall"
-)
-
-// Getpagesize returns the underlying system's memory page size.
-func Getpagesize() int { return syscall.Getpagesize() }
-
-// File represents an open file descriptor.
-type File struct {
- *file // os specific
-}
-
-// A FileInfo describes a file and is returned by Stat and Lstat.
-type FileInfo = fs.FileInfo
-
-// A FileMode represents a file's mode and permission bits.
-// The bits have the same definition on all systems, so that
-// information about files can be moved from one system
-// to another portably. Not all bits apply to all systems.
-// The only required bit is ModeDir for directories.
-type FileMode = fs.FileMode
-
-// The defined file mode bits are the most significant bits of the FileMode.
-// The nine least-significant bits are the standard Unix rwxrwxrwx permissions.
-// The values of these bits should be considered part of the public API and
-// may be used in wire protocols or disk representations: they must not be
-// changed, although new bits might be added.
-const (
- // The single letters are the abbreviations
- // used by the String method's formatting.
- ModeDir = fs.ModeDir // d: is a directory
- ModeAppend = fs.ModeAppend // a: append-only
- ModeExclusive = fs.ModeExclusive // l: exclusive use
- ModeTemporary = fs.ModeTemporary // T: temporary file; Plan 9 only
- ModeSymlink = fs.ModeSymlink // L: symbolic link
- ModeDevice = fs.ModeDevice // D: device file
- ModeNamedPipe = fs.ModeNamedPipe // p: named pipe (FIFO)
- ModeSocket = fs.ModeSocket // S: Unix domain socket
- ModeSetuid = fs.ModeSetuid // u: setuid
- ModeSetgid = fs.ModeSetgid // g: setgid
- ModeCharDevice = fs.ModeCharDevice // c: Unix character device, when ModeDevice is set
- ModeSticky = fs.ModeSticky // t: sticky
- ModeIrregular = fs.ModeIrregular // ?: non-regular file; nothing else is known about this file
-
- // Mask for the type bits. For regular files, none will be set.
- ModeType = fs.ModeType
-
- ModePerm = fs.ModePerm // Unix permission bits, 0o777
-)
-
-func (fs *fileStat) Name() string { return fs.name }
-func (fs *fileStat) IsDir() bool { return fs.Mode().IsDir() }
-
-// SameFile reports whether fi1 and fi2 describe the same file.
-// For example, on Unix this means that the device and inode fields
-// of the two underlying structures are identical; on other systems
-// the decision may be based on the path names.
-// SameFile only applies to results returned by this package's Stat.
-// It returns false in other cases.
-func SameFile(fi1, fi2 FileInfo) bool {
- fs1, ok1 := fi1.(*fileStat)
- fs2, ok2 := fi2.(*fileStat)
- if !ok1 || !ok2 {
- return false
- }
- return sameFile(fs1, fs2)
-}
diff --git a/contrib/go/_std_1.22/src/os/types_windows.go b/contrib/go/_std_1.22/src/os/types_windows.go
deleted file mode 100644
index 6b9fef6c123f..000000000000
--- a/contrib/go/_std_1.22/src/os/types_windows.go
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright 2009 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.
-
-package os
-
-import (
- "internal/syscall/windows"
- "sync"
- "syscall"
- "time"
- "unsafe"
-)
-
-// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
-type fileStat struct {
- name string
-
- // from ByHandleFileInformation, Win32FileAttributeData, Win32finddata, and GetFileInformationByHandleEx
- FileAttributes uint32
- CreationTime syscall.Filetime
- LastAccessTime syscall.Filetime
- LastWriteTime syscall.Filetime
- FileSizeHigh uint32
- FileSizeLow uint32
-
- // from Win32finddata and GetFileInformationByHandleEx
- ReparseTag uint32
-
- // what syscall.GetFileType returns
- filetype uint32
-
- // used to implement SameFile
- sync.Mutex
- path string
- vol uint32
- idxhi uint32
- idxlo uint32
- appendNameToPath bool
-}
-
-// newFileStatFromGetFileInformationByHandle calls GetFileInformationByHandle
-// to gather all required information about the file handle h.
-func newFileStatFromGetFileInformationByHandle(path string, h syscall.Handle) (fs *fileStat, err error) {
- var d syscall.ByHandleFileInformation
- err = syscall.GetFileInformationByHandle(h, &d)
- if err != nil {
- return nil, &PathError{Op: "GetFileInformationByHandle", Path: path, Err: err}
- }
-
- var ti windows.FILE_ATTRIBUTE_TAG_INFO
- err = windows.GetFileInformationByHandleEx(h, windows.FileAttributeTagInfo, (*byte)(unsafe.Pointer(&ti)), uint32(unsafe.Sizeof(ti)))
- if err != nil {
- if errno, ok := err.(syscall.Errno); ok && errno == windows.ERROR_INVALID_PARAMETER {
- // It appears calling GetFileInformationByHandleEx with
- // FILE_ATTRIBUTE_TAG_INFO fails on FAT file system with
- // ERROR_INVALID_PARAMETER. Clear ti.ReparseTag in that
- // instance to indicate no symlinks are possible.
- ti.ReparseTag = 0
- } else {
- return nil, &PathError{Op: "GetFileInformationByHandleEx", Path: path, Err: err}
- }
- }
-
- return &fileStat{
- name: basename(path),
- FileAttributes: d.FileAttributes,
- CreationTime: d.CreationTime,
- LastAccessTime: d.LastAccessTime,
- LastWriteTime: d.LastWriteTime,
- FileSizeHigh: d.FileSizeHigh,
- FileSizeLow: d.FileSizeLow,
- vol: d.VolumeSerialNumber,
- idxhi: d.FileIndexHigh,
- idxlo: d.FileIndexLow,
- ReparseTag: ti.ReparseTag,
- // fileStat.path is used by os.SameFile to decide if it needs
- // to fetch vol, idxhi and idxlo. But these are already set,
- // so set fileStat.path to "" to prevent os.SameFile doing it again.
- }, nil
-}
-
-// newFileStatFromFileIDBothDirInfo copies all required information
-// from windows.FILE_ID_BOTH_DIR_INFO d into the newly created fileStat.
-func newFileStatFromFileIDBothDirInfo(d *windows.FILE_ID_BOTH_DIR_INFO) *fileStat {
- // The FILE_ID_BOTH_DIR_INFO MSDN documentations isn't completely correct.
- // FileAttributes can contain any file attributes that is currently set on the file,
- // not just the ones documented.
- // EaSize contains the reparse tag if the file is a reparse point.
- return &fileStat{
- FileAttributes: d.FileAttributes,
- CreationTime: d.CreationTime,
- LastAccessTime: d.LastAccessTime,
- LastWriteTime: d.LastWriteTime,
- FileSizeHigh: uint32(d.EndOfFile >> 32),
- FileSizeLow: uint32(d.EndOfFile),
- ReparseTag: d.EaSize,
- idxhi: uint32(d.FileID >> 32),
- idxlo: uint32(d.FileID),
- }
-}
-
-// newFileStatFromFileFullDirInfo copies all required information
-// from windows.FILE_FULL_DIR_INFO d into the newly created fileStat.
-func newFileStatFromFileFullDirInfo(d *windows.FILE_FULL_DIR_INFO) *fileStat {
- return &fileStat{
- FileAttributes: d.FileAttributes,
- CreationTime: d.CreationTime,
- LastAccessTime: d.LastAccessTime,
- LastWriteTime: d.LastWriteTime,
- FileSizeHigh: uint32(d.EndOfFile >> 32),
- FileSizeLow: uint32(d.EndOfFile),
- ReparseTag: d.EaSize,
- }
-}
-
-// newFileStatFromWin32finddata copies all required information
-// from syscall.Win32finddata d into the newly created fileStat.
-func newFileStatFromWin32finddata(d *syscall.Win32finddata) *fileStat {
- fs := &fileStat{
- FileAttributes: d.FileAttributes,
- CreationTime: d.CreationTime,
- LastAccessTime: d.LastAccessTime,
- LastWriteTime: d.LastWriteTime,
- FileSizeHigh: d.FileSizeHigh,
- FileSizeLow: d.FileSizeLow,
- }
- if d.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
- // Per https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw:
- // “If the dwFileAttributes member includes the FILE_ATTRIBUTE_REPARSE_POINT
- // attribute, this member specifies the reparse point tag. Otherwise, this
- // value is undefined and should not be used.”
- fs.ReparseTag = d.Reserved0
- }
- return fs
-}
-
-// isReparseTagNameSurrogate determines whether a tag's associated
-// reparse point is a surrogate for another named entity (for example, a mounted folder).
-//
-// See https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-isreparsetagnamesurrogate
-// and https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags.
-func (fs *fileStat) isReparseTagNameSurrogate() bool {
- // True for IO_REPARSE_TAG_SYMLINK and IO_REPARSE_TAG_MOUNT_POINT.
- return fs.ReparseTag&0x20000000 != 0
-}
-
-func (fs *fileStat) isSymlink() bool {
- // As of https://go.dev/cl/86556, we treat MOUNT_POINT reparse points as
- // symlinks because otherwise certain directory junction tests in the
- // path/filepath package would fail.
- //
- // However,
- // https://learn.microsoft.com/en-us/windows/win32/fileio/hard-links-and-junctions
- // seems to suggest that directory junctions should be treated like hard
- // links, not symlinks.
- //
- // TODO(bcmills): Get more input from Microsoft on what the behavior ought to
- // be for MOUNT_POINT reparse points.
-
- return fs.ReparseTag == syscall.IO_REPARSE_TAG_SYMLINK ||
- fs.ReparseTag == windows.IO_REPARSE_TAG_MOUNT_POINT
-}
-
-func (fs *fileStat) Size() int64 {
- return int64(fs.FileSizeHigh)<<32 + int64(fs.FileSizeLow)
-}
-
-func (fs *fileStat) Mode() (m FileMode) {
- if fs.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 {
- m |= 0444
- } else {
- m |= 0666
- }
- if fs.isSymlink() {
- return m | ModeSymlink
- }
- if fs.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
- m |= ModeDir | 0111
- }
- switch fs.filetype {
- case syscall.FILE_TYPE_PIPE:
- m |= ModeNamedPipe
- case syscall.FILE_TYPE_CHAR:
- m |= ModeDevice | ModeCharDevice
- }
- if fs.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 && m&ModeType == 0 {
- if fs.ReparseTag == windows.IO_REPARSE_TAG_DEDUP {
- // If the Data Deduplication service is enabled on Windows Server, its
- // Optimization job may convert regular files to IO_REPARSE_TAG_DEDUP
- // whenever that job runs.
- //
- // However, DEDUP reparse points remain similar in most respects to
- // regular files: they continue to support random-access reads and writes
- // of persistent data, and they shouldn't add unexpected latency or
- // unavailability in the way that a network filesystem might.
- //
- // Go programs may use ModeIrregular to filter out unusual files (such as
- // raw device files on Linux, POSIX FIFO special files, and so on), so
- // to avoid files changing unpredictably from regular to irregular we will
- // consider DEDUP files to be close enough to regular to treat as such.
- } else {
- m |= ModeIrregular
- }
- }
- return m
-}
-
-func (fs *fileStat) ModTime() time.Time {
- return time.Unix(0, fs.LastWriteTime.Nanoseconds())
-}
-
-// Sys returns syscall.Win32FileAttributeData for file fs.
-func (fs *fileStat) Sys() any {
- return &syscall.Win32FileAttributeData{
- FileAttributes: fs.FileAttributes,
- CreationTime: fs.CreationTime,
- LastAccessTime: fs.LastAccessTime,
- LastWriteTime: fs.LastWriteTime,
- FileSizeHigh: fs.FileSizeHigh,
- FileSizeLow: fs.FileSizeLow,
- }
-}
-
-func (fs *fileStat) loadFileId() error {
- fs.Lock()
- defer fs.Unlock()
- if fs.path == "" {
- // already done
- return nil
- }
- var path string
- if fs.appendNameToPath {
- path = fixLongPath(fs.path + `\` + fs.name)
- } else {
- path = fs.path
- }
- pathp, err := syscall.UTF16PtrFromString(path)
- if err != nil {
- return err
- }
-
- // Per https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-points-and-file-operations,
- // “Applications that use the CreateFile function should specify the
- // FILE_FLAG_OPEN_REPARSE_POINT flag when opening the file if it is a reparse
- // point.”
- //
- // And per https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew,
- // “If the file is not a reparse point, then this flag is ignored.”
- //
- // So we set FILE_FLAG_OPEN_REPARSE_POINT unconditionally, since we want
- // information about the reparse point itself.
- //
- // If the file is a symlink, the symlink target should have already been
- // resolved when the fileStat was created, so we don't need to worry about
- // resolving symlink reparse points again here.
- attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS | syscall.FILE_FLAG_OPEN_REPARSE_POINT)
-
- h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, attrs, 0)
- if err != nil {
- return err
- }
- defer syscall.CloseHandle(h)
- var i syscall.ByHandleFileInformation
- err = syscall.GetFileInformationByHandle(h, &i)
- if err != nil {
- return err
- }
- fs.path = ""
- fs.vol = i.VolumeSerialNumber
- fs.idxhi = i.FileIndexHigh
- fs.idxlo = i.FileIndexLow
- return nil
-}
-
-// saveInfoFromPath saves full path of the file to be used by os.SameFile later,
-// and set name from path.
-func (fs *fileStat) saveInfoFromPath(path string) error {
- fs.path = path
- if !isAbs(fs.path) {
- var err error
- fs.path, err = syscall.FullPath(fs.path)
- if err != nil {
- return &PathError{Op: "FullPath", Path: path, Err: err}
- }
- }
- fs.name = basename(path)
- return nil
-}
-
-func sameFile(fs1, fs2 *fileStat) bool {
- e := fs1.loadFileId()
- if e != nil {
- return false
- }
- e = fs2.loadFileId()
- if e != nil {
- return false
- }
- return fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo
-}
-
-// For testing.
-func atime(fi FileInfo) time.Time {
- return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
-}
diff --git a/contrib/go/_std_1.22/src/os/user/lookup.go b/contrib/go/_std_1.22/src/os/user/lookup.go
deleted file mode 100644
index ed33d0c7cd17..000000000000
--- a/contrib/go/_std_1.22/src/os/user/lookup.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2011 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.
-
-package user
-
-import "sync"
-
-const (
- userFile = "/etc/passwd"
- groupFile = "/etc/group"
-)
-
-var colon = []byte{':'}
-
-// Current returns the current user.
-//
-// The first call will cache the current user information.
-// Subsequent calls will return the cached value and will not reflect
-// changes to the current user.
-func Current() (*User, error) {
- cache.Do(func() { cache.u, cache.err = current() })
- if cache.err != nil {
- return nil, cache.err
- }
- u := *cache.u // copy
- return &u, nil
-}
-
-// cache of the current user
-var cache struct {
- sync.Once
- u *User
- err error
-}
-
-// Lookup looks up a user by username. If the user cannot be found, the
-// returned error is of type UnknownUserError.
-func Lookup(username string) (*User, error) {
- if u, err := Current(); err == nil && u.Username == username {
- return u, err
- }
- return lookupUser(username)
-}
-
-// LookupId looks up a user by userid. If the user cannot be found, the
-// returned error is of type UnknownUserIdError.
-func LookupId(uid string) (*User, error) {
- if u, err := Current(); err == nil && u.Uid == uid {
- return u, err
- }
- return lookupUserId(uid)
-}
-
-// LookupGroup looks up a group by name. If the group cannot be found, the
-// returned error is of type UnknownGroupError.
-func LookupGroup(name string) (*Group, error) {
- return lookupGroup(name)
-}
-
-// LookupGroupId looks up a group by groupid. If the group cannot be found, the
-// returned error is of type UnknownGroupIdError.
-func LookupGroupId(gid string) (*Group, error) {
- return lookupGroupId(gid)
-}
-
-// GroupIds returns the list of group IDs that the user is a member of.
-func (u *User) GroupIds() ([]string, error) {
- return listGroups(u)
-}
diff --git a/contrib/go/_std_1.22/src/os/user/ya.make b/contrib/go/_std_1.22/src/os/user/ya.make
deleted file mode 100644
index 9e0e9f8f2ae4..000000000000
--- a/contrib/go/_std_1.22/src/os/user/ya.make
+++ /dev/null
@@ -1,42 +0,0 @@
-SUBSCRIBER(g:contrib)
-
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- cgo_listgroups_unix.go
- cgo_lookup_syscall.go
- cgo_lookup_unix.go
- getgrouplist_syscall.go
- lookup.go
- user.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED)
- SRCS(
- cgo_listgroups_unix.go
- cgo_lookup_unix.go
- lookup.go
- user.go
- )
-
-IF (CGO_ENABLED)
- CGO_SRCS(
- cgo_lookup_cgo.go
- getgrouplist_unix.go
- )
-ENDIF()
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- listgroups_unix.go
- lookup.go
- lookup_stubs.go
- lookup_unix.go
- user.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- lookup.go
- lookup_windows.go
- user.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/os/ya.make b/contrib/go/_std_1.22/src/os/ya.make
deleted file mode 100644
index 8911bf552df5..000000000000
--- a/contrib/go/_std_1.22/src/os/ya.make
+++ /dev/null
@@ -1,113 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- dir.go
- dir_darwin.go
- endian_little.go
- env.go
- error.go
- error_errno.go
- error_posix.go
- exec.go
- exec_posix.go
- exec_unix.go
- executable.go
- executable_darwin.go
- file.go
- file_open_unix.go
- file_posix.go
- file_unix.go
- getwd.go
- path.go
- path_unix.go
- pipe_unix.go
- proc.go
- rawconn.go
- removeall_at.go
- stat.go
- stat_darwin.go
- stat_unix.go
- sticky_bsd.go
- sys.go
- sys_bsd.go
- sys_unix.go
- tempfile.go
- types.go
- types_unix.go
- wait_unimp.go
- zero_copy_stub.go
- )
-ELSEIF (OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- dir.go
- dir_unix.go
- dirent_linux.go
- endian_little.go
- env.go
- error.go
- error_errno.go
- error_posix.go
- exec.go
- exec_posix.go
- exec_unix.go
- executable.go
- executable_procfs.go
- file.go
- file_open_unix.go
- file_posix.go
- file_unix.go
- getwd.go
- path.go
- path_unix.go
- pipe2_unix.go
- proc.go
- rawconn.go
- removeall_at.go
- stat.go
- stat_linux.go
- stat_unix.go
- sticky_notbsd.go
- sys.go
- sys_linux.go
- sys_unix.go
- tempfile.go
- types.go
- types_unix.go
- wait_waitid.go
- zero_copy_linux.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- dir.go
- dir_windows.go
- endian_little.go
- env.go
- error.go
- error_errno.go
- error_posix.go
- exec.go
- exec_posix.go
- exec_windows.go
- executable.go
- executable_windows.go
- file.go
- file_posix.go
- file_windows.go
- getwd.go
- path.go
- path_windows.go
- proc.go
- rawconn.go
- removeall_noat.go
- stat.go
- stat_windows.go
- sticky_notbsd.go
- sys.go
- sys_windows.go
- tempfile.go
- types.go
- types_windows.go
- zero_copy_stub.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/path/filepath/path.go b/contrib/go/_std_1.22/src/path/filepath/path.go
deleted file mode 100644
index 2af0f5b04cfc..000000000000
--- a/contrib/go/_std_1.22/src/path/filepath/path.go
+++ /dev/null
@@ -1,639 +0,0 @@
-// Copyright 2009 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.
-
-// Package filepath implements utility routines for manipulating filename paths
-// in a way compatible with the target operating system-defined file paths.
-//
-// The filepath package uses either forward slashes or backslashes,
-// depending on the operating system. To process paths such as URLs
-// that always use forward slashes regardless of the operating
-// system, see the [path] package.
-package filepath
-
-import (
- "errors"
- "io/fs"
- "os"
- "slices"
- "sort"
- "strings"
-)
-
-// A lazybuf is a lazily constructed path buffer.
-// It supports append, reading previously appended bytes,
-// and retrieving the final string. It does not allocate a buffer
-// to hold the output until that output diverges from s.
-type lazybuf struct {
- path string
- buf []byte
- w int
- volAndPath string
- volLen int
-}
-
-func (b *lazybuf) index(i int) byte {
- if b.buf != nil {
- return b.buf[i]
- }
- return b.path[i]
-}
-
-func (b *lazybuf) append(c byte) {
- if b.buf == nil {
- if b.w < len(b.path) && b.path[b.w] == c {
- b.w++
- return
- }
- b.buf = make([]byte, len(b.path))
- copy(b.buf, b.path[:b.w])
- }
- b.buf[b.w] = c
- b.w++
-}
-
-func (b *lazybuf) prepend(prefix ...byte) {
- b.buf = slices.Insert(b.buf, 0, prefix...)
- b.w += len(prefix)
-}
-
-func (b *lazybuf) string() string {
- if b.buf == nil {
- return b.volAndPath[:b.volLen+b.w]
- }
- return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
-}
-
-const (
- Separator = os.PathSeparator
- ListSeparator = os.PathListSeparator
-)
-
-// Clean returns the shortest path name equivalent to path
-// by purely lexical processing. It applies the following rules
-// iteratively until no further processing can be done:
-//
-// 1. Replace multiple [Separator] elements with a single one.
-// 2. Eliminate each . path name element (the current directory).
-// 3. Eliminate each inner .. path name element (the parent directory)
-// along with the non-.. element that precedes it.
-// 4. Eliminate .. elements that begin a rooted path:
-// that is, replace "/.." by "/" at the beginning of a path,
-// assuming Separator is '/'.
-//
-// The returned path ends in a slash only if it represents a root directory,
-// such as "/" on Unix or `C:\` on Windows.
-//
-// Finally, any occurrences of slash are replaced by Separator.
-//
-// If the result of this process is an empty string, Clean
-// returns the string ".".
-//
-// On Windows, Clean does not modify the volume name other than to replace
-// occurrences of "/" with `\`.
-// For example, Clean("//host/share/../x") returns `\\host\share\x`.
-//
-// See also Rob Pike, “Lexical File Names in Plan 9 or
-// Getting Dot-Dot Right,”
-// https://9p.io/sys/doc/lexnames.html
-func Clean(path string) string {
- originalPath := path
- volLen := volumeNameLen(path)
- path = path[volLen:]
- if path == "" {
- if volLen > 1 && os.IsPathSeparator(originalPath[0]) && os.IsPathSeparator(originalPath[1]) {
- // should be UNC
- return FromSlash(originalPath)
- }
- return originalPath + "."
- }
- rooted := os.IsPathSeparator(path[0])
-
- // Invariants:
- // reading from path; r is index of next byte to process.
- // writing to buf; w is index of next byte to write.
- // dotdot is index in buf where .. must stop, either because
- // it is the leading slash or it is a leading ../../.. prefix.
- n := len(path)
- out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
- r, dotdot := 0, 0
- if rooted {
- out.append(Separator)
- r, dotdot = 1, 1
- }
-
- for r < n {
- switch {
- case os.IsPathSeparator(path[r]):
- // empty path element
- r++
- case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
- // . element
- r++
- case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
- // .. element: remove to last separator
- r += 2
- switch {
- case out.w > dotdot:
- // can backtrack
- out.w--
- for out.w > dotdot && !os.IsPathSeparator(out.index(out.w)) {
- out.w--
- }
- case !rooted:
- // cannot backtrack, but not rooted, so append .. element.
- if out.w > 0 {
- out.append(Separator)
- }
- out.append('.')
- out.append('.')
- dotdot = out.w
- }
- default:
- // real path element.
- // add slash if needed
- if rooted && out.w != 1 || !rooted && out.w != 0 {
- out.append(Separator)
- }
- // copy element
- for ; r < n && !os.IsPathSeparator(path[r]); r++ {
- out.append(path[r])
- }
- }
- }
-
- // Turn empty string into "."
- if out.w == 0 {
- out.append('.')
- }
-
- postClean(&out) // avoid creating absolute paths on Windows
- return FromSlash(out.string())
-}
-
-// IsLocal reports whether path, using lexical analysis only, has all of these properties:
-//
-// - is within the subtree rooted at the directory in which path is evaluated
-// - is not an absolute path
-// - is not empty
-// - on Windows, is not a reserved name such as "NUL"
-//
-// If IsLocal(path) returns true, then
-// Join(base, path) will always produce a path contained within base and
-// Clean(path) will always produce an unrooted path with no ".." path elements.
-//
-// IsLocal is a purely lexical operation.
-// In particular, it does not account for the effect of any symbolic links
-// that may exist in the filesystem.
-func IsLocal(path string) bool {
- return isLocal(path)
-}
-
-func unixIsLocal(path string) bool {
- if IsAbs(path) || path == "" {
- return false
- }
- hasDots := false
- for p := path; p != ""; {
- var part string
- part, p, _ = strings.Cut(p, "/")
- if part == "." || part == ".." {
- hasDots = true
- break
- }
- }
- if hasDots {
- path = Clean(path)
- }
- if path == ".." || strings.HasPrefix(path, "../") {
- return false
- }
- return true
-}
-
-// ToSlash returns the result of replacing each separator character
-// in path with a slash ('/') character. Multiple separators are
-// replaced by multiple slashes.
-func ToSlash(path string) string {
- if Separator == '/' {
- return path
- }
- return strings.ReplaceAll(path, string(Separator), "/")
-}
-
-// FromSlash returns the result of replacing each slash ('/') character
-// in path with a separator character. Multiple slashes are replaced
-// by multiple separators.
-func FromSlash(path string) string {
- if Separator == '/' {
- return path
- }
- return strings.ReplaceAll(path, "/", string(Separator))
-}
-
-// SplitList splits a list of paths joined by the OS-specific [ListSeparator],
-// usually found in PATH or GOPATH environment variables.
-// Unlike strings.Split, SplitList returns an empty slice when passed an empty
-// string.
-func SplitList(path string) []string {
- return splitList(path)
-}
-
-// Split splits path immediately following the final [Separator],
-// separating it into a directory and file name component.
-// If there is no Separator in path, Split returns an empty dir
-// and file set to path.
-// The returned values have the property that path = dir+file.
-func Split(path string) (dir, file string) {
- vol := VolumeName(path)
- i := len(path) - 1
- for i >= len(vol) && !os.IsPathSeparator(path[i]) {
- i--
- }
- return path[:i+1], path[i+1:]
-}
-
-// Join joins any number of path elements into a single path,
-// separating them with an OS specific [Separator]. Empty elements
-// are ignored. The result is Cleaned. However, if the argument
-// list is empty or all its elements are empty, Join returns
-// an empty string.
-// On Windows, the result will only be a UNC path if the first
-// non-empty element is a UNC path.
-func Join(elem ...string) string {
- return join(elem)
-}
-
-// Ext returns the file name extension used by path.
-// The extension is the suffix beginning at the final dot
-// in the final element of path; it is empty if there is
-// no dot.
-func Ext(path string) string {
- for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
- if path[i] == '.' {
- return path[i:]
- }
- }
- return ""
-}
-
-// EvalSymlinks returns the path name after the evaluation of any symbolic
-// links.
-// If path is relative the result will be relative to the current directory,
-// unless one of the components is an absolute symbolic link.
-// EvalSymlinks calls [Clean] on the result.
-func EvalSymlinks(path string) (string, error) {
- return evalSymlinks(path)
-}
-
-// Abs returns an absolute representation of path.
-// If the path is not absolute it will be joined with the current
-// working directory to turn it into an absolute path. The absolute
-// path name for a given file is not guaranteed to be unique.
-// Abs calls [Clean] on the result.
-func Abs(path string) (string, error) {
- return abs(path)
-}
-
-func unixAbs(path string) (string, error) {
- if IsAbs(path) {
- return Clean(path), nil
- }
- wd, err := os.Getwd()
- if err != nil {
- return "", err
- }
- return Join(wd, path), nil
-}
-
-// Rel returns a relative path that is lexically equivalent to targpath when
-// joined to basepath with an intervening separator. That is,
-// [Join](basepath, Rel(basepath, targpath)) is equivalent to targpath itself.
-// On success, the returned path will always be relative to basepath,
-// even if basepath and targpath share no elements.
-// An error is returned if targpath can't be made relative to basepath or if
-// knowing the current working directory would be necessary to compute it.
-// Rel calls [Clean] on the result.
-func Rel(basepath, targpath string) (string, error) {
- baseVol := VolumeName(basepath)
- targVol := VolumeName(targpath)
- base := Clean(basepath)
- targ := Clean(targpath)
- if sameWord(targ, base) {
- return ".", nil
- }
- base = base[len(baseVol):]
- targ = targ[len(targVol):]
- if base == "." {
- base = ""
- } else if base == "" && volumeNameLen(baseVol) > 2 /* isUNC */ {
- // Treat any targetpath matching `\\host\share` basepath as absolute path.
- base = string(Separator)
- }
-
- // Can't use IsAbs - `\a` and `a` are both relative in Windows.
- baseSlashed := len(base) > 0 && base[0] == Separator
- targSlashed := len(targ) > 0 && targ[0] == Separator
- if baseSlashed != targSlashed || !sameWord(baseVol, targVol) {
- return "", errors.New("Rel: can't make " + targpath + " relative to " + basepath)
- }
- // Position base[b0:bi] and targ[t0:ti] at the first differing elements.
- bl := len(base)
- tl := len(targ)
- var b0, bi, t0, ti int
- for {
- for bi < bl && base[bi] != Separator {
- bi++
- }
- for ti < tl && targ[ti] != Separator {
- ti++
- }
- if !sameWord(targ[t0:ti], base[b0:bi]) {
- break
- }
- if bi < bl {
- bi++
- }
- if ti < tl {
- ti++
- }
- b0 = bi
- t0 = ti
- }
- if base[b0:bi] == ".." {
- return "", errors.New("Rel: can't make " + targpath + " relative to " + basepath)
- }
- if b0 != bl {
- // Base elements left. Must go up before going down.
- seps := strings.Count(base[b0:bl], string(Separator))
- size := 2 + seps*3
- if tl != t0 {
- size += 1 + tl - t0
- }
- buf := make([]byte, size)
- n := copy(buf, "..")
- for i := 0; i < seps; i++ {
- buf[n] = Separator
- copy(buf[n+1:], "..")
- n += 3
- }
- if t0 != tl {
- buf[n] = Separator
- copy(buf[n+1:], targ[t0:])
- }
- return string(buf), nil
- }
- return targ[t0:], nil
-}
-
-// SkipDir is used as a return value from [WalkFunc] to indicate that
-// the directory named in the call is to be skipped. It is not returned
-// as an error by any function.
-var SkipDir error = fs.SkipDir
-
-// SkipAll is used as a return value from [WalkFunc] to indicate that
-// all remaining files and directories are to be skipped. It is not returned
-// as an error by any function.
-var SkipAll error = fs.SkipAll
-
-// WalkFunc is the type of the function called by [Walk] to visit each
-// file or directory.
-//
-// The path argument contains the argument to Walk as a prefix.
-// That is, if Walk is called with root argument "dir" and finds a file
-// named "a" in that directory, the walk function will be called with
-// argument "dir/a".
-//
-// The directory and file are joined with Join, which may clean the
-// directory name: if Walk is called with the root argument "x/../dir"
-// and finds a file named "a" in that directory, the walk function will
-// be called with argument "dir/a", not "x/../dir/a".
-//
-// The info argument is the fs.FileInfo for the named path.
-//
-// The error result returned by the function controls how Walk continues.
-// If the function returns the special value [SkipDir], Walk skips the
-// current directory (path if info.IsDir() is true, otherwise path's
-// parent directory). If the function returns the special value [SkipAll],
-// Walk skips all remaining files and directories. Otherwise, if the function
-// returns a non-nil error, Walk stops entirely and returns that error.
-//
-// The err argument reports an error related to path, signaling that Walk
-// will not walk into that directory. The function can decide how to
-// handle that error; as described earlier, returning the error will
-// cause Walk to stop walking the entire tree.
-//
-// Walk calls the function with a non-nil err argument in two cases.
-//
-// First, if an [os.Lstat] on the root directory or any directory or file
-// in the tree fails, Walk calls the function with path set to that
-// directory or file's path, info set to nil, and err set to the error
-// from os.Lstat.
-//
-// Second, if a directory's Readdirnames method fails, Walk calls the
-// function with path set to the directory's path, info, set to an
-// [fs.FileInfo] describing the directory, and err set to the error from
-// Readdirnames.
-type WalkFunc func(path string, info fs.FileInfo, err error) error
-
-var lstat = os.Lstat // for testing
-
-// walkDir recursively descends path, calling walkDirFn.
-func walkDir(path string, d fs.DirEntry, walkDirFn fs.WalkDirFunc) error {
- if err := walkDirFn(path, d, nil); err != nil || !d.IsDir() {
- if err == SkipDir && d.IsDir() {
- // Successfully skipped directory.
- err = nil
- }
- return err
- }
-
- dirs, err := os.ReadDir(path)
- if err != nil {
- // Second call, to report ReadDir error.
- err = walkDirFn(path, d, err)
- if err != nil {
- if err == SkipDir && d.IsDir() {
- err = nil
- }
- return err
- }
- }
-
- for _, d1 := range dirs {
- path1 := Join(path, d1.Name())
- if err := walkDir(path1, d1, walkDirFn); err != nil {
- if err == SkipDir {
- break
- }
- return err
- }
- }
- return nil
-}
-
-// walk recursively descends path, calling walkFn.
-func walk(path string, info fs.FileInfo, walkFn WalkFunc) error {
- if !info.IsDir() {
- return walkFn(path, info, nil)
- }
-
- names, err := readDirNames(path)
- err1 := walkFn(path, info, err)
- // If err != nil, walk can't walk into this directory.
- // err1 != nil means walkFn want walk to skip this directory or stop walking.
- // Therefore, if one of err and err1 isn't nil, walk will return.
- if err != nil || err1 != nil {
- // The caller's behavior is controlled by the return value, which is decided
- // by walkFn. walkFn may ignore err and return nil.
- // If walkFn returns SkipDir or SkipAll, it will be handled by the caller.
- // So walk should return whatever walkFn returns.
- return err1
- }
-
- for _, name := range names {
- filename := Join(path, name)
- fileInfo, err := lstat(filename)
- if err != nil {
- if err := walkFn(filename, fileInfo, err); err != nil && err != SkipDir {
- return err
- }
- } else {
- err = walk(filename, fileInfo, walkFn)
- if err != nil {
- if !fileInfo.IsDir() || err != SkipDir {
- return err
- }
- }
- }
- }
- return nil
-}
-
-// WalkDir walks the file tree rooted at root, calling fn for each file or
-// directory in the tree, including root.
-//
-// All errors that arise visiting files and directories are filtered by fn:
-// see the [fs.WalkDirFunc] documentation for details.
-//
-// The files are walked in lexical order, which makes the output deterministic
-// but requires WalkDir to read an entire directory into memory before proceeding
-// to walk that directory.
-//
-// WalkDir does not follow symbolic links.
-//
-// WalkDir calls fn with paths that use the separator character appropriate
-// for the operating system. This is unlike [io/fs.WalkDir], which always
-// uses slash separated paths.
-func WalkDir(root string, fn fs.WalkDirFunc) error {
- info, err := os.Lstat(root)
- if err != nil {
- err = fn(root, nil, err)
- } else {
- err = walkDir(root, fs.FileInfoToDirEntry(info), fn)
- }
- if err == SkipDir || err == SkipAll {
- return nil
- }
- return err
-}
-
-// Walk walks the file tree rooted at root, calling fn for each file or
-// directory in the tree, including root.
-//
-// All errors that arise visiting files and directories are filtered by fn:
-// see the [WalkFunc] documentation for details.
-//
-// The files are walked in lexical order, which makes the output deterministic
-// but requires Walk to read an entire directory into memory before proceeding
-// to walk that directory.
-//
-// Walk does not follow symbolic links.
-//
-// Walk is less efficient than [WalkDir], introduced in Go 1.16,
-// which avoids calling os.Lstat on every visited file or directory.
-func Walk(root string, fn WalkFunc) error {
- info, err := os.Lstat(root)
- if err != nil {
- err = fn(root, nil, err)
- } else {
- err = walk(root, info, fn)
- }
- if err == SkipDir || err == SkipAll {
- return nil
- }
- return err
-}
-
-// readDirNames reads the directory named by dirname and returns
-// a sorted list of directory entry names.
-func readDirNames(dirname string) ([]string, error) {
- f, err := os.Open(dirname)
- if err != nil {
- return nil, err
- }
- names, err := f.Readdirnames(-1)
- f.Close()
- if err != nil {
- return nil, err
- }
- sort.Strings(names)
- return names, nil
-}
-
-// Base returns the last element of path.
-// Trailing path separators are removed before extracting the last element.
-// If the path is empty, Base returns ".".
-// If the path consists entirely of separators, Base returns a single separator.
-func Base(path string) string {
- if path == "" {
- return "."
- }
- // Strip trailing slashes.
- for len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
- path = path[0 : len(path)-1]
- }
- // Throw away volume name
- path = path[len(VolumeName(path)):]
- // Find the last element
- i := len(path) - 1
- for i >= 0 && !os.IsPathSeparator(path[i]) {
- i--
- }
- if i >= 0 {
- path = path[i+1:]
- }
- // If empty now, it had only slashes.
- if path == "" {
- return string(Separator)
- }
- return path
-}
-
-// Dir returns all but the last element of path, typically the path's directory.
-// After dropping the final element, Dir calls [Clean] on the path and trailing
-// slashes are removed.
-// If the path is empty, Dir returns ".".
-// If the path consists entirely of separators, Dir returns a single separator.
-// The returned path does not end in a separator unless it is the root directory.
-func Dir(path string) string {
- vol := VolumeName(path)
- i := len(path) - 1
- for i >= len(vol) && !os.IsPathSeparator(path[i]) {
- i--
- }
- dir := Clean(path[len(vol) : i+1])
- if dir == "." && len(vol) > 2 {
- // must be UNC
- return vol
- }
- return vol + dir
-}
-
-// VolumeName returns leading volume name.
-// Given "C:\foo\bar" it returns "C:" on Windows.
-// Given "\\host\share\foo" it returns "\\host\share".
-// On other platforms it returns "".
-func VolumeName(path string) string {
- return FromSlash(path[:volumeNameLen(path)])
-}
diff --git a/contrib/go/_std_1.22/src/path/filepath/path_plan9.go b/contrib/go/_std_1.22/src/path/filepath/path_plan9.go
deleted file mode 100644
index 453206aee3e0..000000000000
--- a/contrib/go/_std_1.22/src/path/filepath/path_plan9.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2010 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.
-
-package filepath
-
-import "strings"
-
-func isLocal(path string) bool {
- return unixIsLocal(path)
-}
-
-// IsAbs reports whether the path is absolute.
-func IsAbs(path string) bool {
- return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
-}
-
-// volumeNameLen returns length of the leading volume name on Windows.
-// It returns 0 elsewhere.
-func volumeNameLen(path string) int {
- return 0
-}
-
-// HasPrefix exists for historical compatibility and should not be used.
-//
-// Deprecated: HasPrefix does not respect path boundaries and
-// does not ignore case when required.
-func HasPrefix(p, prefix string) bool {
- return strings.HasPrefix(p, prefix)
-}
-
-func splitList(path string) []string {
- if path == "" {
- return []string{}
- }
- return strings.Split(path, string(ListSeparator))
-}
-
-func abs(path string) (string, error) {
- return unixAbs(path)
-}
-
-func join(elem []string) string {
- // If there's a bug here, fix the logic in ./path_unix.go too.
- for i, e := range elem {
- if e != "" {
- return Clean(strings.Join(elem[i:], string(Separator)))
- }
- }
- return ""
-}
-
-func sameWord(a, b string) bool {
- return a == b
-}
diff --git a/contrib/go/_std_1.22/src/path/filepath/path_unix.go b/contrib/go/_std_1.22/src/path/filepath/path_unix.go
deleted file mode 100644
index 57e621743434..000000000000
--- a/contrib/go/_std_1.22/src/path/filepath/path_unix.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2010 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.
-
-//go:build unix || (js && wasm) || wasip1
-
-package filepath
-
-import "strings"
-
-func isLocal(path string) bool {
- return unixIsLocal(path)
-}
-
-// IsAbs reports whether the path is absolute.
-func IsAbs(path string) bool {
- return strings.HasPrefix(path, "/")
-}
-
-// volumeNameLen returns length of the leading volume name on Windows.
-// It returns 0 elsewhere.
-func volumeNameLen(path string) int {
- return 0
-}
-
-// HasPrefix exists for historical compatibility and should not be used.
-//
-// Deprecated: HasPrefix does not respect path boundaries and
-// does not ignore case when required.
-func HasPrefix(p, prefix string) bool {
- return strings.HasPrefix(p, prefix)
-}
-
-func splitList(path string) []string {
- if path == "" {
- return []string{}
- }
- return strings.Split(path, string(ListSeparator))
-}
-
-func abs(path string) (string, error) {
- return unixAbs(path)
-}
-
-func join(elem []string) string {
- // If there's a bug here, fix the logic in ./path_plan9.go too.
- for i, e := range elem {
- if e != "" {
- return Clean(strings.Join(elem[i:], string(Separator)))
- }
- }
- return ""
-}
-
-func sameWord(a, b string) bool {
- return a == b
-}
diff --git a/contrib/go/_std_1.22/src/path/filepath/path_windows.go b/contrib/go/_std_1.22/src/path/filepath/path_windows.go
deleted file mode 100644
index eacab0e5ced6..000000000000
--- a/contrib/go/_std_1.22/src/path/filepath/path_windows.go
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright 2010 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.
-
-package filepath
-
-import (
- "internal/safefilepath"
- "os"
- "strings"
- "syscall"
-)
-
-func isSlash(c uint8) bool {
- return c == '\\' || c == '/'
-}
-
-func toUpper(c byte) byte {
- if 'a' <= c && c <= 'z' {
- return c - ('a' - 'A')
- }
- return c
-}
-
-func isLocal(path string) bool {
- if path == "" {
- return false
- }
- if isSlash(path[0]) {
- // Path rooted in the current drive.
- return false
- }
- if strings.IndexByte(path, ':') >= 0 {
- // Colons are only valid when marking a drive letter ("C:foo").
- // Rejecting any path with a colon is conservative but safe.
- return false
- }
- hasDots := false // contains . or .. path elements
- for p := path; p != ""; {
- var part string
- part, p, _ = cutPath(p)
- if part == "." || part == ".." {
- hasDots = true
- }
- if safefilepath.IsReservedName(part) {
- return false
- }
- }
- if hasDots {
- path = Clean(path)
- }
- if path == ".." || strings.HasPrefix(path, `..\`) {
- return false
- }
- return true
-}
-
-// IsAbs reports whether the path is absolute.
-func IsAbs(path string) (b bool) {
- l := volumeNameLen(path)
- if l == 0 {
- return false
- }
- // If the volume name starts with a double slash, this is an absolute path.
- if isSlash(path[0]) && isSlash(path[1]) {
- return true
- }
- path = path[l:]
- if path == "" {
- return false
- }
- return isSlash(path[0])
-}
-
-// volumeNameLen returns length of the leading volume name on Windows.
-// It returns 0 elsewhere.
-//
-// See:
-// https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
-// https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
-func volumeNameLen(path string) int {
- switch {
- case len(path) >= 2 && path[1] == ':':
- // Path starts with a drive letter.
- //
- // Not all Windows functions necessarily enforce the requirement that
- // drive letters be in the set A-Z, and we don't try to here.
- //
- // We don't handle the case of a path starting with a non-ASCII character,
- // in which case the "drive letter" might be multiple bytes long.
- return 2
-
- case len(path) == 0 || !isSlash(path[0]):
- // Path does not have a volume component.
- return 0
-
- case pathHasPrefixFold(path, `\\.\UNC`):
- // We're going to treat the UNC host and share as part of the volume
- // prefix for historical reasons, but this isn't really principled;
- // Windows's own GetFullPathName will happily remove the first
- // component of the path in this space, converting
- // \\.\unc\a\b\..\c into \\.\unc\a\c.
- return uncLen(path, len(`\\.\UNC\`))
-
- case pathHasPrefixFold(path, `\\.`) ||
- pathHasPrefixFold(path, `\\?`) || pathHasPrefixFold(path, `\??`):
- // Path starts with \\.\, and is a Local Device path; or
- // path starts with \\?\ or \??\ and is a Root Local Device path.
- //
- // We treat the next component after the \\.\ prefix as
- // part of the volume name, which means Clean(`\\?\c:\`)
- // won't remove the trailing \. (See #64028.)
- if len(path) == 3 {
- return 3 // exactly \\.
- }
- _, rest, ok := cutPath(path[4:])
- if !ok {
- return len(path)
- }
- return len(path) - len(rest) - 1
-
- case len(path) >= 2 && isSlash(path[1]):
- // Path starts with \\, and is a UNC path.
- return uncLen(path, 2)
- }
- return 0
-}
-
-// pathHasPrefixFold tests whether the path s begins with prefix,
-// ignoring case and treating all path separators as equivalent.
-// If s is longer than prefix, then s[len(prefix)] must be a path separator.
-func pathHasPrefixFold(s, prefix string) bool {
- if len(s) < len(prefix) {
- return false
- }
- for i := 0; i < len(prefix); i++ {
- if isSlash(prefix[i]) {
- if !isSlash(s[i]) {
- return false
- }
- } else if toUpper(prefix[i]) != toUpper(s[i]) {
- return false
- }
- }
- if len(s) > len(prefix) && !isSlash(s[len(prefix)]) {
- return false
- }
- return true
-}
-
-// uncLen returns the length of the volume prefix of a UNC path.
-// prefixLen is the prefix prior to the start of the UNC host;
-// for example, for "//host/share", the prefixLen is len("//")==2.
-func uncLen(path string, prefixLen int) int {
- count := 0
- for i := prefixLen; i < len(path); i++ {
- if isSlash(path[i]) {
- count++
- if count == 2 {
- return i
- }
- }
- }
- return len(path)
-}
-
-// cutPath slices path around the first path separator.
-func cutPath(path string) (before, after string, found bool) {
- for i := range path {
- if isSlash(path[i]) {
- return path[:i], path[i+1:], true
- }
- }
- return path, "", false
-}
-
-// HasPrefix exists for historical compatibility and should not be used.
-//
-// Deprecated: HasPrefix does not respect path boundaries and
-// does not ignore case when required.
-func HasPrefix(p, prefix string) bool {
- if strings.HasPrefix(p, prefix) {
- return true
- }
- return strings.HasPrefix(strings.ToLower(p), strings.ToLower(prefix))
-}
-
-func splitList(path string) []string {
- // The same implementation is used in LookPath in os/exec;
- // consider changing os/exec when changing this.
-
- if path == "" {
- return []string{}
- }
-
- // Split path, respecting but preserving quotes.
- list := []string{}
- start := 0
- quo := false
- for i := 0; i < len(path); i++ {
- switch c := path[i]; {
- case c == '"':
- quo = !quo
- case c == ListSeparator && !quo:
- list = append(list, path[start:i])
- start = i + 1
- }
- }
- list = append(list, path[start:])
-
- // Remove quotes.
- for i, s := range list {
- list[i] = strings.ReplaceAll(s, `"`, ``)
- }
-
- return list
-}
-
-func abs(path string) (string, error) {
- if path == "" {
- // syscall.FullPath returns an error on empty path, because it's not a valid path.
- // To implement Abs behavior of returning working directory on empty string input,
- // special-case empty path by changing it to "." path. See golang.org/issue/24441.
- path = "."
- }
- fullPath, err := syscall.FullPath(path)
- if err != nil {
- return "", err
- }
- return Clean(fullPath), nil
-}
-
-func join(elem []string) string {
- var b strings.Builder
- var lastChar byte
- for _, e := range elem {
- switch {
- case b.Len() == 0:
- // Add the first non-empty path element unchanged.
- case isSlash(lastChar):
- // If the path ends in a slash, strip any leading slashes from the next
- // path element to avoid creating a UNC path (any path starting with "\\")
- // from non-UNC elements.
- //
- // The correct behavior for Join when the first element is an incomplete UNC
- // path (for example, "\\") is underspecified. We currently join subsequent
- // elements so Join("\\", "host", "share") produces "\\host\share".
- for len(e) > 0 && isSlash(e[0]) {
- e = e[1:]
- }
- // If the path is \ and the next path element is ??,
- // add an extra .\ to create \.\?? rather than \??\
- // (a Root Local Device path).
- if b.Len() == 1 && pathHasPrefixFold(e, "??") {
- b.WriteString(`.\`)
- }
- case lastChar == ':':
- // If the path ends in a colon, keep the path relative to the current directory
- // on a drive and don't add a separator. Preserve leading slashes in the next
- // path element, which may make the path absolute.
- //
- // Join(`C:`, `f`) = `C:f`
- // Join(`C:`, `\f`) = `C:\f`
- default:
- // In all other cases, add a separator between elements.
- b.WriteByte('\\')
- lastChar = '\\'
- }
- if len(e) > 0 {
- b.WriteString(e)
- lastChar = e[len(e)-1]
- }
- }
- if b.Len() == 0 {
- return ""
- }
- return Clean(b.String())
-}
-
-// joinNonEmpty is like join, but it assumes that the first element is non-empty.
-func joinNonEmpty(elem []string) string {
- if len(elem[0]) == 2 && elem[0][1] == ':' {
- // First element is drive letter without terminating slash.
- // Keep path relative to current directory on that drive.
- // Skip empty elements.
- i := 1
- for ; i < len(elem); i++ {
- if elem[i] != "" {
- break
- }
- }
- return Clean(elem[0] + strings.Join(elem[i:], string(Separator)))
- }
- // The following logic prevents Join from inadvertently creating a
- // UNC path on Windows. Unless the first element is a UNC path, Join
- // shouldn't create a UNC path. See golang.org/issue/9167.
- p := Clean(strings.Join(elem, string(Separator)))
- if !isUNC(p) {
- return p
- }
- // p == UNC only allowed when the first element is a UNC path.
- head := Clean(elem[0])
- if isUNC(head) {
- return p
- }
- // head + tail == UNC, but joining two non-UNC paths should not result
- // in a UNC path. Undo creation of UNC path.
- tail := Clean(strings.Join(elem[1:], string(Separator)))
- if head[len(head)-1] == Separator {
- return head + tail
- }
- return head + string(Separator) + tail
-}
-
-// isUNC reports whether path is a UNC path.
-func isUNC(path string) bool {
- return len(path) > 1 && isSlash(path[0]) && isSlash(path[1])
-}
-
-func sameWord(a, b string) bool {
- return strings.EqualFold(a, b)
-}
-
-// postClean adjusts the results of Clean to avoid turning a relative path
-// into an absolute or rooted one.
-func postClean(out *lazybuf) {
- if out.volLen != 0 || out.buf == nil {
- return
- }
- // If a ':' appears in the path element at the start of a path,
- // insert a .\ at the beginning to avoid converting relative paths
- // like a/../c: into c:.
- for _, c := range out.buf {
- if os.IsPathSeparator(c) {
- break
- }
- if c == ':' {
- out.prepend('.', Separator)
- return
- }
- }
- // If a path begins with \??\, insert a \. at the beginning
- // to avoid converting paths like \a\..\??\c:\x into \??\c:\x
- // (equivalent to c:\x).
- if len(out.buf) >= 3 && os.IsPathSeparator(out.buf[0]) && out.buf[1] == '?' && out.buf[2] == '?' {
- out.prepend(Separator, '.')
- }
-}
diff --git a/contrib/go/_std_1.22/src/path/filepath/ya.make b/contrib/go/_std_1.22/src/path/filepath/ya.make
deleted file mode 100644
index 40919fc1b05e..000000000000
--- a/contrib/go/_std_1.22/src/path/filepath/ya.make
+++ /dev/null
@@ -1,20 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- match.go
- path.go
- path_nonwindows.go
- path_unix.go
- symlink.go
- symlink_unix.go
- )
-ELSEIF (OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- match.go
- path.go
- path_windows.go
- symlink.go
- symlink_windows.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/reflect/arena.go b/contrib/go/_std_1.22/src/reflect/arena.go
deleted file mode 100644
index cac1a1da5eaa..000000000000
--- a/contrib/go/_std_1.22/src/reflect/arena.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2022 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.
-
-//go:build goexperiment.arenas
-
-package reflect
-
-import "arena"
-
-// ArenaNew returns a Value representing a pointer to a new zero value for the
-// specified type, allocating storage for it in the provided arena. That is,
-// the returned Value's Type is PointerTo(typ).
-func ArenaNew(a *arena.Arena, typ Type) Value {
- return ValueOf(arena_New(a, PointerTo(typ)))
-}
-
-func arena_New(a *arena.Arena, typ any) any
diff --git a/contrib/go/_std_1.22/src/reflect/asm_loong64.s b/contrib/go/_std_1.22/src/reflect/asm_loong64.s
deleted file mode 100644
index 520f0afdd516..000000000000
--- a/contrib/go/_std_1.22/src/reflect/asm_loong64.s
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2022 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.
-
-#include "textflag.h"
-#include "funcdata.h"
-
-#define REGCTXT R29
-
-// The frames of each of the two functions below contain two locals, at offsets
-// that are known to the runtime.
-//
-// The first local is a bool called retValid with a whole pointer-word reserved
-// for it on the stack. The purpose of this word is so that the runtime knows
-// whether the stack-allocated return space contains valid values for stack
-// scanning.
-//
-// The second local is an abi.RegArgs value whose offset is also known to the
-// runtime, so that a stack map for it can be constructed, since it contains
-// pointers visible to the GC.
-#define LOCAL_RETVALID 40
-#define LOCAL_REGARGS 48
-
-// The frame size of the functions below is
-// 32 (args of callReflect) + 8 (bool + padding) + 392 (abi.RegArgs) = 432.
-
-// makeFuncStub is the code half of the function returned by MakeFunc.
-// See the comment on the declaration of makeFuncStub in makefunc.go
-// for more details.
-// No arg size here, runtime pulls arg map out of the func value.
-TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$432
- NO_LOCAL_POINTERS
- ADDV $LOCAL_REGARGS, R3, R25 // spillArgs using R25
- JAL runtime·spillArgs(SB)
- MOVV REGCTXT, 32(R3) // save REGCTXT > args of moveMakeFuncArgPtrs < LOCAL_REGARGS
-
-#ifdef GOEXPERIMENT_regabiargs
- MOVV REGCTXT, R4
- MOVV R25, R5
-#else
- MOVV REGCTXT, 8(R3)
- MOVV R25, 16(R3)
-#endif
- JAL ·moveMakeFuncArgPtrs(SB)
- MOVV 32(R3), REGCTXT // restore REGCTXT
-
- MOVV REGCTXT, 8(R3)
- MOVV $argframe+0(FP), R20
- MOVV R20, 16(R3)
- MOVV R0, LOCAL_RETVALID(R3)
- ADDV $LOCAL_RETVALID, R3, R20
- MOVV R20, 24(R3)
- ADDV $LOCAL_REGARGS, R3, R20
- MOVV R20, 32(R3)
- JAL ·callReflect(SB)
- ADDV $LOCAL_REGARGS, R3, R25 //unspillArgs using R25
- JAL runtime·unspillArgs(SB)
- RET
-
-// methodValueCall is the code half of the function returned by makeMethodValue.
-// See the comment on the declaration of methodValueCall in makefunc.go
-// for more details.
-// No arg size here; runtime pulls arg map out of the func value.
-TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$432
- NO_LOCAL_POINTERS
- ADDV $LOCAL_REGARGS, R3, R25 // spillArgs using R25
- JAL runtime·spillArgs(SB)
- MOVV REGCTXT, 32(R3) // save REGCTXT > args of moveMakeFuncArgPtrs < LOCAL_REGARGS
-#ifdef GOEXPERIMENT_regabiargs
- MOVV REGCTXT, R4
- MOVV R25, R5
-#else
- MOVV REGCTXT, 8(R3)
- MOVV R25, 16(R3)
-#endif
- JAL ·moveMakeFuncArgPtrs(SB)
- MOVV 32(R3), REGCTXT // restore REGCTXT
- MOVV REGCTXT, 8(R3)
- MOVV $argframe+0(FP), R20
- MOVV R20, 16(R3)
- MOVB R0, LOCAL_RETVALID(R3)
- ADDV $LOCAL_RETVALID, R3, R20
- MOVV R20, 24(R3)
- ADDV $LOCAL_REGARGS, R3, R20
- MOVV R20, 32(R3) // frame size to 32+SP as callreflect args)
- JAL ·callMethod(SB)
- ADDV $LOCAL_REGARGS, R3, R25 // unspillArgs using R25
- JAL runtime·unspillArgs(SB)
- RET
diff --git a/contrib/go/_std_1.22/src/reflect/swapper.go b/contrib/go/_std_1.22/src/reflect/swapper.go
deleted file mode 100644
index 1e8f4ed16364..000000000000
--- a/contrib/go/_std_1.22/src/reflect/swapper.go
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2016 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.
-
-package reflect
-
-import (
- "internal/abi"
- "internal/goarch"
- "internal/unsafeheader"
- "unsafe"
-)
-
-// Swapper returns a function that swaps the elements in the provided
-// slice.
-//
-// Swapper panics if the provided interface is not a slice.
-func Swapper(slice any) func(i, j int) {
- v := ValueOf(slice)
- if v.Kind() != Slice {
- panic(&ValueError{Method: "Swapper", Kind: v.Kind()})
- }
- // Fast path for slices of size 0 and 1. Nothing to swap.
- switch v.Len() {
- case 0:
- return func(i, j int) { panic("reflect: slice index out of range") }
- case 1:
- return func(i, j int) {
- if i != 0 || j != 0 {
- panic("reflect: slice index out of range")
- }
- }
- }
-
- typ := v.Type().Elem().common()
- size := typ.Size()
- hasPtr := typ.PtrBytes != 0
-
- // Some common & small cases, without using memmove:
- if hasPtr {
- if size == goarch.PtrSize {
- ps := *(*[]unsafe.Pointer)(v.ptr)
- return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] }
- }
- if typ.Kind() == abi.String {
- ss := *(*[]string)(v.ptr)
- return func(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
- }
- } else {
- switch size {
- case 8:
- is := *(*[]int64)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- case 4:
- is := *(*[]int32)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- case 2:
- is := *(*[]int16)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- case 1:
- is := *(*[]int8)(v.ptr)
- return func(i, j int) { is[i], is[j] = is[j], is[i] }
- }
- }
-
- s := (*unsafeheader.Slice)(v.ptr)
- tmp := unsafe_New(typ) // swap scratch space
-
- return func(i, j int) {
- if uint(i) >= uint(s.Len) || uint(j) >= uint(s.Len) {
- panic("reflect: slice index out of range")
- }
- val1 := arrayAt(s.Data, i, size, "i < s.Len")
- val2 := arrayAt(s.Data, j, size, "j < s.Len")
- typedmemmove(typ, tmp, val1)
- typedmemmove(typ, val1, val2)
- typedmemmove(typ, val2, tmp)
- }
-}
diff --git a/contrib/go/_std_1.22/src/reflect/type.go b/contrib/go/_std_1.22/src/reflect/type.go
deleted file mode 100644
index 89c501553023..000000000000
--- a/contrib/go/_std_1.22/src/reflect/type.go
+++ /dev/null
@@ -1,2885 +0,0 @@
-// Copyright 2009 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.
-
-// Package reflect implements run-time reflection, allowing a program to
-// manipulate objects with arbitrary types. The typical use is to take a value
-// with static type interface{} and extract its dynamic type information by
-// calling TypeOf, which returns a Type.
-//
-// A call to ValueOf returns a Value representing the run-time data.
-// Zero takes a Type and returns a Value representing a zero value
-// for that type.
-//
-// See "The Laws of Reflection" for an introduction to reflection in Go:
-// https://golang.org/doc/articles/laws_of_reflection.html
-package reflect
-
-import (
- "internal/abi"
- "internal/goarch"
- "strconv"
- "sync"
- "unicode"
- "unicode/utf8"
- "unsafe"
-)
-
-// Type is the representation of a Go type.
-//
-// Not all methods apply to all kinds of types. Restrictions,
-// if any, are noted in the documentation for each method.
-// Use the Kind method to find out the kind of type before
-// calling kind-specific methods. Calling a method
-// inappropriate to the kind of type causes a run-time panic.
-//
-// Type values are comparable, such as with the == operator,
-// so they can be used as map keys.
-// Two Type values are equal if they represent identical types.
-type Type interface {
- // Methods applicable to all types.
-
- // Align returns the alignment in bytes of a value of
- // this type when allocated in memory.
- Align() int
-
- // FieldAlign returns the alignment in bytes of a value of
- // this type when used as a field in a struct.
- FieldAlign() int
-
- // Method returns the i'th method in the type's method set.
- // It panics if i is not in the range [0, NumMethod()).
- //
- // For a non-interface type T or *T, the returned Method's Type and Func
- // fields describe a function whose first argument is the receiver,
- // and only exported methods are accessible.
- //
- // For an interface type, the returned Method's Type field gives the
- // method signature, without a receiver, and the Func field is nil.
- //
- // Methods are sorted in lexicographic order.
- Method(int) Method
-
- // MethodByName returns the method with that name in the type's
- // method set and a boolean indicating if the method was found.
- //
- // For a non-interface type T or *T, the returned Method's Type and Func
- // fields describe a function whose first argument is the receiver.
- //
- // For an interface type, the returned Method's Type field gives the
- // method signature, without a receiver, and the Func field is nil.
- MethodByName(string) (Method, bool)
-
- // NumMethod returns the number of methods accessible using Method.
- //
- // For a non-interface type, it returns the number of exported methods.
- //
- // For an interface type, it returns the number of exported and unexported methods.
- NumMethod() int
-
- // Name returns the type's name within its package for a defined type.
- // For other (non-defined) types it returns the empty string.
- Name() string
-
- // PkgPath returns a defined type's package path, that is, the import path
- // that uniquely identifies the package, such as "encoding/base64".
- // If the type was predeclared (string, error) or not defined (*T, struct{},
- // []int, or A where A is an alias for a non-defined type), the package path
- // will be the empty string.
- PkgPath() string
-
- // Size returns the number of bytes needed to store
- // a value of the given type; it is analogous to unsafe.Sizeof.
- Size() uintptr
-
- // String returns a string representation of the type.
- // The string representation may use shortened package names
- // (e.g., base64 instead of "encoding/base64") and is not
- // guaranteed to be unique among types. To test for type identity,
- // compare the Types directly.
- String() string
-
- // Kind returns the specific kind of this type.
- Kind() Kind
-
- // Implements reports whether the type implements the interface type u.
- Implements(u Type) bool
-
- // AssignableTo reports whether a value of the type is assignable to type u.
- AssignableTo(u Type) bool
-
- // ConvertibleTo reports whether a value of the type is convertible to type u.
- // Even if ConvertibleTo returns true, the conversion may still panic.
- // For example, a slice of type []T is convertible to *[N]T,
- // but the conversion will panic if its length is less than N.
- ConvertibleTo(u Type) bool
-
- // Comparable reports whether values of this type are comparable.
- // Even if Comparable returns true, the comparison may still panic.
- // For example, values of interface type are comparable,
- // but the comparison will panic if their dynamic type is not comparable.
- Comparable() bool
-
- // Methods applicable only to some types, depending on Kind.
- // The methods allowed for each kind are:
- //
- // Int*, Uint*, Float*, Complex*: Bits
- // Array: Elem, Len
- // Chan: ChanDir, Elem
- // Func: In, NumIn, Out, NumOut, IsVariadic.
- // Map: Key, Elem
- // Pointer: Elem
- // Slice: Elem
- // Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
-
- // Bits returns the size of the type in bits.
- // It panics if the type's Kind is not one of the
- // sized or unsized Int, Uint, Float, or Complex kinds.
- Bits() int
-
- // ChanDir returns a channel type's direction.
- // It panics if the type's Kind is not Chan.
- ChanDir() ChanDir
-
- // IsVariadic reports whether a function type's final input parameter
- // is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
- // implicit actual type []T.
- //
- // For concreteness, if t represents func(x int, y ... float64), then
- //
- // t.NumIn() == 2
- // t.In(0) is the reflect.Type for "int"
- // t.In(1) is the reflect.Type for "[]float64"
- // t.IsVariadic() == true
- //
- // IsVariadic panics if the type's Kind is not Func.
- IsVariadic() bool
-
- // Elem returns a type's element type.
- // It panics if the type's Kind is not Array, Chan, Map, Pointer, or Slice.
- Elem() Type
-
- // Field returns a struct type's i'th field.
- // It panics if the type's Kind is not Struct.
- // It panics if i is not in the range [0, NumField()).
- Field(i int) StructField
-
- // FieldByIndex returns the nested field corresponding
- // to the index sequence. It is equivalent to calling Field
- // successively for each index i.
- // It panics if the type's Kind is not Struct.
- FieldByIndex(index []int) StructField
-
- // FieldByName returns the struct field with the given name
- // and a boolean indicating if the field was found.
- // If the returned field is promoted from an embedded struct,
- // then Offset in the returned StructField is the offset in
- // the embedded struct.
- FieldByName(name string) (StructField, bool)
-
- // FieldByNameFunc returns the struct field with a name
- // that satisfies the match function and a boolean indicating if
- // the field was found.
- //
- // FieldByNameFunc considers the fields in the struct itself
- // and then the fields in any embedded structs, in breadth first order,
- // stopping at the shallowest nesting depth containing one or more
- // fields satisfying the match function. If multiple fields at that depth
- // satisfy the match function, they cancel each other
- // and FieldByNameFunc returns no match.
- // This behavior mirrors Go's handling of name lookup in
- // structs containing embedded fields.
- //
- // If the returned field is promoted from an embedded struct,
- // then Offset in the returned StructField is the offset in
- // the embedded struct.
- FieldByNameFunc(match func(string) bool) (StructField, bool)
-
- // In returns the type of a function type's i'th input parameter.
- // It panics if the type's Kind is not Func.
- // It panics if i is not in the range [0, NumIn()).
- In(i int) Type
-
- // Key returns a map type's key type.
- // It panics if the type's Kind is not Map.
- Key() Type
-
- // Len returns an array type's length.
- // It panics if the type's Kind is not Array.
- Len() int
-
- // NumField returns a struct type's field count.
- // It panics if the type's Kind is not Struct.
- NumField() int
-
- // NumIn returns a function type's input parameter count.
- // It panics if the type's Kind is not Func.
- NumIn() int
-
- // NumOut returns a function type's output parameter count.
- // It panics if the type's Kind is not Func.
- NumOut() int
-
- // Out returns the type of a function type's i'th output parameter.
- // It panics if the type's Kind is not Func.
- // It panics if i is not in the range [0, NumOut()).
- Out(i int) Type
-
- common() *abi.Type
- uncommon() *uncommonType
-}
-
-// BUG(rsc): FieldByName and related functions consider struct field names to be equal
-// if the names are equal, even if they are unexported names originating
-// in different packages. The practical effect of this is that the result of
-// t.FieldByName("x") is not well defined if the struct type t contains
-// multiple fields named x (embedded from different packages).
-// FieldByName may return one of the fields named x or may report that there are none.
-// See https://golang.org/issue/4876 for more details.
-
-/*
- * These data structures are known to the compiler (../cmd/compile/internal/reflectdata/reflect.go).
- * A few are known to ../runtime/type.go to convey to debuggers.
- * They are also known to ../runtime/type.go.
- */
-
-// A Kind represents the specific kind of type that a [Type] represents.
-// The zero Kind is not a valid kind.
-type Kind uint
-
-const (
- Invalid Kind = iota
- Bool
- Int
- Int8
- Int16
- Int32
- Int64
- Uint
- Uint8
- Uint16
- Uint32
- Uint64
- Uintptr
- Float32
- Float64
- Complex64
- Complex128
- Array
- Chan
- Func
- Interface
- Map
- Pointer
- Slice
- String
- Struct
- UnsafePointer
-)
-
-// Ptr is the old name for the [Pointer] kind.
-const Ptr = Pointer
-
-// uncommonType is present only for defined types or types with methods
-// (if T is a defined type, the uncommonTypes for T and *T have methods).
-// Using a pointer to this struct reduces the overall size required
-// to describe a non-defined type with no methods.
-type uncommonType = abi.UncommonType
-
-// Embed this type to get common/uncommon
-type common struct {
- abi.Type
-}
-
-// rtype is the common implementation of most values.
-// It is embedded in other struct types.
-type rtype struct {
- t abi.Type
-}
-
-func (t *rtype) common() *abi.Type {
- return &t.t
-}
-
-func (t *rtype) uncommon() *abi.UncommonType {
- return t.t.Uncommon()
-}
-
-type aNameOff = abi.NameOff
-type aTypeOff = abi.TypeOff
-type aTextOff = abi.TextOff
-
-// ChanDir represents a channel type's direction.
-type ChanDir int
-
-const (
- RecvDir ChanDir = 1 << iota // <-chan
- SendDir // chan<-
- BothDir = RecvDir | SendDir // chan
-)
-
-// arrayType represents a fixed array type.
-type arrayType = abi.ArrayType
-
-// chanType represents a channel type.
-type chanType = abi.ChanType
-
-// funcType represents a function type.
-//
-// A *rtype for each in and out parameter is stored in an array that
-// directly follows the funcType (and possibly its uncommonType). So
-// a function type with one method, one input, and one output is:
-//
-// struct {
-// funcType
-// uncommonType
-// [2]*rtype // [0] is in, [1] is out
-// }
-type funcType = abi.FuncType
-
-// interfaceType represents an interface type.
-type interfaceType struct {
- abi.InterfaceType // can embed directly because not a public type.
-}
-
-func (t *interfaceType) nameOff(off aNameOff) abi.Name {
- return toRType(&t.Type).nameOff(off)
-}
-
-func nameOffFor(t *abi.Type, off aNameOff) abi.Name {
- return toRType(t).nameOff(off)
-}
-
-func typeOffFor(t *abi.Type, off aTypeOff) *abi.Type {
- return toRType(t).typeOff(off)
-}
-
-func (t *interfaceType) typeOff(off aTypeOff) *abi.Type {
- return toRType(&t.Type).typeOff(off)
-}
-
-func (t *interfaceType) common() *abi.Type {
- return &t.Type
-}
-
-func (t *interfaceType) uncommon() *abi.UncommonType {
- return t.Uncommon()
-}
-
-// mapType represents a map type.
-type mapType struct {
- abi.MapType
-}
-
-// ptrType represents a pointer type.
-type ptrType struct {
- abi.PtrType
-}
-
-// sliceType represents a slice type.
-type sliceType struct {
- abi.SliceType
-}
-
-// Struct field
-type structField = abi.StructField
-
-// structType represents a struct type.
-type structType struct {
- abi.StructType
-}
-
-func pkgPath(n abi.Name) string {
- if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
- return ""
- }
- i, l := n.ReadVarint(1)
- off := 1 + i + l
- if n.HasTag() {
- i2, l2 := n.ReadVarint(off)
- off += i2 + l2
- }
- var nameOff int32
- // Note that this field may not be aligned in memory,
- // so we cannot use a direct int32 assignment here.
- copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
- pkgPathName := abi.Name{Bytes: (*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
- return pkgPathName.Name()
-}
-
-func newName(n, tag string, exported, embedded bool) abi.Name {
- return abi.NewName(n, tag, exported, embedded)
-}
-
-/*
- * The compiler knows the exact layout of all the data structures above.
- * The compiler does not know about the data structures and methods below.
- */
-
-// Method represents a single method.
-type Method struct {
- // Name is the method name.
- Name string
-
- // PkgPath is the package path that qualifies a lower case (unexported)
- // method name. It is empty for upper case (exported) method names.
- // The combination of PkgPath and Name uniquely identifies a method
- // in a method set.
- // See https://golang.org/ref/spec#Uniqueness_of_identifiers
- PkgPath string
-
- Type Type // method type
- Func Value // func with receiver as first argument
- Index int // index for Type.Method
-}
-
-// IsExported reports whether the method is exported.
-func (m Method) IsExported() bool {
- return m.PkgPath == ""
-}
-
-const (
- kindDirectIface = 1 << 5
- kindGCProg = 1 << 6 // Type.gc points to GC program
- kindMask = (1 << 5) - 1
-)
-
-// String returns the name of k.
-func (k Kind) String() string {
- if uint(k) < uint(len(kindNames)) {
- return kindNames[uint(k)]
- }
- return "kind" + strconv.Itoa(int(k))
-}
-
-var kindNames = []string{
- Invalid: "invalid",
- Bool: "bool",
- Int: "int",
- Int8: "int8",
- Int16: "int16",
- Int32: "int32",
- Int64: "int64",
- Uint: "uint",
- Uint8: "uint8",
- Uint16: "uint16",
- Uint32: "uint32",
- Uint64: "uint64",
- Uintptr: "uintptr",
- Float32: "float32",
- Float64: "float64",
- Complex64: "complex64",
- Complex128: "complex128",
- Array: "array",
- Chan: "chan",
- Func: "func",
- Interface: "interface",
- Map: "map",
- Pointer: "ptr",
- Slice: "slice",
- String: "string",
- Struct: "struct",
- UnsafePointer: "unsafe.Pointer",
-}
-
-// resolveNameOff resolves a name offset from a base pointer.
-// The (*rtype).nameOff method is a convenience wrapper for this function.
-// Implemented in the runtime package.
-//
-//go:noescape
-func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
-
-// resolveTypeOff resolves an *rtype offset from a base type.
-// The (*rtype).typeOff method is a convenience wrapper for this function.
-// Implemented in the runtime package.
-//
-//go:noescape
-func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
-
-// resolveTextOff resolves a function pointer offset from a base type.
-// The (*rtype).textOff method is a convenience wrapper for this function.
-// Implemented in the runtime package.
-//
-//go:noescape
-func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
-
-// addReflectOff adds a pointer to the reflection lookup map in the runtime.
-// It returns a new ID that can be used as a typeOff or textOff, and will
-// be resolved correctly. Implemented in the runtime package.
-//
-//go:noescape
-func addReflectOff(ptr unsafe.Pointer) int32
-
-// resolveReflectName adds a name to the reflection lookup map in the runtime.
-// It returns a new nameOff that can be used to refer to the pointer.
-func resolveReflectName(n abi.Name) aNameOff {
- return aNameOff(addReflectOff(unsafe.Pointer(n.Bytes)))
-}
-
-// resolveReflectType adds a *rtype to the reflection lookup map in the runtime.
-// It returns a new typeOff that can be used to refer to the pointer.
-func resolveReflectType(t *abi.Type) aTypeOff {
- return aTypeOff(addReflectOff(unsafe.Pointer(t)))
-}
-
-// resolveReflectText adds a function pointer to the reflection lookup map in
-// the runtime. It returns a new textOff that can be used to refer to the
-// pointer.
-func resolveReflectText(ptr unsafe.Pointer) aTextOff {
- return aTextOff(addReflectOff(ptr))
-}
-
-func (t *rtype) nameOff(off aNameOff) abi.Name {
- return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
-}
-
-func (t *rtype) typeOff(off aTypeOff) *abi.Type {
- return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
-}
-
-func (t *rtype) textOff(off aTextOff) unsafe.Pointer {
- return resolveTextOff(unsafe.Pointer(t), int32(off))
-}
-
-func textOffFor(t *abi.Type, off aTextOff) unsafe.Pointer {
- return toRType(t).textOff(off)
-}
-
-func (t *rtype) String() string {
- s := t.nameOff(t.t.Str).Name()
- if t.t.TFlag&abi.TFlagExtraStar != 0 {
- return s[1:]
- }
- return s
-}
-
-func (t *rtype) Size() uintptr { return t.t.Size() }
-
-func (t *rtype) Bits() int {
- if t == nil {
- panic("reflect: Bits of nil Type")
- }
- k := t.Kind()
- if k < Int || k > Complex128 {
- panic("reflect: Bits of non-arithmetic Type " + t.String())
- }
- return int(t.t.Size_) * 8
-}
-
-func (t *rtype) Align() int { return t.t.Align() }
-
-func (t *rtype) FieldAlign() int { return t.t.FieldAlign() }
-
-func (t *rtype) Kind() Kind { return Kind(t.t.Kind()) }
-
-func (t *rtype) exportedMethods() []abi.Method {
- ut := t.uncommon()
- if ut == nil {
- return nil
- }
- return ut.ExportedMethods()
-}
-
-func (t *rtype) NumMethod() int {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.NumMethod()
- }
- return len(t.exportedMethods())
-}
-
-func (t *rtype) Method(i int) (m Method) {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.Method(i)
- }
- methods := t.exportedMethods()
- if i < 0 || i >= len(methods) {
- panic("reflect: Method index out of range")
- }
- p := methods[i]
- pname := t.nameOff(p.Name)
- m.Name = pname.Name()
- fl := flag(Func)
- mtyp := t.typeOff(p.Mtyp)
- ft := (*funcType)(unsafe.Pointer(mtyp))
- in := make([]Type, 0, 1+ft.NumIn())
- in = append(in, t)
- for _, arg := range ft.InSlice() {
- in = append(in, toRType(arg))
- }
- out := make([]Type, 0, ft.NumOut())
- for _, ret := range ft.OutSlice() {
- out = append(out, toRType(ret))
- }
- mt := FuncOf(in, out, ft.IsVariadic())
- m.Type = mt
- tfn := t.textOff(p.Tfn)
- fn := unsafe.Pointer(&tfn)
- m.Func = Value{&mt.(*rtype).t, fn, fl}
-
- m.Index = i
- return m
-}
-
-func (t *rtype) MethodByName(name string) (m Method, ok bool) {
- if t.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(t))
- return tt.MethodByName(name)
- }
- ut := t.uncommon()
- if ut == nil {
- return Method{}, false
- }
-
- methods := ut.ExportedMethods()
-
- // We are looking for the first index i where the string becomes >= s.
- // This is a copy of sort.Search, with f(h) replaced by (t.nameOff(methods[h].name).name() >= name).
- i, j := 0, len(methods)
- for i < j {
- h := int(uint(i+j) >> 1) // avoid overflow when computing h
- // i ≤ h < j
- if !(t.nameOff(methods[h].Name).Name() >= name) {
- i = h + 1 // preserves f(i-1) == false
- } else {
- j = h // preserves f(j) == true
- }
- }
- // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
- if i < len(methods) && name == t.nameOff(methods[i].Name).Name() {
- return t.Method(i), true
- }
-
- return Method{}, false
-}
-
-func (t *rtype) PkgPath() string {
- if t.t.TFlag&abi.TFlagNamed == 0 {
- return ""
- }
- ut := t.uncommon()
- if ut == nil {
- return ""
- }
- return t.nameOff(ut.PkgPath).Name()
-}
-
-func pkgPathFor(t *abi.Type) string {
- return toRType(t).PkgPath()
-}
-
-func (t *rtype) Name() string {
- if !t.t.HasName() {
- return ""
- }
- s := t.String()
- i := len(s) - 1
- sqBrackets := 0
- for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
- switch s[i] {
- case ']':
- sqBrackets++
- case '[':
- sqBrackets--
- }
- i--
- }
- return s[i+1:]
-}
-
-func nameFor(t *abi.Type) string {
- return toRType(t).Name()
-}
-
-func (t *rtype) ChanDir() ChanDir {
- if t.Kind() != Chan {
- panic("reflect: ChanDir of non-chan type " + t.String())
- }
- tt := (*abi.ChanType)(unsafe.Pointer(t))
- return ChanDir(tt.Dir)
-}
-
-func toRType(t *abi.Type) *rtype {
- return (*rtype)(unsafe.Pointer(t))
-}
-
-func elem(t *abi.Type) *abi.Type {
- et := t.Elem()
- if et != nil {
- return et
- }
- panic("reflect: Elem of invalid type " + stringFor(t))
-}
-
-func (t *rtype) Elem() Type {
- return toType(elem(t.common()))
-}
-
-func (t *rtype) Field(i int) StructField {
- if t.Kind() != Struct {
- panic("reflect: Field of non-struct type " + t.String())
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.Field(i)
-}
-
-func (t *rtype) FieldByIndex(index []int) StructField {
- if t.Kind() != Struct {
- panic("reflect: FieldByIndex of non-struct type " + t.String())
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.FieldByIndex(index)
-}
-
-func (t *rtype) FieldByName(name string) (StructField, bool) {
- if t.Kind() != Struct {
- panic("reflect: FieldByName of non-struct type " + t.String())
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.FieldByName(name)
-}
-
-func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
- if t.Kind() != Struct {
- panic("reflect: FieldByNameFunc of non-struct type " + t.String())
- }
- tt := (*structType)(unsafe.Pointer(t))
- return tt.FieldByNameFunc(match)
-}
-
-func (t *rtype) Key() Type {
- if t.Kind() != Map {
- panic("reflect: Key of non-map type " + t.String())
- }
- tt := (*mapType)(unsafe.Pointer(t))
- return toType(tt.Key)
-}
-
-func (t *rtype) Len() int {
- if t.Kind() != Array {
- panic("reflect: Len of non-array type " + t.String())
- }
- tt := (*arrayType)(unsafe.Pointer(t))
- return int(tt.Len)
-}
-
-func (t *rtype) NumField() int {
- if t.Kind() != Struct {
- panic("reflect: NumField of non-struct type " + t.String())
- }
- tt := (*structType)(unsafe.Pointer(t))
- return len(tt.Fields)
-}
-
-func (t *rtype) In(i int) Type {
- if t.Kind() != Func {
- panic("reflect: In of non-func type " + t.String())
- }
- tt := (*abi.FuncType)(unsafe.Pointer(t))
- return toType(tt.InSlice()[i])
-}
-
-func (t *rtype) NumIn() int {
- if t.Kind() != Func {
- panic("reflect: NumIn of non-func type " + t.String())
- }
- tt := (*abi.FuncType)(unsafe.Pointer(t))
- return tt.NumIn()
-}
-
-func (t *rtype) NumOut() int {
- if t.Kind() != Func {
- panic("reflect: NumOut of non-func type " + t.String())
- }
- tt := (*abi.FuncType)(unsafe.Pointer(t))
- return tt.NumOut()
-}
-
-func (t *rtype) Out(i int) Type {
- if t.Kind() != Func {
- panic("reflect: Out of non-func type " + t.String())
- }
- tt := (*abi.FuncType)(unsafe.Pointer(t))
- return toType(tt.OutSlice()[i])
-}
-
-func (t *rtype) IsVariadic() bool {
- if t.Kind() != Func {
- panic("reflect: IsVariadic of non-func type " + t.String())
- }
- tt := (*abi.FuncType)(unsafe.Pointer(t))
- return tt.IsVariadic()
-}
-
-// add returns p+x.
-//
-// The whySafe string is ignored, so that the function still inlines
-// as efficiently as p+x, but all call sites should use the string to
-// record why the addition is safe, which is to say why the addition
-// does not cause x to advance to the very end of p's allocation
-// and therefore point incorrectly at the next block in memory.
-func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
- return unsafe.Pointer(uintptr(p) + x)
-}
-
-func (d ChanDir) String() string {
- switch d {
- case SendDir:
- return "chan<-"
- case RecvDir:
- return "<-chan"
- case BothDir:
- return "chan"
- }
- return "ChanDir" + strconv.Itoa(int(d))
-}
-
-// Method returns the i'th method in the type's method set.
-func (t *interfaceType) Method(i int) (m Method) {
- if i < 0 || i >= len(t.Methods) {
- return
- }
- p := &t.Methods[i]
- pname := t.nameOff(p.Name)
- m.Name = pname.Name()
- if !pname.IsExported() {
- m.PkgPath = pkgPath(pname)
- if m.PkgPath == "" {
- m.PkgPath = t.PkgPath.Name()
- }
- }
- m.Type = toType(t.typeOff(p.Typ))
- m.Index = i
- return
-}
-
-// NumMethod returns the number of interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.Methods) }
-
-// MethodByName method with the given name in the type's method set.
-func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
- if t == nil {
- return
- }
- var p *abi.Imethod
- for i := range t.Methods {
- p = &t.Methods[i]
- if t.nameOff(p.Name).Name() == name {
- return t.Method(i), true
- }
- }
- return
-}
-
-// A StructField describes a single field in a struct.
-type StructField struct {
- // Name is the field name.
- Name string
-
- // PkgPath is the package path that qualifies a lower case (unexported)
- // field name. It is empty for upper case (exported) field names.
- // See https://golang.org/ref/spec#Uniqueness_of_identifiers
- PkgPath string
-
- Type Type // field type
- Tag StructTag // field tag string
- Offset uintptr // offset within struct, in bytes
- Index []int // index sequence for Type.FieldByIndex
- Anonymous bool // is an embedded field
-}
-
-// IsExported reports whether the field is exported.
-func (f StructField) IsExported() bool {
- return f.PkgPath == ""
-}
-
-// A StructTag is the tag string in a struct field.
-//
-// By convention, tag strings are a concatenation of
-// optionally space-separated key:"value" pairs.
-// Each key is a non-empty string consisting of non-control
-// characters other than space (U+0020 ' '), quote (U+0022 '"'),
-// and colon (U+003A ':'). Each value is quoted using U+0022 '"'
-// characters and Go string literal syntax.
-type StructTag string
-
-// Get returns the value associated with key in the tag string.
-// If there is no such key in the tag, Get returns the empty string.
-// If the tag does not have the conventional format, the value
-// returned by Get is unspecified. To determine whether a tag is
-// explicitly set to the empty string, use Lookup.
-func (tag StructTag) Get(key string) string {
- v, _ := tag.Lookup(key)
- return v
-}
-
-// Lookup returns the value associated with key in the tag string.
-// If the key is present in the tag the value (which may be empty)
-// is returned. Otherwise the returned value will be the empty string.
-// The ok return value reports whether the value was explicitly set in
-// the tag string. If the tag does not have the conventional format,
-// the value returned by Lookup is unspecified.
-func (tag StructTag) Lookup(key string) (value string, ok bool) {
- // When modifying this code, also update the validateStructTag code
- // in cmd/vet/structtag.go.
-
- for tag != "" {
- // Skip leading space.
- i := 0
- for i < len(tag) && tag[i] == ' ' {
- i++
- }
- tag = tag[i:]
- if tag == "" {
- break
- }
-
- // Scan to colon. A space, a quote or a control character is a syntax error.
- // Strictly speaking, control chars include the range [0x7f, 0x9f], not just
- // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
- // as it is simpler to inspect the tag's bytes than the tag's runes.
- i = 0
- for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
- i++
- }
- if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
- break
- }
- name := string(tag[:i])
- tag = tag[i+1:]
-
- // Scan quoted string to find value.
- i = 1
- for i < len(tag) && tag[i] != '"' {
- if tag[i] == '\\' {
- i++
- }
- i++
- }
- if i >= len(tag) {
- break
- }
- qvalue := string(tag[:i+1])
- tag = tag[i+1:]
-
- if key == name {
- value, err := strconv.Unquote(qvalue)
- if err != nil {
- break
- }
- return value, true
- }
- }
- return "", false
-}
-
-// Field returns the i'th struct field.
-func (t *structType) Field(i int) (f StructField) {
- if i < 0 || i >= len(t.Fields) {
- panic("reflect: Field index out of bounds")
- }
- p := &t.Fields[i]
- f.Type = toType(p.Typ)
- f.Name = p.Name.Name()
- f.Anonymous = p.Embedded()
- if !p.Name.IsExported() {
- f.PkgPath = t.PkgPath.Name()
- }
- if tag := p.Name.Tag(); tag != "" {
- f.Tag = StructTag(tag)
- }
- f.Offset = p.Offset
-
- // NOTE(rsc): This is the only allocation in the interface
- // presented by a reflect.Type. It would be nice to avoid,
- // at least in the common cases, but we need to make sure
- // that misbehaving clients of reflect cannot affect other
- // uses of reflect. One possibility is CL 5371098, but we
- // postponed that ugliness until there is a demonstrated
- // need for the performance. This is issue 2320.
- f.Index = []int{i}
- return
-}
-
-// TODO(gri): Should there be an error/bool indicator if the index
-// is wrong for FieldByIndex?
-
-// FieldByIndex returns the nested field corresponding to index.
-func (t *structType) FieldByIndex(index []int) (f StructField) {
- f.Type = toType(&t.Type)
- for i, x := range index {
- if i > 0 {
- ft := f.Type
- if ft.Kind() == Pointer && ft.Elem().Kind() == Struct {
- ft = ft.Elem()
- }
- f.Type = ft
- }
- f = f.Type.Field(x)
- }
- return
-}
-
-// A fieldScan represents an item on the fieldByNameFunc scan work list.
-type fieldScan struct {
- typ *structType
- index []int
-}
-
-// FieldByNameFunc returns the struct field with a name that satisfies the
-// match function and a boolean to indicate if the field was found.
-func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
- // This uses the same condition that the Go language does: there must be a unique instance
- // of the match at a given depth level. If there are multiple instances of a match at the
- // same depth, they annihilate each other and inhibit any possible match at a lower level.
- // The algorithm is breadth first search, one depth level at a time.
-
- // The current and next slices are work queues:
- // current lists the fields to visit on this depth level,
- // and next lists the fields on the next lower level.
- current := []fieldScan{}
- next := []fieldScan{{typ: t}}
-
- // nextCount records the number of times an embedded type has been
- // encountered and considered for queueing in the 'next' slice.
- // We only queue the first one, but we increment the count on each.
- // If a struct type T can be reached more than once at a given depth level,
- // then it annihilates itself and need not be considered at all when we
- // process that next depth level.
- var nextCount map[*structType]int
-
- // visited records the structs that have been considered already.
- // Embedded pointer fields can create cycles in the graph of
- // reachable embedded types; visited avoids following those cycles.
- // It also avoids duplicated effort: if we didn't find the field in an
- // embedded type T at level 2, we won't find it in one at level 4 either.
- visited := map[*structType]bool{}
-
- for len(next) > 0 {
- current, next = next, current[:0]
- count := nextCount
- nextCount = nil
-
- // Process all the fields at this depth, now listed in 'current'.
- // The loop queues embedded fields found in 'next', for processing during the next
- // iteration. The multiplicity of the 'current' field counts is recorded
- // in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
- for _, scan := range current {
- t := scan.typ
- if visited[t] {
- // We've looked through this type before, at a higher level.
- // That higher level would shadow the lower level we're now at,
- // so this one can't be useful to us. Ignore it.
- continue
- }
- visited[t] = true
- for i := range t.Fields {
- f := &t.Fields[i]
- // Find name and (for embedded field) type for field f.
- fname := f.Name.Name()
- var ntyp *abi.Type
- if f.Embedded() {
- // Embedded field of type T or *T.
- ntyp = f.Typ
- if ntyp.Kind() == abi.Pointer {
- ntyp = ntyp.Elem()
- }
- }
-
- // Does it match?
- if match(fname) {
- // Potential match
- if count[t] > 1 || ok {
- // Name appeared multiple times at this level: annihilate.
- return StructField{}, false
- }
- result = t.Field(i)
- result.Index = nil
- result.Index = append(result.Index, scan.index...)
- result.Index = append(result.Index, i)
- ok = true
- continue
- }
-
- // Queue embedded struct fields for processing with next level,
- // but only if we haven't seen a match yet at this level and only
- // if the embedded types haven't already been queued.
- if ok || ntyp == nil || ntyp.Kind() != abi.Struct {
- continue
- }
- styp := (*structType)(unsafe.Pointer(ntyp))
- if nextCount[styp] > 0 {
- nextCount[styp] = 2 // exact multiple doesn't matter
- continue
- }
- if nextCount == nil {
- nextCount = map[*structType]int{}
- }
- nextCount[styp] = 1
- if count[t] > 1 {
- nextCount[styp] = 2 // exact multiple doesn't matter
- }
- var index []int
- index = append(index, scan.index...)
- index = append(index, i)
- next = append(next, fieldScan{styp, index})
- }
- }
- if ok {
- break
- }
- }
- return
-}
-
-// FieldByName returns the struct field with the given name
-// and a boolean to indicate if the field was found.
-func (t *structType) FieldByName(name string) (f StructField, present bool) {
- // Quick check for top-level name, or struct without embedded fields.
- hasEmbeds := false
- if name != "" {
- for i := range t.Fields {
- tf := &t.Fields[i]
- if tf.Name.Name() == name {
- return t.Field(i), true
- }
- if tf.Embedded() {
- hasEmbeds = true
- }
- }
- }
- if !hasEmbeds {
- return
- }
- return t.FieldByNameFunc(func(s string) bool { return s == name })
-}
-
-// TypeOf returns the reflection [Type] that represents the dynamic type of i.
-// If i is a nil interface value, TypeOf returns nil.
-func TypeOf(i any) Type {
- eface := *(*emptyInterface)(unsafe.Pointer(&i))
- // Noescape so this doesn't make i to escape. See the comment
- // at Value.typ for why this is safe.
- return toType((*abi.Type)(noescape(unsafe.Pointer(eface.typ))))
-}
-
-// rtypeOf directly extracts the *rtype of the provided value.
-func rtypeOf(i any) *abi.Type {
- eface := *(*emptyInterface)(unsafe.Pointer(&i))
- return eface.typ
-}
-
-// ptrMap is the cache for PointerTo.
-var ptrMap sync.Map // map[*rtype]*ptrType
-
-// PtrTo returns the pointer type with element t.
-// For example, if t represents type Foo, PtrTo(t) represents *Foo.
-//
-// PtrTo is the old spelling of [PointerTo].
-// The two functions behave identically.
-//
-// Deprecated: Superseded by [PointerTo].
-func PtrTo(t Type) Type { return PointerTo(t) }
-
-// PointerTo returns the pointer type with element t.
-// For example, if t represents type Foo, PointerTo(t) represents *Foo.
-func PointerTo(t Type) Type {
- return toRType(t.(*rtype).ptrTo())
-}
-
-func (t *rtype) ptrTo() *abi.Type {
- at := &t.t
- if at.PtrToThis != 0 {
- return t.typeOff(at.PtrToThis)
- }
-
- // Check the cache.
- if pi, ok := ptrMap.Load(t); ok {
- return &pi.(*ptrType).Type
- }
-
- // Look in known types.
- s := "*" + t.String()
- for _, tt := range typesByString(s) {
- p := (*ptrType)(unsafe.Pointer(tt))
- if p.Elem != &t.t {
- continue
- }
- pi, _ := ptrMap.LoadOrStore(t, p)
- return &pi.(*ptrType).Type
- }
-
- // Create a new ptrType starting with the description
- // of an *unsafe.Pointer.
- var iptr any = (*unsafe.Pointer)(nil)
- prototype := *(**ptrType)(unsafe.Pointer(&iptr))
- pp := *prototype
-
- pp.Str = resolveReflectName(newName(s, "", false, false))
- pp.PtrToThis = 0
-
- // For the type structures linked into the binary, the
- // compiler provides a good hash of the string.
- // Create a good hash for the new string by using
- // the FNV-1 hash's mixing function to combine the
- // old hash and the new "*".
- pp.Hash = fnv1(t.t.Hash, '*')
-
- pp.Elem = at
-
- pi, _ := ptrMap.LoadOrStore(t, &pp)
- return &pi.(*ptrType).Type
-}
-
-func ptrTo(t *abi.Type) *abi.Type {
- return toRType(t).ptrTo()
-}
-
-// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
-func fnv1(x uint32, list ...byte) uint32 {
- for _, b := range list {
- x = x*16777619 ^ uint32(b)
- }
- return x
-}
-
-func (t *rtype) Implements(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.Implements")
- }
- if u.Kind() != Interface {
- panic("reflect: non-interface type passed to Type.Implements")
- }
- return implements(u.common(), t.common())
-}
-
-func (t *rtype) AssignableTo(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.AssignableTo")
- }
- uu := u.common()
- return directlyAssignable(uu, t.common()) || implements(uu, t.common())
-}
-
-func (t *rtype) ConvertibleTo(u Type) bool {
- if u == nil {
- panic("reflect: nil type passed to Type.ConvertibleTo")
- }
- return convertOp(u.common(), t.common()) != nil
-}
-
-func (t *rtype) Comparable() bool {
- return t.t.Equal != nil
-}
-
-// implements reports whether the type V implements the interface type T.
-func implements(T, V *abi.Type) bool {
- if T.Kind() != abi.Interface {
- return false
- }
- t := (*interfaceType)(unsafe.Pointer(T))
- if len(t.Methods) == 0 {
- return true
- }
-
- // The same algorithm applies in both cases, but the
- // method tables for an interface type and a concrete type
- // are different, so the code is duplicated.
- // In both cases the algorithm is a linear scan over the two
- // lists - T's methods and V's methods - simultaneously.
- // Since method tables are stored in a unique sorted order
- // (alphabetical, with no duplicate method names), the scan
- // through V's methods must hit a match for each of T's
- // methods along the way, or else V does not implement T.
- // This lets us run the scan in overall linear time instead of
- // the quadratic time a naive search would require.
- // See also ../runtime/iface.go.
- if V.Kind() == abi.Interface {
- v := (*interfaceType)(unsafe.Pointer(V))
- i := 0
- for j := 0; j < len(v.Methods); j++ {
- tm := &t.Methods[i]
- tmName := t.nameOff(tm.Name)
- vm := &v.Methods[j]
- vmName := nameOffFor(V, vm.Name)
- if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Typ) == t.typeOff(tm.Typ) {
- if !tmName.IsExported() {
- tmPkgPath := pkgPath(tmName)
- if tmPkgPath == "" {
- tmPkgPath = t.PkgPath.Name()
- }
- vmPkgPath := pkgPath(vmName)
- if vmPkgPath == "" {
- vmPkgPath = v.PkgPath.Name()
- }
- if tmPkgPath != vmPkgPath {
- continue
- }
- }
- if i++; i >= len(t.Methods) {
- return true
- }
- }
- }
- return false
- }
-
- v := V.Uncommon()
- if v == nil {
- return false
- }
- i := 0
- vmethods := v.Methods()
- for j := 0; j < int(v.Mcount); j++ {
- tm := &t.Methods[i]
- tmName := t.nameOff(tm.Name)
- vm := vmethods[j]
- vmName := nameOffFor(V, vm.Name)
- if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Mtyp) == t.typeOff(tm.Typ) {
- if !tmName.IsExported() {
- tmPkgPath := pkgPath(tmName)
- if tmPkgPath == "" {
- tmPkgPath = t.PkgPath.Name()
- }
- vmPkgPath := pkgPath(vmName)
- if vmPkgPath == "" {
- vmPkgPath = nameOffFor(V, v.PkgPath).Name()
- }
- if tmPkgPath != vmPkgPath {
- continue
- }
- }
- if i++; i >= len(t.Methods) {
- return true
- }
- }
- }
- return false
-}
-
-// specialChannelAssignability reports whether a value x of channel type V
-// can be directly assigned (using memmove) to another channel type T.
-// https://golang.org/doc/go_spec.html#Assignability
-// T and V must be both of Chan kind.
-func specialChannelAssignability(T, V *abi.Type) bool {
- // Special case:
- // x is a bidirectional channel value, T is a channel type,
- // x's type V and T have identical element types,
- // and at least one of V or T is not a defined type.
- return V.ChanDir() == abi.BothDir && (nameFor(T) == "" || nameFor(V) == "") && haveIdenticalType(T.Elem(), V.Elem(), true)
-}
-
-// directlyAssignable reports whether a value x of type V can be directly
-// assigned (using memmove) to a value of type T.
-// https://golang.org/doc/go_spec.html#Assignability
-// Ignoring the interface rules (implemented elsewhere)
-// and the ideal constant rules (no ideal constants at run time).
-func directlyAssignable(T, V *abi.Type) bool {
- // x's type V is identical to T?
- if T == V {
- return true
- }
-
- // Otherwise at least one of T and V must not be defined
- // and they must have the same kind.
- if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
- return false
- }
-
- if T.Kind() == abi.Chan && specialChannelAssignability(T, V) {
- return true
- }
-
- // x's type T and V must have identical underlying types.
- return haveIdenticalUnderlyingType(T, V, true)
-}
-
-func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
- if cmpTags {
- return T == V
- }
-
- if nameFor(T) != nameFor(V) || T.Kind() != V.Kind() || pkgPathFor(T) != pkgPathFor(V) {
- return false
- }
-
- return haveIdenticalUnderlyingType(T, V, false)
-}
-
-func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
- if T == V {
- return true
- }
-
- kind := Kind(T.Kind())
- if kind != Kind(V.Kind()) {
- return false
- }
-
- // Non-composite types of equal kind have same underlying type
- // (the predefined instance of the type).
- if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
- return true
- }
-
- // Composite types.
- switch kind {
- case Array:
- return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case Chan:
- return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case Func:
- t := (*funcType)(unsafe.Pointer(T))
- v := (*funcType)(unsafe.Pointer(V))
- if t.OutCount != v.OutCount || t.InCount != v.InCount {
- return false
- }
- for i := 0; i < t.NumIn(); i++ {
- if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
- return false
- }
- }
- for i := 0; i < t.NumOut(); i++ {
- if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
- return false
- }
- }
- return true
-
- case Interface:
- t := (*interfaceType)(unsafe.Pointer(T))
- v := (*interfaceType)(unsafe.Pointer(V))
- if len(t.Methods) == 0 && len(v.Methods) == 0 {
- return true
- }
- // Might have the same methods but still
- // need a run time conversion.
- return false
-
- case Map:
- return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case Pointer, Slice:
- return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
-
- case Struct:
- t := (*structType)(unsafe.Pointer(T))
- v := (*structType)(unsafe.Pointer(V))
- if len(t.Fields) != len(v.Fields) {
- return false
- }
- if t.PkgPath.Name() != v.PkgPath.Name() {
- return false
- }
- for i := range t.Fields {
- tf := &t.Fields[i]
- vf := &v.Fields[i]
- if tf.Name.Name() != vf.Name.Name() {
- return false
- }
- if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
- return false
- }
- if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
- return false
- }
- if tf.Offset != vf.Offset {
- return false
- }
- if tf.Embedded() != vf.Embedded() {
- return false
- }
- }
- return true
- }
-
- return false
-}
-
-// typelinks is implemented in package runtime.
-// It returns a slice of the sections in each module,
-// and a slice of *rtype offsets in each module.
-//
-// The types in each module are sorted by string. That is, the first
-// two linked types of the first module are:
-//
-// d0 := sections[0]
-// t1 := (*rtype)(add(d0, offset[0][0]))
-// t2 := (*rtype)(add(d0, offset[0][1]))
-//
-// and
-//
-// t1.String() < t2.String()
-//
-// Note that strings are not unique identifiers for types:
-// there can be more than one with a given string.
-// Only types we might want to look up are included:
-// pointers, channels, maps, slices, and arrays.
-func typelinks() (sections []unsafe.Pointer, offset [][]int32)
-
-func rtypeOff(section unsafe.Pointer, off int32) *abi.Type {
- return (*abi.Type)(add(section, uintptr(off), "sizeof(rtype) > 0"))
-}
-
-// typesByString returns the subslice of typelinks() whose elements have
-// the given string representation.
-// It may be empty (no known types with that string) or may have
-// multiple elements (multiple types with that string).
-func typesByString(s string) []*abi.Type {
- sections, offset := typelinks()
- var ret []*abi.Type
-
- for offsI, offs := range offset {
- section := sections[offsI]
-
- // We are looking for the first index i where the string becomes >= s.
- // This is a copy of sort.Search, with f(h) replaced by (*typ[h].String() >= s).
- i, j := 0, len(offs)
- for i < j {
- h := int(uint(i+j) >> 1) // avoid overflow when computing h
- // i ≤ h < j
- if !(stringFor(rtypeOff(section, offs[h])) >= s) {
- i = h + 1 // preserves f(i-1) == false
- } else {
- j = h // preserves f(j) == true
- }
- }
- // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
-
- // Having found the first, linear scan forward to find the last.
- // We could do a second binary search, but the caller is going
- // to do a linear scan anyway.
- for j := i; j < len(offs); j++ {
- typ := rtypeOff(section, offs[j])
- if stringFor(typ) != s {
- break
- }
- ret = append(ret, typ)
- }
- }
- return ret
-}
-
-// The lookupCache caches ArrayOf, ChanOf, MapOf and SliceOf lookups.
-var lookupCache sync.Map // map[cacheKey]*rtype
-
-// A cacheKey is the key for use in the lookupCache.
-// Four values describe any of the types we are looking for:
-// type kind, one or two subtypes, and an extra integer.
-type cacheKey struct {
- kind Kind
- t1 *abi.Type
- t2 *abi.Type
- extra uintptr
-}
-
-// The funcLookupCache caches FuncOf lookups.
-// FuncOf does not share the common lookupCache since cacheKey is not
-// sufficient to represent functions unambiguously.
-var funcLookupCache struct {
- sync.Mutex // Guards stores (but not loads) on m.
-
- // m is a map[uint32][]*rtype keyed by the hash calculated in FuncOf.
- // Elements of m are append-only and thus safe for concurrent reading.
- m sync.Map
-}
-
-// ChanOf returns the channel type with the given direction and element type.
-// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
-//
-// The gc runtime imposes a limit of 64 kB on channel element types.
-// If t's size is equal to or exceeds this limit, ChanOf panics.
-func ChanOf(dir ChanDir, t Type) Type {
- typ := t.common()
-
- // Look in cache.
- ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
- if ch, ok := lookupCache.Load(ckey); ok {
- return ch.(*rtype)
- }
-
- // This restriction is imposed by the gc compiler and the runtime.
- if typ.Size_ >= 1<<16 {
- panic("reflect.ChanOf: element size too large")
- }
-
- // Look in known types.
- var s string
- switch dir {
- default:
- panic("reflect.ChanOf: invalid dir")
- case SendDir:
- s = "chan<- " + stringFor(typ)
- case RecvDir:
- s = "<-chan " + stringFor(typ)
- case BothDir:
- typeStr := stringFor(typ)
- if typeStr[0] == '<' {
- // typ is recv chan, need parentheses as "<-" associates with leftmost
- // chan possible, see:
- // * https://golang.org/ref/spec#Channel_types
- // * https://github.com/golang/go/issues/39897
- s = "chan (" + typeStr + ")"
- } else {
- s = "chan " + typeStr
- }
- }
- for _, tt := range typesByString(s) {
- ch := (*chanType)(unsafe.Pointer(tt))
- if ch.Elem == typ && ch.Dir == abi.ChanDir(dir) {
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
- return ti.(Type)
- }
- }
-
- // Make a channel type.
- var ichan any = (chan unsafe.Pointer)(nil)
- prototype := *(**chanType)(unsafe.Pointer(&ichan))
- ch := *prototype
- ch.TFlag = abi.TFlagRegularMemory
- ch.Dir = abi.ChanDir(dir)
- ch.Str = resolveReflectName(newName(s, "", false, false))
- ch.Hash = fnv1(typ.Hash, 'c', byte(dir))
- ch.Elem = typ
-
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(&ch.Type))
- return ti.(Type)
-}
-
-// MapOf returns the map type with the given key and element types.
-// For example, if k represents int and e represents string,
-// MapOf(k, e) represents map[int]string.
-//
-// If the key type is not a valid map key type (that is, if it does
-// not implement Go's == operator), MapOf panics.
-func MapOf(key, elem Type) Type {
- ktyp := key.common()
- etyp := elem.common()
-
- if ktyp.Equal == nil {
- panic("reflect.MapOf: invalid key type " + stringFor(ktyp))
- }
-
- // Look in cache.
- ckey := cacheKey{Map, ktyp, etyp, 0}
- if mt, ok := lookupCache.Load(ckey); ok {
- return mt.(Type)
- }
-
- // Look in known types.
- s := "map[" + stringFor(ktyp) + "]" + stringFor(etyp)
- for _, tt := range typesByString(s) {
- mt := (*mapType)(unsafe.Pointer(tt))
- if mt.Key == ktyp && mt.Elem == etyp {
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
- return ti.(Type)
- }
- }
-
- // Make a map type.
- // Note: flag values must match those used in the TMAP case
- // in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
- var imap any = (map[unsafe.Pointer]unsafe.Pointer)(nil)
- mt := **(**mapType)(unsafe.Pointer(&imap))
- mt.Str = resolveReflectName(newName(s, "", false, false))
- mt.TFlag = 0
- mt.Hash = fnv1(etyp.Hash, 'm', byte(ktyp.Hash>>24), byte(ktyp.Hash>>16), byte(ktyp.Hash>>8), byte(ktyp.Hash))
- mt.Key = ktyp
- mt.Elem = etyp
- mt.Bucket = bucketOf(ktyp, etyp)
- mt.Hasher = func(p unsafe.Pointer, seed uintptr) uintptr {
- return typehash(ktyp, p, seed)
- }
- mt.Flags = 0
- if ktyp.Size_ > maxKeySize {
- mt.KeySize = uint8(goarch.PtrSize)
- mt.Flags |= 1 // indirect key
- } else {
- mt.KeySize = uint8(ktyp.Size_)
- }
- if etyp.Size_ > maxValSize {
- mt.ValueSize = uint8(goarch.PtrSize)
- mt.Flags |= 2 // indirect value
- } else {
- mt.MapType.ValueSize = uint8(etyp.Size_)
- }
- mt.MapType.BucketSize = uint16(mt.Bucket.Size_)
- if isReflexive(ktyp) {
- mt.Flags |= 4
- }
- if needKeyUpdate(ktyp) {
- mt.Flags |= 8
- }
- if hashMightPanic(ktyp) {
- mt.Flags |= 16
- }
- mt.PtrToThis = 0
-
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(&mt.Type))
- return ti.(Type)
-}
-
-var funcTypes []Type
-var funcTypesMutex sync.Mutex
-
-func initFuncTypes(n int) Type {
- funcTypesMutex.Lock()
- defer funcTypesMutex.Unlock()
- if n >= len(funcTypes) {
- newFuncTypes := make([]Type, n+1)
- copy(newFuncTypes, funcTypes)
- funcTypes = newFuncTypes
- }
- if funcTypes[n] != nil {
- return funcTypes[n]
- }
-
- funcTypes[n] = StructOf([]StructField{
- {
- Name: "FuncType",
- Type: TypeOf(funcType{}),
- },
- {
- Name: "Args",
- Type: ArrayOf(n, TypeOf(&rtype{})),
- },
- })
- return funcTypes[n]
-}
-
-// FuncOf returns the function type with the given argument and result types.
-// For example if k represents int and e represents string,
-// FuncOf([]Type{k}, []Type{e}, false) represents func(int) string.
-//
-// The variadic argument controls whether the function is variadic. FuncOf
-// panics if the in[len(in)-1] does not represent a slice and variadic is
-// true.
-func FuncOf(in, out []Type, variadic bool) Type {
- if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) {
- panic("reflect.FuncOf: last arg of variadic func must be slice")
- }
-
- // Make a func type.
- var ifunc any = (func())(nil)
- prototype := *(**funcType)(unsafe.Pointer(&ifunc))
- n := len(in) + len(out)
-
- if n > 128 {
- panic("reflect.FuncOf: too many arguments")
- }
-
- o := New(initFuncTypes(n)).Elem()
- ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
- args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
- *ft = *prototype
-
- // Build a hash and minimally populate ft.
- var hash uint32
- for _, in := range in {
- t := in.(*rtype)
- args = append(args, t)
- hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
- }
- if variadic {
- hash = fnv1(hash, 'v')
- }
- hash = fnv1(hash, '.')
- for _, out := range out {
- t := out.(*rtype)
- args = append(args, t)
- hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
- }
-
- ft.TFlag = 0
- ft.Hash = hash
- ft.InCount = uint16(len(in))
- ft.OutCount = uint16(len(out))
- if variadic {
- ft.OutCount |= 1 << 15
- }
-
- // Look in cache.
- if ts, ok := funcLookupCache.m.Load(hash); ok {
- for _, t := range ts.([]*abi.Type) {
- if haveIdenticalUnderlyingType(&ft.Type, t, true) {
- return toRType(t)
- }
- }
- }
-
- // Not in cache, lock and retry.
- funcLookupCache.Lock()
- defer funcLookupCache.Unlock()
- if ts, ok := funcLookupCache.m.Load(hash); ok {
- for _, t := range ts.([]*abi.Type) {
- if haveIdenticalUnderlyingType(&ft.Type, t, true) {
- return toRType(t)
- }
- }
- }
-
- addToCache := func(tt *abi.Type) Type {
- var rts []*abi.Type
- if rti, ok := funcLookupCache.m.Load(hash); ok {
- rts = rti.([]*abi.Type)
- }
- funcLookupCache.m.Store(hash, append(rts, tt))
- return toType(tt)
- }
-
- // Look in known types for the same string representation.
- str := funcStr(ft)
- for _, tt := range typesByString(str) {
- if haveIdenticalUnderlyingType(&ft.Type, tt, true) {
- return addToCache(tt)
- }
- }
-
- // Populate the remaining fields of ft and store in cache.
- ft.Str = resolveReflectName(newName(str, "", false, false))
- ft.PtrToThis = 0
- return addToCache(&ft.Type)
-}
-func stringFor(t *abi.Type) string {
- return toRType(t).String()
-}
-
-// funcStr builds a string representation of a funcType.
-func funcStr(ft *funcType) string {
- repr := make([]byte, 0, 64)
- repr = append(repr, "func("...)
- for i, t := range ft.InSlice() {
- if i > 0 {
- repr = append(repr, ", "...)
- }
- if ft.IsVariadic() && i == int(ft.InCount)-1 {
- repr = append(repr, "..."...)
- repr = append(repr, stringFor((*sliceType)(unsafe.Pointer(t)).Elem)...)
- } else {
- repr = append(repr, stringFor(t)...)
- }
- }
- repr = append(repr, ')')
- out := ft.OutSlice()
- if len(out) == 1 {
- repr = append(repr, ' ')
- } else if len(out) > 1 {
- repr = append(repr, " ("...)
- }
- for i, t := range out {
- if i > 0 {
- repr = append(repr, ", "...)
- }
- repr = append(repr, stringFor(t)...)
- }
- if len(out) > 1 {
- repr = append(repr, ')')
- }
- return string(repr)
-}
-
-// isReflexive reports whether the == operation on the type is reflexive.
-// That is, x == x for all values x of type t.
-func isReflexive(t *abi.Type) bool {
- switch Kind(t.Kind()) {
- case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, String, UnsafePointer:
- return true
- case Float32, Float64, Complex64, Complex128, Interface:
- return false
- case Array:
- tt := (*arrayType)(unsafe.Pointer(t))
- return isReflexive(tt.Elem)
- case Struct:
- tt := (*structType)(unsafe.Pointer(t))
- for _, f := range tt.Fields {
- if !isReflexive(f.Typ) {
- return false
- }
- }
- return true
- default:
- // Func, Map, Slice, Invalid
- panic("isReflexive called on non-key type " + stringFor(t))
- }
-}
-
-// needKeyUpdate reports whether map overwrites require the key to be copied.
-func needKeyUpdate(t *abi.Type) bool {
- switch Kind(t.Kind()) {
- case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, UnsafePointer:
- return false
- case Float32, Float64, Complex64, Complex128, Interface, String:
- // Float keys can be updated from +0 to -0.
- // String keys can be updated to use a smaller backing store.
- // Interfaces might have floats or strings in them.
- return true
- case Array:
- tt := (*arrayType)(unsafe.Pointer(t))
- return needKeyUpdate(tt.Elem)
- case Struct:
- tt := (*structType)(unsafe.Pointer(t))
- for _, f := range tt.Fields {
- if needKeyUpdate(f.Typ) {
- return true
- }
- }
- return false
- default:
- // Func, Map, Slice, Invalid
- panic("needKeyUpdate called on non-key type " + stringFor(t))
- }
-}
-
-// hashMightPanic reports whether the hash of a map key of type t might panic.
-func hashMightPanic(t *abi.Type) bool {
- switch Kind(t.Kind()) {
- case Interface:
- return true
- case Array:
- tt := (*arrayType)(unsafe.Pointer(t))
- return hashMightPanic(tt.Elem)
- case Struct:
- tt := (*structType)(unsafe.Pointer(t))
- for _, f := range tt.Fields {
- if hashMightPanic(f.Typ) {
- return true
- }
- }
- return false
- default:
- return false
- }
-}
-
-// Make sure these routines stay in sync with ../runtime/map.go!
-// These types exist only for GC, so we only fill out GC relevant info.
-// Currently, that's just size and the GC program. We also fill in string
-// for possible debugging use.
-const (
- bucketSize uintptr = abi.MapBucketCount
- maxKeySize uintptr = abi.MapMaxKeyBytes
- maxValSize uintptr = abi.MapMaxElemBytes
-)
-
-func bucketOf(ktyp, etyp *abi.Type) *abi.Type {
- if ktyp.Size_ > maxKeySize {
- ktyp = ptrTo(ktyp)
- }
- if etyp.Size_ > maxValSize {
- etyp = ptrTo(etyp)
- }
-
- // Prepare GC data if any.
- // A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+ptrSize bytes,
- // or 2064 bytes, or 258 pointer-size words, or 33 bytes of pointer bitmap.
- // Note that since the key and value are known to be <= 128 bytes,
- // they're guaranteed to have bitmaps instead of GC programs.
- var gcdata *byte
- var ptrdata uintptr
-
- size := bucketSize*(1+ktyp.Size_+etyp.Size_) + goarch.PtrSize
- if size&uintptr(ktyp.Align_-1) != 0 || size&uintptr(etyp.Align_-1) != 0 {
- panic("reflect: bad size computation in MapOf")
- }
-
- if ktyp.PtrBytes != 0 || etyp.PtrBytes != 0 {
- nptr := (bucketSize*(1+ktyp.Size_+etyp.Size_) + goarch.PtrSize) / goarch.PtrSize
- n := (nptr + 7) / 8
-
- // Runtime needs pointer masks to be a multiple of uintptr in size.
- n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
- mask := make([]byte, n)
- base := bucketSize / goarch.PtrSize
-
- if ktyp.PtrBytes != 0 {
- emitGCMask(mask, base, ktyp, bucketSize)
- }
- base += bucketSize * ktyp.Size_ / goarch.PtrSize
-
- if etyp.PtrBytes != 0 {
- emitGCMask(mask, base, etyp, bucketSize)
- }
- base += bucketSize * etyp.Size_ / goarch.PtrSize
-
- word := base
- mask[word/8] |= 1 << (word % 8)
- gcdata = &mask[0]
- ptrdata = (word + 1) * goarch.PtrSize
-
- // overflow word must be last
- if ptrdata != size {
- panic("reflect: bad layout computation in MapOf")
- }
- }
-
- b := &abi.Type{
- Align_: goarch.PtrSize,
- Size_: size,
- Kind_: uint8(Struct),
- PtrBytes: ptrdata,
- GCData: gcdata,
- }
- s := "bucket(" + stringFor(ktyp) + "," + stringFor(etyp) + ")"
- b.Str = resolveReflectName(newName(s, "", false, false))
- return b
-}
-
-func (t *rtype) gcSlice(begin, end uintptr) []byte {
- return (*[1 << 30]byte)(unsafe.Pointer(t.t.GCData))[begin:end:end]
-}
-
-// emitGCMask writes the GC mask for [n]typ into out, starting at bit
-// offset base.
-func emitGCMask(out []byte, base uintptr, typ *abi.Type, n uintptr) {
- if typ.Kind_&kindGCProg != 0 {
- panic("reflect: unexpected GC program")
- }
- ptrs := typ.PtrBytes / goarch.PtrSize
- words := typ.Size_ / goarch.PtrSize
- mask := typ.GcSlice(0, (ptrs+7)/8)
- for j := uintptr(0); j < ptrs; j++ {
- if (mask[j/8]>>(j%8))&1 != 0 {
- for i := uintptr(0); i < n; i++ {
- k := base + i*words + j
- out[k/8] |= 1 << (k % 8)
- }
- }
- }
-}
-
-// appendGCProg appends the GC program for the first ptrdata bytes of
-// typ to dst and returns the extended slice.
-func appendGCProg(dst []byte, typ *abi.Type) []byte {
- if typ.Kind_&kindGCProg != 0 {
- // Element has GC program; emit one element.
- n := uintptr(*(*uint32)(unsafe.Pointer(typ.GCData)))
- prog := typ.GcSlice(4, 4+n-1)
- return append(dst, prog...)
- }
-
- // Element is small with pointer mask; use as literal bits.
- ptrs := typ.PtrBytes / goarch.PtrSize
- mask := typ.GcSlice(0, (ptrs+7)/8)
-
- // Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes).
- for ; ptrs > 120; ptrs -= 120 {
- dst = append(dst, 120)
- dst = append(dst, mask[:15]...)
- mask = mask[15:]
- }
-
- dst = append(dst, byte(ptrs))
- dst = append(dst, mask...)
- return dst
-}
-
-// SliceOf returns the slice type with element type t.
-// For example, if t represents int, SliceOf(t) represents []int.
-func SliceOf(t Type) Type {
- typ := t.common()
-
- // Look in cache.
- ckey := cacheKey{Slice, typ, nil, 0}
- if slice, ok := lookupCache.Load(ckey); ok {
- return slice.(Type)
- }
-
- // Look in known types.
- s := "[]" + stringFor(typ)
- for _, tt := range typesByString(s) {
- slice := (*sliceType)(unsafe.Pointer(tt))
- if slice.Elem == typ {
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
- return ti.(Type)
- }
- }
-
- // Make a slice type.
- var islice any = ([]unsafe.Pointer)(nil)
- prototype := *(**sliceType)(unsafe.Pointer(&islice))
- slice := *prototype
- slice.TFlag = 0
- slice.Str = resolveReflectName(newName(s, "", false, false))
- slice.Hash = fnv1(typ.Hash, '[')
- slice.Elem = typ
- slice.PtrToThis = 0
-
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(&slice.Type))
- return ti.(Type)
-}
-
-// The structLookupCache caches StructOf lookups.
-// StructOf does not share the common lookupCache since we need to pin
-// the memory associated with *structTypeFixedN.
-var structLookupCache struct {
- sync.Mutex // Guards stores (but not loads) on m.
-
- // m is a map[uint32][]Type keyed by the hash calculated in StructOf.
- // Elements in m are append-only and thus safe for concurrent reading.
- m sync.Map
-}
-
-type structTypeUncommon struct {
- structType
- u uncommonType
-}
-
-// isLetter reports whether a given 'rune' is classified as a Letter.
-func isLetter(ch rune) bool {
- return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
-}
-
-// isValidFieldName checks if a string is a valid (struct) field name or not.
-//
-// According to the language spec, a field name should be an identifier.
-//
-// identifier = letter { letter | unicode_digit } .
-// letter = unicode_letter | "_" .
-func isValidFieldName(fieldName string) bool {
- for i, c := range fieldName {
- if i == 0 && !isLetter(c) {
- return false
- }
-
- if !(isLetter(c) || unicode.IsDigit(c)) {
- return false
- }
- }
-
- return len(fieldName) > 0
-}
-
-// StructOf returns the struct type containing fields.
-// The Offset and Index fields are ignored and computed as they would be
-// by the compiler.
-//
-// StructOf currently does not support promoted methods of embedded fields
-// and panics if passed unexported StructFields.
-func StructOf(fields []StructField) Type {
- var (
- hash = fnv1(0, []byte("struct {")...)
- size uintptr
- typalign uint8
- comparable = true
- methods []abi.Method
-
- fs = make([]structField, len(fields))
- repr = make([]byte, 0, 64)
- fset = map[string]struct{}{} // fields' names
-
- hasGCProg = false // records whether a struct-field type has a GCProg
- )
-
- lastzero := uintptr(0)
- repr = append(repr, "struct {"...)
- pkgpath := ""
- for i, field := range fields {
- if field.Name == "" {
- panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
- }
- if !isValidFieldName(field.Name) {
- panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
- }
- if field.Type == nil {
- panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
- }
- f, fpkgpath := runtimeStructField(field)
- ft := f.Typ
- if ft.Kind_&kindGCProg != 0 {
- hasGCProg = true
- }
- if fpkgpath != "" {
- if pkgpath == "" {
- pkgpath = fpkgpath
- } else if pkgpath != fpkgpath {
- panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
- }
- }
-
- // Update string and hash
- name := f.Name.Name()
- hash = fnv1(hash, []byte(name)...)
- repr = append(repr, (" " + name)...)
- if f.Embedded() {
- // Embedded field
- if f.Typ.Kind() == abi.Pointer {
- // Embedded ** and *interface{} are illegal
- elem := ft.Elem()
- if k := elem.Kind(); k == abi.Pointer || k == abi.Interface {
- panic("reflect.StructOf: illegal embedded field type " + stringFor(ft))
- }
- }
-
- switch Kind(f.Typ.Kind()) {
- case Interface:
- ift := (*interfaceType)(unsafe.Pointer(ft))
- for _, m := range ift.Methods {
- if pkgPath(ift.nameOff(m.Name)) != "" {
- // TODO(sbinet). Issue 15924.
- panic("reflect: embedded interface with unexported method(s) not implemented")
- }
-
- fnStub := resolveReflectText(unsafe.Pointer(abi.FuncPCABIInternal(embeddedIfaceMethStub)))
- methods = append(methods, abi.Method{
- Name: resolveReflectName(ift.nameOff(m.Name)),
- Mtyp: resolveReflectType(ift.typeOff(m.Typ)),
- Ifn: fnStub,
- Tfn: fnStub,
- })
- }
- case Pointer:
- ptr := (*ptrType)(unsafe.Pointer(ft))
- if unt := ptr.Uncommon(); unt != nil {
- if i > 0 && unt.Mcount > 0 {
- // Issue 15924.
- panic("reflect: embedded type with methods not implemented if type is not first field")
- }
- if len(fields) > 1 {
- panic("reflect: embedded type with methods not implemented if there is more than one field")
- }
- for _, m := range unt.Methods() {
- mname := nameOffFor(ft, m.Name)
- if pkgPath(mname) != "" {
- // TODO(sbinet).
- // Issue 15924.
- panic("reflect: embedded interface with unexported method(s) not implemented")
- }
- methods = append(methods, abi.Method{
- Name: resolveReflectName(mname),
- Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
- Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
- Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
- })
- }
- }
- if unt := ptr.Elem.Uncommon(); unt != nil {
- for _, m := range unt.Methods() {
- mname := nameOffFor(ft, m.Name)
- if pkgPath(mname) != "" {
- // TODO(sbinet)
- // Issue 15924.
- panic("reflect: embedded interface with unexported method(s) not implemented")
- }
- methods = append(methods, abi.Method{
- Name: resolveReflectName(mname),
- Mtyp: resolveReflectType(typeOffFor(ptr.Elem, m.Mtyp)),
- Ifn: resolveReflectText(textOffFor(ptr.Elem, m.Ifn)),
- Tfn: resolveReflectText(textOffFor(ptr.Elem, m.Tfn)),
- })
- }
- }
- default:
- if unt := ft.Uncommon(); unt != nil {
- if i > 0 && unt.Mcount > 0 {
- // Issue 15924.
- panic("reflect: embedded type with methods not implemented if type is not first field")
- }
- if len(fields) > 1 && ft.Kind_&kindDirectIface != 0 {
- panic("reflect: embedded type with methods not implemented for non-pointer type")
- }
- for _, m := range unt.Methods() {
- mname := nameOffFor(ft, m.Name)
- if pkgPath(mname) != "" {
- // TODO(sbinet)
- // Issue 15924.
- panic("reflect: embedded interface with unexported method(s) not implemented")
- }
- methods = append(methods, abi.Method{
- Name: resolveReflectName(mname),
- Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
- Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
- Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
- })
-
- }
- }
- }
- }
- if _, dup := fset[name]; dup && name != "_" {
- panic("reflect.StructOf: duplicate field " + name)
- }
- fset[name] = struct{}{}
-
- hash = fnv1(hash, byte(ft.Hash>>24), byte(ft.Hash>>16), byte(ft.Hash>>8), byte(ft.Hash))
-
- repr = append(repr, (" " + stringFor(ft))...)
- if f.Name.HasTag() {
- hash = fnv1(hash, []byte(f.Name.Tag())...)
- repr = append(repr, (" " + strconv.Quote(f.Name.Tag()))...)
- }
- if i < len(fields)-1 {
- repr = append(repr, ';')
- }
-
- comparable = comparable && (ft.Equal != nil)
-
- offset := align(size, uintptr(ft.Align_))
- if offset < size {
- panic("reflect.StructOf: struct size would exceed virtual address space")
- }
- if ft.Align_ > typalign {
- typalign = ft.Align_
- }
- size = offset + ft.Size_
- if size < offset {
- panic("reflect.StructOf: struct size would exceed virtual address space")
- }
- f.Offset = offset
-
- if ft.Size_ == 0 {
- lastzero = size
- }
-
- fs[i] = f
- }
-
- if size > 0 && lastzero == size {
- // This is a non-zero sized struct that ends in a
- // zero-sized field. We add an extra byte of padding,
- // to ensure that taking the address of the final
- // zero-sized field can't manufacture a pointer to the
- // next object in the heap. See issue 9401.
- size++
- if size == 0 {
- panic("reflect.StructOf: struct size would exceed virtual address space")
- }
- }
-
- var typ *structType
- var ut *uncommonType
-
- if len(methods) == 0 {
- t := new(structTypeUncommon)
- typ = &t.structType
- ut = &t.u
- } else {
- // A *rtype representing a struct is followed directly in memory by an
- // array of method objects representing the methods attached to the
- // struct. To get the same layout for a run time generated type, we
- // need an array directly following the uncommonType memory.
- // A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN.
- tt := New(StructOf([]StructField{
- {Name: "S", Type: TypeOf(structType{})},
- {Name: "U", Type: TypeOf(uncommonType{})},
- {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
- }))
-
- typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer())
- ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer())
-
- copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]abi.Method), methods)
- }
- // TODO(sbinet): Once we allow embedding multiple types,
- // methods will need to be sorted like the compiler does.
- // TODO(sbinet): Once we allow non-exported methods, we will
- // need to compute xcount as the number of exported methods.
- ut.Mcount = uint16(len(methods))
- ut.Xcount = ut.Mcount
- ut.Moff = uint32(unsafe.Sizeof(uncommonType{}))
-
- if len(fs) > 0 {
- repr = append(repr, ' ')
- }
- repr = append(repr, '}')
- hash = fnv1(hash, '}')
- str := string(repr)
-
- // Round the size up to be a multiple of the alignment.
- s := align(size, uintptr(typalign))
- if s < size {
- panic("reflect.StructOf: struct size would exceed virtual address space")
- }
- size = s
-
- // Make the struct type.
- var istruct any = struct{}{}
- prototype := *(**structType)(unsafe.Pointer(&istruct))
- *typ = *prototype
- typ.Fields = fs
- if pkgpath != "" {
- typ.PkgPath = newName(pkgpath, "", false, false)
- }
-
- // Look in cache.
- if ts, ok := structLookupCache.m.Load(hash); ok {
- for _, st := range ts.([]Type) {
- t := st.common()
- if haveIdenticalUnderlyingType(&typ.Type, t, true) {
- return toType(t)
- }
- }
- }
-
- // Not in cache, lock and retry.
- structLookupCache.Lock()
- defer structLookupCache.Unlock()
- if ts, ok := structLookupCache.m.Load(hash); ok {
- for _, st := range ts.([]Type) {
- t := st.common()
- if haveIdenticalUnderlyingType(&typ.Type, t, true) {
- return toType(t)
- }
- }
- }
-
- addToCache := func(t Type) Type {
- var ts []Type
- if ti, ok := structLookupCache.m.Load(hash); ok {
- ts = ti.([]Type)
- }
- structLookupCache.m.Store(hash, append(ts, t))
- return t
- }
-
- // Look in known types.
- for _, t := range typesByString(str) {
- if haveIdenticalUnderlyingType(&typ.Type, t, true) {
- // even if 't' wasn't a structType with methods, we should be ok
- // as the 'u uncommonType' field won't be accessed except when
- // tflag&abi.TFlagUncommon is set.
- return addToCache(toType(t))
- }
- }
-
- typ.Str = resolveReflectName(newName(str, "", false, false))
- typ.TFlag = 0 // TODO: set tflagRegularMemory
- typ.Hash = hash
- typ.Size_ = size
- typ.PtrBytes = typeptrdata(&typ.Type)
- typ.Align_ = typalign
- typ.FieldAlign_ = typalign
- typ.PtrToThis = 0
- if len(methods) > 0 {
- typ.TFlag |= abi.TFlagUncommon
- }
-
- if hasGCProg {
- lastPtrField := 0
- for i, ft := range fs {
- if ft.Typ.Pointers() {
- lastPtrField = i
- }
- }
- prog := []byte{0, 0, 0, 0} // will be length of prog
- var off uintptr
- for i, ft := range fs {
- if i > lastPtrField {
- // gcprog should not include anything for any field after
- // the last field that contains pointer data
- break
- }
- if !ft.Typ.Pointers() {
- // Ignore pointerless fields.
- continue
- }
- // Pad to start of this field with zeros.
- if ft.Offset > off {
- n := (ft.Offset - off) / goarch.PtrSize
- prog = append(prog, 0x01, 0x00) // emit a 0 bit
- if n > 1 {
- prog = append(prog, 0x81) // repeat previous bit
- prog = appendVarint(prog, n-1) // n-1 times
- }
- off = ft.Offset
- }
-
- prog = appendGCProg(prog, ft.Typ)
- off += ft.Typ.PtrBytes
- }
- prog = append(prog, 0)
- *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
- typ.Kind_ |= kindGCProg
- typ.GCData = &prog[0]
- } else {
- typ.Kind_ &^= kindGCProg
- bv := new(bitVector)
- addTypeBits(bv, 0, &typ.Type)
- if len(bv.data) > 0 {
- typ.GCData = &bv.data[0]
- }
- }
- typ.Equal = nil
- if comparable {
- typ.Equal = func(p, q unsafe.Pointer) bool {
- for _, ft := range typ.Fields {
- pi := add(p, ft.Offset, "&x.field safe")
- qi := add(q, ft.Offset, "&x.field safe")
- if !ft.Typ.Equal(pi, qi) {
- return false
- }
- }
- return true
- }
- }
-
- switch {
- case len(fs) == 1 && !ifaceIndir(fs[0].Typ):
- // structs of 1 direct iface type can be direct
- typ.Kind_ |= kindDirectIface
- default:
- typ.Kind_ &^= kindDirectIface
- }
-
- return addToCache(toType(&typ.Type))
-}
-
-func embeddedIfaceMethStub() {
- panic("reflect: StructOf does not support methods of embedded interfaces")
-}
-
-// runtimeStructField takes a StructField value passed to StructOf and
-// returns both the corresponding internal representation, of type
-// structField, and the pkgpath value to use for this field.
-func runtimeStructField(field StructField) (structField, string) {
- if field.Anonymous && field.PkgPath != "" {
- panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
- }
-
- if field.IsExported() {
- // Best-effort check for misuse.
- // Since this field will be treated as exported, not much harm done if Unicode lowercase slips through.
- c := field.Name[0]
- if 'a' <= c && c <= 'z' || c == '_' {
- panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
- }
- }
-
- resolveReflectType(field.Type.common()) // install in runtime
- f := structField{
- Name: newName(field.Name, string(field.Tag), field.IsExported(), field.Anonymous),
- Typ: field.Type.common(),
- Offset: 0,
- }
- return f, field.PkgPath
-}
-
-// typeptrdata returns the length in bytes of the prefix of t
-// containing pointer data. Anything after this offset is scalar data.
-// keep in sync with ../cmd/compile/internal/reflectdata/reflect.go
-func typeptrdata(t *abi.Type) uintptr {
- switch t.Kind() {
- case abi.Struct:
- st := (*structType)(unsafe.Pointer(t))
- // find the last field that has pointers.
- field := -1
- for i := range st.Fields {
- ft := st.Fields[i].Typ
- if ft.Pointers() {
- field = i
- }
- }
- if field == -1 {
- return 0
- }
- f := st.Fields[field]
- return f.Offset + f.Typ.PtrBytes
-
- default:
- panic("reflect.typeptrdata: unexpected type, " + stringFor(t))
- }
-}
-
-// See cmd/compile/internal/reflectdata/reflect.go for derivation of constant.
-const maxPtrmaskBytes = 2048
-
-// ArrayOf returns the array type with the given length and element type.
-// For example, if t represents int, ArrayOf(5, t) represents [5]int.
-//
-// If the resulting type would be larger than the available address space,
-// ArrayOf panics.
-func ArrayOf(length int, elem Type) Type {
- if length < 0 {
- panic("reflect: negative length passed to ArrayOf")
- }
-
- typ := elem.common()
-
- // Look in cache.
- ckey := cacheKey{Array, typ, nil, uintptr(length)}
- if array, ok := lookupCache.Load(ckey); ok {
- return array.(Type)
- }
-
- // Look in known types.
- s := "[" + strconv.Itoa(length) + "]" + stringFor(typ)
- for _, tt := range typesByString(s) {
- array := (*arrayType)(unsafe.Pointer(tt))
- if array.Elem == typ {
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
- return ti.(Type)
- }
- }
-
- // Make an array type.
- var iarray any = [1]unsafe.Pointer{}
- prototype := *(**arrayType)(unsafe.Pointer(&iarray))
- array := *prototype
- array.TFlag = typ.TFlag & abi.TFlagRegularMemory
- array.Str = resolveReflectName(newName(s, "", false, false))
- array.Hash = fnv1(typ.Hash, '[')
- for n := uint32(length); n > 0; n >>= 8 {
- array.Hash = fnv1(array.Hash, byte(n))
- }
- array.Hash = fnv1(array.Hash, ']')
- array.Elem = typ
- array.PtrToThis = 0
- if typ.Size_ > 0 {
- max := ^uintptr(0) / typ.Size_
- if uintptr(length) > max {
- panic("reflect.ArrayOf: array size would exceed virtual address space")
- }
- }
- array.Size_ = typ.Size_ * uintptr(length)
- if length > 0 && typ.PtrBytes != 0 {
- array.PtrBytes = typ.Size_*uintptr(length-1) + typ.PtrBytes
- }
- array.Align_ = typ.Align_
- array.FieldAlign_ = typ.FieldAlign_
- array.Len = uintptr(length)
- array.Slice = &(SliceOf(elem).(*rtype).t)
-
- switch {
- case typ.PtrBytes == 0 || array.Size_ == 0:
- // No pointers.
- array.GCData = nil
- array.PtrBytes = 0
-
- case length == 1:
- // In memory, 1-element array looks just like the element.
- array.Kind_ |= typ.Kind_ & kindGCProg
- array.GCData = typ.GCData
- array.PtrBytes = typ.PtrBytes
-
- case typ.Kind_&kindGCProg == 0 && array.Size_ <= maxPtrmaskBytes*8*goarch.PtrSize:
- // Element is small with pointer mask; array is still small.
- // Create direct pointer mask by turning each 1 bit in elem
- // into length 1 bits in larger mask.
- n := (array.PtrBytes/goarch.PtrSize + 7) / 8
- // Runtime needs pointer masks to be a multiple of uintptr in size.
- n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
- mask := make([]byte, n)
- emitGCMask(mask, 0, typ, array.Len)
- array.GCData = &mask[0]
-
- default:
- // Create program that emits one element
- // and then repeats to make the array.
- prog := []byte{0, 0, 0, 0} // will be length of prog
- prog = appendGCProg(prog, typ)
- // Pad from ptrdata to size.
- elemPtrs := typ.PtrBytes / goarch.PtrSize
- elemWords := typ.Size_ / goarch.PtrSize
- if elemPtrs < elemWords {
- // Emit literal 0 bit, then repeat as needed.
- prog = append(prog, 0x01, 0x00)
- if elemPtrs+1 < elemWords {
- prog = append(prog, 0x81)
- prog = appendVarint(prog, elemWords-elemPtrs-1)
- }
- }
- // Repeat length-1 times.
- if elemWords < 0x80 {
- prog = append(prog, byte(elemWords|0x80))
- } else {
- prog = append(prog, 0x80)
- prog = appendVarint(prog, elemWords)
- }
- prog = appendVarint(prog, uintptr(length)-1)
- prog = append(prog, 0)
- *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
- array.Kind_ |= kindGCProg
- array.GCData = &prog[0]
- array.PtrBytes = array.Size_ // overestimate but ok; must match program
- }
-
- etyp := typ
- esize := etyp.Size()
-
- array.Equal = nil
- if eequal := etyp.Equal; eequal != nil {
- array.Equal = func(p, q unsafe.Pointer) bool {
- for i := 0; i < length; i++ {
- pi := arrayAt(p, i, esize, "i < length")
- qi := arrayAt(q, i, esize, "i < length")
- if !eequal(pi, qi) {
- return false
- }
-
- }
- return true
- }
- }
-
- switch {
- case length == 1 && !ifaceIndir(typ):
- // array of 1 direct iface type can be direct
- array.Kind_ |= kindDirectIface
- default:
- array.Kind_ &^= kindDirectIface
- }
-
- ti, _ := lookupCache.LoadOrStore(ckey, toRType(&array.Type))
- return ti.(Type)
-}
-
-func appendVarint(x []byte, v uintptr) []byte {
- for ; v >= 0x80; v >>= 7 {
- x = append(x, byte(v|0x80))
- }
- x = append(x, byte(v))
- return x
-}
-
-// toType converts from a *rtype to a Type that can be returned
-// to the client of package reflect. In gc, the only concern is that
-// a nil *rtype must be replaced by a nil Type, but in gccgo this
-// function takes care of ensuring that multiple *rtype for the same
-// type are coalesced into a single Type.
-func toType(t *abi.Type) Type {
- if t == nil {
- return nil
- }
- return toRType(t)
-}
-
-type layoutKey struct {
- ftyp *funcType // function signature
- rcvr *abi.Type // receiver type, or nil if none
-}
-
-type layoutType struct {
- t *abi.Type
- framePool *sync.Pool
- abid abiDesc
-}
-
-var layoutCache sync.Map // map[layoutKey]layoutType
-
-// funcLayout computes a struct type representing the layout of the
-// stack-assigned function arguments and return values for the function
-// type t.
-// If rcvr != nil, rcvr specifies the type of the receiver.
-// The returned type exists only for GC, so we only fill out GC relevant info.
-// Currently, that's just size and the GC program. We also fill in
-// the name for possible debugging use.
-func funcLayout(t *funcType, rcvr *abi.Type) (frametype *abi.Type, framePool *sync.Pool, abid abiDesc) {
- if t.Kind() != abi.Func {
- panic("reflect: funcLayout of non-func type " + stringFor(&t.Type))
- }
- if rcvr != nil && rcvr.Kind() == abi.Interface {
- panic("reflect: funcLayout with interface receiver " + stringFor(rcvr))
- }
- k := layoutKey{t, rcvr}
- if lti, ok := layoutCache.Load(k); ok {
- lt := lti.(layoutType)
- return lt.t, lt.framePool, lt.abid
- }
-
- // Compute the ABI layout.
- abid = newAbiDesc(t, rcvr)
-
- // build dummy rtype holding gc program
- x := &abi.Type{
- Align_: goarch.PtrSize,
- // Don't add spill space here; it's only necessary in
- // reflectcall's frame, not in the allocated frame.
- // TODO(mknyszek): Remove this comment when register
- // spill space in the frame is no longer required.
- Size_: align(abid.retOffset+abid.ret.stackBytes, goarch.PtrSize),
- PtrBytes: uintptr(abid.stackPtrs.n) * goarch.PtrSize,
- }
- if abid.stackPtrs.n > 0 {
- x.GCData = &abid.stackPtrs.data[0]
- }
-
- var s string
- if rcvr != nil {
- s = "methodargs(" + stringFor(rcvr) + ")(" + stringFor(&t.Type) + ")"
- } else {
- s = "funcargs(" + stringFor(&t.Type) + ")"
- }
- x.Str = resolveReflectName(newName(s, "", false, false))
-
- // cache result for future callers
- framePool = &sync.Pool{New: func() any {
- return unsafe_New(x)
- }}
- lti, _ := layoutCache.LoadOrStore(k, layoutType{
- t: x,
- framePool: framePool,
- abid: abid,
- })
- lt := lti.(layoutType)
- return lt.t, lt.framePool, lt.abid
-}
-
-// ifaceIndir reports whether t is stored indirectly in an interface value.
-func ifaceIndir(t *abi.Type) bool {
- return t.Kind_&kindDirectIface == 0
-}
-
-// Note: this type must agree with runtime.bitvector.
-type bitVector struct {
- n uint32 // number of bits
- data []byte
-}
-
-// append a bit to the bitmap.
-func (bv *bitVector) append(bit uint8) {
- if bv.n%(8*goarch.PtrSize) == 0 {
- // Runtime needs pointer masks to be a multiple of uintptr in size.
- // Since reflect passes bv.data directly to the runtime as a pointer mask,
- // we append a full uintptr of zeros at a time.
- for i := 0; i < goarch.PtrSize; i++ {
- bv.data = append(bv.data, 0)
- }
- }
- bv.data[bv.n/8] |= bit << (bv.n % 8)
- bv.n++
-}
-
-func addTypeBits(bv *bitVector, offset uintptr, t *abi.Type) {
- if t.PtrBytes == 0 {
- return
- }
-
- switch Kind(t.Kind_ & kindMask) {
- case Chan, Func, Map, Pointer, Slice, String, UnsafePointer:
- // 1 pointer at start of representation
- for bv.n < uint32(offset/uintptr(goarch.PtrSize)) {
- bv.append(0)
- }
- bv.append(1)
-
- case Interface:
- // 2 pointers
- for bv.n < uint32(offset/uintptr(goarch.PtrSize)) {
- bv.append(0)
- }
- bv.append(1)
- bv.append(1)
-
- case Array:
- // repeat inner type
- tt := (*arrayType)(unsafe.Pointer(t))
- for i := 0; i < int(tt.Len); i++ {
- addTypeBits(bv, offset+uintptr(i)*tt.Elem.Size_, tt.Elem)
- }
-
- case Struct:
- // apply fields
- tt := (*structType)(unsafe.Pointer(t))
- for i := range tt.Fields {
- f := &tt.Fields[i]
- addTypeBits(bv, offset+f.Offset, f.Typ)
- }
- }
-}
-
-// TypeFor returns the [Type] that represents the type argument T.
-func TypeFor[T any]() Type {
- return TypeOf((*T)(nil)).Elem()
-}
diff --git a/contrib/go/_std_1.22/src/reflect/value.go b/contrib/go/_std_1.22/src/reflect/value.go
deleted file mode 100644
index 06f22f742813..000000000000
--- a/contrib/go/_std_1.22/src/reflect/value.go
+++ /dev/null
@@ -1,4011 +0,0 @@
-// Copyright 2009 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.
-
-package reflect
-
-import (
- "errors"
- "internal/abi"
- "internal/goarch"
- "internal/itoa"
- "internal/unsafeheader"
- "math"
- "runtime"
- "unsafe"
-)
-
-// Value is the reflection interface to a Go value.
-//
-// Not all methods apply to all kinds of values. Restrictions,
-// if any, are noted in the documentation for each method.
-// Use the Kind method to find out the kind of value before
-// calling kind-specific methods. Calling a method
-// inappropriate to the kind of type causes a run time panic.
-//
-// The zero Value represents no value.
-// Its IsValid method returns false, its Kind method returns Invalid,
-// its String method returns "", and all other methods panic.
-// Most functions and methods never return an invalid value.
-// If one does, its documentation states the conditions explicitly.
-//
-// A Value can be used concurrently by multiple goroutines provided that
-// the underlying Go value can be used concurrently for the equivalent
-// direct operations.
-//
-// To compare two Values, compare the results of the Interface method.
-// Using == on two Values does not compare the underlying values
-// they represent.
-type Value struct {
- // typ_ holds the type of the value represented by a Value.
- // Access using the typ method to avoid escape of v.
- typ_ *abi.Type
-
- // Pointer-valued data or, if flagIndir is set, pointer to data.
- // Valid when either flagIndir is set or typ.pointers() is true.
- ptr unsafe.Pointer
-
- // flag holds metadata about the value.
- //
- // The lowest five bits give the Kind of the value, mirroring typ.Kind().
- //
- // The next set of bits are flag bits:
- // - flagStickyRO: obtained via unexported not embedded field, so read-only
- // - flagEmbedRO: obtained via unexported embedded field, so read-only
- // - flagIndir: val holds a pointer to the data
- // - flagAddr: v.CanAddr is true (implies flagIndir and ptr is non-nil)
- // - flagMethod: v is a method value.
- // If ifaceIndir(typ), code can assume that flagIndir is set.
- //
- // The remaining 22+ bits give a method number for method values.
- // If flag.kind() != Func, code can assume that flagMethod is unset.
- flag
-
- // A method value represents a curried method invocation
- // like r.Read for some receiver r. The typ+val+flag bits describe
- // the receiver r, but the flag's Kind bits say Func (methods are
- // functions), and the top bits of the flag give the method number
- // in r's type's method table.
-}
-
-type flag uintptr
-
-const (
- flagKindWidth = 5 // there are 27 kinds
- flagKindMask flag = 1< len(prefix) && name[:len(prefix)] == prefix {
- methodName := name[len(prefix):]
- if len(methodName) > 0 && 'A' <= methodName[0] && methodName[0] <= 'Z' {
- return name
- }
- }
- }
- return "unknown method"
-}
-
-// emptyInterface is the header for an interface{} value.
-type emptyInterface struct {
- typ *abi.Type
- word unsafe.Pointer
-}
-
-// nonEmptyInterface is the header for an interface value with methods.
-type nonEmptyInterface struct {
- // see ../runtime/iface.go:/Itab
- itab *struct {
- ityp *abi.Type // static interface type
- typ *abi.Type // dynamic concrete type
- hash uint32 // copy of typ.hash
- _ [4]byte
- fun [100000]unsafe.Pointer // method table
- }
- word unsafe.Pointer
-}
-
-// mustBe panics if f's kind is not expected.
-// Making this a method on flag instead of on Value
-// (and embedding flag in Value) means that we can write
-// the very clear v.mustBe(Bool) and have it compile into
-// v.flag.mustBe(Bool), which will only bother to copy the
-// single important word for the receiver.
-func (f flag) mustBe(expected Kind) {
- // TODO(mvdan): use f.kind() again once mid-stack inlining gets better
- if Kind(f&flagKindMask) != expected {
- panic(&ValueError{valueMethodName(), f.kind()})
- }
-}
-
-// mustBeExported panics if f records that the value was obtained using
-// an unexported field.
-func (f flag) mustBeExported() {
- if f == 0 || f&flagRO != 0 {
- f.mustBeExportedSlow()
- }
-}
-
-func (f flag) mustBeExportedSlow() {
- if f == 0 {
- panic(&ValueError{valueMethodName(), Invalid})
- }
- if f&flagRO != 0 {
- panic("reflect: " + valueMethodName() + " using value obtained using unexported field")
- }
-}
-
-// mustBeAssignable panics if f records that the value is not assignable,
-// which is to say that either it was obtained using an unexported field
-// or it is not addressable.
-func (f flag) mustBeAssignable() {
- if f&flagRO != 0 || f&flagAddr == 0 {
- f.mustBeAssignableSlow()
- }
-}
-
-func (f flag) mustBeAssignableSlow() {
- if f == 0 {
- panic(&ValueError{valueMethodName(), Invalid})
- }
- // Assignable if addressable and not read-only.
- if f&flagRO != 0 {
- panic("reflect: " + valueMethodName() + " using value obtained using unexported field")
- }
- if f&flagAddr == 0 {
- panic("reflect: " + valueMethodName() + " using unaddressable value")
- }
-}
-
-// Addr returns a pointer value representing the address of v.
-// It panics if [Value.CanAddr] returns false.
-// Addr is typically used to obtain a pointer to a struct field
-// or slice element in order to call a method that requires a
-// pointer receiver.
-func (v Value) Addr() Value {
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.Addr of unaddressable value")
- }
- // Preserve flagRO instead of using v.flag.ro() so that
- // v.Addr().Elem() is equivalent to v (#32772)
- fl := v.flag & flagRO
- return Value{ptrTo(v.typ()), v.ptr, fl | flag(Pointer)}
-}
-
-// Bool returns v's underlying value.
-// It panics if v's kind is not [Bool].
-func (v Value) Bool() bool {
- // panicNotBool is split out to keep Bool inlineable.
- if v.kind() != Bool {
- v.panicNotBool()
- }
- return *(*bool)(v.ptr)
-}
-
-func (v Value) panicNotBool() {
- v.mustBe(Bool)
-}
-
-var bytesType = rtypeOf(([]byte)(nil))
-
-// Bytes returns v's underlying value.
-// It panics if v's underlying value is not a slice of bytes or
-// an addressable array of bytes.
-func (v Value) Bytes() []byte {
- // bytesSlow is split out to keep Bytes inlineable for unnamed []byte.
- if v.typ_ == bytesType { // ok to use v.typ_ directly as comparison doesn't cause escape
- return *(*[]byte)(v.ptr)
- }
- return v.bytesSlow()
-}
-
-func (v Value) bytesSlow() []byte {
- switch v.kind() {
- case Slice:
- if v.typ().Elem().Kind() != abi.Uint8 {
- panic("reflect.Value.Bytes of non-byte slice")
- }
- // Slice is always bigger than a word; assume flagIndir.
- return *(*[]byte)(v.ptr)
- case Array:
- if v.typ().Elem().Kind() != abi.Uint8 {
- panic("reflect.Value.Bytes of non-byte array")
- }
- if !v.CanAddr() {
- panic("reflect.Value.Bytes of unaddressable byte array")
- }
- p := (*byte)(v.ptr)
- n := int((*arrayType)(unsafe.Pointer(v.typ())).Len)
- return unsafe.Slice(p, n)
- }
- panic(&ValueError{"reflect.Value.Bytes", v.kind()})
-}
-
-// runes returns v's underlying value.
-// It panics if v's underlying value is not a slice of runes (int32s).
-func (v Value) runes() []rune {
- v.mustBe(Slice)
- if v.typ().Elem().Kind() != abi.Int32 {
- panic("reflect.Value.Bytes of non-rune slice")
- }
- // Slice is always bigger than a word; assume flagIndir.
- return *(*[]rune)(v.ptr)
-}
-
-// CanAddr reports whether the value's address can be obtained with [Value.Addr].
-// Such values are called addressable. A value is addressable if it is
-// an element of a slice, an element of an addressable array,
-// a field of an addressable struct, or the result of dereferencing a pointer.
-// If CanAddr returns false, calling [Value.Addr] will panic.
-func (v Value) CanAddr() bool {
- return v.flag&flagAddr != 0
-}
-
-// CanSet reports whether the value of v can be changed.
-// A [Value] can be changed only if it is addressable and was not
-// obtained by the use of unexported struct fields.
-// If CanSet returns false, calling [Value.Set] or any type-specific
-// setter (e.g., [Value.SetBool], [Value.SetInt]) will panic.
-func (v Value) CanSet() bool {
- return v.flag&(flagAddr|flagRO) == flagAddr
-}
-
-// Call calls the function v with the input arguments in.
-// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
-// Call panics if v's Kind is not [Func].
-// It returns the output results as Values.
-// As in Go, each input argument must be assignable to the
-// type of the function's corresponding input parameter.
-// If v is a variadic function, Call creates the variadic slice parameter
-// itself, copying in the corresponding values.
-func (v Value) Call(in []Value) []Value {
- v.mustBe(Func)
- v.mustBeExported()
- return v.call("Call", in)
-}
-
-// CallSlice calls the variadic function v with the input arguments in,
-// assigning the slice in[len(in)-1] to v's final variadic argument.
-// For example, if len(in) == 3, v.CallSlice(in) represents the Go call v(in[0], in[1], in[2]...).
-// CallSlice panics if v's Kind is not [Func] or if v is not variadic.
-// It returns the output results as Values.
-// As in Go, each input argument must be assignable to the
-// type of the function's corresponding input parameter.
-func (v Value) CallSlice(in []Value) []Value {
- v.mustBe(Func)
- v.mustBeExported()
- return v.call("CallSlice", in)
-}
-
-var callGC bool // for testing; see TestCallMethodJump and TestCallArgLive
-
-const debugReflectCall = false
-
-func (v Value) call(op string, in []Value) []Value {
- // Get function pointer, type.
- t := (*funcType)(unsafe.Pointer(v.typ()))
- var (
- fn unsafe.Pointer
- rcvr Value
- rcvrtype *abi.Type
- )
- if v.flag&flagMethod != 0 {
- rcvr = v
- rcvrtype, t, fn = methodReceiver(op, v, int(v.flag)>>flagMethodShift)
- } else if v.flag&flagIndir != 0 {
- fn = *(*unsafe.Pointer)(v.ptr)
- } else {
- fn = v.ptr
- }
-
- if fn == nil {
- panic("reflect.Value.Call: call of nil function")
- }
-
- isSlice := op == "CallSlice"
- n := t.NumIn()
- isVariadic := t.IsVariadic()
- if isSlice {
- if !isVariadic {
- panic("reflect: CallSlice of non-variadic function")
- }
- if len(in) < n {
- panic("reflect: CallSlice with too few input arguments")
- }
- if len(in) > n {
- panic("reflect: CallSlice with too many input arguments")
- }
- } else {
- if isVariadic {
- n--
- }
- if len(in) < n {
- panic("reflect: Call with too few input arguments")
- }
- if !isVariadic && len(in) > n {
- panic("reflect: Call with too many input arguments")
- }
- }
- for _, x := range in {
- if x.Kind() == Invalid {
- panic("reflect: " + op + " using zero Value argument")
- }
- }
- for i := 0; i < n; i++ {
- if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(toRType(targ)) {
- panic("reflect: " + op + " using " + xt.String() + " as type " + stringFor(targ))
- }
- }
- if !isSlice && isVariadic {
- // prepare slice for remaining values
- m := len(in) - n
- slice := MakeSlice(toRType(t.In(n)), m, m)
- elem := toRType(t.In(n)).Elem() // FIXME cast to slice type and Elem()
- for i := 0; i < m; i++ {
- x := in[n+i]
- if xt := x.Type(); !xt.AssignableTo(elem) {
- panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op)
- }
- slice.Index(i).Set(x)
- }
- origIn := in
- in = make([]Value, n+1)
- copy(in[:n], origIn)
- in[n] = slice
- }
-
- nin := len(in)
- if nin != t.NumIn() {
- panic("reflect.Value.Call: wrong argument count")
- }
- nout := t.NumOut()
-
- // Register argument space.
- var regArgs abi.RegArgs
-
- // Compute frame type.
- frametype, framePool, abid := funcLayout(t, rcvrtype)
-
- // Allocate a chunk of memory for frame if needed.
- var stackArgs unsafe.Pointer
- if frametype.Size() != 0 {
- if nout == 0 {
- stackArgs = framePool.Get().(unsafe.Pointer)
- } else {
- // Can't use pool if the function has return values.
- // We will leak pointer to args in ret, so its lifetime is not scoped.
- stackArgs = unsafe_New(frametype)
- }
- }
- frameSize := frametype.Size()
-
- if debugReflectCall {
- println("reflect.call", stringFor(&t.Type))
- abid.dump()
- }
-
- // Copy inputs into args.
-
- // Handle receiver.
- inStart := 0
- if rcvrtype != nil {
- // Guaranteed to only be one word in size,
- // so it will only take up exactly 1 abiStep (either
- // in a register or on the stack).
- switch st := abid.call.steps[0]; st.kind {
- case abiStepStack:
- storeRcvr(rcvr, stackArgs)
- case abiStepPointer:
- storeRcvr(rcvr, unsafe.Pointer(®Args.Ptrs[st.ireg]))
- fallthrough
- case abiStepIntReg:
- storeRcvr(rcvr, unsafe.Pointer(®Args.Ints[st.ireg]))
- case abiStepFloatReg:
- storeRcvr(rcvr, unsafe.Pointer(®Args.Floats[st.freg]))
- default:
- panic("unknown ABI parameter kind")
- }
- inStart = 1
- }
-
- // Handle arguments.
- for i, v := range in {
- v.mustBeExported()
- targ := toRType(t.In(i))
- // TODO(mknyszek): Figure out if it's possible to get some
- // scratch space for this assignment check. Previously, it
- // was possible to use space in the argument frame.
- v = v.assignTo("reflect.Value.Call", &targ.t, nil)
- stepsLoop:
- for _, st := range abid.call.stepsForValue(i + inStart) {
- switch st.kind {
- case abiStepStack:
- // Copy values to the "stack."
- addr := add(stackArgs, st.stkOff, "precomputed stack arg offset")
- if v.flag&flagIndir != 0 {
- typedmemmove(&targ.t, addr, v.ptr)
- } else {
- *(*unsafe.Pointer)(addr) = v.ptr
- }
- // There's only one step for a stack-allocated value.
- break stepsLoop
- case abiStepIntReg, abiStepPointer:
- // Copy values to "integer registers."
- if v.flag&flagIndir != 0 {
- offset := add(v.ptr, st.offset, "precomputed value offset")
- if st.kind == abiStepPointer {
- // Duplicate this pointer in the pointer area of the
- // register space. Otherwise, there's the potential for
- // this to be the last reference to v.ptr.
- regArgs.Ptrs[st.ireg] = *(*unsafe.Pointer)(offset)
- }
- intToReg(®Args, st.ireg, st.size, offset)
- } else {
- if st.kind == abiStepPointer {
- // See the comment in abiStepPointer case above.
- regArgs.Ptrs[st.ireg] = v.ptr
- }
- regArgs.Ints[st.ireg] = uintptr(v.ptr)
- }
- case abiStepFloatReg:
- // Copy values to "float registers."
- if v.flag&flagIndir == 0 {
- panic("attempted to copy pointer to FP register")
- }
- offset := add(v.ptr, st.offset, "precomputed value offset")
- floatToReg(®Args, st.freg, st.size, offset)
- default:
- panic("unknown ABI part kind")
- }
- }
- }
- // TODO(mknyszek): Remove this when we no longer have
- // caller reserved spill space.
- frameSize = align(frameSize, goarch.PtrSize)
- frameSize += abid.spill
-
- // Mark pointers in registers for the return path.
- regArgs.ReturnIsPtr = abid.outRegPtrs
-
- if debugReflectCall {
- regArgs.Dump()
- }
-
- // For testing; see TestCallArgLive.
- if callGC {
- runtime.GC()
- }
-
- // Call.
- call(frametype, fn, stackArgs, uint32(frametype.Size()), uint32(abid.retOffset), uint32(frameSize), ®Args)
-
- // For testing; see TestCallMethodJump.
- if callGC {
- runtime.GC()
- }
-
- var ret []Value
- if nout == 0 {
- if stackArgs != nil {
- typedmemclr(frametype, stackArgs)
- framePool.Put(stackArgs)
- }
- } else {
- if stackArgs != nil {
- // Zero the now unused input area of args,
- // because the Values returned by this function contain pointers to the args object,
- // and will thus keep the args object alive indefinitely.
- typedmemclrpartial(frametype, stackArgs, 0, abid.retOffset)
- }
-
- // Wrap Values around return values in args.
- ret = make([]Value, nout)
- for i := 0; i < nout; i++ {
- tv := t.Out(i)
- if tv.Size() == 0 {
- // For zero-sized return value, args+off may point to the next object.
- // In this case, return the zero value instead.
- ret[i] = Zero(toRType(tv))
- continue
- }
- steps := abid.ret.stepsForValue(i)
- if st := steps[0]; st.kind == abiStepStack {
- // This value is on the stack. If part of a value is stack
- // allocated, the entire value is according to the ABI. So
- // just make an indirection into the allocated frame.
- fl := flagIndir | flag(tv.Kind())
- ret[i] = Value{tv, add(stackArgs, st.stkOff, "tv.Size() != 0"), fl}
- // Note: this does introduce false sharing between results -
- // if any result is live, they are all live.
- // (And the space for the args is live as well, but as we've
- // cleared that space it isn't as big a deal.)
- continue
- }
-
- // Handle pointers passed in registers.
- if !ifaceIndir(tv) {
- // Pointer-valued data gets put directly
- // into v.ptr.
- if steps[0].kind != abiStepPointer {
- print("kind=", steps[0].kind, ", type=", stringFor(tv), "\n")
- panic("mismatch between ABI description and types")
- }
- ret[i] = Value{tv, regArgs.Ptrs[steps[0].ireg], flag(tv.Kind())}
- continue
- }
-
- // All that's left is values passed in registers that we need to
- // create space for and copy values back into.
- //
- // TODO(mknyszek): We make a new allocation for each register-allocated
- // value, but previously we could always point into the heap-allocated
- // stack frame. This is a regression that could be fixed by adding
- // additional space to the allocated stack frame and storing the
- // register-allocated return values into the allocated stack frame and
- // referring there in the resulting Value.
- s := unsafe_New(tv)
- for _, st := range steps {
- switch st.kind {
- case abiStepIntReg:
- offset := add(s, st.offset, "precomputed value offset")
- intFromReg(®Args, st.ireg, st.size, offset)
- case abiStepPointer:
- s := add(s, st.offset, "precomputed value offset")
- *((*unsafe.Pointer)(s)) = regArgs.Ptrs[st.ireg]
- case abiStepFloatReg:
- offset := add(s, st.offset, "precomputed value offset")
- floatFromReg(®Args, st.freg, st.size, offset)
- case abiStepStack:
- panic("register-based return value has stack component")
- default:
- panic("unknown ABI part kind")
- }
- }
- ret[i] = Value{tv, s, flagIndir | flag(tv.Kind())}
- }
- }
-
- return ret
-}
-
-// callReflect is the call implementation used by a function
-// returned by MakeFunc. In many ways it is the opposite of the
-// method Value.call above. The method above converts a call using Values
-// into a call of a function with a concrete argument frame, while
-// callReflect converts a call of a function with a concrete argument
-// frame into a call using Values.
-// It is in this file so that it can be next to the call method above.
-// The remainder of the MakeFunc implementation is in makefunc.go.
-//
-// NOTE: This function must be marked as a "wrapper" in the generated code,
-// so that the linker can make it work correctly for panic and recover.
-// The gc compilers know to do that for the name "reflect.callReflect".
-//
-// ctxt is the "closure" generated by MakeFunc.
-// frame is a pointer to the arguments to that closure on the stack.
-// retValid points to a boolean which should be set when the results
-// section of frame is set.
-//
-// regs contains the argument values passed in registers and will contain
-// the values returned from ctxt.fn in registers.
-func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs *abi.RegArgs) {
- if callGC {
- // Call GC upon entry during testing.
- // Getting our stack scanned here is the biggest hazard, because
- // our caller (makeFuncStub) could have failed to place the last
- // pointer to a value in regs' pointer space, in which case it
- // won't be visible to the GC.
- runtime.GC()
- }
- ftyp := ctxt.ftyp
- f := ctxt.fn
-
- _, _, abid := funcLayout(ftyp, nil)
-
- // Copy arguments into Values.
- ptr := frame
- in := make([]Value, 0, int(ftyp.InCount))
- for i, typ := range ftyp.InSlice() {
- if typ.Size() == 0 {
- in = append(in, Zero(toRType(typ)))
- continue
- }
- v := Value{typ, nil, flag(typ.Kind())}
- steps := abid.call.stepsForValue(i)
- if st := steps[0]; st.kind == abiStepStack {
- if ifaceIndir(typ) {
- // value cannot be inlined in interface data.
- // Must make a copy, because f might keep a reference to it,
- // and we cannot let f keep a reference to the stack frame
- // after this function returns, not even a read-only reference.
- v.ptr = unsafe_New(typ)
- if typ.Size() > 0 {
- typedmemmove(typ, v.ptr, add(ptr, st.stkOff, "typ.size > 0"))
- }
- v.flag |= flagIndir
- } else {
- v.ptr = *(*unsafe.Pointer)(add(ptr, st.stkOff, "1-ptr"))
- }
- } else {
- if ifaceIndir(typ) {
- // All that's left is values passed in registers that we need to
- // create space for the values.
- v.flag |= flagIndir
- v.ptr = unsafe_New(typ)
- for _, st := range steps {
- switch st.kind {
- case abiStepIntReg:
- offset := add(v.ptr, st.offset, "precomputed value offset")
- intFromReg(regs, st.ireg, st.size, offset)
- case abiStepPointer:
- s := add(v.ptr, st.offset, "precomputed value offset")
- *((*unsafe.Pointer)(s)) = regs.Ptrs[st.ireg]
- case abiStepFloatReg:
- offset := add(v.ptr, st.offset, "precomputed value offset")
- floatFromReg(regs, st.freg, st.size, offset)
- case abiStepStack:
- panic("register-based return value has stack component")
- default:
- panic("unknown ABI part kind")
- }
- }
- } else {
- // Pointer-valued data gets put directly
- // into v.ptr.
- if steps[0].kind != abiStepPointer {
- print("kind=", steps[0].kind, ", type=", stringFor(typ), "\n")
- panic("mismatch between ABI description and types")
- }
- v.ptr = regs.Ptrs[steps[0].ireg]
- }
- }
- in = append(in, v)
- }
-
- // Call underlying function.
- out := f(in)
- numOut := ftyp.NumOut()
- if len(out) != numOut {
- panic("reflect: wrong return count from function created by MakeFunc")
- }
-
- // Copy results back into argument frame and register space.
- if numOut > 0 {
- for i, typ := range ftyp.OutSlice() {
- v := out[i]
- if v.typ() == nil {
- panic("reflect: function created by MakeFunc using " + funcName(f) +
- " returned zero Value")
- }
- if v.flag&flagRO != 0 {
- panic("reflect: function created by MakeFunc using " + funcName(f) +
- " returned value obtained from unexported field")
- }
- if typ.Size() == 0 {
- continue
- }
-
- // Convert v to type typ if v is assignable to a variable
- // of type t in the language spec.
- // See issue 28761.
- //
- //
- // TODO(mknyszek): In the switch to the register ABI we lost
- // the scratch space here for the register cases (and
- // temporarily for all the cases).
- //
- // If/when this happens, take note of the following:
- //
- // We must clear the destination before calling assignTo,
- // in case assignTo writes (with memory barriers) to the
- // target location used as scratch space. See issue 39541.
- v = v.assignTo("reflect.MakeFunc", typ, nil)
- stepsLoop:
- for _, st := range abid.ret.stepsForValue(i) {
- switch st.kind {
- case abiStepStack:
- // Copy values to the "stack."
- addr := add(ptr, st.stkOff, "precomputed stack arg offset")
- // Do not use write barriers. The stack space used
- // for this call is not adequately zeroed, and we
- // are careful to keep the arguments alive until we
- // return to makeFuncStub's caller.
- if v.flag&flagIndir != 0 {
- memmove(addr, v.ptr, st.size)
- } else {
- // This case must be a pointer type.
- *(*uintptr)(addr) = uintptr(v.ptr)
- }
- // There's only one step for a stack-allocated value.
- break stepsLoop
- case abiStepIntReg, abiStepPointer:
- // Copy values to "integer registers."
- if v.flag&flagIndir != 0 {
- offset := add(v.ptr, st.offset, "precomputed value offset")
- intToReg(regs, st.ireg, st.size, offset)
- } else {
- // Only populate the Ints space on the return path.
- // This is safe because out is kept alive until the
- // end of this function, and the return path through
- // makeFuncStub has no preemption, so these pointers
- // are always visible to the GC.
- regs.Ints[st.ireg] = uintptr(v.ptr)
- }
- case abiStepFloatReg:
- // Copy values to "float registers."
- if v.flag&flagIndir == 0 {
- panic("attempted to copy pointer to FP register")
- }
- offset := add(v.ptr, st.offset, "precomputed value offset")
- floatToReg(regs, st.freg, st.size, offset)
- default:
- panic("unknown ABI part kind")
- }
- }
- }
- }
-
- // Announce that the return values are valid.
- // After this point the runtime can depend on the return values being valid.
- *retValid = true
-
- // We have to make sure that the out slice lives at least until
- // the runtime knows the return values are valid. Otherwise, the
- // return values might not be scanned by anyone during a GC.
- // (out would be dead, and the return slots not yet alive.)
- runtime.KeepAlive(out)
-
- // runtime.getArgInfo expects to be able to find ctxt on the
- // stack when it finds our caller, makeFuncStub. Make sure it
- // doesn't get garbage collected.
- runtime.KeepAlive(ctxt)
-}
-
-// methodReceiver returns information about the receiver
-// described by v. The Value v may or may not have the
-// flagMethod bit set, so the kind cached in v.flag should
-// not be used.
-// The return value rcvrtype gives the method's actual receiver type.
-// The return value t gives the method type signature (without the receiver).
-// The return value fn is a pointer to the method code.
-func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *abi.Type, t *funcType, fn unsafe.Pointer) {
- i := methodIndex
- if v.typ().Kind() == abi.Interface {
- tt := (*interfaceType)(unsafe.Pointer(v.typ()))
- if uint(i) >= uint(len(tt.Methods)) {
- panic("reflect: internal error: invalid method index")
- }
- m := &tt.Methods[i]
- if !tt.nameOff(m.Name).IsExported() {
- panic("reflect: " + op + " of unexported method")
- }
- iface := (*nonEmptyInterface)(v.ptr)
- if iface.itab == nil {
- panic("reflect: " + op + " of method on nil interface value")
- }
- rcvrtype = iface.itab.typ
- fn = unsafe.Pointer(&iface.itab.fun[i])
- t = (*funcType)(unsafe.Pointer(tt.typeOff(m.Typ)))
- } else {
- rcvrtype = v.typ()
- ms := v.typ().ExportedMethods()
- if uint(i) >= uint(len(ms)) {
- panic("reflect: internal error: invalid method index")
- }
- m := ms[i]
- if !nameOffFor(v.typ(), m.Name).IsExported() {
- panic("reflect: " + op + " of unexported method")
- }
- ifn := textOffFor(v.typ(), m.Ifn)
- fn = unsafe.Pointer(&ifn)
- t = (*funcType)(unsafe.Pointer(typeOffFor(v.typ(), m.Mtyp)))
- }
- return
-}
-
-// v is a method receiver. Store at p the word which is used to
-// encode that receiver at the start of the argument list.
-// Reflect uses the "interface" calling convention for
-// methods, which always uses one word to record the receiver.
-func storeRcvr(v Value, p unsafe.Pointer) {
- t := v.typ()
- if t.Kind() == abi.Interface {
- // the interface data word becomes the receiver word
- iface := (*nonEmptyInterface)(v.ptr)
- *(*unsafe.Pointer)(p) = iface.word
- } else if v.flag&flagIndir != 0 && !ifaceIndir(t) {
- *(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
- } else {
- *(*unsafe.Pointer)(p) = v.ptr
- }
-}
-
-// align returns the result of rounding x up to a multiple of n.
-// n must be a power of two.
-func align(x, n uintptr) uintptr {
- return (x + n - 1) &^ (n - 1)
-}
-
-// callMethod is the call implementation used by a function returned
-// by makeMethodValue (used by v.Method(i).Interface()).
-// It is a streamlined version of the usual reflect call: the caller has
-// already laid out the argument frame for us, so we don't have
-// to deal with individual Values for each argument.
-// It is in this file so that it can be next to the two similar functions above.
-// The remainder of the makeMethodValue implementation is in makefunc.go.
-//
-// NOTE: This function must be marked as a "wrapper" in the generated code,
-// so that the linker can make it work correctly for panic and recover.
-// The gc compilers know to do that for the name "reflect.callMethod".
-//
-// ctxt is the "closure" generated by makeVethodValue.
-// frame is a pointer to the arguments to that closure on the stack.
-// retValid points to a boolean which should be set when the results
-// section of frame is set.
-//
-// regs contains the argument values passed in registers and will contain
-// the values returned from ctxt.fn in registers.
-func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *abi.RegArgs) {
- rcvr := ctxt.rcvr
- rcvrType, valueFuncType, methodFn := methodReceiver("call", rcvr, ctxt.method)
-
- // There are two ABIs at play here.
- //
- // methodValueCall was invoked with the ABI assuming there was no
- // receiver ("value ABI") and that's what frame and regs are holding.
- //
- // Meanwhile, we need to actually call the method with a receiver, which
- // has its own ABI ("method ABI"). Everything that follows is a translation
- // between the two.
- _, _, valueABI := funcLayout(valueFuncType, nil)
- valueFrame, valueRegs := frame, regs
- methodFrameType, methodFramePool, methodABI := funcLayout(valueFuncType, rcvrType)
-
- // Make a new frame that is one word bigger so we can store the receiver.
- // This space is used for both arguments and return values.
- methodFrame := methodFramePool.Get().(unsafe.Pointer)
- var methodRegs abi.RegArgs
-
- // Deal with the receiver. It's guaranteed to only be one word in size.
- switch st := methodABI.call.steps[0]; st.kind {
- case abiStepStack:
- // Only copy the receiver to the stack if the ABI says so.
- // Otherwise, it'll be in a register already.
- storeRcvr(rcvr, methodFrame)
- case abiStepPointer:
- // Put the receiver in a register.
- storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Ptrs[st.ireg]))
- fallthrough
- case abiStepIntReg:
- storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Ints[st.ireg]))
- case abiStepFloatReg:
- storeRcvr(rcvr, unsafe.Pointer(&methodRegs.Floats[st.freg]))
- default:
- panic("unknown ABI parameter kind")
- }
-
- // Translate the rest of the arguments.
- for i, t := range valueFuncType.InSlice() {
- valueSteps := valueABI.call.stepsForValue(i)
- methodSteps := methodABI.call.stepsForValue(i + 1)
-
- // Zero-sized types are trivial: nothing to do.
- if len(valueSteps) == 0 {
- if len(methodSteps) != 0 {
- panic("method ABI and value ABI do not align")
- }
- continue
- }
-
- // There are four cases to handle in translating each
- // argument:
- // 1. Stack -> stack translation.
- // 2. Stack -> registers translation.
- // 3. Registers -> stack translation.
- // 4. Registers -> registers translation.
-
- // If the value ABI passes the value on the stack,
- // then the method ABI does too, because it has strictly
- // fewer arguments. Simply copy between the two.
- if vStep := valueSteps[0]; vStep.kind == abiStepStack {
- mStep := methodSteps[0]
- // Handle stack -> stack translation.
- if mStep.kind == abiStepStack {
- if vStep.size != mStep.size {
- panic("method ABI and value ABI do not align")
- }
- typedmemmove(t,
- add(methodFrame, mStep.stkOff, "precomputed stack offset"),
- add(valueFrame, vStep.stkOff, "precomputed stack offset"))
- continue
- }
- // Handle stack -> register translation.
- for _, mStep := range methodSteps {
- from := add(valueFrame, vStep.stkOff+mStep.offset, "precomputed stack offset")
- switch mStep.kind {
- case abiStepPointer:
- // Do the pointer copy directly so we get a write barrier.
- methodRegs.Ptrs[mStep.ireg] = *(*unsafe.Pointer)(from)
- fallthrough // We need to make sure this ends up in Ints, too.
- case abiStepIntReg:
- intToReg(&methodRegs, mStep.ireg, mStep.size, from)
- case abiStepFloatReg:
- floatToReg(&methodRegs, mStep.freg, mStep.size, from)
- default:
- panic("unexpected method step")
- }
- }
- continue
- }
- // Handle register -> stack translation.
- if mStep := methodSteps[0]; mStep.kind == abiStepStack {
- for _, vStep := range valueSteps {
- to := add(methodFrame, mStep.stkOff+vStep.offset, "precomputed stack offset")
- switch vStep.kind {
- case abiStepPointer:
- // Do the pointer copy directly so we get a write barrier.
- *(*unsafe.Pointer)(to) = valueRegs.Ptrs[vStep.ireg]
- case abiStepIntReg:
- intFromReg(valueRegs, vStep.ireg, vStep.size, to)
- case abiStepFloatReg:
- floatFromReg(valueRegs, vStep.freg, vStep.size, to)
- default:
- panic("unexpected value step")
- }
- }
- continue
- }
- // Handle register -> register translation.
- if len(valueSteps) != len(methodSteps) {
- // Because it's the same type for the value, and it's assigned
- // to registers both times, it should always take up the same
- // number of registers for each ABI.
- panic("method ABI and value ABI don't align")
- }
- for i, vStep := range valueSteps {
- mStep := methodSteps[i]
- if mStep.kind != vStep.kind {
- panic("method ABI and value ABI don't align")
- }
- switch vStep.kind {
- case abiStepPointer:
- // Copy this too, so we get a write barrier.
- methodRegs.Ptrs[mStep.ireg] = valueRegs.Ptrs[vStep.ireg]
- fallthrough
- case abiStepIntReg:
- methodRegs.Ints[mStep.ireg] = valueRegs.Ints[vStep.ireg]
- case abiStepFloatReg:
- methodRegs.Floats[mStep.freg] = valueRegs.Floats[vStep.freg]
- default:
- panic("unexpected value step")
- }
- }
- }
-
- methodFrameSize := methodFrameType.Size()
- // TODO(mknyszek): Remove this when we no longer have
- // caller reserved spill space.
- methodFrameSize = align(methodFrameSize, goarch.PtrSize)
- methodFrameSize += methodABI.spill
-
- // Mark pointers in registers for the return path.
- methodRegs.ReturnIsPtr = methodABI.outRegPtrs
-
- // Call.
- // Call copies the arguments from scratch to the stack, calls fn,
- // and then copies the results back into scratch.
- call(methodFrameType, methodFn, methodFrame, uint32(methodFrameType.Size()), uint32(methodABI.retOffset), uint32(methodFrameSize), &methodRegs)
-
- // Copy return values.
- //
- // This is somewhat simpler because both ABIs have an identical
- // return value ABI (the types are identical). As a result, register
- // results can simply be copied over. Stack-allocated values are laid
- // out the same, but are at different offsets from the start of the frame
- // Ignore any changes to args.
- // Avoid constructing out-of-bounds pointers if there are no return values.
- // because the arguments may be laid out differently.
- if valueRegs != nil {
- *valueRegs = methodRegs
- }
- if retSize := methodFrameType.Size() - methodABI.retOffset; retSize > 0 {
- valueRet := add(valueFrame, valueABI.retOffset, "valueFrame's size > retOffset")
- methodRet := add(methodFrame, methodABI.retOffset, "methodFrame's size > retOffset")
- // This copies to the stack. Write barriers are not needed.
- memmove(valueRet, methodRet, retSize)
- }
-
- // Tell the runtime it can now depend on the return values
- // being properly initialized.
- *retValid = true
-
- // Clear the scratch space and put it back in the pool.
- // This must happen after the statement above, so that the return
- // values will always be scanned by someone.
- typedmemclr(methodFrameType, methodFrame)
- methodFramePool.Put(methodFrame)
-
- // See the comment in callReflect.
- runtime.KeepAlive(ctxt)
-
- // Keep valueRegs alive because it may hold live pointer results.
- // The caller (methodValueCall) has it as a stack object, which is only
- // scanned when there is a reference to it.
- runtime.KeepAlive(valueRegs)
-}
-
-// funcName returns the name of f, for use in error messages.
-func funcName(f func([]Value) []Value) string {
- pc := *(*uintptr)(unsafe.Pointer(&f))
- rf := runtime.FuncForPC(pc)
- if rf != nil {
- return rf.Name()
- }
- return "closure"
-}
-
-// Cap returns v's capacity.
-// It panics if v's Kind is not [Array], [Chan], [Slice] or pointer to [Array].
-func (v Value) Cap() int {
- // capNonSlice is split out to keep Cap inlineable for slice kinds.
- if v.kind() == Slice {
- return (*unsafeheader.Slice)(v.ptr).Cap
- }
- return v.capNonSlice()
-}
-
-func (v Value) capNonSlice() int {
- k := v.kind()
- switch k {
- case Array:
- return v.typ().Len()
- case Chan:
- return chancap(v.pointer())
- case Ptr:
- if v.typ().Elem().Kind() == abi.Array {
- return v.typ().Elem().Len()
- }
- panic("reflect: call of reflect.Value.Cap on ptr to non-array Value")
- }
- panic(&ValueError{"reflect.Value.Cap", v.kind()})
-}
-
-// Close closes the channel v.
-// It panics if v's Kind is not [Chan] or
-// v is a receive-only channel.
-func (v Value) Close() {
- v.mustBe(Chan)
- v.mustBeExported()
- tt := (*chanType)(unsafe.Pointer(v.typ()))
- if ChanDir(tt.Dir)&SendDir == 0 {
- panic("reflect: close of receive-only channel")
- }
-
- chanclose(v.pointer())
-}
-
-// CanComplex reports whether [Value.Complex] can be used without panicking.
-func (v Value) CanComplex() bool {
- switch v.kind() {
- case Complex64, Complex128:
- return true
- default:
- return false
- }
-}
-
-// Complex returns v's underlying value, as a complex128.
-// It panics if v's Kind is not [Complex64] or [Complex128]
-func (v Value) Complex() complex128 {
- k := v.kind()
- switch k {
- case Complex64:
- return complex128(*(*complex64)(v.ptr))
- case Complex128:
- return *(*complex128)(v.ptr)
- }
- panic(&ValueError{"reflect.Value.Complex", v.kind()})
-}
-
-// Elem returns the value that the interface v contains
-// or that the pointer v points to.
-// It panics if v's Kind is not [Interface] or [Pointer].
-// It returns the zero Value if v is nil.
-func (v Value) Elem() Value {
- k := v.kind()
- switch k {
- case Interface:
- var eface any
- if v.typ().NumMethod() == 0 {
- eface = *(*any)(v.ptr)
- } else {
- eface = (any)(*(*interface {
- M()
- })(v.ptr))
- }
- x := unpackEface(eface)
- if x.flag != 0 {
- x.flag |= v.flag.ro()
- }
- return x
- case Pointer:
- ptr := v.ptr
- if v.flag&flagIndir != 0 {
- if ifaceIndir(v.typ()) {
- // This is a pointer to a not-in-heap object. ptr points to a uintptr
- // in the heap. That uintptr is the address of a not-in-heap object.
- // In general, pointers to not-in-heap objects can be total junk.
- // But Elem() is asking to dereference it, so the user has asserted
- // that at least it is a valid pointer (not just an integer stored in
- // a pointer slot). So let's check, to make sure that it isn't a pointer
- // that the runtime will crash on if it sees it during GC or write barriers.
- // Since it is a not-in-heap pointer, all pointers to the heap are
- // forbidden! That makes the test pretty easy.
- // See issue 48399.
- if !verifyNotInHeapPtr(*(*uintptr)(ptr)) {
- panic("reflect: reflect.Value.Elem on an invalid notinheap pointer")
- }
- }
- ptr = *(*unsafe.Pointer)(ptr)
- }
- // The returned value's address is v's value.
- if ptr == nil {
- return Value{}
- }
- tt := (*ptrType)(unsafe.Pointer(v.typ()))
- typ := tt.Elem
- fl := v.flag&flagRO | flagIndir | flagAddr
- fl |= flag(typ.Kind())
- return Value{typ, ptr, fl}
- }
- panic(&ValueError{"reflect.Value.Elem", v.kind()})
-}
-
-// Field returns the i'th field of the struct v.
-// It panics if v's Kind is not [Struct] or i is out of range.
-func (v Value) Field(i int) Value {
- if v.kind() != Struct {
- panic(&ValueError{"reflect.Value.Field", v.kind()})
- }
- tt := (*structType)(unsafe.Pointer(v.typ()))
- if uint(i) >= uint(len(tt.Fields)) {
- panic("reflect: Field index out of range")
- }
- field := &tt.Fields[i]
- typ := field.Typ
-
- // Inherit permission bits from v, but clear flagEmbedRO.
- fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
- // Using an unexported field forces flagRO.
- if !field.Name.IsExported() {
- if field.Embedded() {
- fl |= flagEmbedRO
- } else {
- fl |= flagStickyRO
- }
- }
- // Either flagIndir is set and v.ptr points at struct,
- // or flagIndir is not set and v.ptr is the actual struct data.
- // In the former case, we want v.ptr + offset.
- // In the latter case, we must have field.offset = 0,
- // so v.ptr + field.offset is still the correct address.
- ptr := add(v.ptr, field.Offset, "same as non-reflect &v.field")
- return Value{typ, ptr, fl}
-}
-
-// FieldByIndex returns the nested field corresponding to index.
-// It panics if evaluation requires stepping through a nil
-// pointer or a field that is not a struct.
-func (v Value) FieldByIndex(index []int) Value {
- if len(index) == 1 {
- return v.Field(index[0])
- }
- v.mustBe(Struct)
- for i, x := range index {
- if i > 0 {
- if v.Kind() == Pointer && v.typ().Elem().Kind() == abi.Struct {
- if v.IsNil() {
- panic("reflect: indirection through nil pointer to embedded struct")
- }
- v = v.Elem()
- }
- }
- v = v.Field(x)
- }
- return v
-}
-
-// FieldByIndexErr returns the nested field corresponding to index.
-// It returns an error if evaluation requires stepping through a nil
-// pointer, but panics if it must step through a field that
-// is not a struct.
-func (v Value) FieldByIndexErr(index []int) (Value, error) {
- if len(index) == 1 {
- return v.Field(index[0]), nil
- }
- v.mustBe(Struct)
- for i, x := range index {
- if i > 0 {
- if v.Kind() == Ptr && v.typ().Elem().Kind() == abi.Struct {
- if v.IsNil() {
- return Value{}, errors.New("reflect: indirection through nil pointer to embedded struct field " + nameFor(v.typ().Elem()))
- }
- v = v.Elem()
- }
- }
- v = v.Field(x)
- }
- return v, nil
-}
-
-// FieldByName returns the struct field with the given name.
-// It returns the zero Value if no field was found.
-// It panics if v's Kind is not [Struct].
-func (v Value) FieldByName(name string) Value {
- v.mustBe(Struct)
- if f, ok := toRType(v.typ()).FieldByName(name); ok {
- return v.FieldByIndex(f.Index)
- }
- return Value{}
-}
-
-// FieldByNameFunc returns the struct field with a name
-// that satisfies the match function.
-// It panics if v's Kind is not [Struct].
-// It returns the zero Value if no field was found.
-func (v Value) FieldByNameFunc(match func(string) bool) Value {
- if f, ok := toRType(v.typ()).FieldByNameFunc(match); ok {
- return v.FieldByIndex(f.Index)
- }
- return Value{}
-}
-
-// CanFloat reports whether [Value.Float] can be used without panicking.
-func (v Value) CanFloat() bool {
- switch v.kind() {
- case Float32, Float64:
- return true
- default:
- return false
- }
-}
-
-// Float returns v's underlying value, as a float64.
-// It panics if v's Kind is not [Float32] or [Float64]
-func (v Value) Float() float64 {
- k := v.kind()
- switch k {
- case Float32:
- return float64(*(*float32)(v.ptr))
- case Float64:
- return *(*float64)(v.ptr)
- }
- panic(&ValueError{"reflect.Value.Float", v.kind()})
-}
-
-var uint8Type = rtypeOf(uint8(0))
-
-// Index returns v's i'th element.
-// It panics if v's Kind is not [Array], [Slice], or [String] or i is out of range.
-func (v Value) Index(i int) Value {
- switch v.kind() {
- case Array:
- tt := (*arrayType)(unsafe.Pointer(v.typ()))
- if uint(i) >= uint(tt.Len) {
- panic("reflect: array index out of range")
- }
- typ := tt.Elem
- offset := uintptr(i) * typ.Size()
-
- // Either flagIndir is set and v.ptr points at array,
- // or flagIndir is not set and v.ptr is the actual array data.
- // In the former case, we want v.ptr + offset.
- // In the latter case, we must be doing Index(0), so offset = 0,
- // so v.ptr + offset is still the correct address.
- val := add(v.ptr, offset, "same as &v[i], i < tt.len")
- fl := v.flag&(flagIndir|flagAddr) | v.flag.ro() | flag(typ.Kind()) // bits same as overall array
- return Value{typ, val, fl}
-
- case Slice:
- // Element flag same as Elem of Pointer.
- // Addressable, indirect, possibly read-only.
- s := (*unsafeheader.Slice)(v.ptr)
- if uint(i) >= uint(s.Len) {
- panic("reflect: slice index out of range")
- }
- tt := (*sliceType)(unsafe.Pointer(v.typ()))
- typ := tt.Elem
- val := arrayAt(s.Data, i, typ.Size(), "i < s.Len")
- fl := flagAddr | flagIndir | v.flag.ro() | flag(typ.Kind())
- return Value{typ, val, fl}
-
- case String:
- s := (*unsafeheader.String)(v.ptr)
- if uint(i) >= uint(s.Len) {
- panic("reflect: string index out of range")
- }
- p := arrayAt(s.Data, i, 1, "i < s.Len")
- fl := v.flag.ro() | flag(Uint8) | flagIndir
- return Value{uint8Type, p, fl}
- }
- panic(&ValueError{"reflect.Value.Index", v.kind()})
-}
-
-// CanInt reports whether Int can be used without panicking.
-func (v Value) CanInt() bool {
- switch v.kind() {
- case Int, Int8, Int16, Int32, Int64:
- return true
- default:
- return false
- }
-}
-
-// Int returns v's underlying value, as an int64.
-// It panics if v's Kind is not [Int], [Int8], [Int16], [Int32], or [Int64].
-func (v Value) Int() int64 {
- k := v.kind()
- p := v.ptr
- switch k {
- case Int:
- return int64(*(*int)(p))
- case Int8:
- return int64(*(*int8)(p))
- case Int16:
- return int64(*(*int16)(p))
- case Int32:
- return int64(*(*int32)(p))
- case Int64:
- return *(*int64)(p)
- }
- panic(&ValueError{"reflect.Value.Int", v.kind()})
-}
-
-// CanInterface reports whether [Value.Interface] can be used without panicking.
-func (v Value) CanInterface() bool {
- if v.flag == 0 {
- panic(&ValueError{"reflect.Value.CanInterface", Invalid})
- }
- return v.flag&flagRO == 0
-}
-
-// Interface returns v's current value as an interface{}.
-// It is equivalent to:
-//
-// var i interface{} = (v's underlying value)
-//
-// It panics if the Value was obtained by accessing
-// unexported struct fields.
-func (v Value) Interface() (i any) {
- return valueInterface(v, true)
-}
-
-func valueInterface(v Value, safe bool) any {
- if v.flag == 0 {
- panic(&ValueError{"reflect.Value.Interface", Invalid})
- }
- if safe && v.flag&flagRO != 0 {
- // Do not allow access to unexported values via Interface,
- // because they might be pointers that should not be
- // writable or methods or function that should not be callable.
- panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
- }
- if v.flag&flagMethod != 0 {
- v = makeMethodValue("Interface", v)
- }
-
- if v.kind() == Interface {
- // Special case: return the element inside the interface.
- // Empty interface has one layout, all interfaces with
- // methods have a second layout.
- if v.NumMethod() == 0 {
- return *(*any)(v.ptr)
- }
- return *(*interface {
- M()
- })(v.ptr)
- }
-
- // TODO: pass safe to packEface so we don't need to copy if safe==true?
- return packEface(v)
-}
-
-// InterfaceData returns a pair of unspecified uintptr values.
-// It panics if v's Kind is not Interface.
-//
-// In earlier versions of Go, this function returned the interface's
-// value as a uintptr pair. As of Go 1.4, the implementation of
-// interface values precludes any defined use of InterfaceData.
-//
-// Deprecated: The memory representation of interface values is not
-// compatible with InterfaceData.
-func (v Value) InterfaceData() [2]uintptr {
- v.mustBe(Interface)
- // The compiler loses track as it converts to uintptr. Force escape.
- escapes(v.ptr)
- // We treat this as a read operation, so we allow
- // it even for unexported data, because the caller
- // has to import "unsafe" to turn it into something
- // that can be abused.
- // Interface value is always bigger than a word; assume flagIndir.
- return *(*[2]uintptr)(v.ptr)
-}
-
-// IsNil reports whether its argument v is nil. The argument must be
-// a chan, func, interface, map, pointer, or slice value; if it is
-// not, IsNil panics. Note that IsNil is not always equivalent to a
-// regular comparison with nil in Go. For example, if v was created
-// by calling ValueOf with an uninitialized interface variable i,
-// i==nil will be true but v.IsNil will panic as v will be the zero
-// Value.
-func (v Value) IsNil() bool {
- k := v.kind()
- switch k {
- case Chan, Func, Map, Pointer, UnsafePointer:
- if v.flag&flagMethod != 0 {
- return false
- }
- ptr := v.ptr
- if v.flag&flagIndir != 0 {
- ptr = *(*unsafe.Pointer)(ptr)
- }
- return ptr == nil
- case Interface, Slice:
- // Both interface and slice are nil if first word is 0.
- // Both are always bigger than a word; assume flagIndir.
- return *(*unsafe.Pointer)(v.ptr) == nil
- }
- panic(&ValueError{"reflect.Value.IsNil", v.kind()})
-}
-
-// IsValid reports whether v represents a value.
-// It returns false if v is the zero Value.
-// If IsValid returns false, all other methods except String panic.
-// Most functions and methods never return an invalid Value.
-// If one does, its documentation states the conditions explicitly.
-func (v Value) IsValid() bool {
- return v.flag != 0
-}
-
-// IsZero reports whether v is the zero value for its type.
-// It panics if the argument is invalid.
-func (v Value) IsZero() bool {
- switch v.kind() {
- case Bool:
- return !v.Bool()
- case Int, Int8, Int16, Int32, Int64:
- return v.Int() == 0
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return v.Uint() == 0
- case Float32, Float64:
- return v.Float() == 0
- case Complex64, Complex128:
- return v.Complex() == 0
- case Array:
- if v.flag&flagIndir == 0 {
- return v.ptr == nil
- }
- typ := (*abi.ArrayType)(unsafe.Pointer(v.typ()))
- // If the type is comparable, then compare directly with zero.
- if typ.Equal != nil && typ.Size() <= abi.ZeroValSize {
- // v.ptr doesn't escape, as Equal functions are compiler generated
- // and never escape. The escape analysis doesn't know, as it is a
- // function pointer call.
- return typ.Equal(noescape(v.ptr), unsafe.Pointer(&zeroVal[0]))
- }
- if typ.TFlag&abi.TFlagRegularMemory != 0 {
- // For some types where the zero value is a value where all bits of this type are 0
- // optimize it.
- return isZero(unsafe.Slice(((*byte)(v.ptr)), typ.Size()))
- }
- n := int(typ.Len)
- for i := 0; i < n; i++ {
- if !v.Index(i).IsZero() {
- return false
- }
- }
- return true
- case Chan, Func, Interface, Map, Pointer, Slice, UnsafePointer:
- return v.IsNil()
- case String:
- return v.Len() == 0
- case Struct:
- if v.flag&flagIndir == 0 {
- return v.ptr == nil
- }
- typ := (*abi.StructType)(unsafe.Pointer(v.typ()))
- // If the type is comparable, then compare directly with zero.
- if typ.Equal != nil && typ.Size() <= abi.ZeroValSize {
- // See noescape justification above.
- return typ.Equal(noescape(v.ptr), unsafe.Pointer(&zeroVal[0]))
- }
- if typ.TFlag&abi.TFlagRegularMemory != 0 {
- // For some types where the zero value is a value where all bits of this type are 0
- // optimize it.
- return isZero(unsafe.Slice(((*byte)(v.ptr)), typ.Size()))
- }
-
- n := v.NumField()
- for i := 0; i < n; i++ {
- if !v.Field(i).IsZero() && v.Type().Field(i).Name != "_" {
- return false
- }
- }
- return true
- default:
- // This should never happen, but will act as a safeguard for later,
- // as a default value doesn't makes sense here.
- panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
- }
-}
-
-// isZero For all zeros, performance is not as good as
-// return bytealg.Count(b, byte(0)) == len(b)
-func isZero(b []byte) bool {
- if len(b) == 0 {
- return true
- }
- const n = 32
- // Align memory addresses to 8 bytes.
- for uintptr(unsafe.Pointer(&b[0]))%8 != 0 {
- if b[0] != 0 {
- return false
- }
- b = b[1:]
- if len(b) == 0 {
- return true
- }
- }
- for len(b)%8 != 0 {
- if b[len(b)-1] != 0 {
- return false
- }
- b = b[:len(b)-1]
- }
- if len(b) == 0 {
- return true
- }
- w := unsafe.Slice((*uint64)(unsafe.Pointer(&b[0])), len(b)/8)
- for len(w)%n != 0 {
- if w[0] != 0 {
- return false
- }
- w = w[1:]
- }
- for len(w) >= n {
- if w[0] != 0 || w[1] != 0 || w[2] != 0 || w[3] != 0 ||
- w[4] != 0 || w[5] != 0 || w[6] != 0 || w[7] != 0 ||
- w[8] != 0 || w[9] != 0 || w[10] != 0 || w[11] != 0 ||
- w[12] != 0 || w[13] != 0 || w[14] != 0 || w[15] != 0 ||
- w[16] != 0 || w[17] != 0 || w[18] != 0 || w[19] != 0 ||
- w[20] != 0 || w[21] != 0 || w[22] != 0 || w[23] != 0 ||
- w[24] != 0 || w[25] != 0 || w[26] != 0 || w[27] != 0 ||
- w[28] != 0 || w[29] != 0 || w[30] != 0 || w[31] != 0 {
- return false
- }
- w = w[n:]
- }
- return true
-}
-
-// SetZero sets v to be the zero value of v's type.
-// It panics if [Value.CanSet] returns false.
-func (v Value) SetZero() {
- v.mustBeAssignable()
- switch v.kind() {
- case Bool:
- *(*bool)(v.ptr) = false
- case Int:
- *(*int)(v.ptr) = 0
- case Int8:
- *(*int8)(v.ptr) = 0
- case Int16:
- *(*int16)(v.ptr) = 0
- case Int32:
- *(*int32)(v.ptr) = 0
- case Int64:
- *(*int64)(v.ptr) = 0
- case Uint:
- *(*uint)(v.ptr) = 0
- case Uint8:
- *(*uint8)(v.ptr) = 0
- case Uint16:
- *(*uint16)(v.ptr) = 0
- case Uint32:
- *(*uint32)(v.ptr) = 0
- case Uint64:
- *(*uint64)(v.ptr) = 0
- case Uintptr:
- *(*uintptr)(v.ptr) = 0
- case Float32:
- *(*float32)(v.ptr) = 0
- case Float64:
- *(*float64)(v.ptr) = 0
- case Complex64:
- *(*complex64)(v.ptr) = 0
- case Complex128:
- *(*complex128)(v.ptr) = 0
- case String:
- *(*string)(v.ptr) = ""
- case Slice:
- *(*unsafeheader.Slice)(v.ptr) = unsafeheader.Slice{}
- case Interface:
- *(*emptyInterface)(v.ptr) = emptyInterface{}
- case Chan, Func, Map, Pointer, UnsafePointer:
- *(*unsafe.Pointer)(v.ptr) = nil
- case Array, Struct:
- typedmemclr(v.typ(), v.ptr)
- default:
- // This should never happen, but will act as a safeguard for later,
- // as a default value doesn't makes sense here.
- panic(&ValueError{"reflect.Value.SetZero", v.Kind()})
- }
-}
-
-// Kind returns v's Kind.
-// If v is the zero Value ([Value.IsValid] returns false), Kind returns Invalid.
-func (v Value) Kind() Kind {
- return v.kind()
-}
-
-// Len returns v's length.
-// It panics if v's Kind is not [Array], [Chan], [Map], [Slice], [String], or pointer to [Array].
-func (v Value) Len() int {
- // lenNonSlice is split out to keep Len inlineable for slice kinds.
- if v.kind() == Slice {
- return (*unsafeheader.Slice)(v.ptr).Len
- }
- return v.lenNonSlice()
-}
-
-func (v Value) lenNonSlice() int {
- switch k := v.kind(); k {
- case Array:
- tt := (*arrayType)(unsafe.Pointer(v.typ()))
- return int(tt.Len)
- case Chan:
- return chanlen(v.pointer())
- case Map:
- return maplen(v.pointer())
- case String:
- // String is bigger than a word; assume flagIndir.
- return (*unsafeheader.String)(v.ptr).Len
- case Ptr:
- if v.typ().Elem().Kind() == abi.Array {
- return v.typ().Elem().Len()
- }
- panic("reflect: call of reflect.Value.Len on ptr to non-array Value")
- }
- panic(&ValueError{"reflect.Value.Len", v.kind()})
-}
-
-var stringType = rtypeOf("")
-
-// MapIndex returns the value associated with key in the map v.
-// It panics if v's Kind is not [Map].
-// It returns the zero Value if key is not found in the map or if v represents a nil map.
-// As in Go, the key's value must be assignable to the map's key type.
-func (v Value) MapIndex(key Value) Value {
- v.mustBe(Map)
- tt := (*mapType)(unsafe.Pointer(v.typ()))
-
- // Do not require key to be exported, so that DeepEqual
- // and other programs can use all the keys returned by
- // MapKeys as arguments to MapIndex. If either the map
- // or the key is unexported, though, the result will be
- // considered unexported. This is consistent with the
- // behavior for structs, which allow read but not write
- // of unexported fields.
-
- var e unsafe.Pointer
- if (tt.Key == stringType || key.kind() == String) && tt.Key == key.typ() && tt.Elem.Size() <= maxValSize {
- k := *(*string)(key.ptr)
- e = mapaccess_faststr(v.typ(), v.pointer(), k)
- } else {
- key = key.assignTo("reflect.Value.MapIndex", tt.Key, nil)
- var k unsafe.Pointer
- if key.flag&flagIndir != 0 {
- k = key.ptr
- } else {
- k = unsafe.Pointer(&key.ptr)
- }
- e = mapaccess(v.typ(), v.pointer(), k)
- }
- if e == nil {
- return Value{}
- }
- typ := tt.Elem
- fl := (v.flag | key.flag).ro()
- fl |= flag(typ.Kind())
- return copyVal(typ, fl, e)
-}
-
-// MapKeys returns a slice containing all the keys present in the map,
-// in unspecified order.
-// It panics if v's Kind is not [Map].
-// It returns an empty slice if v represents a nil map.
-func (v Value) MapKeys() []Value {
- v.mustBe(Map)
- tt := (*mapType)(unsafe.Pointer(v.typ()))
- keyType := tt.Key
-
- fl := v.flag.ro() | flag(keyType.Kind())
-
- m := v.pointer()
- mlen := int(0)
- if m != nil {
- mlen = maplen(m)
- }
- var it hiter
- mapiterinit(v.typ(), m, &it)
- a := make([]Value, mlen)
- var i int
- for i = 0; i < len(a); i++ {
- key := mapiterkey(&it)
- if key == nil {
- // Someone deleted an entry from the map since we
- // called maplen above. It's a data race, but nothing
- // we can do about it.
- break
- }
- a[i] = copyVal(keyType, fl, key)
- mapiternext(&it)
- }
- return a[:i]
-}
-
-// hiter's structure matches runtime.hiter's structure.
-// Having a clone here allows us to embed a map iterator
-// inside type MapIter so that MapIters can be re-used
-// without doing any allocations.
-type hiter struct {
- key unsafe.Pointer
- elem unsafe.Pointer
- t unsafe.Pointer
- h unsafe.Pointer
- buckets unsafe.Pointer
- bptr unsafe.Pointer
- overflow *[]unsafe.Pointer
- oldoverflow *[]unsafe.Pointer
- startBucket uintptr
- offset uint8
- wrapped bool
- B uint8
- i uint8
- bucket uintptr
- checkBucket uintptr
-}
-
-func (h *hiter) initialized() bool {
- return h.t != nil
-}
-
-// A MapIter is an iterator for ranging over a map.
-// See [Value.MapRange].
-type MapIter struct {
- m Value
- hiter hiter
-}
-
-// Key returns the key of iter's current map entry.
-func (iter *MapIter) Key() Value {
- if !iter.hiter.initialized() {
- panic("MapIter.Key called before Next")
- }
- iterkey := mapiterkey(&iter.hiter)
- if iterkey == nil {
- panic("MapIter.Key called on exhausted iterator")
- }
-
- t := (*mapType)(unsafe.Pointer(iter.m.typ()))
- ktype := t.Key
- return copyVal(ktype, iter.m.flag.ro()|flag(ktype.Kind()), iterkey)
-}
-
-// SetIterKey assigns to v the key of iter's current map entry.
-// It is equivalent to v.Set(iter.Key()), but it avoids allocating a new Value.
-// As in Go, the key must be assignable to v's type and
-// must not be derived from an unexported field.
-func (v Value) SetIterKey(iter *MapIter) {
- if !iter.hiter.initialized() {
- panic("reflect: Value.SetIterKey called before Next")
- }
- iterkey := mapiterkey(&iter.hiter)
- if iterkey == nil {
- panic("reflect: Value.SetIterKey called on exhausted iterator")
- }
-
- v.mustBeAssignable()
- var target unsafe.Pointer
- if v.kind() == Interface {
- target = v.ptr
- }
-
- t := (*mapType)(unsafe.Pointer(iter.m.typ()))
- ktype := t.Key
-
- iter.m.mustBeExported() // do not let unexported m leak
- key := Value{ktype, iterkey, iter.m.flag | flag(ktype.Kind()) | flagIndir}
- key = key.assignTo("reflect.MapIter.SetKey", v.typ(), target)
- typedmemmove(v.typ(), v.ptr, key.ptr)
-}
-
-// Value returns the value of iter's current map entry.
-func (iter *MapIter) Value() Value {
- if !iter.hiter.initialized() {
- panic("MapIter.Value called before Next")
- }
- iterelem := mapiterelem(&iter.hiter)
- if iterelem == nil {
- panic("MapIter.Value called on exhausted iterator")
- }
-
- t := (*mapType)(unsafe.Pointer(iter.m.typ()))
- vtype := t.Elem
- return copyVal(vtype, iter.m.flag.ro()|flag(vtype.Kind()), iterelem)
-}
-
-// SetIterValue assigns to v the value of iter's current map entry.
-// It is equivalent to v.Set(iter.Value()), but it avoids allocating a new Value.
-// As in Go, the value must be assignable to v's type and
-// must not be derived from an unexported field.
-func (v Value) SetIterValue(iter *MapIter) {
- if !iter.hiter.initialized() {
- panic("reflect: Value.SetIterValue called before Next")
- }
- iterelem := mapiterelem(&iter.hiter)
- if iterelem == nil {
- panic("reflect: Value.SetIterValue called on exhausted iterator")
- }
-
- v.mustBeAssignable()
- var target unsafe.Pointer
- if v.kind() == Interface {
- target = v.ptr
- }
-
- t := (*mapType)(unsafe.Pointer(iter.m.typ()))
- vtype := t.Elem
-
- iter.m.mustBeExported() // do not let unexported m leak
- elem := Value{vtype, iterelem, iter.m.flag | flag(vtype.Kind()) | flagIndir}
- elem = elem.assignTo("reflect.MapIter.SetValue", v.typ(), target)
- typedmemmove(v.typ(), v.ptr, elem.ptr)
-}
-
-// Next advances the map iterator and reports whether there is another
-// entry. It returns false when iter is exhausted; subsequent
-// calls to [MapIter.Key], [MapIter.Value], or [MapIter.Next] will panic.
-func (iter *MapIter) Next() bool {
- if !iter.m.IsValid() {
- panic("MapIter.Next called on an iterator that does not have an associated map Value")
- }
- if !iter.hiter.initialized() {
- mapiterinit(iter.m.typ(), iter.m.pointer(), &iter.hiter)
- } else {
- if mapiterkey(&iter.hiter) == nil {
- panic("MapIter.Next called on exhausted iterator")
- }
- mapiternext(&iter.hiter)
- }
- return mapiterkey(&iter.hiter) != nil
-}
-
-// Reset modifies iter to iterate over v.
-// It panics if v's Kind is not [Map] and v is not the zero Value.
-// Reset(Value{}) causes iter to not to refer to any map,
-// which may allow the previously iterated-over map to be garbage collected.
-func (iter *MapIter) Reset(v Value) {
- if v.IsValid() {
- v.mustBe(Map)
- }
- iter.m = v
- iter.hiter = hiter{}
-}
-
-// MapRange returns a range iterator for a map.
-// It panics if v's Kind is not [Map].
-//
-// Call [MapIter.Next] to advance the iterator, and [MapIter.Key]/[MapIter.Value] to access each entry.
-// [MapIter.Next] returns false when the iterator is exhausted.
-// MapRange follows the same iteration semantics as a range statement.
-//
-// Example:
-//
-// iter := reflect.ValueOf(m).MapRange()
-// for iter.Next() {
-// k := iter.Key()
-// v := iter.Value()
-// ...
-// }
-func (v Value) MapRange() *MapIter {
- // This is inlinable to take advantage of "function outlining".
- // The allocation of MapIter can be stack allocated if the caller
- // does not allow it to escape.
- // See https://blog.filippo.io/efficient-go-apis-with-the-inliner/
- if v.kind() != Map {
- v.panicNotMap()
- }
- return &MapIter{m: v}
-}
-
-// Force slow panicking path not inlined, so it won't add to the
-// inlining budget of the caller.
-// TODO: undo when the inliner is no longer bottom-up only.
-//
-//go:noinline
-func (f flag) panicNotMap() {
- f.mustBe(Map)
-}
-
-// copyVal returns a Value containing the map key or value at ptr,
-// allocating a new variable as needed.
-func copyVal(typ *abi.Type, fl flag, ptr unsafe.Pointer) Value {
- if typ.IfaceIndir() {
- // Copy result so future changes to the map
- // won't change the underlying value.
- c := unsafe_New(typ)
- typedmemmove(typ, c, ptr)
- return Value{typ, c, fl | flagIndir}
- }
- return Value{typ, *(*unsafe.Pointer)(ptr), fl}
-}
-
-// Method returns a function value corresponding to v's i'th method.
-// The arguments to a Call on the returned function should not include
-// a receiver; the returned function will always use v as the receiver.
-// Method panics if i is out of range or if v is a nil interface value.
-func (v Value) Method(i int) Value {
- if v.typ() == nil {
- panic(&ValueError{"reflect.Value.Method", Invalid})
- }
- if v.flag&flagMethod != 0 || uint(i) >= uint(toRType(v.typ()).NumMethod()) {
- panic("reflect: Method index out of range")
- }
- if v.typ().Kind() == abi.Interface && v.IsNil() {
- panic("reflect: Method on nil interface value")
- }
- fl := v.flag.ro() | (v.flag & flagIndir)
- fl |= flag(Func)
- fl |= flag(i)<> (64 - bitSize)
- return x != trunc
- }
- panic(&ValueError{"reflect.Value.OverflowInt", v.kind()})
-}
-
-// OverflowUint reports whether the uint64 x cannot be represented by v's type.
-// It panics if v's Kind is not [Uint], [Uintptr], [Uint8], [Uint16], [Uint32], or [Uint64].
-func (v Value) OverflowUint(x uint64) bool {
- k := v.kind()
- switch k {
- case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
- bitSize := v.typ_.Size() * 8 // ok to use v.typ_ directly as Size doesn't escape
- trunc := (x << (64 - bitSize)) >> (64 - bitSize)
- return x != trunc
- }
- panic(&ValueError{"reflect.Value.OverflowUint", v.kind()})
-}
-
-//go:nocheckptr
-// This prevents inlining Value.Pointer when -d=checkptr is enabled,
-// which ensures cmd/compile can recognize unsafe.Pointer(v.Pointer())
-// and make an exception.
-
-// Pointer returns v's value as a uintptr.
-// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], or [UnsafePointer].
-//
-// If v's Kind is [Func], the returned pointer is an underlying
-// code pointer, but not necessarily enough to identify a
-// single function uniquely. The only guarantee is that the
-// result is zero if and only if v is a nil func Value.
-//
-// If v's Kind is [Slice], the returned pointer is to the first
-// element of the slice. If the slice is nil the returned value
-// is 0. If the slice is empty but non-nil the return value is non-zero.
-//
-// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result.
-func (v Value) Pointer() uintptr {
- // The compiler loses track as it converts to uintptr. Force escape.
- escapes(v.ptr)
-
- k := v.kind()
- switch k {
- case Pointer:
- if v.typ().PtrBytes == 0 {
- val := *(*uintptr)(v.ptr)
- // Since it is a not-in-heap pointer, all pointers to the heap are
- // forbidden! See comment in Value.Elem and issue #48399.
- if !verifyNotInHeapPtr(val) {
- panic("reflect: reflect.Value.Pointer on an invalid notinheap pointer")
- }
- return val
- }
- fallthrough
- case Chan, Map, UnsafePointer:
- return uintptr(v.pointer())
- case Func:
- if v.flag&flagMethod != 0 {
- // As the doc comment says, the returned pointer is an
- // underlying code pointer but not necessarily enough to
- // identify a single function uniquely. All method expressions
- // created via reflect have the same underlying code pointer,
- // so their Pointers are equal. The function used here must
- // match the one used in makeMethodValue.
- return methodValueCallCodePtr()
- }
- p := v.pointer()
- // Non-nil func value points at data block.
- // First word of data block is actual code.
- if p != nil {
- p = *(*unsafe.Pointer)(p)
- }
- return uintptr(p)
-
- case Slice:
- return uintptr((*unsafeheader.Slice)(v.ptr).Data)
- }
- panic(&ValueError{"reflect.Value.Pointer", v.kind()})
-}
-
-// Recv receives and returns a value from the channel v.
-// It panics if v's Kind is not [Chan].
-// The receive blocks until a value is ready.
-// The boolean value ok is true if the value x corresponds to a send
-// on the channel, false if it is a zero value received because the channel is closed.
-func (v Value) Recv() (x Value, ok bool) {
- v.mustBe(Chan)
- v.mustBeExported()
- return v.recv(false)
-}
-
-// internal recv, possibly non-blocking (nb).
-// v is known to be a channel.
-func (v Value) recv(nb bool) (val Value, ok bool) {
- tt := (*chanType)(unsafe.Pointer(v.typ()))
- if ChanDir(tt.Dir)&RecvDir == 0 {
- panic("reflect: recv on send-only channel")
- }
- t := tt.Elem
- val = Value{t, nil, flag(t.Kind())}
- var p unsafe.Pointer
- if ifaceIndir(t) {
- p = unsafe_New(t)
- val.ptr = p
- val.flag |= flagIndir
- } else {
- p = unsafe.Pointer(&val.ptr)
- }
- selected, ok := chanrecv(v.pointer(), nb, p)
- if !selected {
- val = Value{}
- }
- return
-}
-
-// Send sends x on the channel v.
-// It panics if v's kind is not [Chan] or if x's type is not the same type as v's element type.
-// As in Go, x's value must be assignable to the channel's element type.
-func (v Value) Send(x Value) {
- v.mustBe(Chan)
- v.mustBeExported()
- v.send(x, false)
-}
-
-// internal send, possibly non-blocking.
-// v is known to be a channel.
-func (v Value) send(x Value, nb bool) (selected bool) {
- tt := (*chanType)(unsafe.Pointer(v.typ()))
- if ChanDir(tt.Dir)&SendDir == 0 {
- panic("reflect: send on recv-only channel")
- }
- x.mustBeExported()
- x = x.assignTo("reflect.Value.Send", tt.Elem, nil)
- var p unsafe.Pointer
- if x.flag&flagIndir != 0 {
- p = x.ptr
- } else {
- p = unsafe.Pointer(&x.ptr)
- }
- return chansend(v.pointer(), p, nb)
-}
-
-// Set assigns x to the value v.
-// It panics if [Value.CanSet] returns false.
-// As in Go, x's value must be assignable to v's type and
-// must not be derived from an unexported field.
-func (v Value) Set(x Value) {
- v.mustBeAssignable()
- x.mustBeExported() // do not let unexported x leak
- var target unsafe.Pointer
- if v.kind() == Interface {
- target = v.ptr
- }
- x = x.assignTo("reflect.Set", v.typ(), target)
- if x.flag&flagIndir != 0 {
- if x.ptr == unsafe.Pointer(&zeroVal[0]) {
- typedmemclr(v.typ(), v.ptr)
- } else {
- typedmemmove(v.typ(), v.ptr, x.ptr)
- }
- } else {
- *(*unsafe.Pointer)(v.ptr) = x.ptr
- }
-}
-
-// SetBool sets v's underlying value.
-// It panics if v's Kind is not [Bool] or if [Value.CanSet] returns false.
-func (v Value) SetBool(x bool) {
- v.mustBeAssignable()
- v.mustBe(Bool)
- *(*bool)(v.ptr) = x
-}
-
-// SetBytes sets v's underlying value.
-// It panics if v's underlying value is not a slice of bytes.
-func (v Value) SetBytes(x []byte) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- if toRType(v.typ()).Elem().Kind() != Uint8 { // TODO add Elem method, fix mustBe(Slice) to return slice.
- panic("reflect.Value.SetBytes of non-byte slice")
- }
- *(*[]byte)(v.ptr) = x
-}
-
-// setRunes sets v's underlying value.
-// It panics if v's underlying value is not a slice of runes (int32s).
-func (v Value) setRunes(x []rune) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- if v.typ().Elem().Kind() != abi.Int32 {
- panic("reflect.Value.setRunes of non-rune slice")
- }
- *(*[]rune)(v.ptr) = x
-}
-
-// SetComplex sets v's underlying value to x.
-// It panics if v's Kind is not [Complex64] or [Complex128], or if [Value.CanSet] returns false.
-func (v Value) SetComplex(x complex128) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetComplex", v.kind()})
- case Complex64:
- *(*complex64)(v.ptr) = complex64(x)
- case Complex128:
- *(*complex128)(v.ptr) = x
- }
-}
-
-// SetFloat sets v's underlying value to x.
-// It panics if v's Kind is not [Float32] or [Float64], or if [Value.CanSet] returns false.
-func (v Value) SetFloat(x float64) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetFloat", v.kind()})
- case Float32:
- *(*float32)(v.ptr) = float32(x)
- case Float64:
- *(*float64)(v.ptr) = x
- }
-}
-
-// SetInt sets v's underlying value to x.
-// It panics if v's Kind is not [Int], [Int8], [Int16], [Int32], or [Int64], or if [Value.CanSet] returns false.
-func (v Value) SetInt(x int64) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetInt", v.kind()})
- case Int:
- *(*int)(v.ptr) = int(x)
- case Int8:
- *(*int8)(v.ptr) = int8(x)
- case Int16:
- *(*int16)(v.ptr) = int16(x)
- case Int32:
- *(*int32)(v.ptr) = int32(x)
- case Int64:
- *(*int64)(v.ptr) = x
- }
-}
-
-// SetLen sets v's length to n.
-// It panics if v's Kind is not [Slice] or if n is negative or
-// greater than the capacity of the slice.
-func (v Value) SetLen(n int) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- s := (*unsafeheader.Slice)(v.ptr)
- if uint(n) > uint(s.Cap) {
- panic("reflect: slice length out of range in SetLen")
- }
- s.Len = n
-}
-
-// SetCap sets v's capacity to n.
-// It panics if v's Kind is not [Slice] or if n is smaller than the length or
-// greater than the capacity of the slice.
-func (v Value) SetCap(n int) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- s := (*unsafeheader.Slice)(v.ptr)
- if n < s.Len || n > s.Cap {
- panic("reflect: slice capacity out of range in SetCap")
- }
- s.Cap = n
-}
-
-// SetMapIndex sets the element associated with key in the map v to elem.
-// It panics if v's Kind is not [Map].
-// If elem is the zero Value, SetMapIndex deletes the key from the map.
-// Otherwise if v holds a nil map, SetMapIndex will panic.
-// As in Go, key's elem must be assignable to the map's key type,
-// and elem's value must be assignable to the map's elem type.
-func (v Value) SetMapIndex(key, elem Value) {
- v.mustBe(Map)
- v.mustBeExported()
- key.mustBeExported()
- tt := (*mapType)(unsafe.Pointer(v.typ()))
-
- if (tt.Key == stringType || key.kind() == String) && tt.Key == key.typ() && tt.Elem.Size() <= maxValSize {
- k := *(*string)(key.ptr)
- if elem.typ() == nil {
- mapdelete_faststr(v.typ(), v.pointer(), k)
- return
- }
- elem.mustBeExported()
- elem = elem.assignTo("reflect.Value.SetMapIndex", tt.Elem, nil)
- var e unsafe.Pointer
- if elem.flag&flagIndir != 0 {
- e = elem.ptr
- } else {
- e = unsafe.Pointer(&elem.ptr)
- }
- mapassign_faststr(v.typ(), v.pointer(), k, e)
- return
- }
-
- key = key.assignTo("reflect.Value.SetMapIndex", tt.Key, nil)
- var k unsafe.Pointer
- if key.flag&flagIndir != 0 {
- k = key.ptr
- } else {
- k = unsafe.Pointer(&key.ptr)
- }
- if elem.typ() == nil {
- mapdelete(v.typ(), v.pointer(), k)
- return
- }
- elem.mustBeExported()
- elem = elem.assignTo("reflect.Value.SetMapIndex", tt.Elem, nil)
- var e unsafe.Pointer
- if elem.flag&flagIndir != 0 {
- e = elem.ptr
- } else {
- e = unsafe.Pointer(&elem.ptr)
- }
- mapassign(v.typ(), v.pointer(), k, e)
-}
-
-// SetUint sets v's underlying value to x.
-// It panics if v's Kind is not [Uint], [Uintptr], [Uint8], [Uint16], [Uint32], or [Uint64], or if [Value.CanSet] returns false.
-func (v Value) SetUint(x uint64) {
- v.mustBeAssignable()
- switch k := v.kind(); k {
- default:
- panic(&ValueError{"reflect.Value.SetUint", v.kind()})
- case Uint:
- *(*uint)(v.ptr) = uint(x)
- case Uint8:
- *(*uint8)(v.ptr) = uint8(x)
- case Uint16:
- *(*uint16)(v.ptr) = uint16(x)
- case Uint32:
- *(*uint32)(v.ptr) = uint32(x)
- case Uint64:
- *(*uint64)(v.ptr) = x
- case Uintptr:
- *(*uintptr)(v.ptr) = uintptr(x)
- }
-}
-
-// SetPointer sets the [unsafe.Pointer] value v to x.
-// It panics if v's Kind is not UnsafePointer.
-func (v Value) SetPointer(x unsafe.Pointer) {
- v.mustBeAssignable()
- v.mustBe(UnsafePointer)
- *(*unsafe.Pointer)(v.ptr) = x
-}
-
-// SetString sets v's underlying value to x.
-// It panics if v's Kind is not [String] or if [Value.CanSet] returns false.
-func (v Value) SetString(x string) {
- v.mustBeAssignable()
- v.mustBe(String)
- *(*string)(v.ptr) = x
-}
-
-// Slice returns v[i:j].
-// It panics if v's Kind is not [Array], [Slice] or [String], or if v is an unaddressable array,
-// or if the indexes are out of bounds.
-func (v Value) Slice(i, j int) Value {
- var (
- cap int
- typ *sliceType
- base unsafe.Pointer
- )
- switch kind := v.kind(); kind {
- default:
- panic(&ValueError{"reflect.Value.Slice", v.kind()})
-
- case Array:
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.Slice: slice of unaddressable array")
- }
- tt := (*arrayType)(unsafe.Pointer(v.typ()))
- cap = int(tt.Len)
- typ = (*sliceType)(unsafe.Pointer(tt.Slice))
- base = v.ptr
-
- case Slice:
- typ = (*sliceType)(unsafe.Pointer(v.typ()))
- s := (*unsafeheader.Slice)(v.ptr)
- base = s.Data
- cap = s.Cap
-
- case String:
- s := (*unsafeheader.String)(v.ptr)
- if i < 0 || j < i || j > s.Len {
- panic("reflect.Value.Slice: string slice index out of bounds")
- }
- var t unsafeheader.String
- if i < s.Len {
- t = unsafeheader.String{Data: arrayAt(s.Data, i, 1, "i < s.Len"), Len: j - i}
- }
- return Value{v.typ(), unsafe.Pointer(&t), v.flag}
- }
-
- if i < 0 || j < i || j > cap {
- panic("reflect.Value.Slice: slice index out of bounds")
- }
-
- // Declare slice so that gc can see the base pointer in it.
- var x []unsafe.Pointer
-
- // Reinterpret as *unsafeheader.Slice to edit.
- s := (*unsafeheader.Slice)(unsafe.Pointer(&x))
- s.Len = j - i
- s.Cap = cap - i
- if cap-i > 0 {
- s.Data = arrayAt(base, i, typ.Elem.Size(), "i < cap")
- } else {
- // do not advance pointer, to avoid pointing beyond end of slice
- s.Data = base
- }
-
- fl := v.flag.ro() | flagIndir | flag(Slice)
- return Value{typ.Common(), unsafe.Pointer(&x), fl}
-}
-
-// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
-// It panics if v's Kind is not [Array] or [Slice], or if v is an unaddressable array,
-// or if the indexes are out of bounds.
-func (v Value) Slice3(i, j, k int) Value {
- var (
- cap int
- typ *sliceType
- base unsafe.Pointer
- )
- switch kind := v.kind(); kind {
- default:
- panic(&ValueError{"reflect.Value.Slice3", v.kind()})
-
- case Array:
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.Slice3: slice of unaddressable array")
- }
- tt := (*arrayType)(unsafe.Pointer(v.typ()))
- cap = int(tt.Len)
- typ = (*sliceType)(unsafe.Pointer(tt.Slice))
- base = v.ptr
-
- case Slice:
- typ = (*sliceType)(unsafe.Pointer(v.typ()))
- s := (*unsafeheader.Slice)(v.ptr)
- base = s.Data
- cap = s.Cap
- }
-
- if i < 0 || j < i || k < j || k > cap {
- panic("reflect.Value.Slice3: slice index out of bounds")
- }
-
- // Declare slice so that the garbage collector
- // can see the base pointer in it.
- var x []unsafe.Pointer
-
- // Reinterpret as *unsafeheader.Slice to edit.
- s := (*unsafeheader.Slice)(unsafe.Pointer(&x))
- s.Len = j - i
- s.Cap = k - i
- if k-i > 0 {
- s.Data = arrayAt(base, i, typ.Elem.Size(), "i < k <= cap")
- } else {
- // do not advance pointer, to avoid pointing beyond end of slice
- s.Data = base
- }
-
- fl := v.flag.ro() | flagIndir | flag(Slice)
- return Value{typ.Common(), unsafe.Pointer(&x), fl}
-}
-
-// String returns the string v's underlying value, as a string.
-// String is a special case because of Go's String method convention.
-// Unlike the other getters, it does not panic if v's Kind is not [String].
-// Instead, it returns a string of the form "" where T is v's type.
-// The fmt package treats Values specially. It does not call their String
-// method implicitly but instead prints the concrete values they hold.
-func (v Value) String() string {
- // stringNonString is split out to keep String inlineable for string kinds.
- if v.kind() == String {
- return *(*string)(v.ptr)
- }
- return v.stringNonString()
-}
-
-func (v Value) stringNonString() string {
- if v.kind() == Invalid {
- return ""
- }
- // If you call String on a reflect.Value of other type, it's better to
- // print something than to panic. Useful in debugging.
- return "<" + v.Type().String() + " Value>"
-}
-
-// TryRecv attempts to receive a value from the channel v but will not block.
-// It panics if v's Kind is not [Chan].
-// If the receive delivers a value, x is the transferred value and ok is true.
-// If the receive cannot finish without blocking, x is the zero Value and ok is false.
-// If the channel is closed, x is the zero value for the channel's element type and ok is false.
-func (v Value) TryRecv() (x Value, ok bool) {
- v.mustBe(Chan)
- v.mustBeExported()
- return v.recv(true)
-}
-
-// TrySend attempts to send x on the channel v but will not block.
-// It panics if v's Kind is not [Chan].
-// It reports whether the value was sent.
-// As in Go, x's value must be assignable to the channel's element type.
-func (v Value) TrySend(x Value) bool {
- v.mustBe(Chan)
- v.mustBeExported()
- return v.send(x, true)
-}
-
-// Type returns v's type.
-func (v Value) Type() Type {
- if v.flag != 0 && v.flag&flagMethod == 0 {
- return (*rtype)(noescape(unsafe.Pointer(v.typ_))) // inline of toRType(v.typ()), for own inlining in inline test
- }
- return v.typeSlow()
-}
-
-func (v Value) typeSlow() Type {
- if v.flag == 0 {
- panic(&ValueError{"reflect.Value.Type", Invalid})
- }
-
- typ := v.typ()
- if v.flag&flagMethod == 0 {
- return toRType(v.typ())
- }
-
- // Method value.
- // v.typ describes the receiver, not the method type.
- i := int(v.flag) >> flagMethodShift
- if v.typ().Kind() == abi.Interface {
- // Method on interface.
- tt := (*interfaceType)(unsafe.Pointer(typ))
- if uint(i) >= uint(len(tt.Methods)) {
- panic("reflect: internal error: invalid method index")
- }
- m := &tt.Methods[i]
- return toRType(typeOffFor(typ, m.Typ))
- }
- // Method on concrete type.
- ms := typ.ExportedMethods()
- if uint(i) >= uint(len(ms)) {
- panic("reflect: internal error: invalid method index")
- }
- m := ms[i]
- return toRType(typeOffFor(typ, m.Mtyp))
-}
-
-// CanUint reports whether [Value.Uint] can be used without panicking.
-func (v Value) CanUint() bool {
- switch v.kind() {
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return true
- default:
- return false
- }
-}
-
-// Uint returns v's underlying value, as a uint64.
-// It panics if v's Kind is not [Uint], [Uintptr], [Uint8], [Uint16], [Uint32], or [Uint64].
-func (v Value) Uint() uint64 {
- k := v.kind()
- p := v.ptr
- switch k {
- case Uint:
- return uint64(*(*uint)(p))
- case Uint8:
- return uint64(*(*uint8)(p))
- case Uint16:
- return uint64(*(*uint16)(p))
- case Uint32:
- return uint64(*(*uint32)(p))
- case Uint64:
- return *(*uint64)(p)
- case Uintptr:
- return uint64(*(*uintptr)(p))
- }
- panic(&ValueError{"reflect.Value.Uint", v.kind()})
-}
-
-//go:nocheckptr
-// This prevents inlining Value.UnsafeAddr when -d=checkptr is enabled,
-// which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr())
-// and make an exception.
-
-// UnsafeAddr returns a pointer to v's data, as a uintptr.
-// It panics if v is not addressable.
-//
-// It's preferred to use uintptr(Value.Addr().UnsafePointer()) to get the equivalent result.
-func (v Value) UnsafeAddr() uintptr {
- if v.typ() == nil {
- panic(&ValueError{"reflect.Value.UnsafeAddr", Invalid})
- }
- if v.flag&flagAddr == 0 {
- panic("reflect.Value.UnsafeAddr of unaddressable value")
- }
- // The compiler loses track as it converts to uintptr. Force escape.
- escapes(v.ptr)
- return uintptr(v.ptr)
-}
-
-// UnsafePointer returns v's value as a [unsafe.Pointer].
-// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], or [UnsafePointer].
-//
-// If v's Kind is [Func], the returned pointer is an underlying
-// code pointer, but not necessarily enough to identify a
-// single function uniquely. The only guarantee is that the
-// result is zero if and only if v is a nil func Value.
-//
-// If v's Kind is [Slice], the returned pointer is to the first
-// element of the slice. If the slice is nil the returned value
-// is nil. If the slice is empty but non-nil the return value is non-nil.
-func (v Value) UnsafePointer() unsafe.Pointer {
- k := v.kind()
- switch k {
- case Pointer:
- if v.typ().PtrBytes == 0 {
- // Since it is a not-in-heap pointer, all pointers to the heap are
- // forbidden! See comment in Value.Elem and issue #48399.
- if !verifyNotInHeapPtr(*(*uintptr)(v.ptr)) {
- panic("reflect: reflect.Value.UnsafePointer on an invalid notinheap pointer")
- }
- return *(*unsafe.Pointer)(v.ptr)
- }
- fallthrough
- case Chan, Map, UnsafePointer:
- return v.pointer()
- case Func:
- if v.flag&flagMethod != 0 {
- // As the doc comment says, the returned pointer is an
- // underlying code pointer but not necessarily enough to
- // identify a single function uniquely. All method expressions
- // created via reflect have the same underlying code pointer,
- // so their Pointers are equal. The function used here must
- // match the one used in makeMethodValue.
- code := methodValueCallCodePtr()
- return *(*unsafe.Pointer)(unsafe.Pointer(&code))
- }
- p := v.pointer()
- // Non-nil func value points at data block.
- // First word of data block is actual code.
- if p != nil {
- p = *(*unsafe.Pointer)(p)
- }
- return p
-
- case Slice:
- return (*unsafeheader.Slice)(v.ptr).Data
- }
- panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
-}
-
-// StringHeader is the runtime representation of a string.
-// It cannot be used safely or portably and its representation may
-// change in a later release.
-// Moreover, the Data field is not sufficient to guarantee the data
-// it references will not be garbage collected, so programs must keep
-// a separate, correctly typed pointer to the underlying data.
-//
-// Deprecated: Use unsafe.String or unsafe.StringData instead.
-type StringHeader struct {
- Data uintptr
- Len int
-}
-
-// SliceHeader is the runtime representation of a slice.
-// It cannot be used safely or portably and its representation may
-// change in a later release.
-// Moreover, the Data field is not sufficient to guarantee the data
-// it references will not be garbage collected, so programs must keep
-// a separate, correctly typed pointer to the underlying data.
-//
-// Deprecated: Use unsafe.Slice or unsafe.SliceData instead.
-type SliceHeader struct {
- Data uintptr
- Len int
- Cap int
-}
-
-func typesMustMatch(what string, t1, t2 Type) {
- if t1 != t2 {
- panic(what + ": " + t1.String() + " != " + t2.String())
- }
-}
-
-// arrayAt returns the i-th element of p,
-// an array whose elements are eltSize bytes wide.
-// The array pointed at by p must have at least i+1 elements:
-// it is invalid (but impossible to check here) to pass i >= len,
-// because then the result will point outside the array.
-// whySafe must explain why i < len. (Passing "i < len" is fine;
-// the benefit is to surface this assumption at the call site.)
-func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
- return add(p, uintptr(i)*eltSize, "i < len")
-}
-
-// Grow increases the slice's capacity, if necessary, to guarantee space for
-// another n elements. After Grow(n), at least n elements can be appended
-// to the slice without another allocation.
-//
-// It panics if v's Kind is not a [Slice] or if n is negative or too large to
-// allocate the memory.
-func (v Value) Grow(n int) {
- v.mustBeAssignable()
- v.mustBe(Slice)
- v.grow(n)
-}
-
-// grow is identical to Grow but does not check for assignability.
-func (v Value) grow(n int) {
- p := (*unsafeheader.Slice)(v.ptr)
- switch {
- case n < 0:
- panic("reflect.Value.Grow: negative len")
- case p.Len+n < 0:
- panic("reflect.Value.Grow: slice overflow")
- case p.Len+n > p.Cap:
- t := v.typ().Elem()
- *p = growslice(t, *p, n)
- }
-}
-
-// extendSlice extends a slice by n elements.
-//
-// Unlike Value.grow, which modifies the slice in place and
-// does not change the length of the slice in place,
-// extendSlice returns a new slice value with the length
-// incremented by the number of specified elements.
-func (v Value) extendSlice(n int) Value {
- v.mustBeExported()
- v.mustBe(Slice)
-
- // Shallow copy the slice header to avoid mutating the source slice.
- sh := *(*unsafeheader.Slice)(v.ptr)
- s := &sh
- v.ptr = unsafe.Pointer(s)
- v.flag = flagIndir | flag(Slice) // equivalent flag to MakeSlice
-
- v.grow(n) // fine to treat as assignable since we allocate a new slice header
- s.Len += n
- return v
-}
-
-// Clear clears the contents of a map or zeros the contents of a slice.
-//
-// It panics if v's Kind is not [Map] or [Slice].
-func (v Value) Clear() {
- switch v.Kind() {
- case Slice:
- sh := *(*unsafeheader.Slice)(v.ptr)
- st := (*sliceType)(unsafe.Pointer(v.typ()))
- typedarrayclear(st.Elem, sh.Data, sh.Len)
- case Map:
- mapclear(v.typ(), v.pointer())
- default:
- panic(&ValueError{"reflect.Value.Clear", v.Kind()})
- }
-}
-
-// Append appends the values x to a slice s and returns the resulting slice.
-// As in Go, each x's value must be assignable to the slice's element type.
-func Append(s Value, x ...Value) Value {
- s.mustBe(Slice)
- n := s.Len()
- s = s.extendSlice(len(x))
- for i, v := range x {
- s.Index(n + i).Set(v)
- }
- return s
-}
-
-// AppendSlice appends a slice t to a slice s and returns the resulting slice.
-// The slices s and t must have the same element type.
-func AppendSlice(s, t Value) Value {
- s.mustBe(Slice)
- t.mustBe(Slice)
- typesMustMatch("reflect.AppendSlice", s.Type().Elem(), t.Type().Elem())
- ns := s.Len()
- nt := t.Len()
- s = s.extendSlice(nt)
- Copy(s.Slice(ns, ns+nt), t)
- return s
-}
-
-// Copy copies the contents of src into dst until either
-// dst has been filled or src has been exhausted.
-// It returns the number of elements copied.
-// Dst and src each must have kind [Slice] or [Array], and
-// dst and src must have the same element type.
-//
-// As a special case, src can have kind [String] if the element type of dst is kind [Uint8].
-func Copy(dst, src Value) int {
- dk := dst.kind()
- if dk != Array && dk != Slice {
- panic(&ValueError{"reflect.Copy", dk})
- }
- if dk == Array {
- dst.mustBeAssignable()
- }
- dst.mustBeExported()
-
- sk := src.kind()
- var stringCopy bool
- if sk != Array && sk != Slice {
- stringCopy = sk == String && dst.typ().Elem().Kind() == abi.Uint8
- if !stringCopy {
- panic(&ValueError{"reflect.Copy", sk})
- }
- }
- src.mustBeExported()
-
- de := dst.typ().Elem()
- if !stringCopy {
- se := src.typ().Elem()
- typesMustMatch("reflect.Copy", toType(de), toType(se))
- }
-
- var ds, ss unsafeheader.Slice
- if dk == Array {
- ds.Data = dst.ptr
- ds.Len = dst.Len()
- ds.Cap = ds.Len
- } else {
- ds = *(*unsafeheader.Slice)(dst.ptr)
- }
- if sk == Array {
- ss.Data = src.ptr
- ss.Len = src.Len()
- ss.Cap = ss.Len
- } else if sk == Slice {
- ss = *(*unsafeheader.Slice)(src.ptr)
- } else {
- sh := *(*unsafeheader.String)(src.ptr)
- ss.Data = sh.Data
- ss.Len = sh.Len
- ss.Cap = sh.Len
- }
-
- return typedslicecopy(de.Common(), ds, ss)
-}
-
-// A runtimeSelect is a single case passed to rselect.
-// This must match ../runtime/select.go:/runtimeSelect
-type runtimeSelect struct {
- dir SelectDir // SelectSend, SelectRecv or SelectDefault
- typ *rtype // channel type
- ch unsafe.Pointer // channel
- val unsafe.Pointer // ptr to data (SendDir) or ptr to receive buffer (RecvDir)
-}
-
-// rselect runs a select. It returns the index of the chosen case.
-// If the case was a receive, val is filled in with the received value.
-// The conventional OK bool indicates whether the receive corresponds
-// to a sent value.
-//
-// rselect generally doesn't escape the runtimeSelect slice, except
-// that for the send case the value to send needs to escape. We don't
-// have a way to represent that in the function signature. So we handle
-// that with a forced escape in function Select.
-//
-//go:noescape
-func rselect([]runtimeSelect) (chosen int, recvOK bool)
-
-// A SelectDir describes the communication direction of a select case.
-type SelectDir int
-
-// NOTE: These values must match ../runtime/select.go:/selectDir.
-
-const (
- _ SelectDir = iota
- SelectSend // case Chan <- Send
- SelectRecv // case <-Chan:
- SelectDefault // default
-)
-
-// A SelectCase describes a single case in a select operation.
-// The kind of case depends on Dir, the communication direction.
-//
-// If Dir is SelectDefault, the case represents a default case.
-// Chan and Send must be zero Values.
-//
-// If Dir is SelectSend, the case represents a send operation.
-// Normally Chan's underlying value must be a channel, and Send's underlying value must be
-// assignable to the channel's element type. As a special case, if Chan is a zero Value,
-// then the case is ignored, and the field Send will also be ignored and may be either zero
-// or non-zero.
-//
-// If Dir is SelectRecv, the case represents a receive operation.
-// Normally Chan's underlying value must be a channel and Send must be a zero Value.
-// If Chan is a zero Value, then the case is ignored, but Send must still be a zero Value.
-// When a receive operation is selected, the received Value is returned by Select.
-type SelectCase struct {
- Dir SelectDir // direction of case
- Chan Value // channel to use (for send or receive)
- Send Value // value to send (for send)
-}
-
-// Select executes a select operation described by the list of cases.
-// Like the Go select statement, it blocks until at least one of the cases
-// can proceed, makes a uniform pseudo-random choice,
-// and then executes that case. It returns the index of the chosen case
-// and, if that case was a receive operation, the value received and a
-// boolean indicating whether the value corresponds to a send on the channel
-// (as opposed to a zero value received because the channel is closed).
-// Select supports a maximum of 65536 cases.
-func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
- if len(cases) > 65536 {
- panic("reflect.Select: too many cases (max 65536)")
- }
- // NOTE: Do not trust that caller is not modifying cases data underfoot.
- // The range is safe because the caller cannot modify our copy of the len
- // and each iteration makes its own copy of the value c.
- var runcases []runtimeSelect
- if len(cases) > 4 {
- // Slice is heap allocated due to runtime dependent capacity.
- runcases = make([]runtimeSelect, len(cases))
- } else {
- // Slice can be stack allocated due to constant capacity.
- runcases = make([]runtimeSelect, len(cases), 4)
- }
-
- haveDefault := false
- for i, c := range cases {
- rc := &runcases[i]
- rc.dir = c.Dir
- switch c.Dir {
- default:
- panic("reflect.Select: invalid Dir")
-
- case SelectDefault: // default
- if haveDefault {
- panic("reflect.Select: multiple default cases")
- }
- haveDefault = true
- if c.Chan.IsValid() {
- panic("reflect.Select: default case has Chan value")
- }
- if c.Send.IsValid() {
- panic("reflect.Select: default case has Send value")
- }
-
- case SelectSend:
- ch := c.Chan
- if !ch.IsValid() {
- break
- }
- ch.mustBe(Chan)
- ch.mustBeExported()
- tt := (*chanType)(unsafe.Pointer(ch.typ()))
- if ChanDir(tt.Dir)&SendDir == 0 {
- panic("reflect.Select: SendDir case using recv-only channel")
- }
- rc.ch = ch.pointer()
- rc.typ = toRType(&tt.Type)
- v := c.Send
- if !v.IsValid() {
- panic("reflect.Select: SendDir case missing Send value")
- }
- v.mustBeExported()
- v = v.assignTo("reflect.Select", tt.Elem, nil)
- if v.flag&flagIndir != 0 {
- rc.val = v.ptr
- } else {
- rc.val = unsafe.Pointer(&v.ptr)
- }
- // The value to send needs to escape. See the comment at rselect for
- // why we need forced escape.
- escapes(rc.val)
-
- case SelectRecv:
- if c.Send.IsValid() {
- panic("reflect.Select: RecvDir case has Send value")
- }
- ch := c.Chan
- if !ch.IsValid() {
- break
- }
- ch.mustBe(Chan)
- ch.mustBeExported()
- tt := (*chanType)(unsafe.Pointer(ch.typ()))
- if ChanDir(tt.Dir)&RecvDir == 0 {
- panic("reflect.Select: RecvDir case using send-only channel")
- }
- rc.ch = ch.pointer()
- rc.typ = toRType(&tt.Type)
- rc.val = unsafe_New(tt.Elem)
- }
- }
-
- chosen, recvOK = rselect(runcases)
- if runcases[chosen].dir == SelectRecv {
- tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
- t := tt.Elem
- p := runcases[chosen].val
- fl := flag(t.Kind())
- if t.IfaceIndir() {
- recv = Value{t, p, fl | flagIndir}
- } else {
- recv = Value{t, *(*unsafe.Pointer)(p), fl}
- }
- }
- return chosen, recv, recvOK
-}
-
-/*
- * constructors
- */
-
-// implemented in package runtime
-
-//go:noescape
-func unsafe_New(*abi.Type) unsafe.Pointer
-
-//go:noescape
-func unsafe_NewArray(*abi.Type, int) unsafe.Pointer
-
-// MakeSlice creates a new zero-initialized slice value
-// for the specified slice type, length, and capacity.
-func MakeSlice(typ Type, len, cap int) Value {
- if typ.Kind() != Slice {
- panic("reflect.MakeSlice of non-slice type")
- }
- if len < 0 {
- panic("reflect.MakeSlice: negative len")
- }
- if cap < 0 {
- panic("reflect.MakeSlice: negative cap")
- }
- if len > cap {
- panic("reflect.MakeSlice: len > cap")
- }
-
- s := unsafeheader.Slice{Data: unsafe_NewArray(&(typ.Elem().(*rtype).t), cap), Len: len, Cap: cap}
- return Value{&typ.(*rtype).t, unsafe.Pointer(&s), flagIndir | flag(Slice)}
-}
-
-// MakeChan creates a new channel with the specified type and buffer size.
-func MakeChan(typ Type, buffer int) Value {
- if typ.Kind() != Chan {
- panic("reflect.MakeChan of non-chan type")
- }
- if buffer < 0 {
- panic("reflect.MakeChan: negative buffer size")
- }
- if typ.ChanDir() != BothDir {
- panic("reflect.MakeChan: unidirectional channel type")
- }
- t := typ.common()
- ch := makechan(t, buffer)
- return Value{t, ch, flag(Chan)}
-}
-
-// MakeMap creates a new map with the specified type.
-func MakeMap(typ Type) Value {
- return MakeMapWithSize(typ, 0)
-}
-
-// MakeMapWithSize creates a new map with the specified type
-// and initial space for approximately n elements.
-func MakeMapWithSize(typ Type, n int) Value {
- if typ.Kind() != Map {
- panic("reflect.MakeMapWithSize of non-map type")
- }
- t := typ.common()
- m := makemap(t, n)
- return Value{t, m, flag(Map)}
-}
-
-// Indirect returns the value that v points to.
-// If v is a nil pointer, Indirect returns a zero Value.
-// If v is not a pointer, Indirect returns v.
-func Indirect(v Value) Value {
- if v.Kind() != Pointer {
- return v
- }
- return v.Elem()
-}
-
-// ValueOf returns a new Value initialized to the concrete value
-// stored in the interface i. ValueOf(nil) returns the zero Value.
-func ValueOf(i any) Value {
- if i == nil {
- return Value{}
- }
- return unpackEface(i)
-}
-
-// Zero returns a Value representing the zero value for the specified type.
-// The result is different from the zero value of the Value struct,
-// which represents no value at all.
-// For example, Zero(TypeOf(42)) returns a Value with Kind [Int] and value 0.
-// The returned value is neither addressable nor settable.
-func Zero(typ Type) Value {
- if typ == nil {
- panic("reflect: Zero(nil)")
- }
- t := &typ.(*rtype).t
- fl := flag(t.Kind())
- if t.IfaceIndir() {
- var p unsafe.Pointer
- if t.Size() <= abi.ZeroValSize {
- p = unsafe.Pointer(&zeroVal[0])
- } else {
- p = unsafe_New(t)
- }
- return Value{t, p, fl | flagIndir}
- }
- return Value{t, nil, fl}
-}
-
-//go:linkname zeroVal runtime.zeroVal
-var zeroVal [abi.ZeroValSize]byte
-
-// New returns a Value representing a pointer to a new zero value
-// for the specified type. That is, the returned Value's Type is PointerTo(typ).
-func New(typ Type) Value {
- if typ == nil {
- panic("reflect: New(nil)")
- }
- t := &typ.(*rtype).t
- pt := ptrTo(t)
- if ifaceIndir(pt) {
- // This is a pointer to a not-in-heap type.
- panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)")
- }
- ptr := unsafe_New(t)
- fl := flag(Pointer)
- return Value{pt, ptr, fl}
-}
-
-// NewAt returns a Value representing a pointer to a value of the
-// specified type, using p as that pointer.
-func NewAt(typ Type, p unsafe.Pointer) Value {
- fl := flag(Pointer)
- t := typ.(*rtype)
- return Value{t.ptrTo(), p, fl}
-}
-
-// assignTo returns a value v that can be assigned directly to dst.
-// It panics if v is not assignable to dst.
-// For a conversion to an interface type, target, if not nil,
-// is a suggested scratch space to use.
-// target must be initialized memory (or nil).
-func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Value {
- if v.flag&flagMethod != 0 {
- v = makeMethodValue(context, v)
- }
-
- switch {
- case directlyAssignable(dst, v.typ()):
- // Overwrite type so that they match.
- // Same memory layout, so no harm done.
- fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
- fl |= flag(dst.Kind())
- return Value{dst, v.ptr, fl}
-
- case implements(dst, v.typ()):
- if v.Kind() == Interface && v.IsNil() {
- // A nil ReadWriter passed to nil Reader is OK,
- // but using ifaceE2I below will panic.
- // Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
- return Value{dst, nil, flag(Interface)}
- }
- x := valueInterface(v, false)
- if target == nil {
- target = unsafe_New(dst)
- }
- if dst.NumMethod() == 0 {
- *(*any)(target) = x
- } else {
- ifaceE2I(dst, x, target)
- }
- return Value{dst, target, flagIndir | flag(Interface)}
- }
-
- // Failed.
- panic(context + ": value of type " + stringFor(v.typ()) + " is not assignable to type " + stringFor(dst))
-}
-
-// Convert returns the value v converted to type t.
-// If the usual Go conversion rules do not allow conversion
-// of the value v to type t, or if converting v to type t panics, Convert panics.
-func (v Value) Convert(t Type) Value {
- if v.flag&flagMethod != 0 {
- v = makeMethodValue("Convert", v)
- }
- op := convertOp(t.common(), v.typ())
- if op == nil {
- panic("reflect.Value.Convert: value of type " + stringFor(v.typ()) + " cannot be converted to type " + t.String())
- }
- return op(v, t)
-}
-
-// CanConvert reports whether the value v can be converted to type t.
-// If v.CanConvert(t) returns true then v.Convert(t) will not panic.
-func (v Value) CanConvert(t Type) bool {
- vt := v.Type()
- if !vt.ConvertibleTo(t) {
- return false
- }
- // Converting from slice to array or to pointer-to-array can panic
- // depending on the value.
- switch {
- case vt.Kind() == Slice && t.Kind() == Array:
- if t.Len() > v.Len() {
- return false
- }
- case vt.Kind() == Slice && t.Kind() == Pointer && t.Elem().Kind() == Array:
- n := t.Elem().Len()
- if n > v.Len() {
- return false
- }
- }
- return true
-}
-
-// Comparable reports whether the value v is comparable.
-// If the type of v is an interface, this checks the dynamic type.
-// If this reports true then v.Interface() == x will not panic for any x,
-// nor will v.Equal(u) for any Value u.
-func (v Value) Comparable() bool {
- k := v.Kind()
- switch k {
- case Invalid:
- return false
-
- case Array:
- switch v.Type().Elem().Kind() {
- case Interface, Array, Struct:
- for i := 0; i < v.Type().Len(); i++ {
- if !v.Index(i).Comparable() {
- return false
- }
- }
- return true
- }
- return v.Type().Comparable()
-
- case Interface:
- return v.Elem().Comparable()
-
- case Struct:
- for i := 0; i < v.NumField(); i++ {
- if !v.Field(i).Comparable() {
- return false
- }
- }
- return true
-
- default:
- return v.Type().Comparable()
- }
-}
-
-// Equal reports true if v is equal to u.
-// For two invalid values, Equal will report true.
-// For an interface value, Equal will compare the value within the interface.
-// Otherwise, If the values have different types, Equal will report false.
-// Otherwise, for arrays and structs Equal will compare each element in order,
-// and report false if it finds non-equal elements.
-// During all comparisons, if values of the same type are compared,
-// and the type is not comparable, Equal will panic.
-func (v Value) Equal(u Value) bool {
- if v.Kind() == Interface {
- v = v.Elem()
- }
- if u.Kind() == Interface {
- u = u.Elem()
- }
-
- if !v.IsValid() || !u.IsValid() {
- return v.IsValid() == u.IsValid()
- }
-
- if v.Kind() != u.Kind() || v.Type() != u.Type() {
- return false
- }
-
- // Handle each Kind directly rather than calling valueInterface
- // to avoid allocating.
- switch v.Kind() {
- default:
- panic("reflect.Value.Equal: invalid Kind")
- case Bool:
- return v.Bool() == u.Bool()
- case Int, Int8, Int16, Int32, Int64:
- return v.Int() == u.Int()
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return v.Uint() == u.Uint()
- case Float32, Float64:
- return v.Float() == u.Float()
- case Complex64, Complex128:
- return v.Complex() == u.Complex()
- case String:
- return v.String() == u.String()
- case Chan, Pointer, UnsafePointer:
- return v.Pointer() == u.Pointer()
- case Array:
- // u and v have the same type so they have the same length
- vl := v.Len()
- if vl == 0 {
- // panic on [0]func()
- if !v.Type().Elem().Comparable() {
- break
- }
- return true
- }
- for i := 0; i < vl; i++ {
- if !v.Index(i).Equal(u.Index(i)) {
- return false
- }
- }
- return true
- case Struct:
- // u and v have the same type so they have the same fields
- nf := v.NumField()
- for i := 0; i < nf; i++ {
- if !v.Field(i).Equal(u.Field(i)) {
- return false
- }
- }
- return true
- case Func, Map, Slice:
- break
- }
- panic("reflect.Value.Equal: values of type " + v.Type().String() + " are not comparable")
-}
-
-// convertOp returns the function to convert a value of type src
-// to a value of type dst. If the conversion is illegal, convertOp returns nil.
-func convertOp(dst, src *abi.Type) func(Value, Type) Value {
- switch Kind(src.Kind()) {
- case Int, Int8, Int16, Int32, Int64:
- switch Kind(dst.Kind()) {
- case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return cvtInt
- case Float32, Float64:
- return cvtIntFloat
- case String:
- return cvtIntString
- }
-
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- switch Kind(dst.Kind()) {
- case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return cvtUint
- case Float32, Float64:
- return cvtUintFloat
- case String:
- return cvtUintString
- }
-
- case Float32, Float64:
- switch Kind(dst.Kind()) {
- case Int, Int8, Int16, Int32, Int64:
- return cvtFloatInt
- case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
- return cvtFloatUint
- case Float32, Float64:
- return cvtFloat
- }
-
- case Complex64, Complex128:
- switch Kind(dst.Kind()) {
- case Complex64, Complex128:
- return cvtComplex
- }
-
- case String:
- if dst.Kind() == abi.Slice && pkgPathFor(dst.Elem()) == "" {
- switch Kind(dst.Elem().Kind()) {
- case Uint8:
- return cvtStringBytes
- case Int32:
- return cvtStringRunes
- }
- }
-
- case Slice:
- if dst.Kind() == abi.String && pkgPathFor(src.Elem()) == "" {
- switch Kind(src.Elem().Kind()) {
- case Uint8:
- return cvtBytesString
- case Int32:
- return cvtRunesString
- }
- }
- // "x is a slice, T is a pointer-to-array type,
- // and the slice and array types have identical element types."
- if dst.Kind() == abi.Pointer && dst.Elem().Kind() == abi.Array && src.Elem() == dst.Elem().Elem() {
- return cvtSliceArrayPtr
- }
- // "x is a slice, T is an array type,
- // and the slice and array types have identical element types."
- if dst.Kind() == abi.Array && src.Elem() == dst.Elem() {
- return cvtSliceArray
- }
-
- case Chan:
- if dst.Kind() == abi.Chan && specialChannelAssignability(dst, src) {
- return cvtDirect
- }
- }
-
- // dst and src have same underlying type.
- if haveIdenticalUnderlyingType(dst, src, false) {
- return cvtDirect
- }
-
- // dst and src are non-defined pointer types with same underlying base type.
- if dst.Kind() == abi.Pointer && nameFor(dst) == "" &&
- src.Kind() == abi.Pointer && nameFor(src) == "" &&
- haveIdenticalUnderlyingType(elem(dst), elem(src), false) {
- return cvtDirect
- }
-
- if implements(dst, src) {
- if src.Kind() == abi.Interface {
- return cvtI2I
- }
- return cvtT2I
- }
-
- return nil
-}
-
-// makeInt returns a Value of type t equal to bits (possibly truncated),
-// where t is a signed or unsigned int type.
-func makeInt(f flag, bits uint64, t Type) Value {
- typ := t.common()
- ptr := unsafe_New(typ)
- switch typ.Size() {
- case 1:
- *(*uint8)(ptr) = uint8(bits)
- case 2:
- *(*uint16)(ptr) = uint16(bits)
- case 4:
- *(*uint32)(ptr) = uint32(bits)
- case 8:
- *(*uint64)(ptr) = bits
- }
- return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
-}
-
-// makeFloat returns a Value of type t equal to v (possibly truncated to float32),
-// where t is a float32 or float64 type.
-func makeFloat(f flag, v float64, t Type) Value {
- typ := t.common()
- ptr := unsafe_New(typ)
- switch typ.Size() {
- case 4:
- *(*float32)(ptr) = float32(v)
- case 8:
- *(*float64)(ptr) = v
- }
- return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
-}
-
-// makeFloat32 returns a Value of type t equal to v, where t is a float32 type.
-func makeFloat32(f flag, v float32, t Type) Value {
- typ := t.common()
- ptr := unsafe_New(typ)
- *(*float32)(ptr) = v
- return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
-}
-
-// makeComplex returns a Value of type t equal to v (possibly truncated to complex64),
-// where t is a complex64 or complex128 type.
-func makeComplex(f flag, v complex128, t Type) Value {
- typ := t.common()
- ptr := unsafe_New(typ)
- switch typ.Size() {
- case 8:
- *(*complex64)(ptr) = complex64(v)
- case 16:
- *(*complex128)(ptr) = v
- }
- return Value{typ, ptr, f | flagIndir | flag(typ.Kind())}
-}
-
-func makeString(f flag, v string, t Type) Value {
- ret := New(t).Elem()
- ret.SetString(v)
- ret.flag = ret.flag&^flagAddr | f
- return ret
-}
-
-func makeBytes(f flag, v []byte, t Type) Value {
- ret := New(t).Elem()
- ret.SetBytes(v)
- ret.flag = ret.flag&^flagAddr | f
- return ret
-}
-
-func makeRunes(f flag, v []rune, t Type) Value {
- ret := New(t).Elem()
- ret.setRunes(v)
- ret.flag = ret.flag&^flagAddr | f
- return ret
-}
-
-// These conversion functions are returned by convertOp
-// for classes of conversions. For example, the first function, cvtInt,
-// takes any value v of signed int type and returns the value converted
-// to type t, where t is any signed or unsigned int type.
-
-// convertOp: intXX -> [u]intXX
-func cvtInt(v Value, t Type) Value {
- return makeInt(v.flag.ro(), uint64(v.Int()), t)
-}
-
-// convertOp: uintXX -> [u]intXX
-func cvtUint(v Value, t Type) Value {
- return makeInt(v.flag.ro(), v.Uint(), t)
-}
-
-// convertOp: floatXX -> intXX
-func cvtFloatInt(v Value, t Type) Value {
- return makeInt(v.flag.ro(), uint64(int64(v.Float())), t)
-}
-
-// convertOp: floatXX -> uintXX
-func cvtFloatUint(v Value, t Type) Value {
- return makeInt(v.flag.ro(), uint64(v.Float()), t)
-}
-
-// convertOp: intXX -> floatXX
-func cvtIntFloat(v Value, t Type) Value {
- return makeFloat(v.flag.ro(), float64(v.Int()), t)
-}
-
-// convertOp: uintXX -> floatXX
-func cvtUintFloat(v Value, t Type) Value {
- return makeFloat(v.flag.ro(), float64(v.Uint()), t)
-}
-
-// convertOp: floatXX -> floatXX
-func cvtFloat(v Value, t Type) Value {
- if v.Type().Kind() == Float32 && t.Kind() == Float32 {
- // Don't do any conversion if both types have underlying type float32.
- // This avoids converting to float64 and back, which will
- // convert a signaling NaN to a quiet NaN. See issue 36400.
- return makeFloat32(v.flag.ro(), *(*float32)(v.ptr), t)
- }
- return makeFloat(v.flag.ro(), v.Float(), t)
-}
-
-// convertOp: complexXX -> complexXX
-func cvtComplex(v Value, t Type) Value {
- return makeComplex(v.flag.ro(), v.Complex(), t)
-}
-
-// convertOp: intXX -> string
-func cvtIntString(v Value, t Type) Value {
- s := "\uFFFD"
- if x := v.Int(); int64(rune(x)) == x {
- s = string(rune(x))
- }
- return makeString(v.flag.ro(), s, t)
-}
-
-// convertOp: uintXX -> string
-func cvtUintString(v Value, t Type) Value {
- s := "\uFFFD"
- if x := v.Uint(); uint64(rune(x)) == x {
- s = string(rune(x))
- }
- return makeString(v.flag.ro(), s, t)
-}
-
-// convertOp: []byte -> string
-func cvtBytesString(v Value, t Type) Value {
- return makeString(v.flag.ro(), string(v.Bytes()), t)
-}
-
-// convertOp: string -> []byte
-func cvtStringBytes(v Value, t Type) Value {
- return makeBytes(v.flag.ro(), []byte(v.String()), t)
-}
-
-// convertOp: []rune -> string
-func cvtRunesString(v Value, t Type) Value {
- return makeString(v.flag.ro(), string(v.runes()), t)
-}
-
-// convertOp: string -> []rune
-func cvtStringRunes(v Value, t Type) Value {
- return makeRunes(v.flag.ro(), []rune(v.String()), t)
-}
-
-// convertOp: []T -> *[N]T
-func cvtSliceArrayPtr(v Value, t Type) Value {
- n := t.Elem().Len()
- if n > v.Len() {
- panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to pointer to array with length " + itoa.Itoa(n))
- }
- h := (*unsafeheader.Slice)(v.ptr)
- return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Pointer)}
-}
-
-// convertOp: []T -> [N]T
-func cvtSliceArray(v Value, t Type) Value {
- n := t.Len()
- if n > v.Len() {
- panic("reflect: cannot convert slice with length " + itoa.Itoa(v.Len()) + " to array with length " + itoa.Itoa(n))
- }
- h := (*unsafeheader.Slice)(v.ptr)
- typ := t.common()
- ptr := h.Data
- c := unsafe_New(typ)
- typedmemmove(typ, c, ptr)
- ptr = c
-
- return Value{typ, ptr, v.flag&^(flagAddr|flagKindMask) | flag(Array)}
-}
-
-// convertOp: direct copy
-func cvtDirect(v Value, typ Type) Value {
- f := v.flag
- t := typ.common()
- ptr := v.ptr
- if f&flagAddr != 0 {
- // indirect, mutable word - make a copy
- c := unsafe_New(t)
- typedmemmove(t, c, ptr)
- ptr = c
- f &^= flagAddr
- }
- return Value{t, ptr, v.flag.ro() | f} // v.flag.ro()|f == f?
-}
-
-// convertOp: concrete -> interface
-func cvtT2I(v Value, typ Type) Value {
- target := unsafe_New(typ.common())
- x := valueInterface(v, false)
- if typ.NumMethod() == 0 {
- *(*any)(target) = x
- } else {
- ifaceE2I(typ.common(), x, target)
- }
- return Value{typ.common(), target, v.flag.ro() | flagIndir | flag(Interface)}
-}
-
-// convertOp: interface -> interface
-func cvtI2I(v Value, typ Type) Value {
- if v.IsNil() {
- ret := Zero(typ)
- ret.flag |= v.flag.ro()
- return ret
- }
- return cvtT2I(v.Elem(), typ)
-}
-
-// implemented in ../runtime
-//
-//go:noescape
-func chancap(ch unsafe.Pointer) int
-
-//go:noescape
-func chanclose(ch unsafe.Pointer)
-
-//go:noescape
-func chanlen(ch unsafe.Pointer) int
-
-// Note: some of the noescape annotations below are technically a lie,
-// but safe in the context of this package. Functions like chansend0
-// and mapassign0 don't escape the referent, but may escape anything
-// the referent points to (they do shallow copies of the referent).
-// We add a 0 to their names and wrap them in functions with the
-// proper escape behavior.
-
-//go:noescape
-func chanrecv(ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)
-
-//go:noescape
-func chansend0(ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool
-
-func chansend(ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool {
- contentEscapes(val)
- return chansend0(ch, val, nb)
-}
-
-func makechan(typ *abi.Type, size int) (ch unsafe.Pointer)
-func makemap(t *abi.Type, cap int) (m unsafe.Pointer)
-
-//go:noescape
-func mapaccess(t *abi.Type, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
-
-//go:noescape
-func mapaccess_faststr(t *abi.Type, m unsafe.Pointer, key string) (val unsafe.Pointer)
-
-//go:noescape
-func mapassign0(t *abi.Type, m unsafe.Pointer, key, val unsafe.Pointer)
-
-func mapassign(t *abi.Type, m unsafe.Pointer, key, val unsafe.Pointer) {
- contentEscapes(key)
- contentEscapes(val)
- mapassign0(t, m, key, val)
-}
-
-//go:noescape
-func mapassign_faststr0(t *abi.Type, m unsafe.Pointer, key string, val unsafe.Pointer)
-
-func mapassign_faststr(t *abi.Type, m unsafe.Pointer, key string, val unsafe.Pointer) {
- contentEscapes((*unsafeheader.String)(unsafe.Pointer(&key)).Data)
- contentEscapes(val)
- mapassign_faststr0(t, m, key, val)
-}
-
-//go:noescape
-func mapdelete(t *abi.Type, m unsafe.Pointer, key unsafe.Pointer)
-
-//go:noescape
-func mapdelete_faststr(t *abi.Type, m unsafe.Pointer, key string)
-
-//go:noescape
-func mapiterinit(t *abi.Type, m unsafe.Pointer, it *hiter)
-
-//go:noescape
-func mapiterkey(it *hiter) (key unsafe.Pointer)
-
-//go:noescape
-func mapiterelem(it *hiter) (elem unsafe.Pointer)
-
-//go:noescape
-func mapiternext(it *hiter)
-
-//go:noescape
-func maplen(m unsafe.Pointer) int
-
-func mapclear(t *abi.Type, m unsafe.Pointer)
-
-// call calls fn with "stackArgsSize" bytes of stack arguments laid out
-// at stackArgs and register arguments laid out in regArgs. frameSize is
-// the total amount of stack space that will be reserved by call, so this
-// should include enough space to spill register arguments to the stack in
-// case of preemption.
-//
-// After fn returns, call copies stackArgsSize-stackRetOffset result bytes
-// back into stackArgs+stackRetOffset before returning, for any return
-// values passed on the stack. Register-based return values will be found
-// in the same regArgs structure.
-//
-// regArgs must also be prepared with an appropriate ReturnIsPtr bitmap
-// indicating which registers will contain pointer-valued return values. The
-// purpose of this bitmap is to keep pointers visible to the GC between
-// returning from reflectcall and actually using them.
-//
-// If copying result bytes back from the stack, the caller must pass the
-// argument frame type as stackArgsType, so that call can execute appropriate
-// write barriers during the copy.
-//
-// Arguments passed through to call do not escape. The type is used only in a
-// very limited callee of call, the stackArgs are copied, and regArgs is only
-// used in the call frame.
-//
-//go:noescape
-//go:linkname call runtime.reflectcall
-func call(stackArgsType *abi.Type, f, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
-
-func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
-
-// memmove copies size bytes to dst from src. No write barriers are used.
-//
-//go:noescape
-func memmove(dst, src unsafe.Pointer, size uintptr)
-
-// typedmemmove copies a value of type t to dst from src.
-//
-//go:noescape
-func typedmemmove(t *abi.Type, dst, src unsafe.Pointer)
-
-// typedmemclr zeros the value at ptr of type t.
-//
-//go:noescape
-func typedmemclr(t *abi.Type, ptr unsafe.Pointer)
-
-// typedmemclrpartial is like typedmemclr but assumes that
-// dst points off bytes into the value and only clears size bytes.
-//
-//go:noescape
-func typedmemclrpartial(t *abi.Type, ptr unsafe.Pointer, off, size uintptr)
-
-// typedslicecopy copies a slice of elemType values from src to dst,
-// returning the number of elements copied.
-//
-//go:noescape
-func typedslicecopy(t *abi.Type, dst, src unsafeheader.Slice) int
-
-// typedarrayclear zeroes the value at ptr of an array of elemType,
-// only clears len elem.
-//
-//go:noescape
-func typedarrayclear(elemType *abi.Type, ptr unsafe.Pointer, len int)
-
-//go:noescape
-func typehash(t *abi.Type, p unsafe.Pointer, h uintptr) uintptr
-
-func verifyNotInHeapPtr(p uintptr) bool
-
-//go:noescape
-func growslice(t *abi.Type, old unsafeheader.Slice, num int) unsafeheader.Slice
-
-// Dummy annotation marking that the value x escapes,
-// for use in cases where the reflect code is so clever that
-// the compiler cannot follow.
-func escapes(x any) {
- if dummy.b {
- dummy.x = x
- }
-}
-
-var dummy struct {
- b bool
- x any
-}
-
-// Dummy annotation marking that the content of value x
-// escapes (i.e. modeling roughly heap=*x),
-// for use in cases where the reflect code is so clever that
-// the compiler cannot follow.
-func contentEscapes(x unsafe.Pointer) {
- if dummy.b {
- escapes(*(*any)(x)) // the dereference may not always be safe, but never executed
- }
-}
-
-//go:nosplit
-func noescape(p unsafe.Pointer) unsafe.Pointer {
- x := uintptr(p)
- return unsafe.Pointer(x ^ 0)
-}
diff --git a/contrib/go/_std_1.22/src/reflect/ya.make b/contrib/go/_std_1.22/src/reflect/ya.make
deleted file mode 100644
index 49ccadde8e51..000000000000
--- a/contrib/go/_std_1.22/src/reflect/ya.make
+++ /dev/null
@@ -1,27 +0,0 @@
-GO_LIBRARY()
-IF (OS_DARWIN AND ARCH_ARM64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_ARM64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_AARCH64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- abi.go
- asm_arm64.s
- deepequal.go
- float32reg_generic.go
- makefunc.go
- swapper.go
- type.go
- value.go
- visiblefields.go
- )
-ELSEIF (OS_DARWIN AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_DARWIN AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_LINUX AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND RACE AND NOT CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND CGO_ENABLED OR OS_WINDOWS AND ARCH_X86_64 AND NOT RACE AND NOT CGO_ENABLED)
- SRCS(
- abi.go
- asm_amd64.s
- deepequal.go
- float32reg_generic.go
- makefunc.go
- swapper.go
- type.go
- value.go
- visiblefields.go
- )
-ENDIF()
-END()
diff --git a/contrib/go/_std_1.22/src/regexp/regexp.go b/contrib/go/_std_1.22/src/regexp/regexp.go
deleted file mode 100644
index 462f235b1bb1..000000000000
--- a/contrib/go/_std_1.22/src/regexp/regexp.go
+++ /dev/null
@@ -1,1304 +0,0 @@
-// Copyright 2009 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.
-
-// Package regexp implements regular expression search.
-//
-// The syntax of the regular expressions accepted is the same
-// general syntax used by Perl, Python, and other languages.
-// More precisely, it is the syntax accepted by RE2 and described at
-// https://golang.org/s/re2syntax, except for \C.
-// For an overview of the syntax, see the [regexp/syntax] package.
-//
-// The regexp implementation provided by this package is
-// guaranteed to run in time linear in the size of the input.
-// (This is a property not guaranteed by most open source
-// implementations of regular expressions.) For more information
-// about this property, see
-//
-// https://swtch.com/~rsc/regexp/regexp1.html
-//
-// or any book about automata theory.
-//
-// All characters are UTF-8-encoded code points.
-// Following [utf8.DecodeRune], each byte of an invalid UTF-8 sequence
-// is treated as if it encoded utf8.RuneError (U+FFFD).
-//
-// There are 16 methods of [Regexp] that match a regular expression and identify
-// the matched text. Their names are matched by this regular expression:
-//
-// Find(All)?(String)?(Submatch)?(Index)?
-//
-// If 'All' is present, the routine matches successive non-overlapping
-// matches of the entire expression. Empty matches abutting a preceding
-// match are ignored. The return value is a slice containing the successive
-// return values of the corresponding non-'All' routine. These routines take
-// an extra integer argument, n. If n >= 0, the function returns at most n
-// matches/submatches; otherwise, it returns all of them.
-//
-// If 'String' is present, the argument is a string; otherwise it is a slice
-// of bytes; return values are adjusted as appropriate.
-//
-// If 'Submatch' is present, the return value is a slice identifying the
-// successive submatches of the expression. Submatches are matches of
-// parenthesized subexpressions (also known as capturing groups) within the
-// regular expression, numbered from left to right in order of opening
-// parenthesis. Submatch 0 is the match of the entire expression, submatch 1 is
-// the match of the first parenthesized subexpression, and so on.
-//
-// If 'Index' is present, matches and submatches are identified by byte index
-// pairs within the input string: result[2*n:2*n+2] identifies the indexes of
-// the nth submatch. The pair for n==0 identifies the match of the entire
-// expression. If 'Index' is not present, the match is identified by the text
-// of the match/submatch. If an index is negative or text is nil, it means that
-// subexpression did not match any string in the input. For 'String' versions
-// an empty string means either no match or an empty match.
-//
-// There is also a subset of the methods that can be applied to text read
-// from a RuneReader:
-//
-// MatchReader, FindReaderIndex, FindReaderSubmatchIndex
-//
-// This set may grow. Note that regular expression matches may need to
-// examine text beyond the text returned by a match, so the methods that
-// match text from a RuneReader may read arbitrarily far into the input
-// before returning.
-//
-// (There are a few other methods that do not match this pattern.)
-package regexp
-
-import (
- "bytes"
- "io"
- "regexp/syntax"
- "strconv"
- "strings"
- "sync"
- "unicode"
- "unicode/utf8"
-)
-
-// Regexp is the representation of a compiled regular expression.
-// A Regexp is safe for concurrent use by multiple goroutines,
-// except for configuration methods, such as [Regexp.Longest].
-type Regexp struct {
- expr string // as passed to Compile
- prog *syntax.Prog // compiled program
- onepass *onePassProg // onepass program or nil
- numSubexp int
- maxBitStateLen int
- subexpNames []string
- prefix string // required prefix in unanchored matches
- prefixBytes []byte // prefix, as a []byte
- prefixRune rune // first rune in prefix
- prefixEnd uint32 // pc for last rune in prefix
- mpool int // pool for machines
- matchcap int // size of recorded match lengths
- prefixComplete bool // prefix is the entire regexp
- cond syntax.EmptyOp // empty-width conditions required at start of match
- minInputLen int // minimum length of the input in bytes
-
- // This field can be modified by the Longest method,
- // but it is otherwise read-only.
- longest bool // whether regexp prefers leftmost-longest match
-}
-
-// String returns the source text used to compile the regular expression.
-func (re *Regexp) String() string {
- return re.expr
-}
-
-// Copy returns a new [Regexp] object copied from re.
-// Calling [Regexp.Longest] on one copy does not affect another.
-//
-// Deprecated: In earlier releases, when using a [Regexp] in multiple goroutines,
-// giving each goroutine its own copy helped to avoid lock contention.
-// As of Go 1.12, using Copy is no longer necessary to avoid lock contention.
-// Copy may still be appropriate if the reason for its use is to make
-// two copies with different [Regexp.Longest] settings.
-func (re *Regexp) Copy() *Regexp {
- re2 := *re
- return &re2
-}
-
-// Compile parses a regular expression and returns, if successful,
-// a [Regexp] object that can be used to match against text.
-//
-// When matching against text, the regexp returns a match that
-// begins as early as possible in the input (leftmost), and among those
-// it chooses the one that a backtracking search would have found first.
-// This so-called leftmost-first matching is the same semantics
-// that Perl, Python, and other implementations use, although this
-// package implements it without the expense of backtracking.
-// For POSIX leftmost-longest matching, see [CompilePOSIX].
-func Compile(expr string) (*Regexp, error) {
- return compile(expr, syntax.Perl, false)
-}
-
-// CompilePOSIX is like [Compile] but restricts the regular expression
-// to POSIX ERE (egrep) syntax and changes the match semantics to
-// leftmost-longest.
-//
-// That is, when matching against text, the regexp returns a match that
-// begins as early as possible in the input (leftmost), and among those
-// it chooses a match that is as long as possible.
-// This so-called leftmost-longest matching is the same semantics
-// that early regular expression implementations used and that POSIX
-// specifies.
-//
-// However, there can be multiple leftmost-longest matches, with different
-// submatch choices, and here this package diverges from POSIX.
-// Among the possible leftmost-longest matches, this package chooses
-// the one that a backtracking search would have found first, while POSIX
-// specifies that the match be chosen to maximize the length of the first
-// subexpression, then the second, and so on from left to right.
-// The POSIX rule is computationally prohibitive and not even well-defined.
-// See https://swtch.com/~rsc/regexp/regexp2.html#posix for details.
-func CompilePOSIX(expr string) (*Regexp, error) {
- return compile(expr, syntax.POSIX, true)
-}
-
-// Longest makes future searches prefer the leftmost-longest match.
-// That is, when matching against text, the regexp returns a match that
-// begins as early as possible in the input (leftmost), and among those
-// it chooses a match that is as long as possible.
-// This method modifies the [Regexp] and may not be called concurrently
-// with any other methods.
-func (re *Regexp) Longest() {
- re.longest = true
-}
-
-func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, error) {
- re, err := syntax.Parse(expr, mode)
- if err != nil {
- return nil, err
- }
- maxCap := re.MaxCap()
- capNames := re.CapNames()
-
- re = re.Simplify()
- prog, err := syntax.Compile(re)
- if err != nil {
- return nil, err
- }
- matchcap := prog.NumCap
- if matchcap < 2 {
- matchcap = 2
- }
- regexp := &Regexp{
- expr: expr,
- prog: prog,
- onepass: compileOnePass(prog),
- numSubexp: maxCap,
- subexpNames: capNames,
- cond: prog.StartCond(),
- longest: longest,
- matchcap: matchcap,
- minInputLen: minInputLen(re),
- }
- if regexp.onepass == nil {
- regexp.prefix, regexp.prefixComplete = prog.Prefix()
- regexp.maxBitStateLen = maxBitStateLen(prog)
- } else {
- regexp.prefix, regexp.prefixComplete, regexp.prefixEnd = onePassPrefix(prog)
- }
- if regexp.prefix != "" {
- // TODO(rsc): Remove this allocation by adding
- // IndexString to package bytes.
- regexp.prefixBytes = []byte(regexp.prefix)
- regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
- }
-
- n := len(prog.Inst)
- i := 0
- for matchSize[i] != 0 && matchSize[i] < n {
- i++
- }
- regexp.mpool = i
-
- return regexp, nil
-}
-
-// Pools of *machine for use during (*Regexp).doExecute,
-// split up by the size of the execution queues.
-// matchPool[i] machines have queue size matchSize[i].
-// On a 64-bit system each queue entry is 16 bytes,
-// so matchPool[0] has 16*2*128 = 4kB queues, etc.
-// The final matchPool is a catch-all for very large queues.
-var (
- matchSize = [...]int{128, 512, 2048, 16384, 0}
- matchPool [len(matchSize)]sync.Pool
-)
-
-// get returns a machine to use for matching re.
-// It uses the re's machine cache if possible, to avoid
-// unnecessary allocation.
-func (re *Regexp) get() *machine {
- m, ok := matchPool[re.mpool].Get().(*machine)
- if !ok {
- m = new(machine)
- }
- m.re = re
- m.p = re.prog
- if cap(m.matchcap) < re.matchcap {
- m.matchcap = make([]int, re.matchcap)
- for _, t := range m.pool {
- t.cap = make([]int, re.matchcap)
- }
- }
-
- // Allocate queues if needed.
- // Or reallocate, for "large" match pool.
- n := matchSize[re.mpool]
- if n == 0 { // large pool
- n = len(re.prog.Inst)
- }
- if len(m.q0.sparse) < n {
- m.q0 = queue{make([]uint32, n), make([]entry, 0, n)}
- m.q1 = queue{make([]uint32, n), make([]entry, 0, n)}
- }
- return m
-}
-
-// put returns a machine to the correct machine pool.
-func (re *Regexp) put(m *machine) {
- m.re = nil
- m.p = nil
- m.inputs.clear()
- matchPool[re.mpool].Put(m)
-}
-
-// minInputLen walks the regexp to find the minimum length of any matchable input.
-func minInputLen(re *syntax.Regexp) int {
- switch re.Op {
- default:
- return 0
- case syntax.OpAnyChar, syntax.OpAnyCharNotNL, syntax.OpCharClass:
- return 1
- case syntax.OpLiteral:
- l := 0
- for _, r := range re.Rune {
- if r == utf8.RuneError {
- l++
- } else {
- l += utf8.RuneLen(r)
- }
- }
- return l
- case syntax.OpCapture, syntax.OpPlus:
- return minInputLen(re.Sub[0])
- case syntax.OpRepeat:
- return re.Min * minInputLen(re.Sub[0])
- case syntax.OpConcat:
- l := 0
- for _, sub := range re.Sub {
- l += minInputLen(sub)
- }
- return l
- case syntax.OpAlternate:
- l := minInputLen(re.Sub[0])
- var lnext int
- for _, sub := range re.Sub[1:] {
- lnext = minInputLen(sub)
- if lnext < l {
- l = lnext
- }
- }
- return l
- }
-}
-
-// MustCompile is like [Compile] but panics if the expression cannot be parsed.
-// It simplifies safe initialization of global variables holding compiled regular
-// expressions.
-func MustCompile(str string) *Regexp {
- regexp, err := Compile(str)
- if err != nil {
- panic(`regexp: Compile(` + quote(str) + `): ` + err.Error())
- }
- return regexp
-}
-
-// MustCompilePOSIX is like [CompilePOSIX] but panics if the expression cannot be parsed.
-// It simplifies safe initialization of global variables holding compiled regular
-// expressions.
-func MustCompilePOSIX(str string) *Regexp {
- regexp, err := CompilePOSIX(str)
- if err != nil {
- panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + err.Error())
- }
- return regexp
-}
-
-func quote(s string) string {
- if strconv.CanBackquote(s) {
- return "`" + s + "`"
- }
- return strconv.Quote(s)
-}
-
-// NumSubexp returns the number of parenthesized subexpressions in this [Regexp].
-func (re *Regexp) NumSubexp() int {
- return re.numSubexp
-}
-
-// SubexpNames returns the names of the parenthesized subexpressions
-// in this [Regexp]. The name for the first sub-expression is names[1],
-// so that if m is a match slice, the name for m[i] is SubexpNames()[i].
-// Since the Regexp as a whole cannot be named, names[0] is always
-// the empty string. The slice should not be modified.
-func (re *Regexp) SubexpNames() []string {
- return re.subexpNames
-}
-
-// SubexpIndex returns the index of the first subexpression with the given name,
-// or -1 if there is no subexpression with that name.
-//
-// Note that multiple subexpressions can be written using the same name, as in
-// (?Pa+)(?Pb+), which declares two subexpressions named "bob".
-// In this case, SubexpIndex returns the index of the leftmost such subexpression
-// in the regular expression.
-func (re *Regexp) SubexpIndex(name string) int {
- if name != "" {
- for i, s := range re.subexpNames {
- if name == s {
- return i
- }
- }
- }
- return -1
-}
-
-const endOfText rune = -1
-
-// input abstracts different representations of the input text. It provides
-// one-character lookahead.
-type input interface {
- step(pos int) (r rune, width int) // advance one rune
- canCheckPrefix() bool // can we look ahead without losing info?
- hasPrefix(re *Regexp) bool
- index(re *Regexp, pos int) int
- context(pos int) lazyFlag
-}
-
-// inputString scans a string.
-type inputString struct {
- str string
-}
-
-func (i *inputString) step(pos int) (rune, int) {
- if pos < len(i.str) {
- c := i.str[pos]
- if c < utf8.RuneSelf {
- return rune(c), 1
- }
- return utf8.DecodeRuneInString(i.str[pos:])
- }
- return endOfText, 0
-}
-
-func (i *inputString) canCheckPrefix() bool {
- return true
-}
-
-func (i *inputString) hasPrefix(re *Regexp) bool {
- return strings.HasPrefix(i.str, re.prefix)
-}
-
-func (i *inputString) index(re *Regexp, pos int) int {
- return strings.Index(i.str[pos:], re.prefix)
-}
-
-func (i *inputString) context(pos int) lazyFlag {
- r1, r2 := endOfText, endOfText
- // 0 < pos && pos <= len(i.str)
- if uint(pos-1) < uint(len(i.str)) {
- r1 = rune(i.str[pos-1])
- if r1 >= utf8.RuneSelf {
- r1, _ = utf8.DecodeLastRuneInString(i.str[:pos])
- }
- }
- // 0 <= pos && pos < len(i.str)
- if uint(pos) < uint(len(i.str)) {
- r2 = rune(i.str[pos])
- if r2 >= utf8.RuneSelf {
- r2, _ = utf8.DecodeRuneInString(i.str[pos:])
- }
- }
- return newLazyFlag(r1, r2)
-}
-
-// inputBytes scans a byte slice.
-type inputBytes struct {
- str []byte
-}
-
-func (i *inputBytes) step(pos int) (rune, int) {
- if pos < len(i.str) {
- c := i.str[pos]
- if c < utf8.RuneSelf {
- return rune(c), 1
- }
- return utf8.DecodeRune(i.str[pos:])
- }
- return endOfText, 0
-}
-
-func (i *inputBytes) canCheckPrefix() bool {
- return true
-}
-
-func (i *inputBytes) hasPrefix(re *Regexp) bool {
- return bytes.HasPrefix(i.str, re.prefixBytes)
-}
-
-func (i *inputBytes) index(re *Regexp, pos int) int {
- return bytes.Index(i.str[pos:], re.prefixBytes)
-}
-
-func (i *inputBytes) context(pos int) lazyFlag {
- r1, r2 := endOfText, endOfText
- // 0 < pos && pos <= len(i.str)
- if uint(pos-1) < uint(len(i.str)) {
- r1 = rune(i.str[pos-1])
- if r1 >= utf8.RuneSelf {
- r1, _ = utf8.DecodeLastRune(i.str[:pos])
- }
- }
- // 0 <= pos && pos < len(i.str)
- if uint(pos) < uint(len(i.str)) {
- r2 = rune(i.str[pos])
- if r2 >= utf8.RuneSelf {
- r2, _ = utf8.DecodeRune(i.str[pos:])
- }
- }
- return newLazyFlag(r1, r2)
-}
-
-// inputReader scans a RuneReader.
-type inputReader struct {
- r io.RuneReader
- atEOT bool
- pos int
-}
-
-func (i *inputReader) step(pos int) (rune, int) {
- if !i.atEOT && pos != i.pos {
- return endOfText, 0
-
- }
- r, w, err := i.r.ReadRune()
- if err != nil {
- i.atEOT = true
- return endOfText, 0
- }
- i.pos += w
- return r, w
-}
-
-func (i *inputReader) canCheckPrefix() bool {
- return false
-}
-
-func (i *inputReader) hasPrefix(re *Regexp) bool {
- return false
-}
-
-func (i *inputReader) index(re *Regexp, pos int) int {
- return -1
-}
-
-func (i *inputReader) context(pos int) lazyFlag {
- return 0 // not used
-}
-
-// LiteralPrefix returns a literal string that must begin any match
-// of the regular expression re. It returns the boolean true if the
-// literal string comprises the entire regular expression.
-func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
- return re.prefix, re.prefixComplete
-}
-
-// MatchReader reports whether the text returned by the [io.RuneReader]
-// contains any match of the regular expression re.
-func (re *Regexp) MatchReader(r io.RuneReader) bool {
- return re.doMatch(r, nil, "")
-}
-
-// MatchString reports whether the string s
-// contains any match of the regular expression re.
-func (re *Regexp) MatchString(s string) bool {
- return re.doMatch(nil, nil, s)
-}
-
-// Match reports whether the byte slice b
-// contains any match of the regular expression re.
-func (re *Regexp) Match(b []byte) bool {
- return re.doMatch(nil, b, "")
-}
-
-// MatchReader reports whether the text returned by the RuneReader
-// contains any match of the regular expression pattern.
-// More complicated queries need to use [Compile] and the full [Regexp] interface.
-func MatchReader(pattern string, r io.RuneReader) (matched bool, err error) {
- re, err := Compile(pattern)
- if err != nil {
- return false, err
- }
- return re.MatchReader(r), nil
-}
-
-// MatchString reports whether the string s
-// contains any match of the regular expression pattern.
-// More complicated queries need to use [Compile] and the full [Regexp] interface.
-func MatchString(pattern string, s string) (matched bool, err error) {
- re, err := Compile(pattern)
- if err != nil {
- return false, err
- }
- return re.MatchString(s), nil
-}
-
-// Match reports whether the byte slice b
-// contains any match of the regular expression pattern.
-// More complicated queries need to use [Compile] and the full [Regexp] interface.
-func Match(pattern string, b []byte) (matched bool, err error) {
- re, err := Compile(pattern)
- if err != nil {
- return false, err
- }
- return re.Match(b), nil
-}
-
-// ReplaceAllString returns a copy of src, replacing matches of the [Regexp]
-// with the replacement string repl.
-// Inside repl, $ signs are interpreted as in [Regexp.Expand].
-func (re *Regexp) ReplaceAllString(src, repl string) string {
- n := 2
- if strings.Contains(repl, "$") {
- n = 2 * (re.numSubexp + 1)
- }
- b := re.replaceAll(nil, src, n, func(dst []byte, match []int) []byte {
- return re.expand(dst, repl, nil, src, match)
- })
- return string(b)
-}
-
-// ReplaceAllLiteralString returns a copy of src, replacing matches of the [Regexp]
-// with the replacement string repl. The replacement repl is substituted directly,
-// without using [Regexp.Expand].
-func (re *Regexp) ReplaceAllLiteralString(src, repl string) string {
- return string(re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte {
- return append(dst, repl...)
- }))
-}
-
-// ReplaceAllStringFunc returns a copy of src in which all matches of the
-// [Regexp] have been replaced by the return value of function repl applied
-// to the matched substring. The replacement returned by repl is substituted
-// directly, without using [Regexp.Expand].
-func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
- b := re.replaceAll(nil, src, 2, func(dst []byte, match []int) []byte {
- return append(dst, repl(src[match[0]:match[1]])...)
- })
- return string(b)
-}
-
-func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst []byte, m []int) []byte) []byte {
- lastMatchEnd := 0 // end position of the most recent match
- searchPos := 0 // position where we next look for a match
- var buf []byte
- var endPos int
- if bsrc != nil {
- endPos = len(bsrc)
- } else {
- endPos = len(src)
- }
- if nmatch > re.prog.NumCap {
- nmatch = re.prog.NumCap
- }
-
- var dstCap [2]int
- for searchPos <= endPos {
- a := re.doExecute(nil, bsrc, src, searchPos, nmatch, dstCap[:0])
- if len(a) == 0 {
- break // no more matches
- }
-
- // Copy the unmatched characters before this match.
- if bsrc != nil {
- buf = append(buf, bsrc[lastMatchEnd:a[0]]...)
- } else {
- buf = append(buf, src[lastMatchEnd:a[0]]...)
- }
-
- // Now insert a copy of the replacement string, but not for a
- // match of the empty string immediately after another match.
- // (Otherwise, we get double replacement for patterns that
- // match both empty and nonempty strings.)
- if a[1] > lastMatchEnd || a[0] == 0 {
- buf = repl(buf, a)
- }
- lastMatchEnd = a[1]
-
- // Advance past this match; always advance at least one character.
- var width int
- if bsrc != nil {
- _, width = utf8.DecodeRune(bsrc[searchPos:])
- } else {
- _, width = utf8.DecodeRuneInString(src[searchPos:])
- }
- if searchPos+width > a[1] {
- searchPos += width
- } else if searchPos+1 > a[1] {
- // This clause is only needed at the end of the input
- // string. In that case, DecodeRuneInString returns width=0.
- searchPos++
- } else {
- searchPos = a[1]
- }
- }
-
- // Copy the unmatched characters after the last match.
- if bsrc != nil {
- buf = append(buf, bsrc[lastMatchEnd:]...)
- } else {
- buf = append(buf, src[lastMatchEnd:]...)
- }
-
- return buf
-}
-
-// ReplaceAll returns a copy of src, replacing matches of the [Regexp]
-// with the replacement text repl.
-// Inside repl, $ signs are interpreted as in [Regexp.Expand].
-func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
- n := 2
- if bytes.IndexByte(repl, '$') >= 0 {
- n = 2 * (re.numSubexp + 1)
- }
- srepl := ""
- b := re.replaceAll(src, "", n, func(dst []byte, match []int) []byte {
- if len(srepl) != len(repl) {
- srepl = string(repl)
- }
- return re.expand(dst, srepl, src, "", match)
- })
- return b
-}
-
-// ReplaceAllLiteral returns a copy of src, replacing matches of the [Regexp]
-// with the replacement bytes repl. The replacement repl is substituted directly,
-// without using [Regexp.Expand].
-func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte {
- return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte {
- return append(dst, repl...)
- })
-}
-
-// ReplaceAllFunc returns a copy of src in which all matches of the
-// [Regexp] have been replaced by the return value of function repl applied
-// to the matched byte slice. The replacement returned by repl is substituted
-// directly, without using [Regexp.Expand].
-func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
- return re.replaceAll(src, "", 2, func(dst []byte, match []int) []byte {
- return append(dst, repl(src[match[0]:match[1]])...)
- })
-}
-
-// Bitmap used by func special to check whether a character needs to be escaped.
-var specialBytes [16]byte
-
-// special reports whether byte b needs to be escaped by QuoteMeta.
-func special(b byte) bool {
- return b < utf8.RuneSelf && specialBytes[b%16]&(1<<(b/16)) != 0
-}
-
-func init() {
- for _, b := range []byte(`\.+*?()|[]{}^$`) {
- specialBytes[b%16] |= 1 << (b / 16)
- }
-}
-
-// QuoteMeta returns a string that escapes all regular expression metacharacters
-// inside the argument text; the returned string is a regular expression matching
-// the literal text.
-func QuoteMeta(s string) string {
- // A byte loop is correct because all metacharacters are ASCII.
- var i int
- for i = 0; i < len(s); i++ {
- if special(s[i]) {
- break
- }
- }
- // No meta characters found, so return original string.
- if i >= len(s) {
- return s
- }
-
- b := make([]byte, 2*len(s)-i)
- copy(b, s[:i])
- j := i
- for ; i < len(s); i++ {
- if special(s[i]) {
- b[j] = '\\'
- j++
- }
- b[j] = s[i]
- j++
- }
- return string(b[:j])
-}
-
-// The number of capture values in the program may correspond
-// to fewer capturing expressions than are in the regexp.
-// For example, "(a){0}" turns into an empty program, so the
-// maximum capture in the program is 0 but we need to return
-// an expression for \1. Pad appends -1s to the slice a as needed.
-func (re *Regexp) pad(a []int) []int {
- if a == nil {
- // No match.
- return nil
- }
- n := (1 + re.numSubexp) * 2
- for len(a) < n {
- a = append(a, -1)
- }
- return a
-}
-
-// allMatches calls deliver at most n times
-// with the location of successive matches in the input text.
-// The input text is b if non-nil, otherwise s.
-func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
- var end int
- if b == nil {
- end = len(s)
- } else {
- end = len(b)
- }
-
- for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
- matches := re.doExecute(nil, b, s, pos, re.prog.NumCap, nil)
- if len(matches) == 0 {
- break
- }
-
- accept := true
- if matches[1] == pos {
- // We've found an empty match.
- if matches[0] == prevMatchEnd {
- // We don't allow an empty match right
- // after a previous match, so ignore it.
- accept = false
- }
- var width int
- if b == nil {
- is := inputString{str: s}
- _, width = is.step(pos)
- } else {
- ib := inputBytes{str: b}
- _, width = ib.step(pos)
- }
- if width > 0 {
- pos += width
- } else {
- pos = end + 1
- }
- } else {
- pos = matches[1]
- }
- prevMatchEnd = matches[1]
-
- if accept {
- deliver(re.pad(matches))
- i++
- }
- }
-}
-
-// Find returns a slice holding the text of the leftmost match in b of the regular expression.
-// A return value of nil indicates no match.
-func (re *Regexp) Find(b []byte) []byte {
- var dstCap [2]int
- a := re.doExecute(nil, b, "", 0, 2, dstCap[:0])
- if a == nil {
- return nil
- }
- return b[a[0]:a[1]:a[1]]
-}
-
-// FindIndex returns a two-element slice of integers defining the location of
-// the leftmost match in b of the regular expression. The match itself is at
-// b[loc[0]:loc[1]].
-// A return value of nil indicates no match.
-func (re *Regexp) FindIndex(b []byte) (loc []int) {
- a := re.doExecute(nil, b, "", 0, 2, nil)
- if a == nil {
- return nil
- }
- return a[0:2]
-}
-
-// FindString returns a string holding the text of the leftmost match in s of the regular
-// expression. If there is no match, the return value is an empty string,
-// but it will also be empty if the regular expression successfully matches
-// an empty string. Use [Regexp.FindStringIndex] or [Regexp.FindStringSubmatch] if it is
-// necessary to distinguish these cases.
-func (re *Regexp) FindString(s string) string {
- var dstCap [2]int
- a := re.doExecute(nil, nil, s, 0, 2, dstCap[:0])
- if a == nil {
- return ""
- }
- return s[a[0]:a[1]]
-}
-
-// FindStringIndex returns a two-element slice of integers defining the
-// location of the leftmost match in s of the regular expression. The match
-// itself is at s[loc[0]:loc[1]].
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringIndex(s string) (loc []int) {
- a := re.doExecute(nil, nil, s, 0, 2, nil)
- if a == nil {
- return nil
- }
- return a[0:2]
-}
-
-// FindReaderIndex returns a two-element slice of integers defining the
-// location of the leftmost match of the regular expression in text read from
-// the [io.RuneReader]. The match text was found in the input stream at
-// byte offset loc[0] through loc[1]-1.
-// A return value of nil indicates no match.
-func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
- a := re.doExecute(r, nil, "", 0, 2, nil)
- if a == nil {
- return nil
- }
- return a[0:2]
-}
-
-// FindSubmatch returns a slice of slices holding the text of the leftmost
-// match of the regular expression in b and the matches, if any, of its
-// subexpressions, as defined by the 'Submatch' descriptions in the package
-// comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindSubmatch(b []byte) [][]byte {
- var dstCap [4]int
- a := re.doExecute(nil, b, "", 0, re.prog.NumCap, dstCap[:0])
- if a == nil {
- return nil
- }
- ret := make([][]byte, 1+re.numSubexp)
- for i := range ret {
- if 2*i < len(a) && a[2*i] >= 0 {
- ret[i] = b[a[2*i]:a[2*i+1]:a[2*i+1]]
- }
- }
- return ret
-}
-
-// Expand appends template to dst and returns the result; during the
-// append, Expand replaces variables in the template with corresponding
-// matches drawn from src. The match slice should have been returned by
-// [Regexp.FindSubmatchIndex].
-//
-// In the template, a variable is denoted by a substring of the form
-// $name or ${name}, where name is a non-empty sequence of letters,
-// digits, and underscores. A purely numeric name like $1 refers to
-// the submatch with the corresponding index; other names refer to
-// capturing parentheses named with the (?P...) syntax. A
-// reference to an out of range or unmatched index or a name that is not
-// present in the regular expression is replaced with an empty slice.
-//
-// In the $name form, name is taken to be as long as possible: $1x is
-// equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0.
-//
-// To insert a literal $ in the output, use $$ in the template.
-func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte {
- return re.expand(dst, string(template), src, "", match)
-}
-
-// ExpandString is like [Regexp.Expand] but the template and source are strings.
-// It appends to and returns a byte slice in order to give the calling
-// code control over allocation.
-func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte {
- return re.expand(dst, template, nil, src, match)
-}
-
-func (re *Regexp) expand(dst []byte, template string, bsrc []byte, src string, match []int) []byte {
- for len(template) > 0 {
- before, after, ok := strings.Cut(template, "$")
- if !ok {
- break
- }
- dst = append(dst, before...)
- template = after
- if template != "" && template[0] == '$' {
- // Treat $$ as $.
- dst = append(dst, '$')
- template = template[1:]
- continue
- }
- name, num, rest, ok := extract(template)
- if !ok {
- // Malformed; treat $ as raw text.
- dst = append(dst, '$')
- continue
- }
- template = rest
- if num >= 0 {
- if 2*num+1 < len(match) && match[2*num] >= 0 {
- if bsrc != nil {
- dst = append(dst, bsrc[match[2*num]:match[2*num+1]]...)
- } else {
- dst = append(dst, src[match[2*num]:match[2*num+1]]...)
- }
- }
- } else {
- for i, namei := range re.subexpNames {
- if name == namei && 2*i+1 < len(match) && match[2*i] >= 0 {
- if bsrc != nil {
- dst = append(dst, bsrc[match[2*i]:match[2*i+1]]...)
- } else {
- dst = append(dst, src[match[2*i]:match[2*i+1]]...)
- }
- break
- }
- }
- }
- }
- dst = append(dst, template...)
- return dst
-}
-
-// extract returns the name from a leading "name" or "{name}" in str.
-// (The $ has already been removed by the caller.)
-// If it is a number, extract returns num set to that number; otherwise num = -1.
-func extract(str string) (name string, num int, rest string, ok bool) {
- if str == "" {
- return
- }
- brace := false
- if str[0] == '{' {
- brace = true
- str = str[1:]
- }
- i := 0
- for i < len(str) {
- rune, size := utf8.DecodeRuneInString(str[i:])
- if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' {
- break
- }
- i += size
- }
- if i == 0 {
- // empty name is not okay
- return
- }
- name = str[:i]
- if brace {
- if i >= len(str) || str[i] != '}' {
- // missing closing brace
- return
- }
- i++
- }
-
- // Parse number.
- num = 0
- for i := 0; i < len(name); i++ {
- if name[i] < '0' || '9' < name[i] || num >= 1e8 {
- num = -1
- break
- }
- num = num*10 + int(name[i]) - '0'
- }
- // Disallow leading zeros.
- if name[0] == '0' && len(name) > 1 {
- num = -1
- }
-
- rest = str[i:]
- ok = true
- return
-}
-
-// FindSubmatchIndex returns a slice holding the index pairs identifying the
-// leftmost match of the regular expression in b and the matches, if any, of
-// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindSubmatchIndex(b []byte) []int {
- return re.pad(re.doExecute(nil, b, "", 0, re.prog.NumCap, nil))
-}
-
-// FindStringSubmatch returns a slice of strings holding the text of the
-// leftmost match of the regular expression in s and the matches, if any, of
-// its subexpressions, as defined by the 'Submatch' description in the
-// package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringSubmatch(s string) []string {
- var dstCap [4]int
- a := re.doExecute(nil, nil, s, 0, re.prog.NumCap, dstCap[:0])
- if a == nil {
- return nil
- }
- ret := make([]string, 1+re.numSubexp)
- for i := range ret {
- if 2*i < len(a) && a[2*i] >= 0 {
- ret[i] = s[a[2*i]:a[2*i+1]]
- }
- }
- return ret
-}
-
-// FindStringSubmatchIndex returns a slice holding the index pairs
-// identifying the leftmost match of the regular expression in s and the
-// matches, if any, of its subexpressions, as defined by the 'Submatch' and
-// 'Index' descriptions in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringSubmatchIndex(s string) []int {
- return re.pad(re.doExecute(nil, nil, s, 0, re.prog.NumCap, nil))
-}
-
-// FindReaderSubmatchIndex returns a slice holding the index pairs
-// identifying the leftmost match of the regular expression of text read by
-// the [io.RuneReader], and the matches, if any, of its subexpressions, as defined
-// by the 'Submatch' and 'Index' descriptions in the package comment. A
-// return value of nil indicates no match.
-func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
- return re.pad(re.doExecute(r, nil, "", 0, re.prog.NumCap, nil))
-}
-
-const startSize = 10 // The size at which to start a slice in the 'All' routines.
-
-// FindAll is the 'All' version of Find; it returns a slice of all successive
-// matches of the expression, as defined by the 'All' description in the
-// package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAll(b []byte, n int) [][]byte {
- if n < 0 {
- n = len(b) + 1
- }
- var result [][]byte
- re.allMatches("", b, n, func(match []int) {
- if result == nil {
- result = make([][]byte, 0, startSize)
- }
- result = append(result, b[match[0]:match[1]:match[1]])
- })
- return result
-}
-
-// FindAllIndex is the 'All' version of [Regexp.FindIndex]; it returns a slice of all
-// successive matches of the expression, as defined by the 'All' description
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
- if n < 0 {
- n = len(b) + 1
- }
- var result [][]int
- re.allMatches("", b, n, func(match []int) {
- if result == nil {
- result = make([][]int, 0, startSize)
- }
- result = append(result, match[0:2])
- })
- return result
-}
-
-// FindAllString is the 'All' version of [Regexp.FindString]; it returns a slice of all
-// successive matches of the expression, as defined by the 'All' description
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllString(s string, n int) []string {
- if n < 0 {
- n = len(s) + 1
- }
- var result []string
- re.allMatches(s, nil, n, func(match []int) {
- if result == nil {
- result = make([]string, 0, startSize)
- }
- result = append(result, s[match[0]:match[1]])
- })
- return result
-}
-
-// FindAllStringIndex is the 'All' version of [Regexp.FindStringIndex]; it returns a
-// slice of all successive matches of the expression, as defined by the 'All'
-// description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
- if n < 0 {
- n = len(s) + 1
- }
- var result [][]int
- re.allMatches(s, nil, n, func(match []int) {
- if result == nil {
- result = make([][]int, 0, startSize)
- }
- result = append(result, match[0:2])
- })
- return result
-}
-
-// FindAllSubmatch is the 'All' version of [Regexp.FindSubmatch]; it returns a slice
-// of all successive matches of the expression, as defined by the 'All'
-// description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
- if n < 0 {
- n = len(b) + 1
- }
- var result [][][]byte
- re.allMatches("", b, n, func(match []int) {
- if result == nil {
- result = make([][][]byte, 0, startSize)
- }
- slice := make([][]byte, len(match)/2)
- for j := range slice {
- if match[2*j] >= 0 {
- slice[j] = b[match[2*j]:match[2*j+1]:match[2*j+1]]
- }
- }
- result = append(result, slice)
- })
- return result
-}
-
-// FindAllSubmatchIndex is the 'All' version of [Regexp.FindSubmatchIndex]; it returns
-// a slice of all successive matches of the expression, as defined by the
-// 'All' description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
- if n < 0 {
- n = len(b) + 1
- }
- var result [][]int
- re.allMatches("", b, n, func(match []int) {
- if result == nil {
- result = make([][]int, 0, startSize)
- }
- result = append(result, match)
- })
- return result
-}
-
-// FindAllStringSubmatch is the 'All' version of [Regexp.FindStringSubmatch]; it
-// returns a slice of all successive matches of the expression, as defined by
-// the 'All' description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
- if n < 0 {
- n = len(s) + 1
- }
- var result [][]string
- re.allMatches(s, nil, n, func(match []int) {
- if result == nil {
- result = make([][]string, 0, startSize)
- }
- slice := make([]string, len(match)/2)
- for j := range slice {
- if match[2*j] >= 0 {
- slice[j] = s[match[2*j]:match[2*j+1]]
- }
- }
- result = append(result, slice)
- })
- return result
-}
-
-// FindAllStringSubmatchIndex is the 'All' version of
-// [Regexp.FindStringSubmatchIndex]; it returns a slice of all successive matches of
-// the expression, as defined by the 'All' description in the package
-// comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
- if n < 0 {
- n = len(s) + 1
- }
- var result [][]int
- re.allMatches(s, nil, n, func(match []int) {
- if result == nil {
- result = make([][]int, 0, startSize)
- }
- result = append(result, match)
- })
- return result
-}
-
-// Split slices s into substrings separated by the expression and returns a slice of
-// the substrings between those expression matches.
-//
-// The slice returned by this method consists of all the substrings of s
-// not contained in the slice returned by [Regexp.FindAllString]. When called on an expression
-// that contains no metacharacters, it is equivalent to [strings.SplitN].
-//
-// Example:
-//
-// s := regexp.MustCompile("a*").Split("abaabaccadaaae", 5)
-// // s: ["", "b", "b", "c", "cadaaae"]
-//
-// The count determines the number of substrings to return:
-//
-// n > 0: at most n substrings; the last substring will be the unsplit remainder.
-// n == 0: the result is nil (zero substrings)
-// n < 0: all substrings
-func (re *Regexp) Split(s string, n int) []string {
-
- if n == 0 {
- return nil
- }
-
- if len(re.expr) > 0 && len(s) == 0 {
- return []string{""}
- }
-
- matches := re.FindAllStringIndex(s, n)
- strings := make([]string, 0, len(matches))
-
- beg := 0
- end := 0
- for _, match := range matches {
- if n > 0 && len(strings) >= n-1 {
- break
- }
-
- end = match[0]
- if match[1] != 0 {
- strings = append(strings, s[beg:end])
- }
- beg = match[1]
- }
-
- if end != len(s) {
- strings = append(strings, s[beg:])
- }
-
- return strings
-}
-
-// MarshalText implements [encoding.TextMarshaler]. The output
-// matches that of calling the [Regexp.String] method.
-//
-// Note that the output is lossy in some cases: This method does not indicate
-// POSIX regular expressions (i.e. those compiled by calling [CompilePOSIX]), or
-// those for which the [Regexp.Longest] method has been called.
-func (re *Regexp) MarshalText() ([]byte, error) {
- return []byte(re.String()), nil
-}
-
-// UnmarshalText implements [encoding.TextUnmarshaler] by calling
-// [Compile] on the encoded value.
-func (re *Regexp) UnmarshalText(text []byte) error {
- newRE, err := Compile(string(text))
- if err != nil {
- return err
- }
- *re = *newRE
- return nil
-}
diff --git a/contrib/go/_std_1.22/src/regexp/syntax/doc.go b/contrib/go/_std_1.22/src/regexp/syntax/doc.go
deleted file mode 100644
index eb8a971c7348..000000000000
--- a/contrib/go/_std_1.22/src/regexp/syntax/doc.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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.
-
-// DO NOT EDIT. This file is generated by mksyntaxgo from the RE2 distribution.
-
-/*
-Package syntax parses regular expressions into parse trees and compiles
-parse trees into programs. Most clients of regular expressions will use the
-facilities of package regexp (such as Compile and Match) instead of this package.
-
-# Syntax
-
-The regular expression syntax understood by this package when parsing with the Perl flag is as follows.
-Parts of the syntax can be disabled by passing alternate flags to Parse.
-
-Single characters:
-
- . any character, possibly including newline (flag s=true)
- [xyz] character class
- [^xyz] negated character class
- \d Perl character class
- \D negated Perl character class
- [[:alpha:]] ASCII character class
- [[:^alpha:]] negated ASCII character class
- \pN Unicode character class (one-letter name)
- \p{Greek} Unicode character class
- \PN negated Unicode character class (one-letter name)
- \P{Greek} negated Unicode character class
-
-Composites:
-
- xy x followed by y
- x|y x or y (prefer x)
-
-Repetitions:
-
- x* zero or more x, prefer more
- x+ one or more x, prefer more
- x? zero or one x, prefer one
- x{n,m} n or n+1 or ... or m x, prefer more
- x{n,} n or more x, prefer more
- x{n} exactly n x
- x*? zero or more x, prefer fewer
- x+? one or more x, prefer fewer
- x?? zero or one x, prefer zero
- x{n,m}? n or n+1 or ... or m x, prefer fewer
- x{n,}? n or more x, prefer fewer
- x{n}? exactly n x
-
-Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n}
-reject forms that create a minimum or maximum repetition count above 1000.
-Unlimited repetitions are not subject to this restriction.
-
-Grouping:
-
- (re) numbered capturing group (submatch)
- (?Pre) named & numbered capturing group (submatch)
- (?re) named & numbered capturing group (submatch)
- (?:re) non-capturing group
- (?flags) set flags within current group; non-capturing
- (?flags:re) set flags during re; non-capturing
-
- Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are:
-
- i case-insensitive (default false)
- m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false)
- s let . match \n (default false)
- U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false)
-
-Empty strings:
-
- ^ at beginning of text or line (flag m=true)
- $ at end of text (like \z not \Z) or line (flag m=true)
- \A at beginning of text
- \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other)
- \B not at ASCII word boundary
- \z at end of text
-
-Escape sequences:
-
- \a bell (== \007)
- \f form feed (== \014)
- \t horizontal tab (== \011)
- \n newline (== \012)
- \r carriage return (== \015)
- \v vertical tab character (== \013)
- \* literal *, for any punctuation character *
- \123 octal character code (up to three digits)
- \x7F hex character code (exactly two digits)
- \x{10FFFF} hex character code
- \Q...\E literal text ... even if ... has punctuation
-
-Character class elements:
-
- x single character
- A-Z character range (inclusive)
- \d Perl character class
- [:foo:] ASCII character class foo
- \p{Foo} Unicode character class Foo
- \pF Unicode character class F (one-letter name)
-
-Named character classes as character class elements:
-
- [\d] digits (== \d)
- [^\d] not digits (== \D)
- [\D] not digits (== \D)
- [^\D] not not digits (== \d)
- [[:name:]] named ASCII class inside character class (== [:name:])
- [^[:name:]] named ASCII class inside negated character class (== [:^name:])
- [\p{Name}] named Unicode property inside character class (== \p{Name})
- [^\p{Name}] named Unicode property inside negated character class (== \P{Name})
-
-Perl character classes (all ASCII-only):
-
- \d digits (== [0-9])
- \D not digits (== [^0-9])
- \s whitespace (== [\t\n\f\r ])
- \S not whitespace (== [^\t\n\f\r ])
- \w word characters (== [0-9A-Za-z_])
- \W not word characters (== [^0-9A-Za-z_])
-
-ASCII character classes:
-
- [[:alnum:]] alphanumeric (== [0-9A-Za-z])
- [[:alpha:]] alphabetic (== [A-Za-z])
- [[:ascii:]] ASCII (== [\x00-\x7F])
- [[:blank:]] blank (== [\t ])
- [[:cntrl:]] control (== [\x00-\x1F\x7F])
- [[:digit:]] digits (== [0-9])
- [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
- [[:lower:]] lower case (== [a-z])
- [[:print:]] printable (== [ -~] == [ [:graph:]])
- [[:punct:]] punctuation (== [!-/:-@[-`{-~])
- [[:space:]] whitespace (== [\t\n\v\f\r ])
- [[:upper:]] upper case (== [A-Z])
- [[:word:]] word characters (== [0-9A-Za-z_])
- [[:xdigit:]] hex digit (== [0-9A-Fa-f])
-
-Unicode character classes are those in unicode.Categories and unicode.Scripts.
-*/
-package syntax
diff --git a/contrib/go/_std_1.22/src/regexp/syntax/parse.go b/contrib/go/_std_1.22/src/regexp/syntax/parse.go
deleted file mode 100644
index 6a11b53fb180..000000000000
--- a/contrib/go/_std_1.22/src/regexp/syntax/parse.go
+++ /dev/null
@@ -1,2138 +0,0 @@
-// Copyright 2011 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.
-
-package syntax
-
-import (
- "sort"
- "strings"
- "unicode"
- "unicode/utf8"
-)
-
-// An Error describes a failure to parse a regular expression
-// and gives the offending expression.
-type Error struct {
- Code ErrorCode
- Expr string
-}
-
-func (e *Error) Error() string {
- return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`"
-}
-
-// An ErrorCode describes a failure to parse a regular expression.
-type ErrorCode string
-
-const (
- // Unexpected error
- ErrInternalError ErrorCode = "regexp/syntax: internal error"
-
- // Parse errors
- ErrInvalidCharClass ErrorCode = "invalid character class"
- ErrInvalidCharRange ErrorCode = "invalid character class range"
- ErrInvalidEscape ErrorCode = "invalid escape sequence"
- ErrInvalidNamedCapture ErrorCode = "invalid named capture"
- ErrInvalidPerlOp ErrorCode = "invalid or unsupported Perl syntax"
- ErrInvalidRepeatOp ErrorCode = "invalid nested repetition operator"
- ErrInvalidRepeatSize ErrorCode = "invalid repeat count"
- ErrInvalidUTF8 ErrorCode = "invalid UTF-8"
- ErrMissingBracket ErrorCode = "missing closing ]"
- ErrMissingParen ErrorCode = "missing closing )"
- ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
- ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression"
- ErrUnexpectedParen ErrorCode = "unexpected )"
- ErrNestingDepth ErrorCode = "expression nests too deeply"
- ErrLarge ErrorCode = "expression too large"
-)
-
-func (e ErrorCode) String() string {
- return string(e)
-}
-
-// Flags control the behavior of the parser and record information about regexp context.
-type Flags uint16
-
-const (
- FoldCase Flags = 1 << iota // case-insensitive match
- Literal // treat pattern as literal string
- ClassNL // allow character classes like [^a-z] and [[:space:]] to match newline
- DotNL // allow . to match newline
- OneLine // treat ^ and $ as only matching at beginning and end of text
- NonGreedy // make repetition operators default to non-greedy
- PerlX // allow Perl extensions
- UnicodeGroups // allow \p{Han}, \P{Han} for Unicode group and negation
- WasDollar // regexp OpEndText was $, not \z
- Simple // regexp contains no counted repetition
-
- MatchNL = ClassNL | DotNL
-
- Perl = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible
- POSIX Flags = 0 // POSIX syntax
-)
-
-// Pseudo-ops for parsing stack.
-const (
- opLeftParen = opPseudo + iota
- opVerticalBar
-)
-
-// maxHeight is the maximum height of a regexp parse tree.
-// It is somewhat arbitrarily chosen, but the idea is to be large enough
-// that no one will actually hit in real use but at the same time small enough
-// that recursion on the Regexp tree will not hit the 1GB Go stack limit.
-// The maximum amount of stack for a single recursive frame is probably
-// closer to 1kB, so this could potentially be raised, but it seems unlikely
-// that people have regexps nested even this deeply.
-// We ran a test on Google's C++ code base and turned up only
-// a single use case with depth > 100; it had depth 128.
-// Using depth 1000 should be plenty of margin.
-// As an optimization, we don't even bother calculating heights
-// until we've allocated at least maxHeight Regexp structures.
-const maxHeight = 1000
-
-// maxSize is the maximum size of a compiled regexp in Insts.
-// It too is somewhat arbitrarily chosen, but the idea is to be large enough
-// to allow significant regexps while at the same time small enough that
-// the compiled form will not take up too much memory.
-// 128 MB is enough for a 3.3 million Inst structures, which roughly
-// corresponds to a 3.3 MB regexp.
-const (
- maxSize = 128 << 20 / instSize
- instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words
-)
-
-// maxRunes is the maximum number of runes allowed in a regexp tree
-// counting the runes in all the nodes.
-// Ignoring character classes p.numRunes is always less than the length of the regexp.
-// Character classes can make it much larger: each \pL adds 1292 runes.
-// 128 MB is enough for 32M runes, which is over 26k \pL instances.
-// Note that repetitions do not make copies of the rune slices,
-// so \pL{1000} is only one rune slice, not 1000.
-// We could keep a cache of character classes we've seen,
-// so that all the \pL we see use the same rune list,
-// but that doesn't remove the problem entirely:
-// consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()].
-// And because the Rune slice is exposed directly in the Regexp,
-// there is not an opportunity to change the representation to allow
-// partial sharing between different character classes.
-// So the limit is the best we can do.
-const (
- maxRunes = 128 << 20 / runeSize
- runeSize = 4 // rune is int32
-)
-
-type parser struct {
- flags Flags // parse mode flags
- stack []*Regexp // stack of parsed expressions
- free *Regexp
- numCap int // number of capturing groups seen
- wholeRegexp string
- tmpClass []rune // temporary char class work space
- numRegexp int // number of regexps allocated
- numRunes int // number of runes in char classes
- repeats int64 // product of all repetitions seen
- height map[*Regexp]int // regexp height, for height limit check
- size map[*Regexp]int64 // regexp compiled size, for size limit check
-}
-
-func (p *parser) newRegexp(op Op) *Regexp {
- re := p.free
- if re != nil {
- p.free = re.Sub0[0]
- *re = Regexp{}
- } else {
- re = new(Regexp)
- p.numRegexp++
- }
- re.Op = op
- return re
-}
-
-func (p *parser) reuse(re *Regexp) {
- if p.height != nil {
- delete(p.height, re)
- }
- re.Sub0[0] = p.free
- p.free = re
-}
-
-func (p *parser) checkLimits(re *Regexp) {
- if p.numRunes > maxRunes {
- panic(ErrLarge)
- }
- p.checkSize(re)
- p.checkHeight(re)
-}
-
-func (p *parser) checkSize(re *Regexp) {
- if p.size == nil {
- // We haven't started tracking size yet.
- // Do a relatively cheap check to see if we need to start.
- // Maintain the product of all the repeats we've seen
- // and don't track if the total number of regexp nodes
- // we've seen times the repeat product is in budget.
- if p.repeats == 0 {
- p.repeats = 1
- }
- if re.Op == OpRepeat {
- n := re.Max
- if n == -1 {
- n = re.Min
- }
- if n <= 0 {
- n = 1
- }
- if int64(n) > maxSize/p.repeats {
- p.repeats = maxSize
- } else {
- p.repeats *= int64(n)
- }
- }
- if int64(p.numRegexp) < maxSize/p.repeats {
- return
- }
-
- // We need to start tracking size.
- // Make the map and belatedly populate it
- // with info about everything we've constructed so far.
- p.size = make(map[*Regexp]int64)
- for _, re := range p.stack {
- p.checkSize(re)
- }
- }
-
- if p.calcSize(re, true) > maxSize {
- panic(ErrLarge)
- }
-}
-
-func (p *parser) calcSize(re *Regexp, force bool) int64 {
- if !force {
- if size, ok := p.size[re]; ok {
- return size
- }
- }
-
- var size int64
- switch re.Op {
- case OpLiteral:
- size = int64(len(re.Rune))
- case OpCapture, OpStar:
- // star can be 1+ or 2+; assume 2 pessimistically
- size = 2 + p.calcSize(re.Sub[0], false)
- case OpPlus, OpQuest:
- size = 1 + p.calcSize(re.Sub[0], false)
- case OpConcat:
- for _, sub := range re.Sub {
- size += p.calcSize(sub, false)
- }
- case OpAlternate:
- for _, sub := range re.Sub {
- size += p.calcSize(sub, false)
- }
- if len(re.Sub) > 1 {
- size += int64(len(re.Sub)) - 1
- }
- case OpRepeat:
- sub := p.calcSize(re.Sub[0], false)
- if re.Max == -1 {
- if re.Min == 0 {
- size = 2 + sub // x*
- } else {
- size = 1 + int64(re.Min)*sub // xxx+
- }
- break
- }
- // x{2,5} = xx(x(x(x)?)?)?
- size = int64(re.Max)*sub + int64(re.Max-re.Min)
- }
-
- if size < 1 {
- size = 1
- }
- p.size[re] = size
- return size
-}
-
-func (p *parser) checkHeight(re *Regexp) {
- if p.numRegexp < maxHeight {
- return
- }
- if p.height == nil {
- p.height = make(map[*Regexp]int)
- for _, re := range p.stack {
- p.checkHeight(re)
- }
- }
- if p.calcHeight(re, true) > maxHeight {
- panic(ErrNestingDepth)
- }
-}
-
-func (p *parser) calcHeight(re *Regexp, force bool) int {
- if !force {
- if h, ok := p.height[re]; ok {
- return h
- }
- }
- h := 1
- for _, sub := range re.Sub {
- hsub := p.calcHeight(sub, false)
- if h < 1+hsub {
- h = 1 + hsub
- }
- }
- p.height[re] = h
- return h
-}
-
-// Parse stack manipulation.
-
-// push pushes the regexp re onto the parse stack and returns the regexp.
-func (p *parser) push(re *Regexp) *Regexp {
- p.numRunes += len(re.Rune)
- if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
- // Single rune.
- if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
- return nil
- }
- re.Op = OpLiteral
- re.Rune = re.Rune[:1]
- re.Flags = p.flags &^ FoldCase
- } else if re.Op == OpCharClass && len(re.Rune) == 4 &&
- re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] &&
- unicode.SimpleFold(re.Rune[0]) == re.Rune[2] &&
- unicode.SimpleFold(re.Rune[2]) == re.Rune[0] ||
- re.Op == OpCharClass && len(re.Rune) == 2 &&
- re.Rune[0]+1 == re.Rune[1] &&
- unicode.SimpleFold(re.Rune[0]) == re.Rune[1] &&
- unicode.SimpleFold(re.Rune[1]) == re.Rune[0] {
- // Case-insensitive rune like [Aa] or [Δδ].
- if p.maybeConcat(re.Rune[0], p.flags|FoldCase) {
- return nil
- }
-
- // Rewrite as (case-insensitive) literal.
- re.Op = OpLiteral
- re.Rune = re.Rune[:1]
- re.Flags = p.flags | FoldCase
- } else {
- // Incremental concatenation.
- p.maybeConcat(-1, 0)
- }
-
- p.stack = append(p.stack, re)
- p.checkLimits(re)
- return re
-}
-
-// maybeConcat implements incremental concatenation
-// of literal runes into string nodes. The parser calls this
-// before each push, so only the top fragment of the stack
-// might need processing. Since this is called before a push,
-// the topmost literal is no longer subject to operators like *
-// (Otherwise ab* would turn into (ab)*.)
-// If r >= 0 and there's a node left over, maybeConcat uses it
-// to push r with the given flags.
-// maybeConcat reports whether r was pushed.
-func (p *parser) maybeConcat(r rune, flags Flags) bool {
- n := len(p.stack)
- if n < 2 {
- return false
- }
-
- re1 := p.stack[n-1]
- re2 := p.stack[n-2]
- if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase {
- return false
- }
-
- // Push re1 into re2.
- re2.Rune = append(re2.Rune, re1.Rune...)
-
- // Reuse re1 if possible.
- if r >= 0 {
- re1.Rune = re1.Rune0[:1]
- re1.Rune[0] = r
- re1.Flags = flags
- return true
- }
-
- p.stack = p.stack[:n-1]
- p.reuse(re1)
- return false // did not push r
-}
-
-// literal pushes a literal regexp for the rune r on the stack.
-func (p *parser) literal(r rune) {
- re := p.newRegexp(OpLiteral)
- re.Flags = p.flags
- if p.flags&FoldCase != 0 {
- r = minFoldRune(r)
- }
- re.Rune0[0] = r
- re.Rune = re.Rune0[:1]
- p.push(re)
-}
-
-// minFoldRune returns the minimum rune fold-equivalent to r.
-func minFoldRune(r rune) rune {
- if r < minFold || r > maxFold {
- return r
- }
- m := r
- r0 := r
- for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) {
- m = min(m, r)
- }
- return m
-}
-
-// op pushes a regexp with the given op onto the stack
-// and returns that regexp.
-func (p *parser) op(op Op) *Regexp {
- re := p.newRegexp(op)
- re.Flags = p.flags
- return p.push(re)
-}
-
-// repeat replaces the top stack element with itself repeated according to op, min, max.
-// before is the regexp suffix starting at the repetition operator.
-// after is the regexp suffix following after the repetition operator.
-// repeat returns an updated 'after' and an error, if any.
-func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (string, error) {
- flags := p.flags
- if p.flags&PerlX != 0 {
- if len(after) > 0 && after[0] == '?' {
- after = after[1:]
- flags ^= NonGreedy
- }
- if lastRepeat != "" {
- // In Perl it is not allowed to stack repetition operators:
- // a** is a syntax error, not a doubled star, and a++ means
- // something else entirely, which we don't support!
- return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]}
- }
- }
- n := len(p.stack)
- if n == 0 {
- return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
- }
- sub := p.stack[n-1]
- if sub.Op >= opPseudo {
- return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
- }
-
- re := p.newRegexp(op)
- re.Min = min
- re.Max = max
- re.Flags = flags
- re.Sub = re.Sub0[:1]
- re.Sub[0] = sub
- p.stack[n-1] = re
- p.checkLimits(re)
-
- if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
- return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
- }
-
- return after, nil
-}
-
-// repeatIsValid reports whether the repetition re is valid.
-// Valid means that the combination of the top-level repetition
-// and any inner repetitions does not exceed n copies of the
-// innermost thing.
-// This function rewalks the regexp tree and is called for every repetition,
-// so we have to worry about inducing quadratic behavior in the parser.
-// We avoid this by only calling repeatIsValid when min or max >= 2.
-// In that case the depth of any >= 2 nesting can only get to 9 without
-// triggering a parse error, so each subtree can only be rewalked 9 times.
-func repeatIsValid(re *Regexp, n int) bool {
- if re.Op == OpRepeat {
- m := re.Max
- if m == 0 {
- return true
- }
- if m < 0 {
- m = re.Min
- }
- if m > n {
- return false
- }
- if m > 0 {
- n /= m
- }
- }
- for _, sub := range re.Sub {
- if !repeatIsValid(sub, n) {
- return false
- }
- }
- return true
-}
-
-// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
-func (p *parser) concat() *Regexp {
- p.maybeConcat(-1, 0)
-
- // Scan down to find pseudo-operator | or (.
- i := len(p.stack)
- for i > 0 && p.stack[i-1].Op < opPseudo {
- i--
- }
- subs := p.stack[i:]
- p.stack = p.stack[:i]
-
- // Empty concatenation is special case.
- if len(subs) == 0 {
- return p.push(p.newRegexp(OpEmptyMatch))
- }
-
- return p.push(p.collapse(subs, OpConcat))
-}
-
-// alternate replaces the top of the stack (above the topmost '(') with its alternation.
-func (p *parser) alternate() *Regexp {
- // Scan down to find pseudo-operator (.
- // There are no | above (.
- i := len(p.stack)
- for i > 0 && p.stack[i-1].Op < opPseudo {
- i--
- }
- subs := p.stack[i:]
- p.stack = p.stack[:i]
-
- // Make sure top class is clean.
- // All the others already are (see swapVerticalBar).
- if len(subs) > 0 {
- cleanAlt(subs[len(subs)-1])
- }
-
- // Empty alternate is special case
- // (shouldn't happen but easy to handle).
- if len(subs) == 0 {
- return p.push(p.newRegexp(OpNoMatch))
- }
-
- return p.push(p.collapse(subs, OpAlternate))
-}
-
-// cleanAlt cleans re for eventual inclusion in an alternation.
-func cleanAlt(re *Regexp) {
- switch re.Op {
- case OpCharClass:
- re.Rune = cleanClass(&re.Rune)
- if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune {
- re.Rune = nil
- re.Op = OpAnyChar
- return
- }
- if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune {
- re.Rune = nil
- re.Op = OpAnyCharNotNL
- return
- }
- if cap(re.Rune)-len(re.Rune) > 100 {
- // re.Rune will not grow any more.
- // Make a copy or inline to reclaim storage.
- re.Rune = append(re.Rune0[:0], re.Rune...)
- }
- }
-}
-
-// collapse returns the result of applying op to sub.
-// If sub contains op nodes, they all get hoisted up
-// so that there is never a concat of a concat or an
-// alternate of an alternate.
-func (p *parser) collapse(subs []*Regexp, op Op) *Regexp {
- if len(subs) == 1 {
- return subs[0]
- }
- re := p.newRegexp(op)
- re.Sub = re.Sub0[:0]
- for _, sub := range subs {
- if sub.Op == op {
- re.Sub = append(re.Sub, sub.Sub...)
- p.reuse(sub)
- } else {
- re.Sub = append(re.Sub, sub)
- }
- }
- if op == OpAlternate {
- re.Sub = p.factor(re.Sub)
- if len(re.Sub) == 1 {
- old := re
- re = re.Sub[0]
- p.reuse(old)
- }
- }
- return re
-}
-
-// factor factors common prefixes from the alternation list sub.
-// It returns a replacement list that reuses the same storage and
-// frees (passes to p.reuse) any removed *Regexps.
-//
-// For example,
-//
-// ABC|ABD|AEF|BCX|BCY
-//
-// simplifies by literal prefix extraction to
-//
-// A(B(C|D)|EF)|BC(X|Y)
-//
-// which simplifies by character class introduction to
-//
-// A(B[CD]|EF)|BC[XY]
-func (p *parser) factor(sub []*Regexp) []*Regexp {
- if len(sub) < 2 {
- return sub
- }
-
- // Round 1: Factor out common literal prefixes.
- var str []rune
- var strflags Flags
- start := 0
- out := sub[:0]
- for i := 0; i <= len(sub); i++ {
- // Invariant: the Regexps that were in sub[0:start] have been
- // used or marked for reuse, and the slice space has been reused
- // for out (len(out) <= start).
- //
- // Invariant: sub[start:i] consists of regexps that all begin
- // with str as modified by strflags.
- var istr []rune
- var iflags Flags
- if i < len(sub) {
- istr, iflags = p.leadingString(sub[i])
- if iflags == strflags {
- same := 0
- for same < len(str) && same < len(istr) && str[same] == istr[same] {
- same++
- }
- if same > 0 {
- // Matches at least one rune in current range.
- // Keep going around.
- str = str[:same]
- continue
- }
- }
- }
-
- // Found end of a run with common leading literal string:
- // sub[start:i] all begin with str[0:len(str)], but sub[i]
- // does not even begin with str[0].
- //
- // Factor out common string and append factored expression to out.
- if i == start {
- // Nothing to do - run of length 0.
- } else if i == start+1 {
- // Just one: don't bother factoring.
- out = append(out, sub[start])
- } else {
- // Construct factored form: prefix(suffix1|suffix2|...)
- prefix := p.newRegexp(OpLiteral)
- prefix.Flags = strflags
- prefix.Rune = append(prefix.Rune[:0], str...)
-
- for j := start; j < i; j++ {
- sub[j] = p.removeLeadingString(sub[j], len(str))
- p.checkLimits(sub[j])
- }
- suffix := p.collapse(sub[start:i], OpAlternate) // recurse
-
- re := p.newRegexp(OpConcat)
- re.Sub = append(re.Sub[:0], prefix, suffix)
- out = append(out, re)
- }
-
- // Prepare for next iteration.
- start = i
- str = istr
- strflags = iflags
- }
- sub = out
-
- // Round 2: Factor out common simple prefixes,
- // just the first piece of each concatenation.
- // This will be good enough a lot of the time.
- //
- // Complex subexpressions (e.g. involving quantifiers)
- // are not safe to factor because that collapses their
- // distinct paths through the automaton, which affects
- // correctness in some cases.
- start = 0
- out = sub[:0]
- var first *Regexp
- for i := 0; i <= len(sub); i++ {
- // Invariant: the Regexps that were in sub[0:start] have been
- // used or marked for reuse, and the slice space has been reused
- // for out (len(out) <= start).
- //
- // Invariant: sub[start:i] consists of regexps that all begin with ifirst.
- var ifirst *Regexp
- if i < len(sub) {
- ifirst = p.leadingRegexp(sub[i])
- if first != nil && first.Equal(ifirst) &&
- // first must be a character class OR a fixed repeat of a character class.
- (isCharClass(first) || (first.Op == OpRepeat && first.Min == first.Max && isCharClass(first.Sub[0]))) {
- continue
- }
- }
-
- // Found end of a run with common leading regexp:
- // sub[start:i] all begin with first but sub[i] does not.
- //
- // Factor out common regexp and append factored expression to out.
- if i == start {
- // Nothing to do - run of length 0.
- } else if i == start+1 {
- // Just one: don't bother factoring.
- out = append(out, sub[start])
- } else {
- // Construct factored form: prefix(suffix1|suffix2|...)
- prefix := first
- for j := start; j < i; j++ {
- reuse := j != start // prefix came from sub[start]
- sub[j] = p.removeLeadingRegexp(sub[j], reuse)
- p.checkLimits(sub[j])
- }
- suffix := p.collapse(sub[start:i], OpAlternate) // recurse
-
- re := p.newRegexp(OpConcat)
- re.Sub = append(re.Sub[:0], prefix, suffix)
- out = append(out, re)
- }
-
- // Prepare for next iteration.
- start = i
- first = ifirst
- }
- sub = out
-
- // Round 3: Collapse runs of single literals into character classes.
- start = 0
- out = sub[:0]
- for i := 0; i <= len(sub); i++ {
- // Invariant: the Regexps that were in sub[0:start] have been
- // used or marked for reuse, and the slice space has been reused
- // for out (len(out) <= start).
- //
- // Invariant: sub[start:i] consists of regexps that are either
- // literal runes or character classes.
- if i < len(sub) && isCharClass(sub[i]) {
- continue
- }
-
- // sub[i] is not a char or char class;
- // emit char class for sub[start:i]...
- if i == start {
- // Nothing to do - run of length 0.
- } else if i == start+1 {
- out = append(out, sub[start])
- } else {
- // Make new char class.
- // Start with most complex regexp in sub[start].
- max := start
- for j := start + 1; j < i; j++ {
- if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) {
- max = j
- }
- }
- sub[start], sub[max] = sub[max], sub[start]
-
- for j := start + 1; j < i; j++ {
- mergeCharClass(sub[start], sub[j])
- p.reuse(sub[j])
- }
- cleanAlt(sub[start])
- out = append(out, sub[start])
- }
-
- // ... and then emit sub[i].
- if i < len(sub) {
- out = append(out, sub[i])
- }
- start = i + 1
- }
- sub = out
-
- // Round 4: Collapse runs of empty matches into a single empty match.
- start = 0
- out = sub[:0]
- for i := range sub {
- if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch {
- continue
- }
- out = append(out, sub[i])
- }
- sub = out
-
- return sub
-}
-
-// leadingString returns the leading literal string that re begins with.
-// The string refers to storage in re or its children.
-func (p *parser) leadingString(re *Regexp) ([]rune, Flags) {
- if re.Op == OpConcat && len(re.Sub) > 0 {
- re = re.Sub[0]
- }
- if re.Op != OpLiteral {
- return nil, 0
- }
- return re.Rune, re.Flags & FoldCase
-}
-
-// removeLeadingString removes the first n leading runes
-// from the beginning of re. It returns the replacement for re.
-func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp {
- if re.Op == OpConcat && len(re.Sub) > 0 {
- // Removing a leading string in a concatenation
- // might simplify the concatenation.
- sub := re.Sub[0]
- sub = p.removeLeadingString(sub, n)
- re.Sub[0] = sub
- if sub.Op == OpEmptyMatch {
- p.reuse(sub)
- switch len(re.Sub) {
- case 0, 1:
- // Impossible but handle.
- re.Op = OpEmptyMatch
- re.Sub = nil
- case 2:
- old := re
- re = re.Sub[1]
- p.reuse(old)
- default:
- copy(re.Sub, re.Sub[1:])
- re.Sub = re.Sub[:len(re.Sub)-1]
- }
- }
- return re
- }
-
- if re.Op == OpLiteral {
- re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])]
- if len(re.Rune) == 0 {
- re.Op = OpEmptyMatch
- }
- }
- return re
-}
-
-// leadingRegexp returns the leading regexp that re begins with.
-// The regexp refers to storage in re or its children.
-func (p *parser) leadingRegexp(re *Regexp) *Regexp {
- if re.Op == OpEmptyMatch {
- return nil
- }
- if re.Op == OpConcat && len(re.Sub) > 0 {
- sub := re.Sub[0]
- if sub.Op == OpEmptyMatch {
- return nil
- }
- return sub
- }
- return re
-}
-
-// removeLeadingRegexp removes the leading regexp in re.
-// It returns the replacement for re.
-// If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse.
-func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp {
- if re.Op == OpConcat && len(re.Sub) > 0 {
- if reuse {
- p.reuse(re.Sub[0])
- }
- re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])]
- switch len(re.Sub) {
- case 0:
- re.Op = OpEmptyMatch
- re.Sub = nil
- case 1:
- old := re
- re = re.Sub[0]
- p.reuse(old)
- }
- return re
- }
- if reuse {
- p.reuse(re)
- }
- return p.newRegexp(OpEmptyMatch)
-}
-
-func literalRegexp(s string, flags Flags) *Regexp {
- re := &Regexp{Op: OpLiteral}
- re.Flags = flags
- re.Rune = re.Rune0[:0] // use local storage for small strings
- for _, c := range s {
- if len(re.Rune) >= cap(re.Rune) {
- // string is too long to fit in Rune0. let Go handle it
- re.Rune = []rune(s)
- break
- }
- re.Rune = append(re.Rune, c)
- }
- return re
-}
-
-// Parsing.
-
-// Parse parses a regular expression string s, controlled by the specified
-// Flags, and returns a regular expression parse tree. The syntax is
-// described in the top-level comment.
-func Parse(s string, flags Flags) (*Regexp, error) {
- return parse(s, flags)
-}
-
-func parse(s string, flags Flags) (_ *Regexp, err error) {
- defer func() {
- switch r := recover(); r {
- default:
- panic(r)
- case nil:
- // ok
- case ErrLarge: // too big
- err = &Error{Code: ErrLarge, Expr: s}
- case ErrNestingDepth:
- err = &Error{Code: ErrNestingDepth, Expr: s}
- }
- }()
-
- if flags&Literal != 0 {
- // Trivial parser for literal string.
- if err := checkUTF8(s); err != nil {
- return nil, err
- }
- return literalRegexp(s, flags), nil
- }
-
- // Otherwise, must do real work.
- var (
- p parser
- c rune
- op Op
- lastRepeat string
- )
- p.flags = flags
- p.wholeRegexp = s
- t := s
- for t != "" {
- repeat := ""
- BigSwitch:
- switch t[0] {
- default:
- if c, t, err = nextRune(t); err != nil {
- return nil, err
- }
- p.literal(c)
-
- case '(':
- if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' {
- // Flag changes and non-capturing groups.
- if t, err = p.parsePerlFlags(t); err != nil {
- return nil, err
- }
- break
- }
- p.numCap++
- p.op(opLeftParen).Cap = p.numCap
- t = t[1:]
- case '|':
- if err = p.parseVerticalBar(); err != nil {
- return nil, err
- }
- t = t[1:]
- case ')':
- if err = p.parseRightParen(); err != nil {
- return nil, err
- }
- t = t[1:]
- case '^':
- if p.flags&OneLine != 0 {
- p.op(OpBeginText)
- } else {
- p.op(OpBeginLine)
- }
- t = t[1:]
- case '$':
- if p.flags&OneLine != 0 {
- p.op(OpEndText).Flags |= WasDollar
- } else {
- p.op(OpEndLine)
- }
- t = t[1:]
- case '.':
- if p.flags&DotNL != 0 {
- p.op(OpAnyChar)
- } else {
- p.op(OpAnyCharNotNL)
- }
- t = t[1:]
- case '[':
- if t, err = p.parseClass(t); err != nil {
- return nil, err
- }
- case '*', '+', '?':
- before := t
- switch t[0] {
- case '*':
- op = OpStar
- case '+':
- op = OpPlus
- case '?':
- op = OpQuest
- }
- after := t[1:]
- if after, err = p.repeat(op, 0, 0, before, after, lastRepeat); err != nil {
- return nil, err
- }
- repeat = before
- t = after
- case '{':
- op = OpRepeat
- before := t
- min, max, after, ok := p.parseRepeat(t)
- if !ok {
- // If the repeat cannot be parsed, { is a literal.
- p.literal('{')
- t = t[1:]
- break
- }
- if min < 0 || min > 1000 || max > 1000 || max >= 0 && min > max {
- // Numbers were too big, or max is present and min > max.
- return nil, &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
- }
- if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
- return nil, err
- }
- repeat = before
- t = after
- case '\\':
- if p.flags&PerlX != 0 && len(t) >= 2 {
- switch t[1] {
- case 'A':
- p.op(OpBeginText)
- t = t[2:]
- break BigSwitch
- case 'b':
- p.op(OpWordBoundary)
- t = t[2:]
- break BigSwitch
- case 'B':
- p.op(OpNoWordBoundary)
- t = t[2:]
- break BigSwitch
- case 'C':
- // any byte; not supported
- return nil, &Error{ErrInvalidEscape, t[:2]}
- case 'Q':
- // \Q ... \E: the ... is always literals
- var lit string
- lit, t, _ = strings.Cut(t[2:], `\E`)
- for lit != "" {
- c, rest, err := nextRune(lit)
- if err != nil {
- return nil, err
- }
- p.literal(c)
- lit = rest
- }
- break BigSwitch
- case 'z':
- p.op(OpEndText)
- t = t[2:]
- break BigSwitch
- }
- }
-
- re := p.newRegexp(OpCharClass)
- re.Flags = p.flags
-
- // Look for Unicode character group like \p{Han}
- if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') {
- r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0])
- if err != nil {
- return nil, err
- }
- if r != nil {
- re.Rune = r
- t = rest
- p.push(re)
- break BigSwitch
- }
- }
-
- // Perl character class escape.
- if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil {
- re.Rune = r
- t = rest
- p.push(re)
- break BigSwitch
- }
- p.reuse(re)
-
- // Ordinary single-character escape.
- if c, t, err = p.parseEscape(t); err != nil {
- return nil, err
- }
- p.literal(c)
- }
- lastRepeat = repeat
- }
-
- p.concat()
- if p.swapVerticalBar() {
- // pop vertical bar
- p.stack = p.stack[:len(p.stack)-1]
- }
- p.alternate()
-
- n := len(p.stack)
- if n != 1 {
- return nil, &Error{ErrMissingParen, s}
- }
- return p.stack[0], nil
-}
-
-// parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
-// If s is not of that form, it returns ok == false.
-// If s has the right form but the values are too big, it returns min == -1, ok == true.
-func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) {
- if s == "" || s[0] != '{' {
- return
- }
- s = s[1:]
- var ok1 bool
- if min, s, ok1 = p.parseInt(s); !ok1 {
- return
- }
- if s == "" {
- return
- }
- if s[0] != ',' {
- max = min
- } else {
- s = s[1:]
- if s == "" {
- return
- }
- if s[0] == '}' {
- max = -1
- } else if max, s, ok1 = p.parseInt(s); !ok1 {
- return
- } else if max < 0 {
- // parseInt found too big a number
- min = -1
- }
- }
- if s == "" || s[0] != '}' {
- return
- }
- rest = s[1:]
- ok = true
- return
-}
-
-// parsePerlFlags parses a Perl flag setting or non-capturing group or both,
-// like (?i) or (?: or (?i:. It removes the prefix from s and updates the parse state.
-// The caller must have ensured that s begins with "(?".
-func (p *parser) parsePerlFlags(s string) (rest string, err error) {
- t := s
-
- // Check for named captures, first introduced in Python's regexp library.
- // As usual, there are three slightly different syntaxes:
- //
- // (?Pexpr) the original, introduced by Python
- // (?expr) the .NET alteration, adopted by Perl 5.10
- // (?'name'expr) another .NET alteration, adopted by Perl 5.10
- //
- // Perl 5.10 gave in and implemented the Python version too,
- // but they claim that the last two are the preferred forms.
- // PCRE and languages based on it (specifically, PHP and Ruby)
- // support all three as well. EcmaScript 4 uses only the Python form.
- //
- // In both the open source world (via Code Search) and the
- // Google source tree, (?Pname) and (?name) are the
- // dominant forms of named captures and both are supported.
- startsWithP := len(t) > 4 && t[2] == 'P' && t[3] == '<'
- startsWithName := len(t) > 3 && t[2] == '<'
-
- if startsWithP || startsWithName {
- // position of expr start
- exprStartPos := 4
- if startsWithName {
- exprStartPos = 3
- }
-
- // Pull out name.
- end := strings.IndexRune(t, '>')
- if end < 0 {
- if err = checkUTF8(t); err != nil {
- return "", err
- }
- return "", &Error{ErrInvalidNamedCapture, s}
- }
-
- capture := t[:end+1] // "(?P" or "(?"
- name := t[exprStartPos:end] // "name"
- if err = checkUTF8(name); err != nil {
- return "", err
- }
- if !isValidCaptureName(name) {
- return "", &Error{ErrInvalidNamedCapture, capture}
- }
-
- // Like ordinary capture, but named.
- p.numCap++
- re := p.op(opLeftParen)
- re.Cap = p.numCap
- re.Name = name
- return t[end+1:], nil
- }
-
- // Non-capturing group. Might also twiddle Perl flags.
- var c rune
- t = t[2:] // skip (?
- flags := p.flags
- sign := +1
- sawFlag := false
-Loop:
- for t != "" {
- if c, t, err = nextRune(t); err != nil {
- return "", err
- }
- switch c {
- default:
- break Loop
-
- // Flags.
- case 'i':
- flags |= FoldCase
- sawFlag = true
- case 'm':
- flags &^= OneLine
- sawFlag = true
- case 's':
- flags |= DotNL
- sawFlag = true
- case 'U':
- flags |= NonGreedy
- sawFlag = true
-
- // Switch to negation.
- case '-':
- if sign < 0 {
- break Loop
- }
- sign = -1
- // Invert flags so that | above turn into &^ and vice versa.
- // We'll invert flags again before using it below.
- flags = ^flags
- sawFlag = false
-
- // End of flags, starting group or not.
- case ':', ')':
- if sign < 0 {
- if !sawFlag {
- break Loop
- }
- flags = ^flags
- }
- if c == ':' {
- // Open new group
- p.op(opLeftParen)
- }
- p.flags = flags
- return t, nil
- }
- }
-
- return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]}
-}
-
-// isValidCaptureName reports whether name
-// is a valid capture name: [A-Za-z0-9_]+.
-// PCRE limits names to 32 bytes.
-// Python rejects names starting with digits.
-// We don't enforce either of those.
-func isValidCaptureName(name string) bool {
- if name == "" {
- return false
- }
- for _, c := range name {
- if c != '_' && !isalnum(c) {
- return false
- }
- }
- return true
-}
-
-// parseInt parses a decimal integer.
-func (p *parser) parseInt(s string) (n int, rest string, ok bool) {
- if s == "" || s[0] < '0' || '9' < s[0] {
- return
- }
- // Disallow leading zeros.
- if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' {
- return
- }
- t := s
- for s != "" && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- }
- rest = s
- ok = true
- // Have digits, compute value.
- t = t[:len(t)-len(s)]
- for i := 0; i < len(t); i++ {
- // Avoid overflow.
- if n >= 1e8 {
- n = -1
- break
- }
- n = n*10 + int(t[i]) - '0'
- }
- return
-}
-
-// can this be represented as a character class?
-// single-rune literal string, char class, ., and .|\n.
-func isCharClass(re *Regexp) bool {
- return re.Op == OpLiteral && len(re.Rune) == 1 ||
- re.Op == OpCharClass ||
- re.Op == OpAnyCharNotNL ||
- re.Op == OpAnyChar
-}
-
-// does re match r?
-func matchRune(re *Regexp, r rune) bool {
- switch re.Op {
- case OpLiteral:
- return len(re.Rune) == 1 && re.Rune[0] == r
- case OpCharClass:
- for i := 0; i < len(re.Rune); i += 2 {
- if re.Rune[i] <= r && r <= re.Rune[i+1] {
- return true
- }
- }
- return false
- case OpAnyCharNotNL:
- return r != '\n'
- case OpAnyChar:
- return true
- }
- return false
-}
-
-// parseVerticalBar handles a | in the input.
-func (p *parser) parseVerticalBar() error {
- p.concat()
-
- // The concatenation we just parsed is on top of the stack.
- // If it sits above an opVerticalBar, swap it below
- // (things below an opVerticalBar become an alternation).
- // Otherwise, push a new vertical bar.
- if !p.swapVerticalBar() {
- p.op(opVerticalBar)
- }
-
- return nil
-}
-
-// mergeCharClass makes dst = dst|src.
-// The caller must ensure that dst.Op >= src.Op,
-// to reduce the amount of copying.
-func mergeCharClass(dst, src *Regexp) {
- switch dst.Op {
- case OpAnyChar:
- // src doesn't add anything.
- case OpAnyCharNotNL:
- // src might add \n
- if matchRune(src, '\n') {
- dst.Op = OpAnyChar
- }
- case OpCharClass:
- // src is simpler, so either literal or char class
- if src.Op == OpLiteral {
- dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
- } else {
- dst.Rune = appendClass(dst.Rune, src.Rune)
- }
- case OpLiteral:
- // both literal
- if src.Rune[0] == dst.Rune[0] && src.Flags == dst.Flags {
- break
- }
- dst.Op = OpCharClass
- dst.Rune = appendLiteral(dst.Rune[:0], dst.Rune[0], dst.Flags)
- dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
- }
-}
-
-// If the top of the stack is an element followed by an opVerticalBar
-// swapVerticalBar swaps the two and returns true.
-// Otherwise it returns false.
-func (p *parser) swapVerticalBar() bool {
- // If above and below vertical bar are literal or char class,
- // can merge into a single char class.
- n := len(p.stack)
- if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) {
- re1 := p.stack[n-1]
- re3 := p.stack[n-3]
- // Make re3 the more complex of the two.
- if re1.Op > re3.Op {
- re1, re3 = re3, re1
- p.stack[n-3] = re3
- }
- mergeCharClass(re3, re1)
- p.reuse(re1)
- p.stack = p.stack[:n-1]
- return true
- }
-
- if n >= 2 {
- re1 := p.stack[n-1]
- re2 := p.stack[n-2]
- if re2.Op == opVerticalBar {
- if n >= 3 {
- // Now out of reach.
- // Clean opportunistically.
- cleanAlt(p.stack[n-3])
- }
- p.stack[n-2] = re1
- p.stack[n-1] = re2
- return true
- }
- }
- return false
-}
-
-// parseRightParen handles a ) in the input.
-func (p *parser) parseRightParen() error {
- p.concat()
- if p.swapVerticalBar() {
- // pop vertical bar
- p.stack = p.stack[:len(p.stack)-1]
- }
- p.alternate()
-
- n := len(p.stack)
- if n < 2 {
- return &Error{ErrUnexpectedParen, p.wholeRegexp}
- }
- re1 := p.stack[n-1]
- re2 := p.stack[n-2]
- p.stack = p.stack[:n-2]
- if re2.Op != opLeftParen {
- return &Error{ErrUnexpectedParen, p.wholeRegexp}
- }
- // Restore flags at time of paren.
- p.flags = re2.Flags
- if re2.Cap == 0 {
- // Just for grouping.
- p.push(re1)
- } else {
- re2.Op = OpCapture
- re2.Sub = re2.Sub0[:1]
- re2.Sub[0] = re1
- p.push(re2)
- }
- return nil
-}
-
-// parseEscape parses an escape sequence at the beginning of s
-// and returns the rune.
-func (p *parser) parseEscape(s string) (r rune, rest string, err error) {
- t := s[1:]
- if t == "" {
- return 0, "", &Error{ErrTrailingBackslash, ""}
- }
- c, t, err := nextRune(t)
- if err != nil {
- return 0, "", err
- }
-
-Switch:
- switch c {
- default:
- if c < utf8.RuneSelf && !isalnum(c) {
- // Escaped non-word characters are always themselves.
- // PCRE is not quite so rigorous: it accepts things like
- // \q, but we don't. We once rejected \_, but too many
- // programs and people insist on using it, so allow \_.
- return c, t, nil
- }
-
- // Octal escapes.
- case '1', '2', '3', '4', '5', '6', '7':
- // Single non-zero digit is a backreference; not supported
- if t == "" || t[0] < '0' || t[0] > '7' {
- break
- }
- fallthrough
- case '0':
- // Consume up to three octal digits; already have one.
- r = c - '0'
- for i := 1; i < 3; i++ {
- if t == "" || t[0] < '0' || t[0] > '7' {
- break
- }
- r = r*8 + rune(t[0]) - '0'
- t = t[1:]
- }
- return r, t, nil
-
- // Hexadecimal escapes.
- case 'x':
- if t == "" {
- break
- }
- if c, t, err = nextRune(t); err != nil {
- return 0, "", err
- }
- if c == '{' {
- // Any number of digits in braces.
- // Perl accepts any text at all; it ignores all text
- // after the first non-hex digit. We require only hex digits,
- // and at least one.
- nhex := 0
- r = 0
- for {
- if t == "" {
- break Switch
- }
- if c, t, err = nextRune(t); err != nil {
- return 0, "", err
- }
- if c == '}' {
- break
- }
- v := unhex(c)
- if v < 0 {
- break Switch
- }
- r = r*16 + v
- if r > unicode.MaxRune {
- break Switch
- }
- nhex++
- }
- if nhex == 0 {
- break Switch
- }
- return r, t, nil
- }
-
- // Easy case: two hex digits.
- x := unhex(c)
- if c, t, err = nextRune(t); err != nil {
- return 0, "", err
- }
- y := unhex(c)
- if x < 0 || y < 0 {
- break
- }
- return x*16 + y, t, nil
-
- // C escapes. There is no case 'b', to avoid misparsing
- // the Perl word-boundary \b as the C backspace \b
- // when in POSIX mode. In Perl, /\b/ means word-boundary
- // but /[\b]/ means backspace. We don't support that.
- // If you want a backspace, embed a literal backspace
- // character or use \x08.
- case 'a':
- return '\a', t, err
- case 'f':
- return '\f', t, err
- case 'n':
- return '\n', t, err
- case 'r':
- return '\r', t, err
- case 't':
- return '\t', t, err
- case 'v':
- return '\v', t, err
- }
- return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]}
-}
-
-// parseClassChar parses a character class character at the beginning of s
-// and returns it.
-func (p *parser) parseClassChar(s, wholeClass string) (r rune, rest string, err error) {
- if s == "" {
- return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass}
- }
-
- // Allow regular escape sequences even though
- // many need not be escaped in this context.
- if s[0] == '\\' {
- return p.parseEscape(s)
- }
-
- return nextRune(s)
-}
-
-type charGroup struct {
- sign int
- class []rune
-}
-
-// parsePerlClassEscape parses a leading Perl character class escape like \d
-// from the beginning of s. If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parsePerlClassEscape(s string, r []rune) (out []rune, rest string) {
- if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' {
- return
- }
- g := perlGroup[s[0:2]]
- if g.sign == 0 {
- return
- }
- return p.appendGroup(r, g), s[2:]
-}
-
-// parseNamedClass parses a leading POSIX named character class like [:alnum:]
-// from the beginning of s. If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parseNamedClass(s string, r []rune) (out []rune, rest string, err error) {
- if len(s) < 2 || s[0] != '[' || s[1] != ':' {
- return
- }
-
- i := strings.Index(s[2:], ":]")
- if i < 0 {
- return
- }
- i += 2
- name, s := s[0:i+2], s[i+2:]
- g := posixGroup[name]
- if g.sign == 0 {
- return nil, "", &Error{ErrInvalidCharRange, name}
- }
- return p.appendGroup(r, g), s, nil
-}
-
-func (p *parser) appendGroup(r []rune, g charGroup) []rune {
- if p.flags&FoldCase == 0 {
- if g.sign < 0 {
- r = appendNegatedClass(r, g.class)
- } else {
- r = appendClass(r, g.class)
- }
- } else {
- tmp := p.tmpClass[:0]
- tmp = appendFoldedClass(tmp, g.class)
- p.tmpClass = tmp
- tmp = cleanClass(&p.tmpClass)
- if g.sign < 0 {
- r = appendNegatedClass(r, tmp)
- } else {
- r = appendClass(r, tmp)
- }
- }
- return r
-}
-
-var anyTable = &unicode.RangeTable{
- R16: []unicode.Range16{{Lo: 0, Hi: 1<<16 - 1, Stride: 1}},
- R32: []unicode.Range32{{Lo: 1 << 16, Hi: unicode.MaxRune, Stride: 1}},
-}
-
-// unicodeTable returns the unicode.RangeTable identified by name
-// and the table of additional fold-equivalent code points.
-func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) {
- // Special case: "Any" means any.
- if name == "Any" {
- return anyTable, anyTable
- }
- if t := unicode.Categories[name]; t != nil {
- return t, unicode.FoldCategory[name]
- }
- if t := unicode.Scripts[name]; t != nil {
- return t, unicode.FoldScript[name]
- }
- return nil, nil
-}
-
-// parseUnicodeClass parses a leading Unicode character class like \p{Han}
-// from the beginning of s. If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parseUnicodeClass(s string, r []rune) (out []rune, rest string, err error) {
- if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' {
- return
- }
-
- // Committed to parse or return error.
- sign := +1
- if s[1] == 'P' {
- sign = -1
- }
- t := s[2:]
- c, t, err := nextRune(t)
- if err != nil {
- return
- }
- var seq, name string
- if c != '{' {
- // Single-letter name.
- seq = s[:len(s)-len(t)]
- name = seq[2:]
- } else {
- // Name is in braces.
- end := strings.IndexRune(s, '}')
- if end < 0 {
- if err = checkUTF8(s); err != nil {
- return
- }
- return nil, "", &Error{ErrInvalidCharRange, s}
- }
- seq, t = s[:end+1], s[end+1:]
- name = s[3:end]
- if err = checkUTF8(name); err != nil {
- return
- }
- }
-
- // Group can have leading negation too. \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
- if name != "" && name[0] == '^' {
- sign = -sign
- name = name[1:]
- }
-
- tab, fold := unicodeTable(name)
- if tab == nil {
- return nil, "", &Error{ErrInvalidCharRange, seq}
- }
-
- if p.flags&FoldCase == 0 || fold == nil {
- if sign > 0 {
- r = appendTable(r, tab)
- } else {
- r = appendNegatedTable(r, tab)
- }
- } else {
- // Merge and clean tab and fold in a temporary buffer.
- // This is necessary for the negative case and just tidy
- // for the positive case.
- tmp := p.tmpClass[:0]
- tmp = appendTable(tmp, tab)
- tmp = appendTable(tmp, fold)
- p.tmpClass = tmp
- tmp = cleanClass(&p.tmpClass)
- if sign > 0 {
- r = appendClass(r, tmp)
- } else {
- r = appendNegatedClass(r, tmp)
- }
- }
- return r, t, nil
-}
-
-// parseClass parses a character class at the beginning of s
-// and pushes it onto the parse stack.
-func (p *parser) parseClass(s string) (rest string, err error) {
- t := s[1:] // chop [
- re := p.newRegexp(OpCharClass)
- re.Flags = p.flags
- re.Rune = re.Rune0[:0]
-
- sign := +1
- if t != "" && t[0] == '^' {
- sign = -1
- t = t[1:]
-
- // If character class does not match \n, add it here,
- // so that negation later will do the right thing.
- if p.flags&ClassNL == 0 {
- re.Rune = append(re.Rune, '\n', '\n')
- }
- }
-
- class := re.Rune
- first := true // ] and - are okay as first char in class
- for t == "" || t[0] != ']' || first {
- // POSIX: - is only okay unescaped as first or last in class.
- // Perl: - is okay anywhere.
- if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') {
- _, size := utf8.DecodeRuneInString(t[1:])
- return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]}
- }
- first = false
-
- // Look for POSIX [:alnum:] etc.
- if len(t) > 2 && t[0] == '[' && t[1] == ':' {
- nclass, nt, err := p.parseNamedClass(t, class)
- if err != nil {
- return "", err
- }
- if nclass != nil {
- class, t = nclass, nt
- continue
- }
- }
-
- // Look for Unicode character group like \p{Han}.
- nclass, nt, err := p.parseUnicodeClass(t, class)
- if err != nil {
- return "", err
- }
- if nclass != nil {
- class, t = nclass, nt
- continue
- }
-
- // Look for Perl character class symbols (extension).
- if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil {
- class, t = nclass, nt
- continue
- }
-
- // Single character or simple range.
- rng := t
- var lo, hi rune
- if lo, t, err = p.parseClassChar(t, s); err != nil {
- return "", err
- }
- hi = lo
- // [a-] means (a|-) so check for final ].
- if len(t) >= 2 && t[0] == '-' && t[1] != ']' {
- t = t[1:]
- if hi, t, err = p.parseClassChar(t, s); err != nil {
- return "", err
- }
- if hi < lo {
- rng = rng[:len(rng)-len(t)]
- return "", &Error{Code: ErrInvalidCharRange, Expr: rng}
- }
- }
- if p.flags&FoldCase == 0 {
- class = appendRange(class, lo, hi)
- } else {
- class = appendFoldedRange(class, lo, hi)
- }
- }
- t = t[1:] // chop ]
-
- // Use &re.Rune instead of &class to avoid allocation.
- re.Rune = class
- class = cleanClass(&re.Rune)
- if sign < 0 {
- class = negateClass(class)
- }
- re.Rune = class
- p.push(re)
- return t, nil
-}
-
-// cleanClass sorts the ranges (pairs of elements of r),
-// merges them, and eliminates duplicates.
-func cleanClass(rp *[]rune) []rune {
-
- // Sort by lo increasing, hi decreasing to break ties.
- sort.Sort(ranges{rp})
-
- r := *rp
- if len(r) < 2 {
- return r
- }
-
- // Merge abutting, overlapping.
- w := 2 // write index
- for i := 2; i < len(r); i += 2 {
- lo, hi := r[i], r[i+1]
- if lo <= r[w-1]+1 {
- // merge with previous range
- if hi > r[w-1] {
- r[w-1] = hi
- }
- continue
- }
- // new disjoint range
- r[w] = lo
- r[w+1] = hi
- w += 2
- }
-
- return r[:w]
-}
-
-// inCharClass reports whether r is in the class.
-// It assumes the class has been cleaned by cleanClass.
-func inCharClass(r rune, class []rune) bool {
- _, ok := sort.Find(len(class)/2, func(i int) int {
- lo, hi := class[2*i], class[2*i+1]
- if r > hi {
- return +1
- }
- if r < lo {
- return -1
- }
- return 0
- })
- return ok
-}
-
-// appendLiteral returns the result of appending the literal x to the class r.
-func appendLiteral(r []rune, x rune, flags Flags) []rune {
- if flags&FoldCase != 0 {
- return appendFoldedRange(r, x, x)
- }
- return appendRange(r, x, x)
-}
-
-// appendRange returns the result of appending the range lo-hi to the class r.
-func appendRange(r []rune, lo, hi rune) []rune {
- // Expand last range or next to last range if it overlaps or abuts.
- // Checking two ranges helps when appending case-folded
- // alphabets, so that one range can be expanding A-Z and the
- // other expanding a-z.
- n := len(r)
- for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4
- if n >= i {
- rlo, rhi := r[n-i], r[n-i+1]
- if lo <= rhi+1 && rlo <= hi+1 {
- if lo < rlo {
- r[n-i] = lo
- }
- if hi > rhi {
- r[n-i+1] = hi
- }
- return r
- }
- }
- }
-
- return append(r, lo, hi)
-}
-
-const (
- // minimum and maximum runes involved in folding.
- // checked during test.
- minFold = 0x0041
- maxFold = 0x1e943
-)
-
-// appendFoldedRange returns the result of appending the range lo-hi
-// and its case folding-equivalent runes to the class r.
-func appendFoldedRange(r []rune, lo, hi rune) []rune {
- // Optimizations.
- if lo <= minFold && hi >= maxFold {
- // Range is full: folding can't add more.
- return appendRange(r, lo, hi)
- }
- if hi < minFold || lo > maxFold {
- // Range is outside folding possibilities.
- return appendRange(r, lo, hi)
- }
- if lo < minFold {
- // [lo, minFold-1] needs no folding.
- r = appendRange(r, lo, minFold-1)
- lo = minFold
- }
- if hi > maxFold {
- // [maxFold+1, hi] needs no folding.
- r = appendRange(r, maxFold+1, hi)
- hi = maxFold
- }
-
- // Brute force. Depend on appendRange to coalesce ranges on the fly.
- for c := lo; c <= hi; c++ {
- r = appendRange(r, c, c)
- f := unicode.SimpleFold(c)
- for f != c {
- r = appendRange(r, f, f)
- f = unicode.SimpleFold(f)
- }
- }
- return r
-}
-
-// appendClass returns the result of appending the class x to the class r.
-// It assume x is clean.
-func appendClass(r []rune, x []rune) []rune {
- for i := 0; i < len(x); i += 2 {
- r = appendRange(r, x[i], x[i+1])
- }
- return r
-}
-
-// appendFoldedClass returns the result of appending the case folding of the class x to the class r.
-func appendFoldedClass(r []rune, x []rune) []rune {
- for i := 0; i < len(x); i += 2 {
- r = appendFoldedRange(r, x[i], x[i+1])
- }
- return r
-}
-
-// appendNegatedClass returns the result of appending the negation of the class x to the class r.
-// It assumes x is clean.
-func appendNegatedClass(r []rune, x []rune) []rune {
- nextLo := '\u0000'
- for i := 0; i < len(x); i += 2 {
- lo, hi := x[i], x[i+1]
- if nextLo <= lo-1 {
- r = appendRange(r, nextLo, lo-1)
- }
- nextLo = hi + 1
- }
- if nextLo <= unicode.MaxRune {
- r = appendRange(r, nextLo, unicode.MaxRune)
- }
- return r
-}
-
-// appendTable returns the result of appending x to the class r.
-func appendTable(r []rune, x *unicode.RangeTable) []rune {
- for _, xr := range x.R16 {
- lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
- if stride == 1 {
- r = appendRange(r, lo, hi)
- continue
- }
- for c := lo; c <= hi; c += stride {
- r = appendRange(r, c, c)
- }
- }
- for _, xr := range x.R32 {
- lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
- if stride == 1 {
- r = appendRange(r, lo, hi)
- continue
- }
- for c := lo; c <= hi; c += stride {
- r = appendRange(r, c, c)
- }
- }
- return r
-}
-
-// appendNegatedTable returns the result of appending the negation of x to the class r.
-func appendNegatedTable(r []rune, x *unicode.RangeTable) []rune {
- nextLo := '\u0000' // lo end of next class to add
- for _, xr := range x.R16 {
- lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
- if stride == 1 {
- if nextLo <= lo-1 {
- r = appendRange(r, nextLo, lo-1)
- }
- nextLo = hi + 1
- continue
- }
- for c := lo; c <= hi; c += stride {
- if nextLo <= c-1 {
- r = appendRange(r, nextLo, c-1)
- }
- nextLo = c + 1
- }
- }
- for _, xr := range x.R32 {
- lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
- if stride == 1 {
- if nextLo <= lo-1 {
- r = appendRange(r, nextLo, lo-1)
- }
- nextLo = hi + 1
- continue
- }
- for c := lo; c <= hi; c += stride {
- if nextLo <= c-1 {
- r = appendRange(r, nextLo, c-1)
- }
- nextLo = c + 1
- }
- }
- if nextLo <= unicode.MaxRune {
- r = appendRange(r, nextLo, unicode.MaxRune)
- }
- return r
-}
-
-// negateClass overwrites r and returns r's negation.
-// It assumes the class r is already clean.
-func negateClass(r []rune) []rune {
- nextLo := '\u0000' // lo end of next class to add
- w := 0 // write index
- for i := 0; i < len(r); i += 2 {
- lo, hi := r[i], r[i+1]
- if nextLo <= lo-1 {
- r[w] = nextLo
- r[w+1] = lo - 1
- w += 2
- }
- nextLo = hi + 1
- }
- r = r[:w]
- if nextLo <= unicode.MaxRune {
- // It's possible for the negation to have one more
- // range - this one - than the original class, so use append.
- r = append(r, nextLo, unicode.MaxRune)
- }
- return r
-}
-
-// ranges implements sort.Interface on a []rune.
-// The choice of receiver type definition is strange
-// but avoids an allocation since we already have
-// a *[]rune.
-type ranges struct {
- p *[]rune
-}
-
-func (ra ranges) Less(i, j int) bool {
- p := *ra.p
- i *= 2
- j *= 2
- return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1]
-}
-
-func (ra ranges) Len() int {
- return len(*ra.p) / 2
-}
-
-func (ra ranges) Swap(i, j int) {
- p := *ra.p
- i *= 2
- j *= 2
- p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1]
-}
-
-func checkUTF8(s string) error {
- for s != "" {
- rune, size := utf8.DecodeRuneInString(s)
- if rune == utf8.RuneError && size == 1 {
- return &Error{Code: ErrInvalidUTF8, Expr: s}
- }
- s = s[size:]
- }
- return nil
-}
-
-func nextRune(s string) (c rune, t string, err error) {
- c, size := utf8.DecodeRuneInString(s)
- if c == utf8.RuneError && size == 1 {
- return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s}
- }
- return c, s[size:], nil
-}
-
-func isalnum(c rune) bool {
- return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-}
-
-func unhex(c rune) rune {
- if '0' <= c && c <= '9' {
- return c - '0'
- }
- if 'a' <= c && c <= 'f' {
- return c - 'a' + 10
- }
- if 'A' <= c && c <= 'F' {
- return c - 'A' + 10
- }
- return -1
-}
diff --git a/contrib/go/_std_1.22/src/regexp/syntax/regexp.go b/contrib/go/_std_1.22/src/regexp/syntax/regexp.go
deleted file mode 100644
index 4fa7d0e2f833..000000000000
--- a/contrib/go/_std_1.22/src/regexp/syntax/regexp.go
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright 2011 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.
-
-package syntax
-
-// Note to implementers:
-// In this package, re is always a *Regexp and r is always a rune.
-
-import (
- "strconv"
- "strings"
- "unicode"
-)
-
-// A Regexp is a node in a regular expression syntax tree.
-type Regexp struct {
- Op Op // operator
- Flags Flags
- Sub []*Regexp // subexpressions, if any
- Sub0 [1]*Regexp // storage for short Sub
- Rune []rune // matched runes, for OpLiteral, OpCharClass
- Rune0 [2]rune // storage for short Rune
- Min, Max int // min, max for OpRepeat
- Cap int // capturing index, for OpCapture
- Name string // capturing name, for OpCapture
-}
-
-//go:generate stringer -type Op -trimprefix Op
-
-// An Op is a single regular expression operator.
-type Op uint8
-
-// Operators are listed in precedence order, tightest binding to weakest.
-// Character class operators are listed simplest to most complex
-// (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar).
-
-const (
- OpNoMatch Op = 1 + iota // matches no strings
- OpEmptyMatch // matches empty string
- OpLiteral // matches Runes sequence
- OpCharClass // matches Runes interpreted as range pair list
- OpAnyCharNotNL // matches any character except newline
- OpAnyChar // matches any character
- OpBeginLine // matches empty string at beginning of line
- OpEndLine // matches empty string at end of line
- OpBeginText // matches empty string at beginning of text
- OpEndText // matches empty string at end of text
- OpWordBoundary // matches word boundary `\b`
- OpNoWordBoundary // matches word non-boundary `\B`
- OpCapture // capturing subexpression with index Cap, optional name Name
- OpStar // matches Sub[0] zero or more times
- OpPlus // matches Sub[0] one or more times
- OpQuest // matches Sub[0] zero or one times
- OpRepeat // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
- OpConcat // matches concatenation of Subs
- OpAlternate // matches alternation of Subs
-)
-
-const opPseudo Op = 128 // where pseudo-ops start
-
-// Equal reports whether x and y have identical structure.
-func (x *Regexp) Equal(y *Regexp) bool {
- if x == nil || y == nil {
- return x == y
- }
- if x.Op != y.Op {
- return false
- }
- switch x.Op {
- case OpEndText:
- // The parse flags remember whether this is \z or \Z.
- if x.Flags&WasDollar != y.Flags&WasDollar {
- return false
- }
-
- case OpLiteral, OpCharClass:
- if len(x.Rune) != len(y.Rune) {
- return false
- }
- for i, r := range x.Rune {
- if r != y.Rune[i] {
- return false
- }
- }
-
- case OpAlternate, OpConcat:
- if len(x.Sub) != len(y.Sub) {
- return false
- }
- for i, sub := range x.Sub {
- if !sub.Equal(y.Sub[i]) {
- return false
- }
- }
-
- case OpStar, OpPlus, OpQuest:
- if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) {
- return false
- }
-
- case OpRepeat:
- if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) {
- return false
- }
-
- case OpCapture:
- if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) {
- return false
- }
- }
- return true
-}
-
-// printFlags is a bit set indicating which flags (including non-capturing parens) to print around a regexp.
-type printFlags uint8
-
-const (
- flagI printFlags = 1 << iota // (?i:
- flagM // (?m:
- flagS // (?s:
- flagOff // )
- flagPrec // (?: )
- negShift = 5 // flagI<")
- case OpNoMatch:
- b.WriteString(`[^\x00-\x{10FFFF}]`)
- case OpEmptyMatch:
- b.WriteString(`(?:)`)
- case OpLiteral:
- for _, r := range re.Rune {
- escape(b, r, false)
- }
- case OpCharClass:
- if len(re.Rune)%2 != 0 {
- b.WriteString(`[invalid char class]`)
- break
- }
- b.WriteRune('[')
- if len(re.Rune) == 0 {
- b.WriteString(`^\x00-\x{10FFFF}`)
- } else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune && len(re.Rune) > 2 {
- // Contains 0 and MaxRune. Probably a negated class.
- // Print the gaps.
- b.WriteRune('^')
- for i := 1; i < len(re.Rune)-1; i += 2 {
- lo, hi := re.Rune[i]+1, re.Rune[i+1]-1
- escape(b, lo, lo == '-')
- if lo != hi {
- if hi != lo+1 {
- b.WriteRune('-')
- }
- escape(b, hi, hi == '-')
- }
- }
- } else {
- for i := 0; i < len(re.Rune); i += 2 {
- lo, hi := re.Rune[i], re.Rune[i+1]
- escape(b, lo, lo == '-')
- if lo != hi {
- if hi != lo+1 {
- b.WriteRune('-')
- }
- escape(b, hi, hi == '-')
- }
- }
- }
- b.WriteRune(']')
- case OpAnyCharNotNL, OpAnyChar:
- b.WriteString(`.`)
- case OpBeginLine:
- b.WriteString(`^`)
- case OpEndLine:
- b.WriteString(`$`)
- case OpBeginText:
- b.WriteString(`\A`)
- case OpEndText:
- if re.Flags&WasDollar != 0 {
- b.WriteString(`$`)
- } else {
- b.WriteString(`\z`)
- }
- case OpWordBoundary:
- b.WriteString(`\b`)
- case OpNoWordBoundary:
- b.WriteString(`\B`)
- case OpCapture:
- if re.Name != "" {
- b.WriteString(`(?P<`)
- b.WriteString(re.Name)
- b.WriteRune('>')
- } else {
- b.WriteRune('(')
- }
- if re.Sub[0].Op != OpEmptyMatch {
- writeRegexp(b, re.Sub[0], flags[re.Sub[0]], flags)
- }
- b.WriteRune(')')
- case OpStar, OpPlus, OpQuest, OpRepeat:
- p := printFlags(0)
- sub := re.Sub[0]
- if sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 {
- p = flagPrec
- }
- writeRegexp(b, sub, p, flags)
-
- switch re.Op {
- case OpStar:
- b.WriteRune('*')
- case OpPlus:
- b.WriteRune('+')
- case OpQuest:
- b.WriteRune('?')
- case OpRepeat:
- b.WriteRune('{')
- b.WriteString(strconv.Itoa(re.Min))
- if re.Max != re.Min {
- b.WriteRune(',')
- if re.Max >= 0 {
- b.WriteString(strconv.Itoa(re.Max))
- }
- }
- b.WriteRune('}')
- }
- if re.Flags&NonGreedy != 0 {
- b.WriteRune('?')
- }
- case OpConcat:
- for _, sub := range re.Sub {
- p := printFlags(0)
- if sub.Op == OpAlternate {
- p = flagPrec
- }
- writeRegexp(b, sub, p, flags)
- }
- case OpAlternate:
- for i, sub := range re.Sub {
- if i > 0 {
- b.WriteRune('|')
- }
- writeRegexp(b, sub, 0, flags)
- }
- }
-}
-
-func (re *Regexp) String() string {
- var b strings.Builder
- var flags map[*Regexp]printFlags
- must, cant := calcFlags(re, &flags)
- must |= (cant &^ flagI) << negShift
- if must != 0 {
- must |= flagOff
- }
- writeRegexp(&b, re, must, flags)
- return b.String()
-}
-
-const meta = `\.+*?()|[]{}^$`
-
-func escape(b *strings.Builder, r rune, force bool) {
- if unicode.IsPrint(r) {
- if strings.ContainsRune(meta, r) || force {
- b.WriteRune('\\')
- }
- b.WriteRune(r)
- return
- }
-
- switch r {
- case '\a':
- b.WriteString(`\a`)
- case '\f':
- b.WriteString(`\f`)
- case '\n':
- b.WriteString(`\n`)
- case '\r':
- b.WriteString(`\r`)
- case '\t':
- b.WriteString(`\t`)
- case '\v':
- b.WriteString(`\v`)
- default:
- if r < 0x100 {
- b.WriteString(`\x`)
- s := strconv.FormatInt(int64(r), 16)
- if len(s) == 1 {
- b.WriteRune('0')
- }
- b.WriteString(s)
- break
- }
- b.WriteString(`\x{`)
- b.WriteString(strconv.FormatInt(int64(r), 16))
- b.WriteString(`}`)
- }
-}
-
-// MaxCap walks the regexp to find the maximum capture index.
-func (re *Regexp) MaxCap() int {
- m := 0
- if re.Op == OpCapture {
- m = re.Cap
- }
- for _, sub := range re.Sub {
- if n := sub.MaxCap(); m < n {
- m = n
- }
- }
- return m
-}
-
-// CapNames walks the regexp to find the names of capturing groups.
-func (re *Regexp) CapNames() []string {
- names := make([]string, re.MaxCap()+1)
- re.capNames(names)
- return names
-}
-
-func (re *Regexp) capNames(names []string) {
- if re.Op == OpCapture {
- names[re.Cap] = re.Name
- }
- for _, sub := range re.Sub {
- sub.capNames(names)
- }
-}
diff --git a/contrib/go/_std_1.22/src/runtime/arena.go b/contrib/go/_std_1.22/src/runtime/arena.go
deleted file mode 100644
index e943817ceeab..000000000000
--- a/contrib/go/_std_1.22/src/runtime/arena.go
+++ /dev/null
@@ -1,935 +0,0 @@
-// Copyright 2022 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.
-
-// Implementation of (safe) user arenas.
-//
-// This file contains the implementation of user arenas wherein Go values can
-// be manually allocated and freed in bulk. The act of manually freeing memory,
-// potentially before a GC cycle, means that a garbage collection cycle can be
-// delayed, improving efficiency by reducing GC cycle frequency. There are other
-// potential efficiency benefits, such as improved locality and access to a more
-// efficient allocation strategy.
-//
-// What makes the arenas here safe is that once they are freed, accessing the
-// arena's memory will cause an explicit program fault, and the arena's address
-// space will not be reused until no more pointers into it are found. There's one
-// exception to this: if an arena allocated memory that isn't exhausted, it's placed
-// back into a pool for reuse. This means that a crash is not always guaranteed.
-//
-// While this may seem unsafe, it still prevents memory corruption, and is in fact
-// necessary in order to make new(T) a valid implementation of arenas. Such a property
-// is desirable to allow for a trivial implementation. (It also avoids complexities
-// that arise from synchronization with the GC when trying to set the arena chunks to
-// fault while the GC is active.)
-//
-// The implementation works in layers. At the bottom, arenas are managed in chunks.
-// Each chunk must be a multiple of the heap arena size, or the heap arena size must
-// be divisible by the arena chunks. The address space for each chunk, and each
-// corresponding heapArena for that address space, are eternally reserved for use as
-// arena chunks. That is, they can never be used for the general heap. Each chunk
-// is also represented by a single mspan, and is modeled as a single large heap
-// allocation. It must be, because each chunk contains ordinary Go values that may
-// point into the heap, so it must be scanned just like any other object. Any
-// pointer into a chunk will therefore always cause the whole chunk to be scanned
-// while its corresponding arena is still live.
-//
-// Chunks may be allocated either from new memory mapped by the OS on our behalf,
-// or by reusing old freed chunks. When chunks are freed, their underlying memory
-// is returned to the OS, set to fault on access, and may not be reused until the
-// program doesn't point into the chunk anymore (the code refers to this state as
-// "quarantined"), a property checked by the GC.
-//
-// The sweeper handles moving chunks out of this quarantine state to be ready for
-// reuse. When the chunk is placed into the quarantine state, its corresponding
-// span is marked as noscan so that the GC doesn't try to scan memory that would
-// cause a fault.
-//
-// At the next layer are the user arenas themselves. They consist of a single
-// active chunk which new Go values are bump-allocated into and a list of chunks
-// that were exhausted when allocating into the arena. Once the arena is freed,
-// it frees all full chunks it references, and places the active one onto a reuse
-// list for a future arena to use. Each arena keeps its list of referenced chunks
-// explicitly live until it is freed. Each user arena also maps to an object which
-// has a finalizer attached that ensures the arena's chunks are all freed even if
-// the arena itself is never explicitly freed.
-//
-// Pointer-ful memory is bump-allocated from low addresses to high addresses in each
-// chunk, while pointer-free memory is bump-allocated from high address to low
-// addresses. The reason for this is to take advantage of a GC optimization wherein
-// the GC will stop scanning an object when there are no more pointers in it, which
-// also allows us to elide clearing the heap bitmap for pointer-free Go values
-// allocated into arenas.
-//
-// Note that arenas are not safe to use concurrently.
-//
-// In summary, there are 2 resources: arenas, and arena chunks. They exist in the
-// following lifecycle:
-//
-// (1) A new arena is created via newArena.
-// (2) Chunks are allocated to hold memory allocated into the arena with new or slice.
-// (a) Chunks are first allocated from the reuse list of partially-used chunks.
-// (b) If there are no such chunks, then chunks on the ready list are taken.
-// (c) Failing all the above, memory for a new chunk is mapped.
-// (3) The arena is freed, or all references to it are dropped, triggering its finalizer.
-// (a) If the GC is not active, exhausted chunks are set to fault and placed on a
-// quarantine list.
-// (b) If the GC is active, exhausted chunks are placed on a fault list and will
-// go through step (a) at a later point in time.
-// (c) Any remaining partially-used chunk is placed on a reuse list.
-// (4) Once no more pointers are found into quarantined arena chunks, the sweeper
-// takes these chunks out of quarantine and places them on the ready list.
-
-package runtime
-
-import (
- "internal/goarch"
- "internal/goexperiment"
- "runtime/internal/atomic"
- "runtime/internal/math"
- "unsafe"
-)
-
-// Functions starting with arena_ are meant to be exported to downstream users
-// of arenas. They should wrap these functions in a higher-lever API.
-//
-// The underlying arena and its resources are managed through an opaque unsafe.Pointer.
-
-// arena_newArena is a wrapper around newUserArena.
-//
-//go:linkname arena_newArena arena.runtime_arena_newArena
-func arena_newArena() unsafe.Pointer {
- return unsafe.Pointer(newUserArena())
-}
-
-// arena_arena_New is a wrapper around (*userArena).new, except that typ
-// is an any (must be a *_type, still) and typ must be a type descriptor
-// for a pointer to the type to actually be allocated, i.e. pass a *T
-// to allocate a T. This is necessary because this function returns a *T.
-//
-//go:linkname arena_arena_New arena.runtime_arena_arena_New
-func arena_arena_New(arena unsafe.Pointer, typ any) any {
- t := (*_type)(efaceOf(&typ).data)
- if t.Kind_&kindMask != kindPtr {
- throw("arena_New: non-pointer type")
- }
- te := (*ptrtype)(unsafe.Pointer(t)).Elem
- x := ((*userArena)(arena)).new(te)
- var result any
- e := efaceOf(&result)
- e._type = t
- e.data = x
- return result
-}
-
-// arena_arena_Slice is a wrapper around (*userArena).slice.
-//
-//go:linkname arena_arena_Slice arena.runtime_arena_arena_Slice
-func arena_arena_Slice(arena unsafe.Pointer, slice any, cap int) {
- ((*userArena)(arena)).slice(slice, cap)
-}
-
-// arena_arena_Free is a wrapper around (*userArena).free.
-//
-//go:linkname arena_arena_Free arena.runtime_arena_arena_Free
-func arena_arena_Free(arena unsafe.Pointer) {
- ((*userArena)(arena)).free()
-}
-
-// arena_heapify takes a value that lives in an arena and makes a copy
-// of it on the heap. Values that don't live in an arena are returned unmodified.
-//
-//go:linkname arena_heapify arena.runtime_arena_heapify
-func arena_heapify(s any) any {
- var v unsafe.Pointer
- e := efaceOf(&s)
- t := e._type
- switch t.Kind_ & kindMask {
- case kindString:
- v = stringStructOf((*string)(e.data)).str
- case kindSlice:
- v = (*slice)(e.data).array
- case kindPtr:
- v = e.data
- default:
- panic("arena: Clone only supports pointers, slices, and strings")
- }
- span := spanOf(uintptr(v))
- if span == nil || !span.isUserArenaChunk {
- // Not stored in a user arena chunk.
- return s
- }
- // Heap-allocate storage for a copy.
- var x any
- switch t.Kind_ & kindMask {
- case kindString:
- s1 := s.(string)
- s2, b := rawstring(len(s1))
- copy(b, s1)
- x = s2
- case kindSlice:
- len := (*slice)(e.data).len
- et := (*slicetype)(unsafe.Pointer(t)).Elem
- sl := new(slice)
- *sl = slice{makeslicecopy(et, len, len, (*slice)(e.data).array), len, len}
- xe := efaceOf(&x)
- xe._type = t
- xe.data = unsafe.Pointer(sl)
- case kindPtr:
- et := (*ptrtype)(unsafe.Pointer(t)).Elem
- e2 := newobject(et)
- typedmemmove(et, e2, e.data)
- xe := efaceOf(&x)
- xe._type = t
- xe.data = e2
- }
- return x
-}
-
-const (
- // userArenaChunkBytes is the size of a user arena chunk.
- userArenaChunkBytesMax = 8 << 20
- userArenaChunkBytes = uintptr(int64(userArenaChunkBytesMax-heapArenaBytes)&(int64(userArenaChunkBytesMax-heapArenaBytes)>>63) + heapArenaBytes) // min(userArenaChunkBytesMax, heapArenaBytes)
-
- // userArenaChunkPages is the number of pages a user arena chunk uses.
- userArenaChunkPages = userArenaChunkBytes / pageSize
-
- // userArenaChunkMaxAllocBytes is the maximum size of an object that can
- // be allocated from an arena. This number is chosen to cap worst-case
- // fragmentation of user arenas to 25%. Larger allocations are redirected
- // to the heap.
- userArenaChunkMaxAllocBytes = userArenaChunkBytes / 4
-)
-
-func init() {
- if userArenaChunkPages*pageSize != userArenaChunkBytes {
- throw("user arena chunk size is not a multiple of the page size")
- }
- if userArenaChunkBytes%physPageSize != 0 {
- throw("user arena chunk size is not a multiple of the physical page size")
- }
- if userArenaChunkBytes < heapArenaBytes {
- if heapArenaBytes%userArenaChunkBytes != 0 {
- throw("user arena chunk size is smaller than a heap arena, but doesn't divide it")
- }
- } else {
- if userArenaChunkBytes%heapArenaBytes != 0 {
- throw("user arena chunks size is larger than a heap arena, but not a multiple")
- }
- }
- lockInit(&userArenaState.lock, lockRankUserArenaState)
-}
-
-// userArenaChunkReserveBytes returns the amount of additional bytes to reserve for
-// heap metadata.
-func userArenaChunkReserveBytes() uintptr {
- if goexperiment.AllocHeaders {
- // In the allocation headers experiment, we reserve the end of the chunk for
- // a pointer/scalar bitmap. We also reserve space for a dummy _type that
- // refers to the bitmap. The PtrBytes field of the dummy _type indicates how
- // many of those bits are valid.
- return userArenaChunkBytes/goarch.PtrSize/8 + unsafe.Sizeof(_type{})
- }
- return 0
-}
-
-type userArena struct {
- // full is a list of full chunks that have not enough free memory left, and
- // that we'll free once this user arena is freed.
- //
- // Can't use mSpanList here because it's not-in-heap.
- fullList *mspan
-
- // active is the user arena chunk we're currently allocating into.
- active *mspan
-
- // refs is a set of references to the arena chunks so that they're kept alive.
- //
- // The last reference in the list always refers to active, while the rest of
- // them correspond to fullList. Specifically, the head of fullList is the
- // second-to-last one, fullList.next is the third-to-last, and so on.
- //
- // In other words, every time a new chunk becomes active, its appended to this
- // list.
- refs []unsafe.Pointer
-
- // defunct is true if free has been called on this arena.
- //
- // This is just a best-effort way to discover a concurrent allocation
- // and free. Also used to detect a double-free.
- defunct atomic.Bool
-}
-
-// newUserArena creates a new userArena ready to be used.
-func newUserArena() *userArena {
- a := new(userArena)
- SetFinalizer(a, func(a *userArena) {
- // If arena handle is dropped without being freed, then call
- // free on the arena, so the arena chunks are never reclaimed
- // by the garbage collector.
- a.free()
- })
- a.refill()
- return a
-}
-
-// new allocates a new object of the provided type into the arena, and returns
-// its pointer.
-//
-// This operation is not safe to call concurrently with other operations on the
-// same arena.
-func (a *userArena) new(typ *_type) unsafe.Pointer {
- return a.alloc(typ, -1)
-}
-
-// slice allocates a new slice backing store. slice must be a pointer to a slice
-// (i.e. *[]T), because userArenaSlice will update the slice directly.
-//
-// cap determines the capacity of the slice backing store and must be non-negative.
-//
-// This operation is not safe to call concurrently with other operations on the
-// same arena.
-func (a *userArena) slice(sl any, cap int) {
- if cap < 0 {
- panic("userArena.slice: negative cap")
- }
- i := efaceOf(&sl)
- typ := i._type
- if typ.Kind_&kindMask != kindPtr {
- panic("slice result of non-ptr type")
- }
- typ = (*ptrtype)(unsafe.Pointer(typ)).Elem
- if typ.Kind_&kindMask != kindSlice {
- panic("slice of non-ptr-to-slice type")
- }
- typ = (*slicetype)(unsafe.Pointer(typ)).Elem
- // t is now the element type of the slice we want to allocate.
-
- *((*slice)(i.data)) = slice{a.alloc(typ, cap), cap, cap}
-}
-
-// free returns the userArena's chunks back to mheap and marks it as defunct.
-//
-// Must be called at most once for any given arena.
-//
-// This operation is not safe to call concurrently with other operations on the
-// same arena.
-func (a *userArena) free() {
- // Check for a double-free.
- if a.defunct.Load() {
- panic("arena double free")
- }
-
- // Mark ourselves as defunct.
- a.defunct.Store(true)
- SetFinalizer(a, nil)
-
- // Free all the full arenas.
- //
- // The refs on this list are in reverse order from the second-to-last.
- s := a.fullList
- i := len(a.refs) - 2
- for s != nil {
- a.fullList = s.next
- s.next = nil
- freeUserArenaChunk(s, a.refs[i])
- s = a.fullList
- i--
- }
- if a.fullList != nil || i >= 0 {
- // There's still something left on the full list, or we
- // failed to actually iterate over the entire refs list.
- throw("full list doesn't match refs list in length")
- }
-
- // Put the active chunk onto the reuse list.
- //
- // Note that active's reference is always the last reference in refs.
- s = a.active
- if s != nil {
- if raceenabled || msanenabled || asanenabled {
- // Don't reuse arenas with sanitizers enabled. We want to catch
- // any use-after-free errors aggressively.
- freeUserArenaChunk(s, a.refs[len(a.refs)-1])
- } else {
- lock(&userArenaState.lock)
- userArenaState.reuse = append(userArenaState.reuse, liveUserArenaChunk{s, a.refs[len(a.refs)-1]})
- unlock(&userArenaState.lock)
- }
- }
- // nil out a.active so that a race with freeing will more likely cause a crash.
- a.active = nil
- a.refs = nil
-}
-
-// alloc reserves space in the current chunk or calls refill and reserves space
-// in a new chunk. If cap is negative, the type will be taken literally, otherwise
-// it will be considered as an element type for a slice backing store with capacity
-// cap.
-func (a *userArena) alloc(typ *_type, cap int) unsafe.Pointer {
- s := a.active
- var x unsafe.Pointer
- for {
- x = s.userArenaNextFree(typ, cap)
- if x != nil {
- break
- }
- s = a.refill()
- }
- return x
-}
-
-// refill inserts the current arena chunk onto the full list and obtains a new
-// one, either from the partial list or allocating a new one, both from mheap.
-func (a *userArena) refill() *mspan {
- // If there's an active chunk, assume it's full.
- s := a.active
- if s != nil {
- if s.userArenaChunkFree.size() > userArenaChunkMaxAllocBytes {
- // It's difficult to tell when we're actually out of memory
- // in a chunk because the allocation that failed may still leave
- // some free space available. However, that amount of free space
- // should never exceed the maximum allocation size.
- throw("wasted too much memory in an arena chunk")
- }
- s.next = a.fullList
- a.fullList = s
- a.active = nil
- s = nil
- }
- var x unsafe.Pointer
-
- // Check the partially-used list.
- lock(&userArenaState.lock)
- if len(userArenaState.reuse) > 0 {
- // Pick off the last arena chunk from the list.
- n := len(userArenaState.reuse) - 1
- x = userArenaState.reuse[n].x
- s = userArenaState.reuse[n].mspan
- userArenaState.reuse[n].x = nil
- userArenaState.reuse[n].mspan = nil
- userArenaState.reuse = userArenaState.reuse[:n]
- }
- unlock(&userArenaState.lock)
- if s == nil {
- // Allocate a new one.
- x, s = newUserArenaChunk()
- if s == nil {
- throw("out of memory")
- }
- }
- a.refs = append(a.refs, x)
- a.active = s
- return s
-}
-
-type liveUserArenaChunk struct {
- *mspan // Must represent a user arena chunk.
-
- // Reference to mspan.base() to keep the chunk alive.
- x unsafe.Pointer
-}
-
-var userArenaState struct {
- lock mutex
-
- // reuse contains a list of partially-used and already-live
- // user arena chunks that can be quickly reused for another
- // arena.
- //
- // Protected by lock.
- reuse []liveUserArenaChunk
-
- // fault contains full user arena chunks that need to be faulted.
- //
- // Protected by lock.
- fault []liveUserArenaChunk
-}
-
-// userArenaNextFree reserves space in the user arena for an item of the specified
-// type. If cap is not -1, this is for an array of cap elements of type t.
-func (s *mspan) userArenaNextFree(typ *_type, cap int) unsafe.Pointer {
- size := typ.Size_
- if cap > 0 {
- if size > ^uintptr(0)/uintptr(cap) {
- // Overflow.
- throw("out of memory")
- }
- size *= uintptr(cap)
- }
- if size == 0 || cap == 0 {
- return unsafe.Pointer(&zerobase)
- }
- if size > userArenaChunkMaxAllocBytes {
- // Redirect allocations that don't fit into a chunk well directly
- // from the heap.
- if cap >= 0 {
- return newarray(typ, cap)
- }
- return newobject(typ)
- }
-
- // Prevent preemption as we set up the space for a new object.
- //
- // Act like we're allocating.
- mp := acquirem()
- if mp.mallocing != 0 {
- throw("malloc deadlock")
- }
- if mp.gsignal == getg() {
- throw("malloc during signal")
- }
- mp.mallocing = 1
-
- var ptr unsafe.Pointer
- if typ.PtrBytes == 0 {
- // Allocate pointer-less objects from the tail end of the chunk.
- v, ok := s.userArenaChunkFree.takeFromBack(size, typ.Align_)
- if ok {
- ptr = unsafe.Pointer(v)
- }
- } else {
- v, ok := s.userArenaChunkFree.takeFromFront(size, typ.Align_)
- if ok {
- ptr = unsafe.Pointer(v)
- }
- }
- if ptr == nil {
- // Failed to allocate.
- mp.mallocing = 0
- releasem(mp)
- return nil
- }
- if s.needzero != 0 {
- throw("arena chunk needs zeroing, but should already be zeroed")
- }
- // Set up heap bitmap and do extra accounting.
- if typ.PtrBytes != 0 {
- if cap >= 0 {
- userArenaHeapBitsSetSliceType(typ, cap, ptr, s)
- } else {
- userArenaHeapBitsSetType(typ, ptr, s)
- }
- c := getMCache(mp)
- if c == nil {
- throw("mallocgc called without a P or outside bootstrapping")
- }
- if cap > 0 {
- c.scanAlloc += size - (typ.Size_ - typ.PtrBytes)
- } else {
- c.scanAlloc += typ.PtrBytes
- }
- }
-
- // Ensure that the stores above that initialize x to
- // type-safe memory and set the heap bits occur before
- // the caller can make ptr observable to the garbage
- // collector. Otherwise, on weakly ordered machines,
- // the garbage collector could follow a pointer to x,
- // but see uninitialized memory or stale heap bits.
- publicationBarrier()
-
- mp.mallocing = 0
- releasem(mp)
-
- return ptr
-}
-
-// userArenaHeapBitsSetSliceType is the equivalent of heapBitsSetType but for
-// Go slice backing store values allocated in a user arena chunk. It sets up the
-// heap bitmap for n consecutive values with type typ allocated at address ptr.
-func userArenaHeapBitsSetSliceType(typ *_type, n int, ptr unsafe.Pointer, s *mspan) {
- mem, overflow := math.MulUintptr(typ.Size_, uintptr(n))
- if overflow || n < 0 || mem > maxAlloc {
- panic(plainError("runtime: allocation size out of range"))
- }
- for i := 0; i < n; i++ {
- userArenaHeapBitsSetType(typ, add(ptr, uintptr(i)*typ.Size_), s)
- }
-}
-
-// newUserArenaChunk allocates a user arena chunk, which maps to a single
-// heap arena and single span. Returns a pointer to the base of the chunk
-// (this is really important: we need to keep the chunk alive) and the span.
-func newUserArenaChunk() (unsafe.Pointer, *mspan) {
- if gcphase == _GCmarktermination {
- throw("newUserArenaChunk called with gcphase == _GCmarktermination")
- }
-
- // Deduct assist credit. Because user arena chunks are modeled as one
- // giant heap object which counts toward heapLive, we're obligated to
- // assist the GC proportionally (and it's worth noting that the arena
- // does represent additional work for the GC, but we also have no idea
- // what that looks like until we actually allocate things into the
- // arena).
- deductAssistCredit(userArenaChunkBytes)
-
- // Set mp.mallocing to keep from being preempted by GC.
- mp := acquirem()
- if mp.mallocing != 0 {
- throw("malloc deadlock")
- }
- if mp.gsignal == getg() {
- throw("malloc during signal")
- }
- mp.mallocing = 1
-
- // Allocate a new user arena.
- var span *mspan
- systemstack(func() {
- span = mheap_.allocUserArenaChunk()
- })
- if span == nil {
- throw("out of memory")
- }
- x := unsafe.Pointer(span.base())
-
- // Allocate black during GC.
- // All slots hold nil so no scanning is needed.
- // This may be racing with GC so do it atomically if there can be
- // a race marking the bit.
- if gcphase != _GCoff {
- gcmarknewobject(span, span.base())
- }
-
- if raceenabled {
- // TODO(mknyszek): Track individual objects.
- racemalloc(unsafe.Pointer(span.base()), span.elemsize)
- }
-
- if msanenabled {
- // TODO(mknyszek): Track individual objects.
- msanmalloc(unsafe.Pointer(span.base()), span.elemsize)
- }
-
- if asanenabled {
- // TODO(mknyszek): Track individual objects.
- rzSize := computeRZlog(span.elemsize)
- span.elemsize -= rzSize
- if goexperiment.AllocHeaders {
- span.largeType.Size_ = span.elemsize
- }
- rzStart := span.base() + span.elemsize
- span.userArenaChunkFree = makeAddrRange(span.base(), rzStart)
- asanpoison(unsafe.Pointer(rzStart), span.limit-rzStart)
- asanunpoison(unsafe.Pointer(span.base()), span.elemsize)
- }
-
- if rate := MemProfileRate; rate > 0 {
- c := getMCache(mp)
- if c == nil {
- throw("newUserArenaChunk called without a P or outside bootstrapping")
- }
- // Note cache c only valid while m acquired; see #47302
- if rate != 1 && userArenaChunkBytes < c.nextSample {
- c.nextSample -= userArenaChunkBytes
- } else {
- profilealloc(mp, unsafe.Pointer(span.base()), userArenaChunkBytes)
- }
- }
- mp.mallocing = 0
- releasem(mp)
-
- // Again, because this chunk counts toward heapLive, potentially trigger a GC.
- if t := (gcTrigger{kind: gcTriggerHeap}); t.test() {
- gcStart(t)
- }
-
- if debug.malloc {
- if debug.allocfreetrace != 0 {
- tracealloc(unsafe.Pointer(span.base()), userArenaChunkBytes, nil)
- }
-
- if inittrace.active && inittrace.id == getg().goid {
- // Init functions are executed sequentially in a single goroutine.
- inittrace.bytes += uint64(userArenaChunkBytes)
- }
- }
-
- // Double-check it's aligned to the physical page size. Based on the current
- // implementation this is trivially true, but it need not be in the future.
- // However, if it's not aligned to the physical page size then we can't properly
- // set it to fault later.
- if uintptr(x)%physPageSize != 0 {
- throw("user arena chunk is not aligned to the physical page size")
- }
-
- return x, span
-}
-
-// isUnusedUserArenaChunk indicates that the arena chunk has been set to fault
-// and doesn't contain any scannable memory anymore. However, it might still be
-// mSpanInUse as it sits on the quarantine list, since it needs to be swept.
-//
-// This is not safe to execute unless the caller has ownership of the mspan or
-// the world is stopped (preemption is prevented while the relevant state changes).
-//
-// This is really only meant to be used by accounting tests in the runtime to
-// distinguish when a span shouldn't be counted (since mSpanInUse might not be
-// enough).
-func (s *mspan) isUnusedUserArenaChunk() bool {
- return s.isUserArenaChunk && s.spanclass == makeSpanClass(0, true)
-}
-
-// setUserArenaChunkToFault sets the address space for the user arena chunk to fault
-// and releases any underlying memory resources.
-//
-// Must be in a non-preemptible state to ensure the consistency of statistics
-// exported to MemStats.
-func (s *mspan) setUserArenaChunkToFault() {
- if !s.isUserArenaChunk {
- throw("invalid span in heapArena for user arena")
- }
- if s.npages*pageSize != userArenaChunkBytes {
- throw("span on userArena.faultList has invalid size")
- }
-
- // Update the span class to be noscan. What we want to happen is that
- // any pointer into the span keeps it from getting recycled, so we want
- // the mark bit to get set, but we're about to set the address space to fault,
- // so we have to prevent the GC from scanning this memory.
- //
- // It's OK to set it here because (1) a GC isn't in progress, so the scanning code
- // won't make a bad decision, (2) we're currently non-preemptible and in the runtime,
- // so a GC is blocked from starting. We might race with sweeping, which could
- // put it on the "wrong" sweep list, but really don't care because the chunk is
- // treated as a large object span and there's no meaningful difference between scan
- // and noscan large objects in the sweeper. The STW at the start of the GC acts as a
- // barrier for this update.
- s.spanclass = makeSpanClass(0, true)
-
- // Actually set the arena chunk to fault, so we'll get dangling pointer errors.
- // sysFault currently uses a method on each OS that forces it to evacuate all
- // memory backing the chunk.
- sysFault(unsafe.Pointer(s.base()), s.npages*pageSize)
-
- // Everything on the list is counted as in-use, however sysFault transitions to
- // Reserved, not Prepared, so we skip updating heapFree or heapReleased and just
- // remove the memory from the total altogether; it's just address space now.
- gcController.heapInUse.add(-int64(s.npages * pageSize))
-
- // Count this as a free of an object right now as opposed to when
- // the span gets off the quarantine list. The main reason is so that the
- // amount of bytes allocated doesn't exceed how much is counted as
- // "mapped ready," which could cause a deadlock in the pacer.
- gcController.totalFree.Add(int64(s.elemsize))
-
- // Update consistent stats to match.
- //
- // We're non-preemptible, so it's safe to update consistent stats (our P
- // won't change out from under us).
- stats := memstats.heapStats.acquire()
- atomic.Xaddint64(&stats.committed, -int64(s.npages*pageSize))
- atomic.Xaddint64(&stats.inHeap, -int64(s.npages*pageSize))
- atomic.Xadd64(&stats.largeFreeCount, 1)
- atomic.Xadd64(&stats.largeFree, int64(s.elemsize))
- memstats.heapStats.release()
-
- // This counts as a free, so update heapLive.
- gcController.update(-int64(s.elemsize), 0)
-
- // Mark it as free for the race detector.
- if raceenabled {
- racefree(unsafe.Pointer(s.base()), s.elemsize)
- }
-
- systemstack(func() {
- // Add the user arena to the quarantine list.
- lock(&mheap_.lock)
- mheap_.userArena.quarantineList.insert(s)
- unlock(&mheap_.lock)
- })
-}
-
-// inUserArenaChunk returns true if p points to a user arena chunk.
-func inUserArenaChunk(p uintptr) bool {
- s := spanOf(p)
- if s == nil {
- return false
- }
- return s.isUserArenaChunk
-}
-
-// freeUserArenaChunk releases the user arena represented by s back to the runtime.
-//
-// x must be a live pointer within s.
-//
-// The runtime will set the user arena to fault once it's safe (the GC is no longer running)
-// and then once the user arena is no longer referenced by the application, will allow it to
-// be reused.
-func freeUserArenaChunk(s *mspan, x unsafe.Pointer) {
- if !s.isUserArenaChunk {
- throw("span is not for a user arena")
- }
- if s.npages*pageSize != userArenaChunkBytes {
- throw("invalid user arena span size")
- }
-
- // Mark the region as free to various santizers immediately instead
- // of handling them at sweep time.
- if raceenabled {
- racefree(unsafe.Pointer(s.base()), s.elemsize)
- }
- if msanenabled {
- msanfree(unsafe.Pointer(s.base()), s.elemsize)
- }
- if asanenabled {
- asanpoison(unsafe.Pointer(s.base()), s.elemsize)
- }
-
- // Make ourselves non-preemptible as we manipulate state and statistics.
- //
- // Also required by setUserArenaChunksToFault.
- mp := acquirem()
-
- // We can only set user arenas to fault if we're in the _GCoff phase.
- if gcphase == _GCoff {
- lock(&userArenaState.lock)
- faultList := userArenaState.fault
- userArenaState.fault = nil
- unlock(&userArenaState.lock)
-
- s.setUserArenaChunkToFault()
- for _, lc := range faultList {
- lc.mspan.setUserArenaChunkToFault()
- }
-
- // Until the chunks are set to fault, keep them alive via the fault list.
- KeepAlive(x)
- KeepAlive(faultList)
- } else {
- // Put the user arena on the fault list.
- lock(&userArenaState.lock)
- userArenaState.fault = append(userArenaState.fault, liveUserArenaChunk{s, x})
- unlock(&userArenaState.lock)
- }
- releasem(mp)
-}
-
-// allocUserArenaChunk attempts to reuse a free user arena chunk represented
-// as a span.
-//
-// Must be in a non-preemptible state to ensure the consistency of statistics
-// exported to MemStats.
-//
-// Acquires the heap lock. Must run on the system stack for that reason.
-//
-//go:systemstack
-func (h *mheap) allocUserArenaChunk() *mspan {
- var s *mspan
- var base uintptr
-
- // First check the free list.
- lock(&h.lock)
- if !h.userArena.readyList.isEmpty() {
- s = h.userArena.readyList.first
- h.userArena.readyList.remove(s)
- base = s.base()
- } else {
- // Free list was empty, so allocate a new arena.
- hintList := &h.userArena.arenaHints
- if raceenabled {
- // In race mode just use the regular heap hints. We might fragment
- // the address space, but the race detector requires that the heap
- // is mapped contiguously.
- hintList = &h.arenaHints
- }
- v, size := h.sysAlloc(userArenaChunkBytes, hintList, false)
- if size%userArenaChunkBytes != 0 {
- throw("sysAlloc size is not divisible by userArenaChunkBytes")
- }
- if size > userArenaChunkBytes {
- // We got more than we asked for. This can happen if
- // heapArenaSize > userArenaChunkSize, or if sysAlloc just returns
- // some extra as a result of trying to find an aligned region.
- //
- // Divide it up and put it on the ready list.
- for i := userArenaChunkBytes; i < size; i += userArenaChunkBytes {
- s := h.allocMSpanLocked()
- s.init(uintptr(v)+i, userArenaChunkPages)
- h.userArena.readyList.insertBack(s)
- }
- size = userArenaChunkBytes
- }
- base = uintptr(v)
- if base == 0 {
- // Out of memory.
- unlock(&h.lock)
- return nil
- }
- s = h.allocMSpanLocked()
- }
- unlock(&h.lock)
-
- // sysAlloc returns Reserved address space, and any span we're
- // reusing is set to fault (so, also Reserved), so transition
- // it to Prepared and then Ready.
- //
- // Unlike (*mheap).grow, just map in everything that we
- // asked for. We're likely going to use it all.
- sysMap(unsafe.Pointer(base), userArenaChunkBytes, &gcController.heapReleased)
- sysUsed(unsafe.Pointer(base), userArenaChunkBytes, userArenaChunkBytes)
-
- // Model the user arena as a heap span for a large object.
- spc := makeSpanClass(0, false)
- h.initSpan(s, spanAllocHeap, spc, base, userArenaChunkPages)
- s.isUserArenaChunk = true
- s.elemsize -= userArenaChunkReserveBytes()
- s.limit = s.base() + s.elemsize
- s.freeindex = 1
- s.allocCount = 1
-
- // Account for this new arena chunk memory.
- gcController.heapInUse.add(int64(userArenaChunkBytes))
- gcController.heapReleased.add(-int64(userArenaChunkBytes))
-
- stats := memstats.heapStats.acquire()
- atomic.Xaddint64(&stats.inHeap, int64(userArenaChunkBytes))
- atomic.Xaddint64(&stats.committed, int64(userArenaChunkBytes))
-
- // Model the arena as a single large malloc.
- atomic.Xadd64(&stats.largeAlloc, int64(s.elemsize))
- atomic.Xadd64(&stats.largeAllocCount, 1)
- memstats.heapStats.release()
-
- // Count the alloc in inconsistent, internal stats.
- gcController.totalAlloc.Add(int64(s.elemsize))
-
- // Update heapLive.
- gcController.update(int64(s.elemsize), 0)
-
- // This must clear the entire heap bitmap so that it's safe
- // to allocate noscan data without writing anything out.
- s.initHeapBits(true)
-
- // Clear the span preemptively. It's an arena chunk, so let's assume
- // everything is going to be used.
- //
- // This also seems to make a massive difference as to whether or
- // not Linux decides to back this memory with transparent huge
- // pages. There's latency involved in this zeroing, but the hugepage
- // gains are almost always worth it. Note: it's important that we
- // clear even if it's freshly mapped and we know there's no point
- // to zeroing as *that* is the critical signal to use huge pages.
- memclrNoHeapPointers(unsafe.Pointer(s.base()), s.elemsize)
- s.needzero = 0
-
- s.freeIndexForScan = 1
-
- // Set up the range for allocation.
- s.userArenaChunkFree = makeAddrRange(base, base+s.elemsize)
-
- // Put the large span in the mcentral swept list so that it's
- // visible to the background sweeper.
- h.central[spc].mcentral.fullSwept(h.sweepgen).push(s)
-
- if goexperiment.AllocHeaders {
- // Set up an allocation header. Avoid write barriers here because this type
- // is not a real type, and it exists in an invalid location.
- *(*uintptr)(unsafe.Pointer(&s.largeType)) = uintptr(unsafe.Pointer(s.limit))
- *(*uintptr)(unsafe.Pointer(&s.largeType.GCData)) = s.limit + unsafe.Sizeof(_type{})
- s.largeType.PtrBytes = 0
- s.largeType.Size_ = s.elemsize
- }
- return s
-}
diff --git a/contrib/go/_std_1.22/src/runtime/asan.go b/contrib/go/_std_1.22/src/runtime/asan.go
deleted file mode 100644
index 25b83277e6d7..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asan.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2021 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.
-
-//go:build asan
-
-package runtime
-
-import (
- "unsafe"
-)
-
-// Public address sanitizer API.
-func ASanRead(addr unsafe.Pointer, len int) {
- sp := getcallersp()
- pc := getcallerpc()
- doasanread(addr, uintptr(len), sp, pc)
-}
-
-func ASanWrite(addr unsafe.Pointer, len int) {
- sp := getcallersp()
- pc := getcallerpc()
- doasanwrite(addr, uintptr(len), sp, pc)
-}
-
-// Private interface for the runtime.
-const asanenabled = true
-
-// asan{read,write} are nosplit because they may be called between
-// fork and exec, when the stack must not grow. See issue #50391.
-
-//go:nosplit
-func asanread(addr unsafe.Pointer, sz uintptr) {
- sp := getcallersp()
- pc := getcallerpc()
- doasanread(addr, sz, sp, pc)
-}
-
-//go:nosplit
-func asanwrite(addr unsafe.Pointer, sz uintptr) {
- sp := getcallersp()
- pc := getcallerpc()
- doasanwrite(addr, sz, sp, pc)
-}
-
-//go:noescape
-func doasanread(addr unsafe.Pointer, sz, sp, pc uintptr)
-
-//go:noescape
-func doasanwrite(addr unsafe.Pointer, sz, sp, pc uintptr)
-
-//go:noescape
-func asanunpoison(addr unsafe.Pointer, sz uintptr)
-
-//go:noescape
-func asanpoison(addr unsafe.Pointer, sz uintptr)
-
-//go:noescape
-func asanregisterglobals(addr unsafe.Pointer, n uintptr)
-
-// These are called from asan_GOARCH.s
-//
-//go:cgo_import_static __asan_read_go
-//go:cgo_import_static __asan_write_go
-//go:cgo_import_static __asan_unpoison_go
-//go:cgo_import_static __asan_poison_go
-//go:cgo_import_static __asan_register_globals_go
diff --git a/contrib/go/_std_1.22/src/runtime/asm.s b/contrib/go/_std_1.22/src/runtime/asm.s
deleted file mode 100644
index 24cd0c95db64..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asm.s
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 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.
-
-#include "textflag.h"
-
-#ifndef GOARCH_amd64
-TEXT ·sigpanic0(SB),NOSPLIT,$0-0
- JMP ·sigpanic(SB)
-#endif
-
-// See map.go comment on the need for this routine.
-TEXT ·mapinitnoop(SB),NOSPLIT,$0-0
- RET
-
-#ifndef GOARCH_amd64
-#ifndef GOARCH_arm64
-#ifndef GOARCH_mips64
-#ifndef GOARCH_mips64le
-#ifndef GOARCH_ppc64
-#ifndef GOARCH_ppc64le
-#ifndef GOARCH_riscv64
-#ifndef GOARCH_wasm
-// stub to appease shared build mode.
-TEXT ·switchToCrashStack0(SB),NOSPLIT,$0-0
- UNDEF
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
diff --git a/contrib/go/_std_1.22/src/runtime/asm_amd64.s b/contrib/go/_std_1.22/src/runtime/asm_amd64.s
deleted file mode 100644
index 1071d270c1b8..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asm_amd64.s
+++ /dev/null
@@ -1,2138 +0,0 @@
-// Copyright 2009 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.
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "funcdata.h"
-#include "textflag.h"
-#include "cgo/abi_amd64.h"
-
-// _rt0_amd64 is common startup code for most amd64 systems when using
-// internal linking. This is the entry point for the program from the
-// kernel for an ordinary -buildmode=exe program. The stack holds the
-// number of arguments and the C-style argv.
-TEXT _rt0_amd64(SB),NOSPLIT,$-8
- MOVQ 0(SP), DI // argc
- LEAQ 8(SP), SI // argv
- JMP runtime·rt0_go(SB)
-
-// main is common startup code for most amd64 systems when using
-// external linking. The C startup code will call the symbol "main"
-// passing argc and argv in the usual C ABI registers DI and SI.
-TEXT main(SB),NOSPLIT,$-8
- JMP runtime·rt0_go(SB)
-
-// _rt0_amd64_lib is common startup code for most amd64 systems when
-// using -buildmode=c-archive or -buildmode=c-shared. The linker will
-// arrange to invoke this function as a global constructor (for
-// c-archive) or when the shared library is loaded (for c-shared).
-// We expect argc and argv to be passed in the usual C ABI registers
-// DI and SI.
-TEXT _rt0_amd64_lib(SB),NOSPLIT|NOFRAME,$0
- // Transition from C ABI to Go ABI.
- PUSH_REGS_HOST_TO_ABI0()
-
- MOVQ DI, _rt0_amd64_lib_argc<>(SB)
- MOVQ SI, _rt0_amd64_lib_argv<>(SB)
-
- // Synchronous initialization.
- CALL runtime·libpreinit(SB)
-
- // Create a new thread to finish Go runtime initialization.
- MOVQ _cgo_sys_thread_create(SB), AX
- TESTQ AX, AX
- JZ nocgo
-
- // We're calling back to C.
- // Align stack per ELF ABI requirements.
- MOVQ SP, BX // Callee-save in C ABI
- ANDQ $~15, SP
- MOVQ $_rt0_amd64_lib_go(SB), DI
- MOVQ $0, SI
- CALL AX
- MOVQ BX, SP
- JMP restore
-
-nocgo:
- ADJSP $16
- MOVQ $0x800000, 0(SP) // stacksize
- MOVQ $_rt0_amd64_lib_go(SB), AX
- MOVQ AX, 8(SP) // fn
- CALL runtime·newosproc0(SB)
- ADJSP $-16
-
-restore:
- POP_REGS_HOST_TO_ABI0()
- RET
-
-// _rt0_amd64_lib_go initializes the Go runtime.
-// This is started in a separate thread by _rt0_amd64_lib.
-TEXT _rt0_amd64_lib_go(SB),NOSPLIT,$0
- MOVQ _rt0_amd64_lib_argc<>(SB), DI
- MOVQ _rt0_amd64_lib_argv<>(SB), SI
- JMP runtime·rt0_go(SB)
-
-DATA _rt0_amd64_lib_argc<>(SB)/8, $0
-GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
-DATA _rt0_amd64_lib_argv<>(SB)/8, $0
-GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
-
-#ifdef GOAMD64_v2
-DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v2 microarchitecture support.\n"
-#endif
-
-#ifdef GOAMD64_v3
-DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v3 microarchitecture support.\n"
-#endif
-
-#ifdef GOAMD64_v4
-DATA bad_cpu_msg<>+0x00(SB)/84, $"This program can only be run on AMD64 processors with v4 microarchitecture support.\n"
-#endif
-
-GLOBL bad_cpu_msg<>(SB), RODATA, $84
-
-// Define a list of AMD64 microarchitecture level features
-// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
-
- // SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT
-#define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23)
- // LAHF/SAHF
-#define V2_EXT_FEATURES_CX (1 << 0)
- // FMA MOVBE OSXSAVE AVX F16C
-#define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29)
- // ABM (FOR LZNCT)
-#define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5)
- // BMI1 AVX2 BMI2
-#define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8)
- // XMM YMM
-#define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2)
-
-#define V4_FEATURES_CX V3_FEATURES_CX
-
-#define V4_EXT_FEATURES_CX V3_EXT_FEATURES_CX
- // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL
-#define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31)
- // OPMASK ZMM
-#define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7))
-
-#ifdef GOAMD64_v2
-#define NEED_MAX_CPUID 0x80000001
-#define NEED_FEATURES_CX V2_FEATURES_CX
-#define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX
-#endif
-
-#ifdef GOAMD64_v3
-#define NEED_MAX_CPUID 0x80000001
-#define NEED_FEATURES_CX V3_FEATURES_CX
-#define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX
-#define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX
-#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
-#endif
-
-#ifdef GOAMD64_v4
-#define NEED_MAX_CPUID 0x80000001
-#define NEED_FEATURES_CX V4_FEATURES_CX
-#define NEED_EXT_FEATURES_CX V4_EXT_FEATURES_CX
-#define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX
-
-// Darwin requires a different approach to check AVX512 support, see CL 285572.
-#ifdef GOOS_darwin
-#define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
-// These values are from:
-// https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h
-#define commpage64_base_address 0x00007fffffe00000
-#define commpage64_cpu_capabilities64 (commpage64_base_address+0x010)
-#define commpage64_version (commpage64_base_address+0x01E)
-#define AVX512F 0x0000004000000000
-#define AVX512CD 0x0000008000000000
-#define AVX512DQ 0x0000010000000000
-#define AVX512BW 0x0000020000000000
-#define AVX512VL 0x0000100000000000
-#define NEED_DARWIN_SUPPORT (AVX512F | AVX512DQ | AVX512CD | AVX512BW | AVX512VL)
-#else
-#define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX
-#endif
-
-#endif
-
-TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
- // copy arguments forward on an even stack
- MOVQ DI, AX // argc
- MOVQ SI, BX // argv
- SUBQ $(5*8), SP // 3args 2auto
- ANDQ $~15, SP
- MOVQ AX, 24(SP)
- MOVQ BX, 32(SP)
-
- // create istack out of the given (operating system) stack.
- // _cgo_init may update stackguard.
- MOVQ $runtime·g0(SB), DI
- LEAQ (-64*1024)(SP), BX
- MOVQ BX, g_stackguard0(DI)
- MOVQ BX, g_stackguard1(DI)
- MOVQ BX, (g_stack+stack_lo)(DI)
- MOVQ SP, (g_stack+stack_hi)(DI)
-
- // find out information about the processor we're on
- MOVL $0, AX
- CPUID
- CMPL AX, $0
- JE nocpuinfo
-
- CMPL BX, $0x756E6547 // "Genu"
- JNE notintel
- CMPL DX, $0x49656E69 // "ineI"
- JNE notintel
- CMPL CX, $0x6C65746E // "ntel"
- JNE notintel
- MOVB $1, runtime·isIntel(SB)
-
-notintel:
- // Load EAX=1 cpuid flags
- MOVL $1, AX
- CPUID
- MOVL AX, runtime·processorVersionInfo(SB)
-
-nocpuinfo:
- // if there is an _cgo_init, call it.
- MOVQ _cgo_init(SB), AX
- TESTQ AX, AX
- JZ needtls
- // arg 1: g0, already in DI
- MOVQ $setg_gcc<>(SB), SI // arg 2: setg_gcc
- MOVQ $0, DX // arg 3, 4: not used when using platform's TLS
- MOVQ $0, CX
-#ifdef GOOS_android
- MOVQ $runtime·tls_g(SB), DX // arg 3: &tls_g
- // arg 4: TLS base, stored in slot 0 (Android's TLS_SLOT_SELF).
- // Compensate for tls_g (+16).
- MOVQ -16(TLS), CX
-#endif
-#ifdef GOOS_windows
- MOVQ $runtime·tls_g(SB), DX // arg 3: &tls_g
- // Adjust for the Win64 calling convention.
- MOVQ CX, R9 // arg 4
- MOVQ DX, R8 // arg 3
- MOVQ SI, DX // arg 2
- MOVQ DI, CX // arg 1
-#endif
- CALL AX
-
- // update stackguard after _cgo_init
- MOVQ $runtime·g0(SB), CX
- MOVQ (g_stack+stack_lo)(CX), AX
- ADDQ $const_stackGuard, AX
- MOVQ AX, g_stackguard0(CX)
- MOVQ AX, g_stackguard1(CX)
-
-#ifndef GOOS_windows
- JMP ok
-#endif
-needtls:
-#ifdef GOOS_plan9
- // skip TLS setup on Plan 9
- JMP ok
-#endif
-#ifdef GOOS_solaris
- // skip TLS setup on Solaris
- JMP ok
-#endif
-#ifdef GOOS_illumos
- // skip TLS setup on illumos
- JMP ok
-#endif
-#ifdef GOOS_darwin
- // skip TLS setup on Darwin
- JMP ok
-#endif
-#ifdef GOOS_openbsd
- // skip TLS setup on OpenBSD
- JMP ok
-#endif
-
-#ifdef GOOS_windows
- CALL runtime·wintls(SB)
-#endif
-
- LEAQ runtime·m0+m_tls(SB), DI
- CALL runtime·settls(SB)
-
- // store through it, to make sure it works
- get_tls(BX)
- MOVQ $0x123, g(BX)
- MOVQ runtime·m0+m_tls(SB), AX
- CMPQ AX, $0x123
- JEQ 2(PC)
- CALL runtime·abort(SB)
-ok:
- // set the per-goroutine and per-mach "registers"
- get_tls(BX)
- LEAQ runtime·g0(SB), CX
- MOVQ CX, g(BX)
- LEAQ runtime·m0(SB), AX
-
- // save m->g0 = g0
- MOVQ CX, m_g0(AX)
- // save m0 to g0->m
- MOVQ AX, g_m(CX)
-
- CLD // convention is D is always left cleared
-
- // Check GOAMD64 requirements
- // We need to do this after setting up TLS, so that
- // we can report an error if there is a failure. See issue 49586.
-#ifdef NEED_FEATURES_CX
- MOVL $0, AX
- CPUID
- CMPL AX, $0
- JE bad_cpu
- MOVL $1, AX
- CPUID
- ANDL $NEED_FEATURES_CX, CX
- CMPL CX, $NEED_FEATURES_CX
- JNE bad_cpu
-#endif
-
-#ifdef NEED_MAX_CPUID
- MOVL $0x80000000, AX
- CPUID
- CMPL AX, $NEED_MAX_CPUID
- JL bad_cpu
-#endif
-
-#ifdef NEED_EXT_FEATURES_BX
- MOVL $7, AX
- MOVL $0, CX
- CPUID
- ANDL $NEED_EXT_FEATURES_BX, BX
- CMPL BX, $NEED_EXT_FEATURES_BX
- JNE bad_cpu
-#endif
-
-#ifdef NEED_EXT_FEATURES_CX
- MOVL $0x80000001, AX
- CPUID
- ANDL $NEED_EXT_FEATURES_CX, CX
- CMPL CX, $NEED_EXT_FEATURES_CX
- JNE bad_cpu
-#endif
-
-#ifdef NEED_OS_SUPPORT_AX
- XORL CX, CX
- XGETBV
- ANDL $NEED_OS_SUPPORT_AX, AX
- CMPL AX, $NEED_OS_SUPPORT_AX
- JNE bad_cpu
-#endif
-
-#ifdef NEED_DARWIN_SUPPORT
- MOVQ $commpage64_version, BX
- CMPW (BX), $13 // cpu_capabilities64 undefined in versions < 13
- JL bad_cpu
- MOVQ $commpage64_cpu_capabilities64, BX
- MOVQ (BX), BX
- MOVQ $NEED_DARWIN_SUPPORT, CX
- ANDQ CX, BX
- CMPQ BX, CX
- JNE bad_cpu
-#endif
-
- CALL runtime·check(SB)
-
- MOVL 24(SP), AX // copy argc
- MOVL AX, 0(SP)
- MOVQ 32(SP), AX // copy argv
- MOVQ AX, 8(SP)
- CALL runtime·args(SB)
- CALL runtime·osinit(SB)
- CALL runtime·schedinit(SB)
-
- // create a new goroutine to start program
- MOVQ $runtime·mainPC(SB), AX // entry
- PUSHQ AX
- CALL runtime·newproc(SB)
- POPQ AX
-
- // start this M
- CALL runtime·mstart(SB)
-
- CALL runtime·abort(SB) // mstart should never return
- RET
-
-bad_cpu: // show that the program requires a certain microarchitecture level.
- MOVQ $2, 0(SP)
- MOVQ $bad_cpu_msg<>(SB), AX
- MOVQ AX, 8(SP)
- MOVQ $84, 16(SP)
- CALL runtime·write(SB)
- MOVQ $1, 0(SP)
- CALL runtime·exit(SB)
- CALL runtime·abort(SB)
- RET
-
- // Prevent dead-code elimination of debugCallV2, which is
- // intended to be called by debuggers.
- MOVQ $runtime·debugCallV2(SB), AX
- RET
-
-// mainPC is a function value for runtime.main, to be passed to newproc.
-// The reference to runtime.main is made via ABIInternal, since the
-// actual function (not the ABI0 wrapper) is needed by newproc.
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
-GLOBL runtime·mainPC(SB),RODATA,$8
-
-TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
- BYTE $0xcc
- RET
-
-TEXT runtime·asminit(SB),NOSPLIT,$0-0
- // No per-thread init.
- RET
-
-TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME|NOFRAME,$0
- CALL runtime·mstart0(SB)
- RET // not reached
-
-/*
- * go-routine
- */
-
-// func gogo(buf *gobuf)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT, $0-8
- MOVQ buf+0(FP), BX // gobuf
- MOVQ gobuf_g(BX), DX
- MOVQ 0(DX), CX // make sure g != nil
- JMP gogo<>(SB)
-
-TEXT gogo<>(SB), NOSPLIT, $0
- get_tls(CX)
- MOVQ DX, g(CX)
- MOVQ DX, R14 // set the g register
- MOVQ gobuf_sp(BX), SP // restore SP
- MOVQ gobuf_ret(BX), AX
- MOVQ gobuf_ctxt(BX), DX
- MOVQ gobuf_bp(BX), BP
- MOVQ $0, gobuf_sp(BX) // clear to help garbage collector
- MOVQ $0, gobuf_ret(BX)
- MOVQ $0, gobuf_ctxt(BX)
- MOVQ $0, gobuf_bp(BX)
- MOVQ gobuf_pc(BX), BX
- JMP BX
-
-// func mcall(fn func(*g))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return. It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), NOSPLIT, $0-8
- MOVQ AX, DX // DX = fn
-
- // Save state in g->sched. The caller's SP and PC are restored by gogo to
- // resume execution in the caller's frame (implicit return). The caller's BP
- // is also restored to support frame pointer unwinding.
- MOVQ SP, BX // hide (SP) reads from vet
- MOVQ 8(BX), BX // caller's PC
- MOVQ BX, (g_sched+gobuf_pc)(R14)
- LEAQ fn+0(FP), BX // caller's SP
- MOVQ BX, (g_sched+gobuf_sp)(R14)
- // Get the caller's frame pointer by dereferencing BP. Storing BP as it is
- // can cause a frame pointer cycle, see CL 476235.
- MOVQ (BP), BX // caller's BP
- MOVQ BX, (g_sched+gobuf_bp)(R14)
-
- // switch to m->g0 & its stack, call fn
- MOVQ g_m(R14), BX
- MOVQ m_g0(BX), SI // SI = g.m.g0
- CMPQ SI, R14 // if g == m->g0 call badmcall
- JNE goodm
- JMP runtime·badmcall(SB)
-goodm:
- MOVQ R14, AX // AX (and arg 0) = g
- MOVQ SI, R14 // g = g.m.g0
- get_tls(CX) // Set G in TLS
- MOVQ R14, g(CX)
- MOVQ (g_sched+gobuf_sp)(R14), SP // sp = g0.sched.sp
- PUSHQ AX // open up space for fn's arg spill slot
- MOVQ 0(DX), R12
- CALL R12 // fn(g)
- POPQ AX
- JMP runtime·badmcall2(SB)
- RET
-
-// systemstack_switch is a dummy routine that systemstack leaves at the bottom
-// of the G stack. We need to distinguish the routine that
-// lives at the bottom of the G stack from the one that lives
-// at the top of the system stack because the one at the top of
-// the system stack terminates the stack walk (see topofstack()).
-// The frame layout needs to match systemstack
-// so that it can pretend to be systemstack_switch.
-TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
- UNDEF
- // Make sure this function is not leaf,
- // so the frame is saved.
- CALL runtime·abort(SB)
- RET
-
-// func systemstack(fn func())
-TEXT runtime·systemstack(SB), NOSPLIT, $0-8
- MOVQ fn+0(FP), DI // DI = fn
- get_tls(CX)
- MOVQ g(CX), AX // AX = g
- MOVQ g_m(AX), BX // BX = m
-
- CMPQ AX, m_gsignal(BX)
- JEQ noswitch
-
- MOVQ m_g0(BX), DX // DX = g0
- CMPQ AX, DX
- JEQ noswitch
-
- CMPQ AX, m_curg(BX)
- JNE bad
-
- // Switch stacks.
- // The original frame pointer is stored in BP,
- // which is useful for stack unwinding.
- // Save our state in g->sched. Pretend to
- // be systemstack_switch if the G stack is scanned.
- CALL gosave_systemstack_switch<>(SB)
-
- // switch to g0
- MOVQ DX, g(CX)
- MOVQ DX, R14 // set the g register
- MOVQ (g_sched+gobuf_sp)(DX), SP
-
- // call target function
- MOVQ DI, DX
- MOVQ 0(DI), DI
- CALL DI
-
- // switch back to g
- get_tls(CX)
- MOVQ g(CX), AX
- MOVQ g_m(AX), BX
- MOVQ m_curg(BX), AX
- MOVQ AX, g(CX)
- MOVQ (g_sched+gobuf_sp)(AX), SP
- MOVQ (g_sched+gobuf_bp)(AX), BP
- MOVQ $0, (g_sched+gobuf_sp)(AX)
- MOVQ $0, (g_sched+gobuf_bp)(AX)
- RET
-
-noswitch:
- // already on m stack; tail call the function
- // Using a tail call here cleans up tracebacks since we won't stop
- // at an intermediate systemstack.
- MOVQ DI, DX
- MOVQ 0(DI), DI
- // The function epilogue is not called on a tail call.
- // Pop BP from the stack to simulate it.
- POPQ BP
- JMP DI
-
-bad:
- // Bad: g is not gsignal, not g0, not curg. What is it?
- MOVQ $runtime·badsystemstack(SB), AX
- CALL AX
- INT $3
-
-// func switchToCrashStack0(fn func())
-TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-8
- MOVQ g_m(R14), BX // curm
-
- // set g to gcrash
- LEAQ runtime·gcrash(SB), R14 // g = &gcrash
- MOVQ BX, g_m(R14) // g.m = curm
- MOVQ R14, m_g0(BX) // curm.g0 = g
- get_tls(CX)
- MOVQ R14, g(CX)
-
- // switch to crashstack
- MOVQ (g_stack+stack_hi)(R14), BX
- SUBQ $(4*8), BX
- MOVQ BX, SP
-
- // call target function
- MOVQ AX, DX
- MOVQ 0(AX), AX
- CALL AX
-
- // should never return
- CALL runtime·abort(SB)
- UNDEF
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-//
-// The traceback routines see morestack on a g0 as being
-// the top of a stack (for example, morestack calling newstack
-// calling the scheduler calling newm calling gc), so we must
-// record an argument size. For that purpose, it has no arguments.
-TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
- // Cannot grow scheduler stack (m->g0).
- get_tls(CX)
- MOVQ g(CX), DI // DI = g
- MOVQ g_m(DI), BX // BX = m
-
- // Set g->sched to context in f.
- MOVQ 0(SP), AX // f's PC
- MOVQ AX, (g_sched+gobuf_pc)(DI)
- LEAQ 8(SP), AX // f's SP
- MOVQ AX, (g_sched+gobuf_sp)(DI)
- MOVQ BP, (g_sched+gobuf_bp)(DI)
- MOVQ DX, (g_sched+gobuf_ctxt)(DI)
-
- MOVQ m_g0(BX), SI // SI = m.g0
- CMPQ DI, SI
- JNE 3(PC)
- CALL runtime·badmorestackg0(SB)
- CALL runtime·abort(SB)
-
- // Cannot grow signal stack (m->gsignal).
- MOVQ m_gsignal(BX), SI
- CMPQ DI, SI
- JNE 3(PC)
- CALL runtime·badmorestackgsignal(SB)
- CALL runtime·abort(SB)
-
- // Called from f.
- // Set m->morebuf to f's caller.
- NOP SP // tell vet SP changed - stop checking offsets
- MOVQ 8(SP), AX // f's caller's PC
- MOVQ AX, (m_morebuf+gobuf_pc)(BX)
- LEAQ 16(SP), AX // f's caller's SP
- MOVQ AX, (m_morebuf+gobuf_sp)(BX)
- MOVQ DI, (m_morebuf+gobuf_g)(BX)
-
- // Call newstack on m->g0's stack.
- MOVQ m_g0(BX), BX
- MOVQ BX, g(CX)
- MOVQ (g_sched+gobuf_sp)(BX), SP
- MOVQ (g_sched+gobuf_bp)(BX), BP
- CALL runtime·newstack(SB)
- CALL runtime·abort(SB) // crash if newstack returns
- RET
-
-// morestack but not preserving ctxt.
-TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
- MOVL $0, DX
- JMP runtime·morestack(SB)
-
-// spillArgs stores return values from registers to a *internal/abi.RegArgs in R12.
-TEXT ·spillArgs(SB),NOSPLIT,$0-0
- MOVQ AX, 0(R12)
- MOVQ BX, 8(R12)
- MOVQ CX, 16(R12)
- MOVQ DI, 24(R12)
- MOVQ SI, 32(R12)
- MOVQ R8, 40(R12)
- MOVQ R9, 48(R12)
- MOVQ R10, 56(R12)
- MOVQ R11, 64(R12)
- MOVQ X0, 72(R12)
- MOVQ X1, 80(R12)
- MOVQ X2, 88(R12)
- MOVQ X3, 96(R12)
- MOVQ X4, 104(R12)
- MOVQ X5, 112(R12)
- MOVQ X6, 120(R12)
- MOVQ X7, 128(R12)
- MOVQ X8, 136(R12)
- MOVQ X9, 144(R12)
- MOVQ X10, 152(R12)
- MOVQ X11, 160(R12)
- MOVQ X12, 168(R12)
- MOVQ X13, 176(R12)
- MOVQ X14, 184(R12)
- RET
-
-// unspillArgs loads args into registers from a *internal/abi.RegArgs in R12.
-TEXT ·unspillArgs(SB),NOSPLIT,$0-0
- MOVQ 0(R12), AX
- MOVQ 8(R12), BX
- MOVQ 16(R12), CX
- MOVQ 24(R12), DI
- MOVQ 32(R12), SI
- MOVQ 40(R12), R8
- MOVQ 48(R12), R9
- MOVQ 56(R12), R10
- MOVQ 64(R12), R11
- MOVQ 72(R12), X0
- MOVQ 80(R12), X1
- MOVQ 88(R12), X2
- MOVQ 96(R12), X3
- MOVQ 104(R12), X4
- MOVQ 112(R12), X5
- MOVQ 120(R12), X6
- MOVQ 128(R12), X7
- MOVQ 136(R12), X8
- MOVQ 144(R12), X9
- MOVQ 152(R12), X10
- MOVQ 160(R12), X11
- MOVQ 168(R12), X12
- MOVQ 176(R12), X13
- MOVQ 184(R12), X14
- RET
-
-// reflectcall: call a function with the given argument list
-// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
-// we don't have variable-sized frames, so we use a small number
-// of constant-sized-frame functions to encode a few bits of size in the pc.
-// Caution: ugly multiline assembly macros in your future!
-
-#define DISPATCH(NAME,MAXSIZE) \
- CMPQ CX, $MAXSIZE; \
- JA 3(PC); \
- MOVQ $NAME(SB), AX; \
- JMP AX
-// Note: can't just "JMP NAME(SB)" - bad inlining results.
-
-TEXT ·reflectcall(SB), NOSPLIT, $0-48
- MOVLQZX frameSize+32(FP), CX
- DISPATCH(runtime·call16, 16)
- DISPATCH(runtime·call32, 32)
- DISPATCH(runtime·call64, 64)
- DISPATCH(runtime·call128, 128)
- DISPATCH(runtime·call256, 256)
- DISPATCH(runtime·call512, 512)
- DISPATCH(runtime·call1024, 1024)
- DISPATCH(runtime·call2048, 2048)
- DISPATCH(runtime·call4096, 4096)
- DISPATCH(runtime·call8192, 8192)
- DISPATCH(runtime·call16384, 16384)
- DISPATCH(runtime·call32768, 32768)
- DISPATCH(runtime·call65536, 65536)
- DISPATCH(runtime·call131072, 131072)
- DISPATCH(runtime·call262144, 262144)
- DISPATCH(runtime·call524288, 524288)
- DISPATCH(runtime·call1048576, 1048576)
- DISPATCH(runtime·call2097152, 2097152)
- DISPATCH(runtime·call4194304, 4194304)
- DISPATCH(runtime·call8388608, 8388608)
- DISPATCH(runtime·call16777216, 16777216)
- DISPATCH(runtime·call33554432, 33554432)
- DISPATCH(runtime·call67108864, 67108864)
- DISPATCH(runtime·call134217728, 134217728)
- DISPATCH(runtime·call268435456, 268435456)
- DISPATCH(runtime·call536870912, 536870912)
- DISPATCH(runtime·call1073741824, 1073741824)
- MOVQ $runtime·badreflectcall(SB), AX
- JMP AX
-
-#define CALLFN(NAME,MAXSIZE) \
-TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
- NO_LOCAL_POINTERS; \
- /* copy arguments to stack */ \
- MOVQ stackArgs+16(FP), SI; \
- MOVLQZX stackArgsSize+24(FP), CX; \
- MOVQ SP, DI; \
- REP;MOVSB; \
- /* set up argument registers */ \
- MOVQ regArgs+40(FP), R12; \
- CALL ·unspillArgs(SB); \
- /* call function */ \
- MOVQ f+8(FP), DX; \
- PCDATA $PCDATA_StackMapIndex, $0; \
- MOVQ (DX), R12; \
- CALL R12; \
- /* copy register return values back */ \
- MOVQ regArgs+40(FP), R12; \
- CALL ·spillArgs(SB); \
- MOVLQZX stackArgsSize+24(FP), CX; \
- MOVLQZX stackRetOffset+28(FP), BX; \
- MOVQ stackArgs+16(FP), DI; \
- MOVQ stackArgsType+0(FP), DX; \
- MOVQ SP, SI; \
- ADDQ BX, DI; \
- ADDQ BX, SI; \
- SUBQ BX, CX; \
- CALL callRet<>(SB); \
- RET
-
-// callRet copies return values back at the end of call*. This is a
-// separate function so it can allocate stack space for the arguments
-// to reflectcallmove. It does not follow the Go ABI; it expects its
-// arguments in registers.
-TEXT callRet<>(SB), NOSPLIT, $40-0
- NO_LOCAL_POINTERS
- MOVQ DX, 0(SP)
- MOVQ DI, 8(SP)
- MOVQ SI, 16(SP)
- MOVQ CX, 24(SP)
- MOVQ R12, 32(SP)
- CALL runtime·reflectcallmove(SB)
- RET
-
-CALLFN(·call16, 16)
-CALLFN(·call32, 32)
-CALLFN(·call64, 64)
-CALLFN(·call128, 128)
-CALLFN(·call256, 256)
-CALLFN(·call512, 512)
-CALLFN(·call1024, 1024)
-CALLFN(·call2048, 2048)
-CALLFN(·call4096, 4096)
-CALLFN(·call8192, 8192)
-CALLFN(·call16384, 16384)
-CALLFN(·call32768, 32768)
-CALLFN(·call65536, 65536)
-CALLFN(·call131072, 131072)
-CALLFN(·call262144, 262144)
-CALLFN(·call524288, 524288)
-CALLFN(·call1048576, 1048576)
-CALLFN(·call2097152, 2097152)
-CALLFN(·call4194304, 4194304)
-CALLFN(·call8388608, 8388608)
-CALLFN(·call16777216, 16777216)
-CALLFN(·call33554432, 33554432)
-CALLFN(·call67108864, 67108864)
-CALLFN(·call134217728, 134217728)
-CALLFN(·call268435456, 268435456)
-CALLFN(·call536870912, 536870912)
-CALLFN(·call1073741824, 1073741824)
-
-TEXT runtime·procyield(SB),NOSPLIT,$0-0
- MOVL cycles+0(FP), AX
-again:
- PAUSE
- SUBL $1, AX
- JNZ again
- RET
-
-
-TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
- // Stores are already ordered on x86, so this is just a
- // compile barrier.
- RET
-
-// Save state of caller into g->sched,
-// but using fake PC from systemstack_switch.
-// Must only be called from functions with frame pointer
-// and without locals ($0) or else unwinding from
-// systemstack_switch is incorrect.
-// Smashes R9.
-TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
- // Take systemstack_switch PC and add 8 bytes to skip
- // the prologue. The final location does not matter
- // as long as we are between the prologue and the epilogue.
- MOVQ $runtime·systemstack_switch+8(SB), R9
- MOVQ R9, (g_sched+gobuf_pc)(R14)
- LEAQ 8(SP), R9
- MOVQ R9, (g_sched+gobuf_sp)(R14)
- MOVQ $0, (g_sched+gobuf_ret)(R14)
- MOVQ BP, (g_sched+gobuf_bp)(R14)
- // Assert ctxt is zero. See func save.
- MOVQ (g_sched+gobuf_ctxt)(R14), R9
- TESTQ R9, R9
- JZ 2(PC)
- CALL runtime·abort(SB)
- RET
-
-// func asmcgocall_no_g(fn, arg unsafe.Pointer)
-// Call fn(arg) aligned appropriately for the gcc ABI.
-// Called on a system stack, and there may be no g yet (during needm).
-TEXT ·asmcgocall_no_g(SB),NOSPLIT,$32-16
- MOVQ fn+0(FP), AX
- MOVQ arg+8(FP), BX
- MOVQ SP, DX
- ANDQ $~15, SP // alignment
- MOVQ DX, 8(SP)
- MOVQ BX, DI // DI = first argument in AMD64 ABI
- MOVQ BX, CX // CX = first argument in Win64
- CALL AX
- MOVQ 8(SP), DX
- MOVQ DX, SP
- RET
-
-// asmcgocall_landingpad calls AX with BX as argument.
-// Must be called on the system stack.
-TEXT ·asmcgocall_landingpad(SB),NOSPLIT,$0-0
-#ifdef GOOS_windows
- // Make sure we have enough room for 4 stack-backed fast-call
- // registers as per Windows amd64 calling convention.
- ADJSP $32
- // On Windows, asmcgocall_landingpad acts as landing pad for exceptions
- // thrown in the cgo call. Exceptions that reach this function will be
- // handled by runtime.sehtramp thanks to the SEH metadata added
- // by the compiler.
- // Note that runtime.sehtramp can't be attached directly to asmcgocall
- // because its initial stack pointer can be outside the system stack bounds,
- // and Windows stops the stack unwinding without calling the exception handler
- // when it reaches that point.
- MOVQ BX, CX // CX = first argument in Win64
- CALL AX
- // The exception handler is not called if the next instruction is part of
- // the epilogue, which includes the RET instruction, so we need to add a NOP here.
- BYTE $0x90
- ADJSP $-32
- RET
-#endif
- // Tail call AX on non-Windows, as the extra stack frame is not needed.
- MOVQ BX, DI // DI = first argument in AMD64 ABI
- JMP AX
-
-// func asmcgocall(fn, arg unsafe.Pointer) int32
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.go for more details.
-TEXT ·asmcgocall(SB),NOSPLIT,$0-20
- MOVQ fn+0(FP), AX
- MOVQ arg+8(FP), BX
-
- MOVQ SP, DX
-
- // Figure out if we need to switch to m->g0 stack.
- // We get called to create new OS threads too, and those
- // come in on the m->g0 stack already. Or we might already
- // be on the m->gsignal stack.
- get_tls(CX)
- MOVQ g(CX), DI
- CMPQ DI, $0
- JEQ nosave
- MOVQ g_m(DI), R8
- MOVQ m_gsignal(R8), SI
- CMPQ DI, SI
- JEQ nosave
- MOVQ m_g0(R8), SI
- CMPQ DI, SI
- JEQ nosave
-
- // Switch to system stack.
- // The original frame pointer is stored in BP,
- // which is useful for stack unwinding.
- CALL gosave_systemstack_switch<>(SB)
- MOVQ SI, g(CX)
- MOVQ (g_sched+gobuf_sp)(SI), SP
-
- // Now on a scheduling stack (a pthread-created stack).
- SUBQ $16, SP
- ANDQ $~15, SP // alignment for gcc ABI
- MOVQ DI, 8(SP) // save g
- MOVQ (g_stack+stack_hi)(DI), DI
- SUBQ DX, DI
- MOVQ DI, 0(SP) // save depth in stack (can't just save SP, as stack might be copied during a callback)
- CALL runtime·asmcgocall_landingpad(SB)
-
- // Restore registers, g, stack pointer.
- get_tls(CX)
- MOVQ 8(SP), DI
- MOVQ (g_stack+stack_hi)(DI), SI
- SUBQ 0(SP), SI
- MOVQ DI, g(CX)
- MOVQ SI, SP
-
- MOVL AX, ret+16(FP)
- RET
-
-nosave:
- // Running on a system stack, perhaps even without a g.
- // Having no g can happen during thread creation or thread teardown
- // (see needm/dropm on Solaris, for example).
- // This code is like the above sequence but without saving/restoring g
- // and without worrying about the stack moving out from under us
- // (because we're on a system stack, not a goroutine stack).
- // The above code could be used directly if already on a system stack,
- // but then the only path through this code would be a rare case on Solaris.
- // Using this code for all "already on system stack" calls exercises it more,
- // which should help keep it correct.
- SUBQ $16, SP
- ANDQ $~15, SP
- MOVQ $0, 8(SP) // where above code stores g, in case someone looks during debugging
- MOVQ DX, 0(SP) // save original stack pointer
- CALL runtime·asmcgocall_landingpad(SB)
- MOVQ 0(SP), SI // restore original stack pointer
- MOVQ SI, SP
- MOVL AX, ret+16(FP)
- RET
-
-#ifdef GOOS_windows
-// Dummy TLS that's used on Windows so that we don't crash trying
-// to restore the G register in needm. needm and its callees are
-// very careful never to actually use the G, the TLS just can't be
-// unset since we're in Go code.
-GLOBL zeroTLS<>(SB),RODATA,$const_tlsSize
-#endif
-
-// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
-// See cgocall.go for more details.
-TEXT ·cgocallback(SB),NOSPLIT,$24-24
- NO_LOCAL_POINTERS
-
- // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
- // It is used to dropm while thread is exiting.
- MOVQ fn+0(FP), AX
- CMPQ AX, $0
- JNE loadg
- // Restore the g from frame.
- get_tls(CX)
- MOVQ frame+8(FP), BX
- MOVQ BX, g(CX)
- JMP dropm
-
-loadg:
- // If g is nil, Go did not create the current thread,
- // or if this thread never called into Go on pthread platforms.
- // Call needm to obtain one m for temporary use.
- // In this case, we're running on the thread stack, so there's
- // lots of space, but the linker doesn't know. Hide the call from
- // the linker analysis by using an indirect call through AX.
- get_tls(CX)
-#ifdef GOOS_windows
- MOVL $0, BX
- CMPQ CX, $0
- JEQ 2(PC)
-#endif
- MOVQ g(CX), BX
- CMPQ BX, $0
- JEQ needm
- MOVQ g_m(BX), BX
- MOVQ BX, savedm-8(SP) // saved copy of oldm
- JMP havem
-needm:
-#ifdef GOOS_windows
- // Set up a dummy TLS value. needm is careful not to use it,
- // but it needs to be there to prevent autogenerated code from
- // crashing when it loads from it.
- // We don't need to clear it or anything later because needm
- // will set up TLS properly.
- MOVQ $zeroTLS<>(SB), DI
- CALL runtime·settls(SB)
-#endif
- // On some platforms (Windows) we cannot call needm through
- // an ABI wrapper because there's no TLS set up, and the ABI
- // wrapper will try to restore the G register (R14) from TLS.
- // Clear X15 because Go expects it and we're not calling
- // through a wrapper, but otherwise avoid setting the G
- // register in the wrapper and call needm directly. It
- // takes no arguments and doesn't return any values so
- // there's no need to handle that. Clear R14 so that there's
- // a bad value in there, in case needm tries to use it.
- XORPS X15, X15
- XORQ R14, R14
- MOVQ $runtime·needAndBindM(SB), AX
- CALL AX
- MOVQ $0, savedm-8(SP)
- get_tls(CX)
- MOVQ g(CX), BX
- MOVQ g_m(BX), BX
-
- // Set m->sched.sp = SP, so that if a panic happens
- // during the function we are about to execute, it will
- // have a valid SP to run on the g0 stack.
- // The next few lines (after the havem label)
- // will save this SP onto the stack and then write
- // the same SP back to m->sched.sp. That seems redundant,
- // but if an unrecovered panic happens, unwindm will
- // restore the g->sched.sp from the stack location
- // and then systemstack will try to use it. If we don't set it here,
- // that restored SP will be uninitialized (typically 0) and
- // will not be usable.
- MOVQ m_g0(BX), SI
- MOVQ SP, (g_sched+gobuf_sp)(SI)
-
-havem:
- // Now there's a valid m, and we're running on its m->g0.
- // Save current m->g0->sched.sp on stack and then set it to SP.
- // Save current sp in m->g0->sched.sp in preparation for
- // switch back to m->curg stack.
- // NOTE: unwindm knows that the saved g->sched.sp is at 0(SP).
- MOVQ m_g0(BX), SI
- MOVQ (g_sched+gobuf_sp)(SI), AX
- MOVQ AX, 0(SP)
- MOVQ SP, (g_sched+gobuf_sp)(SI)
-
- // Switch to m->curg stack and call runtime.cgocallbackg.
- // Because we are taking over the execution of m->curg
- // but *not* resuming what had been running, we need to
- // save that information (m->curg->sched) so we can restore it.
- // We can restore m->curg->sched.sp easily, because calling
- // runtime.cgocallbackg leaves SP unchanged upon return.
- // To save m->curg->sched.pc, we push it onto the curg stack and
- // open a frame the same size as cgocallback's g0 frame.
- // Once we switch to the curg stack, the pushed PC will appear
- // to be the return PC of cgocallback, so that the traceback
- // will seamlessly trace back into the earlier calls.
- MOVQ m_curg(BX), SI
- MOVQ SI, g(CX)
- MOVQ (g_sched+gobuf_sp)(SI), DI // prepare stack as DI
- MOVQ (g_sched+gobuf_pc)(SI), BX
- MOVQ BX, -8(DI) // "push" return PC on the g stack
- // Gather our arguments into registers.
- MOVQ fn+0(FP), BX
- MOVQ frame+8(FP), CX
- MOVQ ctxt+16(FP), DX
- // Compute the size of the frame, including return PC and, if
- // GOEXPERIMENT=framepointer, the saved base pointer
- LEAQ fn+0(FP), AX
- SUBQ SP, AX // AX is our actual frame size
- SUBQ AX, DI // Allocate the same frame size on the g stack
- MOVQ DI, SP
-
- MOVQ BX, 0(SP)
- MOVQ CX, 8(SP)
- MOVQ DX, 16(SP)
- MOVQ $runtime·cgocallbackg(SB), AX
- CALL AX // indirect call to bypass nosplit check. We're on a different stack now.
-
- // Compute the size of the frame again. FP and SP have
- // completely different values here than they did above,
- // but only their difference matters.
- LEAQ fn+0(FP), AX
- SUBQ SP, AX
-
- // Restore g->sched (== m->curg->sched) from saved values.
- get_tls(CX)
- MOVQ g(CX), SI
- MOVQ SP, DI
- ADDQ AX, DI
- MOVQ -8(DI), BX
- MOVQ BX, (g_sched+gobuf_pc)(SI)
- MOVQ DI, (g_sched+gobuf_sp)(SI)
-
- // Switch back to m->g0's stack and restore m->g0->sched.sp.
- // (Unlike m->curg, the g0 goroutine never uses sched.pc,
- // so we do not have to restore it.)
- MOVQ g(CX), BX
- MOVQ g_m(BX), BX
- MOVQ m_g0(BX), SI
- MOVQ SI, g(CX)
- MOVQ (g_sched+gobuf_sp)(SI), SP
- MOVQ 0(SP), AX
- MOVQ AX, (g_sched+gobuf_sp)(SI)
-
- // If the m on entry was nil, we called needm above to borrow an m,
- // 1. for the duration of the call on non-pthread platforms,
- // 2. or the duration of the C thread alive on pthread platforms.
- // If the m on entry wasn't nil,
- // 1. the thread might be a Go thread,
- // 2. or it wasn't the first call from a C thread on pthread platforms,
- // since then we skip dropm to reuse the m in the first call.
- MOVQ savedm-8(SP), BX
- CMPQ BX, $0
- JNE done
-
- // Skip dropm to reuse it in the next call, when a pthread key has been created.
- MOVQ _cgo_pthread_key_created(SB), AX
- // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
- CMPQ AX, $0
- JEQ dropm
- CMPQ (AX), $0
- JNE done
-
-dropm:
- MOVQ $runtime·dropm(SB), AX
- CALL AX
-#ifdef GOOS_windows
- // We need to clear the TLS pointer in case the next
- // thread that comes into Go tries to reuse that space
- // but uses the same M.
- XORQ DI, DI
- CALL runtime·settls(SB)
-#endif
-done:
-
- // Done!
- RET
-
-// func setg(gg *g)
-// set g. for use by needm.
-TEXT runtime·setg(SB), NOSPLIT, $0-8
- MOVQ gg+0(FP), BX
- get_tls(CX)
- MOVQ BX, g(CX)
- RET
-
-// void setg_gcc(G*); set g called from gcc.
-TEXT setg_gcc<>(SB),NOSPLIT,$0
- get_tls(AX)
- MOVQ DI, g(AX)
- MOVQ DI, R14 // set the g register
- RET
-
-TEXT runtime·abort(SB),NOSPLIT,$0-0
- INT $3
-loop:
- JMP loop
-
-// check that SP is in range [g->stack.lo, g->stack.hi)
-TEXT runtime·stackcheck(SB), NOSPLIT|NOFRAME, $0-0
- get_tls(CX)
- MOVQ g(CX), AX
- CMPQ (g_stack+stack_hi)(AX), SP
- JHI 2(PC)
- CALL runtime·abort(SB)
- CMPQ SP, (g_stack+stack_lo)(AX)
- JHI 2(PC)
- CALL runtime·abort(SB)
- RET
-
-// func cputicks() int64
-TEXT runtime·cputicks(SB),NOSPLIT,$0-0
- CMPB internal∕cpu·X86+const_offsetX86HasRDTSCP(SB), $1
- JNE fences
- // Instruction stream serializing RDTSCP is supported.
- // RDTSCP is supported by Intel Nehalem (2008) and
- // AMD K8 Rev. F (2006) and newer.
- RDTSCP
-done:
- SHLQ $32, DX
- ADDQ DX, AX
- MOVQ AX, ret+0(FP)
- RET
-fences:
- // MFENCE is instruction stream serializing and flushes the
- // store buffers on AMD. The serialization semantics of LFENCE on AMD
- // are dependent on MSR C001_1029 and CPU generation.
- // LFENCE on Intel does wait for all previous instructions to have executed.
- // Intel recommends MFENCE;LFENCE in its manuals before RDTSC to have all
- // previous instructions executed and all previous loads and stores to globally visible.
- // Using MFENCE;LFENCE here aligns the serializing properties without
- // runtime detection of CPU manufacturer.
- MFENCE
- LFENCE
- RDTSC
- JMP done
-
-// func memhash(p unsafe.Pointer, h, s uintptr) uintptr
-// hash function using AES hardware instructions
-TEXT runtime·memhash(SB),NOSPLIT,$0-32
- // AX = ptr to data
- // BX = seed
- // CX = size
- CMPB runtime·useAeshash(SB), $0
- JEQ noaes
- JMP aeshashbody<>(SB)
-noaes:
- JMP runtime·memhashFallback(SB)
-
-// func strhash(p unsafe.Pointer, h uintptr) uintptr
-TEXT runtime·strhash(SB),NOSPLIT,$0-24
- // AX = ptr to string struct
- // BX = seed
- CMPB runtime·useAeshash(SB), $0
- JEQ noaes
- MOVQ 8(AX), CX // length of string
- MOVQ (AX), AX // string data
- JMP aeshashbody<>(SB)
-noaes:
- JMP runtime·strhashFallback(SB)
-
-// AX: data
-// BX: hash seed
-// CX: length
-// At return: AX = return value
-TEXT aeshashbody<>(SB),NOSPLIT,$0-0
- // Fill an SSE register with our seeds.
- MOVQ BX, X0 // 64 bits of per-table hash seed
- PINSRW $4, CX, X0 // 16 bits of length
- PSHUFHW $0, X0, X0 // repeat length 4 times total
- MOVO X0, X1 // save unscrambled seed
- PXOR runtime·aeskeysched(SB), X0 // xor in per-process seed
- AESENC X0, X0 // scramble seed
-
- CMPQ CX, $16
- JB aes0to15
- JE aes16
- CMPQ CX, $32
- JBE aes17to32
- CMPQ CX, $64
- JBE aes33to64
- CMPQ CX, $128
- JBE aes65to128
- JMP aes129plus
-
-aes0to15:
- TESTQ CX, CX
- JE aes0
-
- ADDQ $16, AX
- TESTW $0xff0, AX
- JE endofpage
-
- // 16 bytes loaded at this address won't cross
- // a page boundary, so we can load it directly.
- MOVOU -16(AX), X1
- ADDQ CX, CX
- MOVQ $masks<>(SB), AX
- PAND (AX)(CX*8), X1
-final1:
- PXOR X0, X1 // xor data with seed
- AESENC X1, X1 // scramble combo 3 times
- AESENC X1, X1
- AESENC X1, X1
- MOVQ X1, AX // return X1
- RET
-
-endofpage:
- // address ends in 1111xxxx. Might be up against
- // a page boundary, so load ending at last byte.
- // Then shift bytes down using pshufb.
- MOVOU -32(AX)(CX*1), X1
- ADDQ CX, CX
- MOVQ $shifts<>(SB), AX
- PSHUFB (AX)(CX*8), X1
- JMP final1
-
-aes0:
- // Return scrambled input seed
- AESENC X0, X0
- MOVQ X0, AX // return X0
- RET
-
-aes16:
- MOVOU (AX), X1
- JMP final1
-
-aes17to32:
- // make second starting seed
- PXOR runtime·aeskeysched+16(SB), X1
- AESENC X1, X1
-
- // load data to be hashed
- MOVOU (AX), X2
- MOVOU -16(AX)(CX*1), X3
-
- // xor with seed
- PXOR X0, X2
- PXOR X1, X3
-
- // scramble 3 times
- AESENC X2, X2
- AESENC X3, X3
- AESENC X2, X2
- AESENC X3, X3
- AESENC X2, X2
- AESENC X3, X3
-
- // combine results
- PXOR X3, X2
- MOVQ X2, AX // return X2
- RET
-
-aes33to64:
- // make 3 more starting seeds
- MOVO X1, X2
- MOVO X1, X3
- PXOR runtime·aeskeysched+16(SB), X1
- PXOR runtime·aeskeysched+32(SB), X2
- PXOR runtime·aeskeysched+48(SB), X3
- AESENC X1, X1
- AESENC X2, X2
- AESENC X3, X3
-
- MOVOU (AX), X4
- MOVOU 16(AX), X5
- MOVOU -32(AX)(CX*1), X6
- MOVOU -16(AX)(CX*1), X7
-
- PXOR X0, X4
- PXOR X1, X5
- PXOR X2, X6
- PXOR X3, X7
-
- AESENC X4, X4
- AESENC X5, X5
- AESENC X6, X6
- AESENC X7, X7
-
- AESENC X4, X4
- AESENC X5, X5
- AESENC X6, X6
- AESENC X7, X7
-
- AESENC X4, X4
- AESENC X5, X5
- AESENC X6, X6
- AESENC X7, X7
-
- PXOR X6, X4
- PXOR X7, X5
- PXOR X5, X4
- MOVQ X4, AX // return X4
- RET
-
-aes65to128:
- // make 7 more starting seeds
- MOVO X1, X2
- MOVO X1, X3
- MOVO X1, X4
- MOVO X1, X5
- MOVO X1, X6
- MOVO X1, X7
- PXOR runtime·aeskeysched+16(SB), X1
- PXOR runtime·aeskeysched+32(SB), X2
- PXOR runtime·aeskeysched+48(SB), X3
- PXOR runtime·aeskeysched+64(SB), X4
- PXOR runtime·aeskeysched+80(SB), X5
- PXOR runtime·aeskeysched+96(SB), X6
- PXOR runtime·aeskeysched+112(SB), X7
- AESENC X1, X1
- AESENC X2, X2
- AESENC X3, X3
- AESENC X4, X4
- AESENC X5, X5
- AESENC X6, X6
- AESENC X7, X7
-
- // load data
- MOVOU (AX), X8
- MOVOU 16(AX), X9
- MOVOU 32(AX), X10
- MOVOU 48(AX), X11
- MOVOU -64(AX)(CX*1), X12
- MOVOU -48(AX)(CX*1), X13
- MOVOU -32(AX)(CX*1), X14
- MOVOU -16(AX)(CX*1), X15
-
- // xor with seed
- PXOR X0, X8
- PXOR X1, X9
- PXOR X2, X10
- PXOR X3, X11
- PXOR X4, X12
- PXOR X5, X13
- PXOR X6, X14
- PXOR X7, X15
-
- // scramble 3 times
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
-
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
-
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
-
- // combine results
- PXOR X12, X8
- PXOR X13, X9
- PXOR X14, X10
- PXOR X15, X11
- PXOR X10, X8
- PXOR X11, X9
- PXOR X9, X8
- // X15 must be zero on return
- PXOR X15, X15
- MOVQ X8, AX // return X8
- RET
-
-aes129plus:
- // make 7 more starting seeds
- MOVO X1, X2
- MOVO X1, X3
- MOVO X1, X4
- MOVO X1, X5
- MOVO X1, X6
- MOVO X1, X7
- PXOR runtime·aeskeysched+16(SB), X1
- PXOR runtime·aeskeysched+32(SB), X2
- PXOR runtime·aeskeysched+48(SB), X3
- PXOR runtime·aeskeysched+64(SB), X4
- PXOR runtime·aeskeysched+80(SB), X5
- PXOR runtime·aeskeysched+96(SB), X6
- PXOR runtime·aeskeysched+112(SB), X7
- AESENC X1, X1
- AESENC X2, X2
- AESENC X3, X3
- AESENC X4, X4
- AESENC X5, X5
- AESENC X6, X6
- AESENC X7, X7
-
- // start with last (possibly overlapping) block
- MOVOU -128(AX)(CX*1), X8
- MOVOU -112(AX)(CX*1), X9
- MOVOU -96(AX)(CX*1), X10
- MOVOU -80(AX)(CX*1), X11
- MOVOU -64(AX)(CX*1), X12
- MOVOU -48(AX)(CX*1), X13
- MOVOU -32(AX)(CX*1), X14
- MOVOU -16(AX)(CX*1), X15
-
- // xor in seed
- PXOR X0, X8
- PXOR X1, X9
- PXOR X2, X10
- PXOR X3, X11
- PXOR X4, X12
- PXOR X5, X13
- PXOR X6, X14
- PXOR X7, X15
-
- // compute number of remaining 128-byte blocks
- DECQ CX
- SHRQ $7, CX
-
- PCALIGN $16
-aesloop:
- // scramble state
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
-
- // scramble state, xor in a block
- MOVOU (AX), X0
- MOVOU 16(AX), X1
- MOVOU 32(AX), X2
- MOVOU 48(AX), X3
- AESENC X0, X8
- AESENC X1, X9
- AESENC X2, X10
- AESENC X3, X11
- MOVOU 64(AX), X4
- MOVOU 80(AX), X5
- MOVOU 96(AX), X6
- MOVOU 112(AX), X7
- AESENC X4, X12
- AESENC X5, X13
- AESENC X6, X14
- AESENC X7, X15
-
- ADDQ $128, AX
- DECQ CX
- JNE aesloop
-
- // 3 more scrambles to finish
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
- AESENC X8, X8
- AESENC X9, X9
- AESENC X10, X10
- AESENC X11, X11
- AESENC X12, X12
- AESENC X13, X13
- AESENC X14, X14
- AESENC X15, X15
-
- PXOR X12, X8
- PXOR X13, X9
- PXOR X14, X10
- PXOR X15, X11
- PXOR X10, X8
- PXOR X11, X9
- PXOR X9, X8
- // X15 must be zero on return
- PXOR X15, X15
- MOVQ X8, AX // return X8
- RET
-
-// func memhash32(p unsafe.Pointer, h uintptr) uintptr
-// ABIInternal for performance.
-TEXT runtime·memhash32(SB),NOSPLIT,$0-24
- // AX = ptr to data
- // BX = seed
- CMPB runtime·useAeshash(SB), $0
- JEQ noaes
- MOVQ BX, X0 // X0 = seed
- PINSRD $2, (AX), X0 // data
- AESENC runtime·aeskeysched+0(SB), X0
- AESENC runtime·aeskeysched+16(SB), X0
- AESENC runtime·aeskeysched+32(SB), X0
- MOVQ X0, AX // return X0
- RET
-noaes:
- JMP runtime·memhash32Fallback(SB)
-
-// func memhash64(p unsafe.Pointer, h uintptr) uintptr
-// ABIInternal for performance.
-TEXT runtime·memhash64(SB),NOSPLIT,$0-24
- // AX = ptr to data
- // BX = seed
- CMPB runtime·useAeshash(SB), $0
- JEQ noaes
- MOVQ BX, X0 // X0 = seed
- PINSRQ $1, (AX), X0 // data
- AESENC runtime·aeskeysched+0(SB), X0
- AESENC runtime·aeskeysched+16(SB), X0
- AESENC runtime·aeskeysched+32(SB), X0
- MOVQ X0, AX // return X0
- RET
-noaes:
- JMP runtime·memhash64Fallback(SB)
-
-// simple mask to get rid of data in the high part of the register.
-DATA masks<>+0x00(SB)/8, $0x0000000000000000
-DATA masks<>+0x08(SB)/8, $0x0000000000000000
-DATA masks<>+0x10(SB)/8, $0x00000000000000ff
-DATA masks<>+0x18(SB)/8, $0x0000000000000000
-DATA masks<>+0x20(SB)/8, $0x000000000000ffff
-DATA masks<>+0x28(SB)/8, $0x0000000000000000
-DATA masks<>+0x30(SB)/8, $0x0000000000ffffff
-DATA masks<>+0x38(SB)/8, $0x0000000000000000
-DATA masks<>+0x40(SB)/8, $0x00000000ffffffff
-DATA masks<>+0x48(SB)/8, $0x0000000000000000
-DATA masks<>+0x50(SB)/8, $0x000000ffffffffff
-DATA masks<>+0x58(SB)/8, $0x0000000000000000
-DATA masks<>+0x60(SB)/8, $0x0000ffffffffffff
-DATA masks<>+0x68(SB)/8, $0x0000000000000000
-DATA masks<>+0x70(SB)/8, $0x00ffffffffffffff
-DATA masks<>+0x78(SB)/8, $0x0000000000000000
-DATA masks<>+0x80(SB)/8, $0xffffffffffffffff
-DATA masks<>+0x88(SB)/8, $0x0000000000000000
-DATA masks<>+0x90(SB)/8, $0xffffffffffffffff
-DATA masks<>+0x98(SB)/8, $0x00000000000000ff
-DATA masks<>+0xa0(SB)/8, $0xffffffffffffffff
-DATA masks<>+0xa8(SB)/8, $0x000000000000ffff
-DATA masks<>+0xb0(SB)/8, $0xffffffffffffffff
-DATA masks<>+0xb8(SB)/8, $0x0000000000ffffff
-DATA masks<>+0xc0(SB)/8, $0xffffffffffffffff
-DATA masks<>+0xc8(SB)/8, $0x00000000ffffffff
-DATA masks<>+0xd0(SB)/8, $0xffffffffffffffff
-DATA masks<>+0xd8(SB)/8, $0x000000ffffffffff
-DATA masks<>+0xe0(SB)/8, $0xffffffffffffffff
-DATA masks<>+0xe8(SB)/8, $0x0000ffffffffffff
-DATA masks<>+0xf0(SB)/8, $0xffffffffffffffff
-DATA masks<>+0xf8(SB)/8, $0x00ffffffffffffff
-GLOBL masks<>(SB),RODATA,$256
-
-// func checkASM() bool
-TEXT ·checkASM(SB),NOSPLIT,$0-1
- // check that masks<>(SB) and shifts<>(SB) are aligned to 16-byte
- MOVQ $masks<>(SB), AX
- MOVQ $shifts<>(SB), BX
- ORQ BX, AX
- TESTQ $15, AX
- SETEQ ret+0(FP)
- RET
-
-// these are arguments to pshufb. They move data down from
-// the high bytes of the register to the low bytes of the register.
-// index is how many bytes to move.
-DATA shifts<>+0x00(SB)/8, $0x0000000000000000
-DATA shifts<>+0x08(SB)/8, $0x0000000000000000
-DATA shifts<>+0x10(SB)/8, $0xffffffffffffff0f
-DATA shifts<>+0x18(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x20(SB)/8, $0xffffffffffff0f0e
-DATA shifts<>+0x28(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x30(SB)/8, $0xffffffffff0f0e0d
-DATA shifts<>+0x38(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x40(SB)/8, $0xffffffff0f0e0d0c
-DATA shifts<>+0x48(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x50(SB)/8, $0xffffff0f0e0d0c0b
-DATA shifts<>+0x58(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x60(SB)/8, $0xffff0f0e0d0c0b0a
-DATA shifts<>+0x68(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x70(SB)/8, $0xff0f0e0d0c0b0a09
-DATA shifts<>+0x78(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x80(SB)/8, $0x0f0e0d0c0b0a0908
-DATA shifts<>+0x88(SB)/8, $0xffffffffffffffff
-DATA shifts<>+0x90(SB)/8, $0x0e0d0c0b0a090807
-DATA shifts<>+0x98(SB)/8, $0xffffffffffffff0f
-DATA shifts<>+0xa0(SB)/8, $0x0d0c0b0a09080706
-DATA shifts<>+0xa8(SB)/8, $0xffffffffffff0f0e
-DATA shifts<>+0xb0(SB)/8, $0x0c0b0a0908070605
-DATA shifts<>+0xb8(SB)/8, $0xffffffffff0f0e0d
-DATA shifts<>+0xc0(SB)/8, $0x0b0a090807060504
-DATA shifts<>+0xc8(SB)/8, $0xffffffff0f0e0d0c
-DATA shifts<>+0xd0(SB)/8, $0x0a09080706050403
-DATA shifts<>+0xd8(SB)/8, $0xffffff0f0e0d0c0b
-DATA shifts<>+0xe0(SB)/8, $0x0908070605040302
-DATA shifts<>+0xe8(SB)/8, $0xffff0f0e0d0c0b0a
-DATA shifts<>+0xf0(SB)/8, $0x0807060504030201
-DATA shifts<>+0xf8(SB)/8, $0xff0f0e0d0c0b0a09
-GLOBL shifts<>(SB),RODATA,$256
-
-TEXT runtime·return0(SB), NOSPLIT, $0
- MOVL $0, AX
- RET
-
-
-// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
-// Must obey the gcc calling convention.
-TEXT _cgo_topofstack(SB),NOSPLIT,$0
- get_tls(CX)
- MOVQ g(CX), AX
- MOVQ g_m(AX), AX
- MOVQ m_curg(AX), AX
- MOVQ (g_stack+stack_hi)(AX), AX
- RET
-
-// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT|TOPFRAME|NOFRAME,$0-0
- BYTE $0x90 // NOP
- CALL runtime·goexit1(SB) // does not return
- // traceback from goexit1 must hit code range of goexit
- BYTE $0x90 // NOP
-
-// This is called from .init_array and follows the platform, not Go, ABI.
-TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
- PUSHQ R15 // The access to global variables below implicitly uses R15, which is callee-save
- MOVQ runtime·lastmoduledatap(SB), AX
- MOVQ DI, moduledata_next(AX)
- MOVQ DI, runtime·lastmoduledatap(SB)
- POPQ R15
- RET
-
-// Initialize special registers then jump to sigpanic.
-// This function is injected from the signal handler for panicking
-// signals. It is quite painful to set X15 in the signal context,
-// so we do it here.
-TEXT ·sigpanic0(SB),NOSPLIT,$0-0
- get_tls(R14)
- MOVQ g(R14), R14
-#ifndef GOOS_plan9
- XORPS X15, X15
-#endif
- JMP ·sigpanic(SB)
-
-// gcWriteBarrier informs the GC about heap pointer writes.
-//
-// gcWriteBarrier returns space in a write barrier buffer which
-// should be filled in by the caller.
-// gcWriteBarrier does NOT follow the Go ABI. It accepts the
-// number of bytes of buffer needed in R11, and returns a pointer
-// to the buffer space in R11.
-// It clobbers FLAGS. It does not clobber any general-purpose registers,
-// but may clobber others (e.g., SSE registers).
-// Typical use would be, when doing *(CX+88) = AX
-// CMPL $0, runtime.writeBarrier(SB)
-// JEQ dowrite
-// CALL runtime.gcBatchBarrier2(SB)
-// MOVQ AX, (R11)
-// MOVQ 88(CX), DX
-// MOVQ DX, 8(R11)
-// dowrite:
-// MOVQ AX, 88(CX)
-TEXT gcWriteBarrier<>(SB),NOSPLIT,$112
- // Save the registers clobbered by the fast path. This is slightly
- // faster than having the caller spill these.
- MOVQ R12, 96(SP)
- MOVQ R13, 104(SP)
-retry:
- // TODO: Consider passing g.m.p in as an argument so they can be shared
- // across a sequence of write barriers.
- MOVQ g_m(R14), R13
- MOVQ m_p(R13), R13
- // Get current buffer write position.
- MOVQ (p_wbBuf+wbBuf_next)(R13), R12 // original next position
- ADDQ R11, R12 // new next position
- // Is the buffer full?
- CMPQ R12, (p_wbBuf+wbBuf_end)(R13)
- JA flush
- // Commit to the larger buffer.
- MOVQ R12, (p_wbBuf+wbBuf_next)(R13)
- // Make return value (the original next position)
- SUBQ R11, R12
- MOVQ R12, R11
- // Restore registers.
- MOVQ 96(SP), R12
- MOVQ 104(SP), R13
- RET
-
-flush:
- // Save all general purpose registers since these could be
- // clobbered by wbBufFlush and were not saved by the caller.
- // It is possible for wbBufFlush to clobber other registers
- // (e.g., SSE registers), but the compiler takes care of saving
- // those in the caller if necessary. This strikes a balance
- // with registers that are likely to be used.
- //
- // We don't have type information for these, but all code under
- // here is NOSPLIT, so nothing will observe these.
- //
- // TODO: We could strike a different balance; e.g., saving X0
- // and not saving GP registers that are less likely to be used.
- MOVQ DI, 0(SP)
- MOVQ AX, 8(SP)
- MOVQ BX, 16(SP)
- MOVQ CX, 24(SP)
- MOVQ DX, 32(SP)
- // DI already saved
- MOVQ SI, 40(SP)
- MOVQ BP, 48(SP)
- MOVQ R8, 56(SP)
- MOVQ R9, 64(SP)
- MOVQ R10, 72(SP)
- MOVQ R11, 80(SP)
- // R12 already saved
- // R13 already saved
- // R14 is g
- MOVQ R15, 88(SP)
-
- CALL runtime·wbBufFlush(SB)
-
- MOVQ 0(SP), DI
- MOVQ 8(SP), AX
- MOVQ 16(SP), BX
- MOVQ 24(SP), CX
- MOVQ 32(SP), DX
- MOVQ 40(SP), SI
- MOVQ 48(SP), BP
- MOVQ 56(SP), R8
- MOVQ 64(SP), R9
- MOVQ 72(SP), R10
- MOVQ 80(SP), R11
- MOVQ 88(SP), R15
- JMP retry
-
-TEXT runtime·gcWriteBarrier1(SB),NOSPLIT|NOFRAME,$0
- MOVL $8, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier2(SB),NOSPLIT|NOFRAME,$0
- MOVL $16, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier3(SB),NOSPLIT|NOFRAME,$0
- MOVL $24, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier4(SB),NOSPLIT|NOFRAME,$0
- MOVL $32, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier5(SB),NOSPLIT|NOFRAME,$0
- MOVL $40, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier6(SB),NOSPLIT|NOFRAME,$0
- MOVL $48, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier7(SB),NOSPLIT|NOFRAME,$0
- MOVL $56, R11
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier8(SB),NOSPLIT|NOFRAME,$0
- MOVL $64, R11
- JMP gcWriteBarrier<>(SB)
-
-DATA debugCallFrameTooLarge<>+0x00(SB)/20, $"call frame too large"
-GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below
-
-// debugCallV2 is the entry point for debugger-injected function
-// calls on running goroutines. It informs the runtime that a
-// debug call has been injected and creates a call frame for the
-// debugger to fill in.
-//
-// To inject a function call, a debugger should:
-// 1. Check that the goroutine is in state _Grunning and that
-// there are at least 256 bytes free on the stack.
-// 2. Push the current PC on the stack (updating SP).
-// 3. Write the desired argument frame size at SP-16 (using the SP
-// after step 2).
-// 4. Save all machine registers (including flags and XMM registers)
-// so they can be restored later by the debugger.
-// 5. Set the PC to debugCallV2 and resume execution.
-//
-// If the goroutine is in state _Grunnable, then it's not generally
-// safe to inject a call because it may return out via other runtime
-// operations. Instead, the debugger should unwind the stack to find
-// the return to non-runtime code, add a temporary breakpoint there,
-// and inject the call once that breakpoint is hit.
-//
-// If the goroutine is in any other state, it's not safe to inject a call.
-//
-// This function communicates back to the debugger by setting R12 and
-// invoking INT3 to raise a breakpoint signal. See the comments in the
-// implementation for the protocol the debugger is expected to
-// follow. InjectDebugCall in the runtime tests demonstrates this protocol.
-//
-// The debugger must ensure that any pointers passed to the function
-// obey escape analysis requirements. Specifically, it must not pass
-// a stack pointer to an escaping argument. debugCallV2 cannot check
-// this invariant.
-//
-// This is ABIInternal because Go code injects its PC directly into new
-// goroutine stacks.
-TEXT runtime·debugCallV2(SB),NOSPLIT,$152-0
- // Save all registers that may contain pointers so they can be
- // conservatively scanned.
- //
- // We can't do anything that might clobber any of these
- // registers before this.
- MOVQ R15, r15-(14*8+8)(SP)
- MOVQ R14, r14-(13*8+8)(SP)
- MOVQ R13, r13-(12*8+8)(SP)
- MOVQ R12, r12-(11*8+8)(SP)
- MOVQ R11, r11-(10*8+8)(SP)
- MOVQ R10, r10-(9*8+8)(SP)
- MOVQ R9, r9-(8*8+8)(SP)
- MOVQ R8, r8-(7*8+8)(SP)
- MOVQ DI, di-(6*8+8)(SP)
- MOVQ SI, si-(5*8+8)(SP)
- MOVQ BP, bp-(4*8+8)(SP)
- MOVQ BX, bx-(3*8+8)(SP)
- MOVQ DX, dx-(2*8+8)(SP)
- // Save the frame size before we clobber it. Either of the last
- // saves could clobber this depending on whether there's a saved BP.
- MOVQ frameSize-24(FP), DX // aka -16(RSP) before prologue
- MOVQ CX, cx-(1*8+8)(SP)
- MOVQ AX, ax-(0*8+8)(SP)
-
- // Save the argument frame size.
- MOVQ DX, frameSize-128(SP)
-
- // Perform a safe-point check.
- MOVQ retpc-8(FP), AX // Caller's PC
- MOVQ AX, 0(SP)
- CALL runtime·debugCallCheck(SB)
- MOVQ 8(SP), AX
- TESTQ AX, AX
- JZ good
- // The safety check failed. Put the reason string at the top
- // of the stack.
- MOVQ AX, 0(SP)
- MOVQ 16(SP), AX
- MOVQ AX, 8(SP)
- // Set R12 to 8 and invoke INT3. The debugger should get the
- // reason a call can't be injected from the top of the stack
- // and resume execution.
- MOVQ $8, R12
- BYTE $0xcc
- JMP restore
-
-good:
- // Registers are saved and it's safe to make a call.
- // Open up a call frame, moving the stack if necessary.
- //
- // Once the frame is allocated, this will set R12 to 0 and
- // invoke INT3. The debugger should write the argument
- // frame for the call at SP, set up argument registers, push
- // the trapping PC on the stack, set the PC to the function to
- // call, set RDX to point to the closure (if a closure call),
- // and resume execution.
- //
- // If the function returns, this will set R12 to 1 and invoke
- // INT3. The debugger can then inspect any return value saved
- // on the stack at SP and in registers and resume execution again.
- //
- // If the function panics, this will set R12 to 2 and invoke INT3.
- // The interface{} value of the panic will be at SP. The debugger
- // can inspect the panic value and resume execution again.
-#define DEBUG_CALL_DISPATCH(NAME,MAXSIZE) \
- CMPQ AX, $MAXSIZE; \
- JA 5(PC); \
- MOVQ $NAME(SB), AX; \
- MOVQ AX, 0(SP); \
- CALL runtime·debugCallWrap(SB); \
- JMP restore
-
- MOVQ frameSize-128(SP), AX
- DEBUG_CALL_DISPATCH(debugCall32<>, 32)
- DEBUG_CALL_DISPATCH(debugCall64<>, 64)
- DEBUG_CALL_DISPATCH(debugCall128<>, 128)
- DEBUG_CALL_DISPATCH(debugCall256<>, 256)
- DEBUG_CALL_DISPATCH(debugCall512<>, 512)
- DEBUG_CALL_DISPATCH(debugCall1024<>, 1024)
- DEBUG_CALL_DISPATCH(debugCall2048<>, 2048)
- DEBUG_CALL_DISPATCH(debugCall4096<>, 4096)
- DEBUG_CALL_DISPATCH(debugCall8192<>, 8192)
- DEBUG_CALL_DISPATCH(debugCall16384<>, 16384)
- DEBUG_CALL_DISPATCH(debugCall32768<>, 32768)
- DEBUG_CALL_DISPATCH(debugCall65536<>, 65536)
- // The frame size is too large. Report the error.
- MOVQ $debugCallFrameTooLarge<>(SB), AX
- MOVQ AX, 0(SP)
- MOVQ $20, 8(SP) // length of debugCallFrameTooLarge string
- MOVQ $8, R12
- BYTE $0xcc
- JMP restore
-
-restore:
- // Calls and failures resume here.
- //
- // Set R12 to 16 and invoke INT3. The debugger should restore
- // all registers except RIP and RSP and resume execution.
- MOVQ $16, R12
- BYTE $0xcc
- // We must not modify flags after this point.
-
- // Restore pointer-containing registers, which may have been
- // modified from the debugger's copy by stack copying.
- MOVQ ax-(0*8+8)(SP), AX
- MOVQ cx-(1*8+8)(SP), CX
- MOVQ dx-(2*8+8)(SP), DX
- MOVQ bx-(3*8+8)(SP), BX
- MOVQ bp-(4*8+8)(SP), BP
- MOVQ si-(5*8+8)(SP), SI
- MOVQ di-(6*8+8)(SP), DI
- MOVQ r8-(7*8+8)(SP), R8
- MOVQ r9-(8*8+8)(SP), R9
- MOVQ r10-(9*8+8)(SP), R10
- MOVQ r11-(10*8+8)(SP), R11
- MOVQ r12-(11*8+8)(SP), R12
- MOVQ r13-(12*8+8)(SP), R13
- MOVQ r14-(13*8+8)(SP), R14
- MOVQ r15-(14*8+8)(SP), R15
-
- RET
-
-// runtime.debugCallCheck assumes that functions defined with the
-// DEBUG_CALL_FN macro are safe points to inject calls.
-#define DEBUG_CALL_FN(NAME,MAXSIZE) \
-TEXT NAME(SB),WRAPPER,$MAXSIZE-0; \
- NO_LOCAL_POINTERS; \
- MOVQ $0, R12; \
- BYTE $0xcc; \
- MOVQ $1, R12; \
- BYTE $0xcc; \
- RET
-DEBUG_CALL_FN(debugCall32<>, 32)
-DEBUG_CALL_FN(debugCall64<>, 64)
-DEBUG_CALL_FN(debugCall128<>, 128)
-DEBUG_CALL_FN(debugCall256<>, 256)
-DEBUG_CALL_FN(debugCall512<>, 512)
-DEBUG_CALL_FN(debugCall1024<>, 1024)
-DEBUG_CALL_FN(debugCall2048<>, 2048)
-DEBUG_CALL_FN(debugCall4096<>, 4096)
-DEBUG_CALL_FN(debugCall8192<>, 8192)
-DEBUG_CALL_FN(debugCall16384<>, 16384)
-DEBUG_CALL_FN(debugCall32768<>, 32768)
-DEBUG_CALL_FN(debugCall65536<>, 65536)
-
-// func debugCallPanicked(val interface{})
-TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16
- // Copy the panic value to the top of stack.
- MOVQ val_type+0(FP), AX
- MOVQ AX, 0(SP)
- MOVQ val_data+8(FP), AX
- MOVQ AX, 8(SP)
- MOVQ $2, R12
- BYTE $0xcc
- RET
-
-// Note: these functions use a special calling convention to save generated code space.
-// Arguments are passed in registers, but the space for those arguments are allocated
-// in the caller's stack frame. These stubs write the args into that stack space and
-// then tail call to the corresponding runtime handler.
-// The tail call makes these stubs disappear in backtraces.
-// Defined as ABIInternal since they do not use the stack-based Go ABI.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
- MOVQ CX, BX
- JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
- MOVQ CX, BX
- JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
- MOVQ CX, AX
- MOVQ DX, BX
- JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
- MOVQ CX, AX
- MOVQ DX, BX
- JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
- MOVQ CX, AX
- MOVQ DX, BX
- JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
- MOVQ CX, AX
- MOVQ DX, BX
- JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
- MOVQ CX, BX
- JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
- MOVQ CX, BX
- JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
- MOVQ DX, AX
- JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
- MOVQ DX, AX
- JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
- MOVQ DX, AX
- JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
- MOVQ DX, AX
- JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
- MOVQ CX, AX
- MOVQ DX, BX
- JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
- MOVQ CX, AX
- MOVQ DX, BX
- JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
- MOVQ CX, BX
- JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
- MOVQ CX, BX
- JMP runtime·goPanicSlice3CU(SB)
-TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
- MOVQ DX, AX
- JMP runtime·goPanicSliceConvert(SB)
-
-#ifdef GOOS_android
-// Use the free TLS_SLOT_APP slot #2 on Android Q.
-// Earlier androids are set up in gcc_android.c.
-DATA runtime·tls_g+0(SB)/8, $16
-GLOBL runtime·tls_g+0(SB), NOPTR, $8
-#endif
-#ifdef GOOS_windows
-GLOBL runtime·tls_g+0(SB), NOPTR, $8
-#endif
-
-// The compiler and assembler's -spectre=ret mode rewrites
-// all indirect CALL AX / JMP AX instructions to be
-// CALL retpolineAX / JMP retpolineAX.
-// See https://support.google.com/faqs/answer/7625886.
-#define RETPOLINE(reg) \
- /* CALL setup */ BYTE $0xE8; BYTE $(2+2); BYTE $0; BYTE $0; BYTE $0; \
- /* nospec: */ \
- /* PAUSE */ BYTE $0xF3; BYTE $0x90; \
- /* JMP nospec */ BYTE $0xEB; BYTE $-(2+2); \
- /* setup: */ \
- /* MOVQ AX, 0(SP) */ BYTE $0x48|((reg&8)>>1); BYTE $0x89; \
- BYTE $0x04|((reg&7)<<3); BYTE $0x24; \
- /* RET */ BYTE $0xC3
-
-TEXT runtime·retpolineAX(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(0)
-TEXT runtime·retpolineCX(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(1)
-TEXT runtime·retpolineDX(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(2)
-TEXT runtime·retpolineBX(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(3)
-/* SP is 4, can't happen / magic encodings */
-TEXT runtime·retpolineBP(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(5)
-TEXT runtime·retpolineSI(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(6)
-TEXT runtime·retpolineDI(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(7)
-TEXT runtime·retpolineR8(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(8)
-TEXT runtime·retpolineR9(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(9)
-TEXT runtime·retpolineR10(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(10)
-TEXT runtime·retpolineR11(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(11)
-TEXT runtime·retpolineR12(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(12)
-TEXT runtime·retpolineR13(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(13)
-TEXT runtime·retpolineR14(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(14)
-TEXT runtime·retpolineR15(SB),NOSPLIT|NOFRAME,$0; RETPOLINE(15)
-
-TEXT ·getfp(SB),NOSPLIT|NOFRAME,$0
- MOVQ BP, AX
- RET
diff --git a/contrib/go/_std_1.22/src/runtime/asm_arm64.s b/contrib/go/_std_1.22/src/runtime/asm_arm64.s
deleted file mode 100644
index 6d77b08a1b90..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asm_arm64.s
+++ /dev/null
@@ -1,1598 +0,0 @@
-// Copyright 2015 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.
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "tls_arm64.h"
-#include "funcdata.h"
-#include "textflag.h"
-
-TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
- // SP = stack; R0 = argc; R1 = argv
-
- SUB $32, RSP
- MOVW R0, 8(RSP) // argc
- MOVD R1, 16(RSP) // argv
-
-#ifdef TLS_darwin
- // Initialize TLS.
- MOVD ZR, g // clear g, make sure it's not junk.
- SUB $32, RSP
- MRS_TPIDR_R0
- AND $~7, R0
- MOVD R0, 16(RSP) // arg2: TLS base
- MOVD $runtime·tls_g(SB), R2
- MOVD R2, 8(RSP) // arg1: &tlsg
- BL ·tlsinit(SB)
- ADD $32, RSP
-#endif
-
- // create istack out of the given (operating system) stack.
- // _cgo_init may update stackguard.
- MOVD $runtime·g0(SB), g
- MOVD RSP, R7
- MOVD $(-64*1024)(R7), R0
- MOVD R0, g_stackguard0(g)
- MOVD R0, g_stackguard1(g)
- MOVD R0, (g_stack+stack_lo)(g)
- MOVD R7, (g_stack+stack_hi)(g)
-
- // if there is a _cgo_init, call it using the gcc ABI.
- MOVD _cgo_init(SB), R12
- CBZ R12, nocgo
-
-#ifdef GOOS_android
- MRS_TPIDR_R0 // load TLS base pointer
- MOVD R0, R3 // arg 3: TLS base pointer
- MOVD $runtime·tls_g(SB), R2 // arg 2: &tls_g
-#else
- MOVD $0, R2 // arg 2: not used when using platform's TLS
-#endif
- MOVD $setg_gcc<>(SB), R1 // arg 1: setg
- MOVD g, R0 // arg 0: G
- SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved.
- BL (R12)
- ADD $16, RSP
-
-nocgo:
- BL runtime·save_g(SB)
- // update stackguard after _cgo_init
- MOVD (g_stack+stack_lo)(g), R0
- ADD $const_stackGuard, R0
- MOVD R0, g_stackguard0(g)
- MOVD R0, g_stackguard1(g)
-
- // set the per-goroutine and per-mach "registers"
- MOVD $runtime·m0(SB), R0
-
- // save m->g0 = g0
- MOVD g, m_g0(R0)
- // save m0 to g0->m
- MOVD R0, g_m(g)
-
- BL runtime·check(SB)
-
-#ifdef GOOS_windows
- BL runtime·wintls(SB)
-#endif
-
- MOVW 8(RSP), R0 // copy argc
- MOVW R0, -8(RSP)
- MOVD 16(RSP), R0 // copy argv
- MOVD R0, 0(RSP)
- BL runtime·args(SB)
- BL runtime·osinit(SB)
- BL runtime·schedinit(SB)
-
- // create a new goroutine to start program
- MOVD $runtime·mainPC(SB), R0 // entry
- SUB $16, RSP
- MOVD R0, 8(RSP) // arg
- MOVD $0, 0(RSP) // dummy LR
- BL runtime·newproc(SB)
- ADD $16, RSP
-
- // start this M
- BL runtime·mstart(SB)
-
- // Prevent dead-code elimination of debugCallV2, which is
- // intended to be called by debuggers.
- MOVD $runtime·debugCallV2(SB), R0
-
- MOVD $0, R0
- MOVD R0, (R0) // boom
- UNDEF
-
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
-GLOBL runtime·mainPC(SB),RODATA,$8
-
-// Windows ARM64 needs an immediate 0xf000 argument.
-// See go.dev/issues/53837.
-#define BREAK \
-#ifdef GOOS_windows \
- BRK $0xf000 \
-#else \
- BRK \
-#endif \
-
-
-TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
- BREAK
- RET
-
-TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
- RET
-
-TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
- BL runtime·mstart0(SB)
- RET // not reached
-
-/*
- * go-routine
- */
-
-// void gogo(Gobuf*)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
- MOVD buf+0(FP), R5
- MOVD gobuf_g(R5), R6
- MOVD 0(R6), R4 // make sure g != nil
- B gogo<>(SB)
-
-TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
- MOVD R6, g
- BL runtime·save_g(SB)
-
- MOVD gobuf_sp(R5), R0
- MOVD R0, RSP
- MOVD gobuf_bp(R5), R29
- MOVD gobuf_lr(R5), LR
- MOVD gobuf_ret(R5), R0
- MOVD gobuf_ctxt(R5), R26
- MOVD $0, gobuf_sp(R5)
- MOVD $0, gobuf_bp(R5)
- MOVD $0, gobuf_ret(R5)
- MOVD $0, gobuf_lr(R5)
- MOVD $0, gobuf_ctxt(R5)
- CMP ZR, ZR // set condition codes for == test, needed by stack split
- MOVD gobuf_pc(R5), R6
- B (R6)
-
-// void mcall(fn func(*g))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return. It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
- MOVD R0, R26 // context
-
- // Save caller state in g->sched
- MOVD RSP, R0
- MOVD R0, (g_sched+gobuf_sp)(g)
- MOVD R29, (g_sched+gobuf_bp)(g)
- MOVD LR, (g_sched+gobuf_pc)(g)
- MOVD $0, (g_sched+gobuf_lr)(g)
-
- // Switch to m->g0 & its stack, call fn.
- MOVD g, R3
- MOVD g_m(g), R8
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- CMP g, R3
- BNE 2(PC)
- B runtime·badmcall(SB)
-
- MOVD (g_sched+gobuf_sp)(g), R0
- MOVD R0, RSP // sp = m->g0->sched.sp
- MOVD (g_sched+gobuf_bp)(g), R29
- MOVD R3, R0 // arg = g
- MOVD $0, -16(RSP) // dummy LR
- SUB $16, RSP
- MOVD 0(R26), R4 // code pointer
- BL (R4)
- B runtime·badmcall2(SB)
-
-// systemstack_switch is a dummy routine that systemstack leaves at the bottom
-// of the G stack. We need to distinguish the routine that
-// lives at the bottom of the G stack from the one that lives
-// at the top of the system stack because the one at the top of
-// the system stack terminates the stack walk (see topofstack()).
-TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
- UNDEF
- BL (LR) // make sure this function is not leaf
- RET
-
-// func systemstack(fn func())
-TEXT runtime·systemstack(SB), NOSPLIT, $0-8
- MOVD fn+0(FP), R3 // R3 = fn
- MOVD R3, R26 // context
- MOVD g_m(g), R4 // R4 = m
-
- MOVD m_gsignal(R4), R5 // R5 = gsignal
- CMP g, R5
- BEQ noswitch
-
- MOVD m_g0(R4), R5 // R5 = g0
- CMP g, R5
- BEQ noswitch
-
- MOVD m_curg(R4), R6
- CMP g, R6
- BEQ switch
-
- // Bad: g is not gsignal, not g0, not curg. What is it?
- // Hide call from linker nosplit analysis.
- MOVD $runtime·badsystemstack(SB), R3
- BL (R3)
- B runtime·abort(SB)
-
-switch:
- // save our state in g->sched. Pretend to
- // be systemstack_switch if the G stack is scanned.
- BL gosave_systemstack_switch<>(SB)
-
- // switch to g0
- MOVD R5, g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R3
- MOVD R3, RSP
- MOVD (g_sched+gobuf_bp)(g), R29
-
- // call target function
- MOVD 0(R26), R3 // code pointer
- BL (R3)
-
- // switch back to g
- MOVD g_m(g), R3
- MOVD m_curg(R3), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R0
- MOVD R0, RSP
- MOVD (g_sched+gobuf_bp)(g), R29
- MOVD $0, (g_sched+gobuf_sp)(g)
- MOVD $0, (g_sched+gobuf_bp)(g)
- RET
-
-noswitch:
- // already on m stack, just call directly
- // Using a tail call here cleans up tracebacks since we won't stop
- // at an intermediate systemstack.
- MOVD 0(R26), R3 // code pointer
- MOVD.P 16(RSP), R30 // restore LR
- SUB $8, RSP, R29 // restore FP
- B (R3)
-
-// func switchToCrashStack0(fn func())
-TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-8
- MOVD R0, R26 // context register
- MOVD g_m(g), R1 // curm
-
- // set g to gcrash
- MOVD $runtime·gcrash(SB), g // g = &gcrash
- BL runtime·save_g(SB) // clobbers R0
- MOVD R1, g_m(g) // g.m = curm
- MOVD g, m_g0(R1) // curm.g0 = g
-
- // switch to crashstack
- MOVD (g_stack+stack_hi)(g), R1
- SUB $(4*8), R1
- MOVD R1, RSP
-
- // call target function
- MOVD 0(R26), R0
- CALL (R0)
-
- // should never return
- CALL runtime·abort(SB)
- UNDEF
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-// Caller has already loaded:
-// R3 prolog's LR (R30)
-//
-// The traceback routines see morestack on a g0 as being
-// the top of a stack (for example, morestack calling newstack
-// calling the scheduler calling newm calling gc), so we must
-// record an argument size. For that purpose, it has no arguments.
-TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
- // Cannot grow scheduler stack (m->g0).
- MOVD g_m(g), R8
- MOVD m_g0(R8), R4
-
- // Called from f.
- // Set g->sched to context in f
- MOVD RSP, R0
- MOVD R0, (g_sched+gobuf_sp)(g)
- MOVD R29, (g_sched+gobuf_bp)(g)
- MOVD LR, (g_sched+gobuf_pc)(g)
- MOVD R3, (g_sched+gobuf_lr)(g)
- MOVD R26, (g_sched+gobuf_ctxt)(g)
-
- CMP g, R4
- BNE 3(PC)
- BL runtime·badmorestackg0(SB)
- B runtime·abort(SB)
-
- // Cannot grow signal stack (m->gsignal).
- MOVD m_gsignal(R8), R4
- CMP g, R4
- BNE 3(PC)
- BL runtime·badmorestackgsignal(SB)
- B runtime·abort(SB)
-
- // Called from f.
- // Set m->morebuf to f's callers.
- MOVD R3, (m_morebuf+gobuf_pc)(R8) // f's caller's PC
- MOVD RSP, R0
- MOVD R0, (m_morebuf+gobuf_sp)(R8) // f's caller's RSP
- MOVD g, (m_morebuf+gobuf_g)(R8)
-
- // Call newstack on m->g0's stack.
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R0
- MOVD R0, RSP
- MOVD (g_sched+gobuf_bp)(g), R29
- MOVD.W $0, -16(RSP) // create a call frame on g0 (saved LR; keep 16-aligned)
- BL runtime·newstack(SB)
-
- // Not reached, but make sure the return PC from the call to newstack
- // is still in this function, and not the beginning of the next.
- UNDEF
-
-TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
- // Force SPWRITE. This function doesn't actually write SP,
- // but it is called with a special calling convention where
- // the caller doesn't save LR on stack but passes it as a
- // register (R3), and the unwinder currently doesn't understand.
- // Make it SPWRITE to stop unwinding. (See issue 54332)
- MOVD RSP, RSP
-
- MOVW $0, R26
- B runtime·morestack(SB)
-
-// spillArgs stores return values from registers to a *internal/abi.RegArgs in R20.
-TEXT ·spillArgs(SB),NOSPLIT,$0-0
- STP (R0, R1), (0*8)(R20)
- STP (R2, R3), (2*8)(R20)
- STP (R4, R5), (4*8)(R20)
- STP (R6, R7), (6*8)(R20)
- STP (R8, R9), (8*8)(R20)
- STP (R10, R11), (10*8)(R20)
- STP (R12, R13), (12*8)(R20)
- STP (R14, R15), (14*8)(R20)
- FSTPD (F0, F1), (16*8)(R20)
- FSTPD (F2, F3), (18*8)(R20)
- FSTPD (F4, F5), (20*8)(R20)
- FSTPD (F6, F7), (22*8)(R20)
- FSTPD (F8, F9), (24*8)(R20)
- FSTPD (F10, F11), (26*8)(R20)
- FSTPD (F12, F13), (28*8)(R20)
- FSTPD (F14, F15), (30*8)(R20)
- RET
-
-// unspillArgs loads args into registers from a *internal/abi.RegArgs in R20.
-TEXT ·unspillArgs(SB),NOSPLIT,$0-0
- LDP (0*8)(R20), (R0, R1)
- LDP (2*8)(R20), (R2, R3)
- LDP (4*8)(R20), (R4, R5)
- LDP (6*8)(R20), (R6, R7)
- LDP (8*8)(R20), (R8, R9)
- LDP (10*8)(R20), (R10, R11)
- LDP (12*8)(R20), (R12, R13)
- LDP (14*8)(R20), (R14, R15)
- FLDPD (16*8)(R20), (F0, F1)
- FLDPD (18*8)(R20), (F2, F3)
- FLDPD (20*8)(R20), (F4, F5)
- FLDPD (22*8)(R20), (F6, F7)
- FLDPD (24*8)(R20), (F8, F9)
- FLDPD (26*8)(R20), (F10, F11)
- FLDPD (28*8)(R20), (F12, F13)
- FLDPD (30*8)(R20), (F14, F15)
- RET
-
-// reflectcall: call a function with the given argument list
-// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
-// we don't have variable-sized frames, so we use a small number
-// of constant-sized-frame functions to encode a few bits of size in the pc.
-// Caution: ugly multiline assembly macros in your future!
-
-#define DISPATCH(NAME,MAXSIZE) \
- MOVD $MAXSIZE, R27; \
- CMP R27, R16; \
- BGT 3(PC); \
- MOVD $NAME(SB), R27; \
- B (R27)
-// Note: can't just "B NAME(SB)" - bad inlining results.
-
-TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
- MOVWU frameSize+32(FP), R16
- DISPATCH(runtime·call16, 16)
- DISPATCH(runtime·call32, 32)
- DISPATCH(runtime·call64, 64)
- DISPATCH(runtime·call128, 128)
- DISPATCH(runtime·call256, 256)
- DISPATCH(runtime·call512, 512)
- DISPATCH(runtime·call1024, 1024)
- DISPATCH(runtime·call2048, 2048)
- DISPATCH(runtime·call4096, 4096)
- DISPATCH(runtime·call8192, 8192)
- DISPATCH(runtime·call16384, 16384)
- DISPATCH(runtime·call32768, 32768)
- DISPATCH(runtime·call65536, 65536)
- DISPATCH(runtime·call131072, 131072)
- DISPATCH(runtime·call262144, 262144)
- DISPATCH(runtime·call524288, 524288)
- DISPATCH(runtime·call1048576, 1048576)
- DISPATCH(runtime·call2097152, 2097152)
- DISPATCH(runtime·call4194304, 4194304)
- DISPATCH(runtime·call8388608, 8388608)
- DISPATCH(runtime·call16777216, 16777216)
- DISPATCH(runtime·call33554432, 33554432)
- DISPATCH(runtime·call67108864, 67108864)
- DISPATCH(runtime·call134217728, 134217728)
- DISPATCH(runtime·call268435456, 268435456)
- DISPATCH(runtime·call536870912, 536870912)
- DISPATCH(runtime·call1073741824, 1073741824)
- MOVD $runtime·badreflectcall(SB), R0
- B (R0)
-
-#define CALLFN(NAME,MAXSIZE) \
-TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
- NO_LOCAL_POINTERS; \
- /* copy arguments to stack */ \
- MOVD stackArgs+16(FP), R3; \
- MOVWU stackArgsSize+24(FP), R4; \
- ADD $8, RSP, R5; \
- BIC $0xf, R4, R6; \
- CBZ R6, 6(PC); \
- /* if R6=(argsize&~15) != 0 */ \
- ADD R6, R5, R6; \
- /* copy 16 bytes a time */ \
- LDP.P 16(R3), (R7, R8); \
- STP.P (R7, R8), 16(R5); \
- CMP R5, R6; \
- BNE -3(PC); \
- AND $0xf, R4, R6; \
- CBZ R6, 6(PC); \
- /* if R6=(argsize&15) != 0 */ \
- ADD R6, R5, R6; \
- /* copy 1 byte a time for the rest */ \
- MOVBU.P 1(R3), R7; \
- MOVBU.P R7, 1(R5); \
- CMP R5, R6; \
- BNE -3(PC); \
- /* set up argument registers */ \
- MOVD regArgs+40(FP), R20; \
- CALL ·unspillArgs(SB); \
- /* call function */ \
- MOVD f+8(FP), R26; \
- MOVD (R26), R20; \
- PCDATA $PCDATA_StackMapIndex, $0; \
- BL (R20); \
- /* copy return values back */ \
- MOVD regArgs+40(FP), R20; \
- CALL ·spillArgs(SB); \
- MOVD stackArgsType+0(FP), R7; \
- MOVD stackArgs+16(FP), R3; \
- MOVWU stackArgsSize+24(FP), R4; \
- MOVWU stackRetOffset+28(FP), R6; \
- ADD $8, RSP, R5; \
- ADD R6, R5; \
- ADD R6, R3; \
- SUB R6, R4; \
- BL callRet<>(SB); \
- RET
-
-// callRet copies return values back at the end of call*. This is a
-// separate function so it can allocate stack space for the arguments
-// to reflectcallmove. It does not follow the Go ABI; it expects its
-// arguments in registers.
-TEXT callRet<>(SB), NOSPLIT, $48-0
- NO_LOCAL_POINTERS
- STP (R7, R3), 8(RSP)
- STP (R5, R4), 24(RSP)
- MOVD R20, 40(RSP)
- BL runtime·reflectcallmove(SB)
- RET
-
-CALLFN(·call16, 16)
-CALLFN(·call32, 32)
-CALLFN(·call64, 64)
-CALLFN(·call128, 128)
-CALLFN(·call256, 256)
-CALLFN(·call512, 512)
-CALLFN(·call1024, 1024)
-CALLFN(·call2048, 2048)
-CALLFN(·call4096, 4096)
-CALLFN(·call8192, 8192)
-CALLFN(·call16384, 16384)
-CALLFN(·call32768, 32768)
-CALLFN(·call65536, 65536)
-CALLFN(·call131072, 131072)
-CALLFN(·call262144, 262144)
-CALLFN(·call524288, 524288)
-CALLFN(·call1048576, 1048576)
-CALLFN(·call2097152, 2097152)
-CALLFN(·call4194304, 4194304)
-CALLFN(·call8388608, 8388608)
-CALLFN(·call16777216, 16777216)
-CALLFN(·call33554432, 33554432)
-CALLFN(·call67108864, 67108864)
-CALLFN(·call134217728, 134217728)
-CALLFN(·call268435456, 268435456)
-CALLFN(·call536870912, 536870912)
-CALLFN(·call1073741824, 1073741824)
-
-// func memhash32(p unsafe.Pointer, h uintptr) uintptr
-TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
- MOVB runtime·useAeshash(SB), R10
- CBZ R10, noaes
- MOVD $runtime·aeskeysched+0(SB), R3
-
- VEOR V0.B16, V0.B16, V0.B16
- VLD1 (R3), [V2.B16]
- VLD1 (R0), V0.S[1]
- VMOV R1, V0.S[0]
-
- AESE V2.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V2.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V2.B16, V0.B16
-
- VMOV V0.D[0], R0
- RET
-noaes:
- B runtime·memhash32Fallback(SB)
-
-// func memhash64(p unsafe.Pointer, h uintptr) uintptr
-TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
- MOVB runtime·useAeshash(SB), R10
- CBZ R10, noaes
- MOVD $runtime·aeskeysched+0(SB), R3
-
- VEOR V0.B16, V0.B16, V0.B16
- VLD1 (R3), [V2.B16]
- VLD1 (R0), V0.D[1]
- VMOV R1, V0.D[0]
-
- AESE V2.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V2.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V2.B16, V0.B16
-
- VMOV V0.D[0], R0
- RET
-noaes:
- B runtime·memhash64Fallback(SB)
-
-// func memhash(p unsafe.Pointer, h, size uintptr) uintptr
-TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
- MOVB runtime·useAeshash(SB), R10
- CBZ R10, noaes
- B aeshashbody<>(SB)
-noaes:
- B runtime·memhashFallback(SB)
-
-// func strhash(p unsafe.Pointer, h uintptr) uintptr
-TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
- MOVB runtime·useAeshash(SB), R10
- CBZ R10, noaes
- LDP (R0), (R0, R2) // string data / length
- B aeshashbody<>(SB)
-noaes:
- B runtime·strhashFallback(SB)
-
-// R0: data
-// R1: seed data
-// R2: length
-// At return, R0 = return value
-TEXT aeshashbody<>(SB),NOSPLIT|NOFRAME,$0
- VEOR V30.B16, V30.B16, V30.B16
- VMOV R1, V30.D[0]
- VMOV R2, V30.D[1] // load length into seed
-
- MOVD $runtime·aeskeysched+0(SB), R4
- VLD1.P 16(R4), [V0.B16]
- AESE V30.B16, V0.B16
- AESMC V0.B16, V0.B16
- CMP $16, R2
- BLO aes0to15
- BEQ aes16
- CMP $32, R2
- BLS aes17to32
- CMP $64, R2
- BLS aes33to64
- CMP $128, R2
- BLS aes65to128
- B aes129plus
-
-aes0to15:
- CBZ R2, aes0
- VEOR V2.B16, V2.B16, V2.B16
- TBZ $3, R2, less_than_8
- VLD1.P 8(R0), V2.D[0]
-
-less_than_8:
- TBZ $2, R2, less_than_4
- VLD1.P 4(R0), V2.S[2]
-
-less_than_4:
- TBZ $1, R2, less_than_2
- VLD1.P 2(R0), V2.H[6]
-
-less_than_2:
- TBZ $0, R2, done
- VLD1 (R0), V2.B[14]
-done:
- AESE V0.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V0.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V0.B16, V2.B16
- AESMC V2.B16, V2.B16
-
- VMOV V2.D[0], R0
- RET
-
-aes0:
- VMOV V0.D[0], R0
- RET
-
-aes16:
- VLD1 (R0), [V2.B16]
- B done
-
-aes17to32:
- // make second seed
- VLD1 (R4), [V1.B16]
- AESE V30.B16, V1.B16
- AESMC V1.B16, V1.B16
- SUB $16, R2, R10
- VLD1.P (R0)(R10), [V2.B16]
- VLD1 (R0), [V3.B16]
-
- AESE V0.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V1.B16, V3.B16
- AESMC V3.B16, V3.B16
-
- AESE V0.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V1.B16, V3.B16
- AESMC V3.B16, V3.B16
-
- AESE V0.B16, V2.B16
- AESE V1.B16, V3.B16
-
- VEOR V3.B16, V2.B16, V2.B16
-
- VMOV V2.D[0], R0
- RET
-
-aes33to64:
- VLD1 (R4), [V1.B16, V2.B16, V3.B16]
- AESE V30.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V30.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V30.B16, V3.B16
- AESMC V3.B16, V3.B16
- SUB $32, R2, R10
-
- VLD1.P (R0)(R10), [V4.B16, V5.B16]
- VLD1 (R0), [V6.B16, V7.B16]
-
- AESE V0.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V1.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V2.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V3.B16, V7.B16
- AESMC V7.B16, V7.B16
-
- AESE V0.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V1.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V2.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V3.B16, V7.B16
- AESMC V7.B16, V7.B16
-
- AESE V0.B16, V4.B16
- AESE V1.B16, V5.B16
- AESE V2.B16, V6.B16
- AESE V3.B16, V7.B16
-
- VEOR V6.B16, V4.B16, V4.B16
- VEOR V7.B16, V5.B16, V5.B16
- VEOR V5.B16, V4.B16, V4.B16
-
- VMOV V4.D[0], R0
- RET
-
-aes65to128:
- VLD1.P 64(R4), [V1.B16, V2.B16, V3.B16, V4.B16]
- VLD1 (R4), [V5.B16, V6.B16, V7.B16]
- AESE V30.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V30.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V30.B16, V3.B16
- AESMC V3.B16, V3.B16
- AESE V30.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V30.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V30.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V30.B16, V7.B16
- AESMC V7.B16, V7.B16
-
- SUB $64, R2, R10
- VLD1.P (R0)(R10), [V8.B16, V9.B16, V10.B16, V11.B16]
- VLD1 (R0), [V12.B16, V13.B16, V14.B16, V15.B16]
- AESE V0.B16, V8.B16
- AESMC V8.B16, V8.B16
- AESE V1.B16, V9.B16
- AESMC V9.B16, V9.B16
- AESE V2.B16, V10.B16
- AESMC V10.B16, V10.B16
- AESE V3.B16, V11.B16
- AESMC V11.B16, V11.B16
- AESE V4.B16, V12.B16
- AESMC V12.B16, V12.B16
- AESE V5.B16, V13.B16
- AESMC V13.B16, V13.B16
- AESE V6.B16, V14.B16
- AESMC V14.B16, V14.B16
- AESE V7.B16, V15.B16
- AESMC V15.B16, V15.B16
-
- AESE V0.B16, V8.B16
- AESMC V8.B16, V8.B16
- AESE V1.B16, V9.B16
- AESMC V9.B16, V9.B16
- AESE V2.B16, V10.B16
- AESMC V10.B16, V10.B16
- AESE V3.B16, V11.B16
- AESMC V11.B16, V11.B16
- AESE V4.B16, V12.B16
- AESMC V12.B16, V12.B16
- AESE V5.B16, V13.B16
- AESMC V13.B16, V13.B16
- AESE V6.B16, V14.B16
- AESMC V14.B16, V14.B16
- AESE V7.B16, V15.B16
- AESMC V15.B16, V15.B16
-
- AESE V0.B16, V8.B16
- AESE V1.B16, V9.B16
- AESE V2.B16, V10.B16
- AESE V3.B16, V11.B16
- AESE V4.B16, V12.B16
- AESE V5.B16, V13.B16
- AESE V6.B16, V14.B16
- AESE V7.B16, V15.B16
-
- VEOR V12.B16, V8.B16, V8.B16
- VEOR V13.B16, V9.B16, V9.B16
- VEOR V14.B16, V10.B16, V10.B16
- VEOR V15.B16, V11.B16, V11.B16
- VEOR V10.B16, V8.B16, V8.B16
- VEOR V11.B16, V9.B16, V9.B16
- VEOR V9.B16, V8.B16, V8.B16
-
- VMOV V8.D[0], R0
- RET
-
-aes129plus:
- PRFM (R0), PLDL1KEEP
- VLD1.P 64(R4), [V1.B16, V2.B16, V3.B16, V4.B16]
- VLD1 (R4), [V5.B16, V6.B16, V7.B16]
- AESE V30.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V30.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V30.B16, V3.B16
- AESMC V3.B16, V3.B16
- AESE V30.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V30.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V30.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V30.B16, V7.B16
- AESMC V7.B16, V7.B16
- ADD R0, R2, R10
- SUB $128, R10, R10
- VLD1.P 64(R10), [V8.B16, V9.B16, V10.B16, V11.B16]
- VLD1 (R10), [V12.B16, V13.B16, V14.B16, V15.B16]
- SUB $1, R2, R2
- LSR $7, R2, R2
-
-aesloop:
- AESE V8.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V9.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V10.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V11.B16, V3.B16
- AESMC V3.B16, V3.B16
- AESE V12.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V13.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V14.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V15.B16, V7.B16
- AESMC V7.B16, V7.B16
-
- VLD1.P 64(R0), [V8.B16, V9.B16, V10.B16, V11.B16]
- AESE V8.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V9.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V10.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V11.B16, V3.B16
- AESMC V3.B16, V3.B16
-
- VLD1.P 64(R0), [V12.B16, V13.B16, V14.B16, V15.B16]
- AESE V12.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V13.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V14.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V15.B16, V7.B16
- AESMC V7.B16, V7.B16
- SUB $1, R2, R2
- CBNZ R2, aesloop
-
- AESE V8.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V9.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V10.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V11.B16, V3.B16
- AESMC V3.B16, V3.B16
- AESE V12.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V13.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V14.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V15.B16, V7.B16
- AESMC V7.B16, V7.B16
-
- AESE V8.B16, V0.B16
- AESMC V0.B16, V0.B16
- AESE V9.B16, V1.B16
- AESMC V1.B16, V1.B16
- AESE V10.B16, V2.B16
- AESMC V2.B16, V2.B16
- AESE V11.B16, V3.B16
- AESMC V3.B16, V3.B16
- AESE V12.B16, V4.B16
- AESMC V4.B16, V4.B16
- AESE V13.B16, V5.B16
- AESMC V5.B16, V5.B16
- AESE V14.B16, V6.B16
- AESMC V6.B16, V6.B16
- AESE V15.B16, V7.B16
- AESMC V7.B16, V7.B16
-
- AESE V8.B16, V0.B16
- AESE V9.B16, V1.B16
- AESE V10.B16, V2.B16
- AESE V11.B16, V3.B16
- AESE V12.B16, V4.B16
- AESE V13.B16, V5.B16
- AESE V14.B16, V6.B16
- AESE V15.B16, V7.B16
-
- VEOR V0.B16, V1.B16, V0.B16
- VEOR V2.B16, V3.B16, V2.B16
- VEOR V4.B16, V5.B16, V4.B16
- VEOR V6.B16, V7.B16, V6.B16
- VEOR V0.B16, V2.B16, V0.B16
- VEOR V4.B16, V6.B16, V4.B16
- VEOR V4.B16, V0.B16, V0.B16
-
- VMOV V0.D[0], R0
- RET
-
-TEXT runtime·procyield(SB),NOSPLIT,$0-0
- MOVWU cycles+0(FP), R0
-again:
- YIELD
- SUBW $1, R0
- CBNZ R0, again
- RET
-
-// Save state of caller into g->sched,
-// but using fake PC from systemstack_switch.
-// Must only be called from functions with no locals ($0)
-// or else unwinding from systemstack_switch is incorrect.
-// Smashes R0.
-TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
- MOVD $runtime·systemstack_switch(SB), R0
- ADD $8, R0 // get past prologue
- MOVD R0, (g_sched+gobuf_pc)(g)
- MOVD RSP, R0
- MOVD R0, (g_sched+gobuf_sp)(g)
- MOVD R29, (g_sched+gobuf_bp)(g)
- MOVD $0, (g_sched+gobuf_lr)(g)
- MOVD $0, (g_sched+gobuf_ret)(g)
- // Assert ctxt is zero. See func save.
- MOVD (g_sched+gobuf_ctxt)(g), R0
- CBZ R0, 2(PC)
- CALL runtime·abort(SB)
- RET
-
-// func asmcgocall_no_g(fn, arg unsafe.Pointer)
-// Call fn(arg) aligned appropriately for the gcc ABI.
-// Called on a system stack, and there may be no g yet (during needm).
-TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-16
- MOVD fn+0(FP), R1
- MOVD arg+8(FP), R0
- SUB $16, RSP // skip over saved frame pointer below RSP
- BL (R1)
- ADD $16, RSP // skip over saved frame pointer below RSP
- RET
-
-// func asmcgocall(fn, arg unsafe.Pointer) int32
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.go for more details.
-TEXT ·asmcgocall(SB),NOSPLIT,$0-20
- MOVD fn+0(FP), R1
- MOVD arg+8(FP), R0
-
- MOVD RSP, R2 // save original stack pointer
- CBZ g, nosave
- MOVD g, R4
-
- // Figure out if we need to switch to m->g0 stack.
- // We get called to create new OS threads too, and those
- // come in on the m->g0 stack already. Or we might already
- // be on the m->gsignal stack.
- MOVD g_m(g), R8
- MOVD m_gsignal(R8), R3
- CMP R3, g
- BEQ nosave
- MOVD m_g0(R8), R3
- CMP R3, g
- BEQ nosave
-
- // Switch to system stack.
- MOVD R0, R9 // gosave_systemstack_switch<> and save_g might clobber R0
- BL gosave_systemstack_switch<>(SB)
- MOVD R3, g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R0
- MOVD R0, RSP
- MOVD (g_sched+gobuf_bp)(g), R29
- MOVD R9, R0
-
- // Now on a scheduling stack (a pthread-created stack).
- // Save room for two of our pointers /*, plus 32 bytes of callee
- // save area that lives on the caller stack. */
- MOVD RSP, R13
- SUB $16, R13
- MOVD R13, RSP
- MOVD R4, 0(RSP) // save old g on stack
- MOVD (g_stack+stack_hi)(R4), R4
- SUB R2, R4
- MOVD R4, 8(RSP) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
- BL (R1)
- MOVD R0, R9
-
- // Restore g, stack pointer. R0 is errno, so don't touch it
- MOVD 0(RSP), g
- BL runtime·save_g(SB)
- MOVD (g_stack+stack_hi)(g), R5
- MOVD 8(RSP), R6
- SUB R6, R5
- MOVD R9, R0
- MOVD R5, RSP
-
- MOVW R0, ret+16(FP)
- RET
-
-nosave:
- // Running on a system stack, perhaps even without a g.
- // Having no g can happen during thread creation or thread teardown
- // (see needm/dropm on Solaris, for example).
- // This code is like the above sequence but without saving/restoring g
- // and without worrying about the stack moving out from under us
- // (because we're on a system stack, not a goroutine stack).
- // The above code could be used directly if already on a system stack,
- // but then the only path through this code would be a rare case on Solaris.
- // Using this code for all "already on system stack" calls exercises it more,
- // which should help keep it correct.
- MOVD RSP, R13
- SUB $16, R13
- MOVD R13, RSP
- MOVD $0, R4
- MOVD R4, 0(RSP) // Where above code stores g, in case someone looks during debugging.
- MOVD R2, 8(RSP) // Save original stack pointer.
- BL (R1)
- // Restore stack pointer.
- MOVD 8(RSP), R2
- MOVD R2, RSP
- MOVD R0, ret+16(FP)
- RET
-
-// cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
-// See cgocall.go for more details.
-TEXT ·cgocallback(SB),NOSPLIT,$24-24
- NO_LOCAL_POINTERS
-
- // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
- // It is used to dropm while thread is exiting.
- MOVD fn+0(FP), R1
- CBNZ R1, loadg
- // Restore the g from frame.
- MOVD frame+8(FP), g
- B dropm
-
-loadg:
- // Load g from thread-local storage.
- BL runtime·load_g(SB)
-
- // If g is nil, Go did not create the current thread,
- // or if this thread never called into Go on pthread platforms.
- // Call needm to obtain one for temporary use.
- // In this case, we're running on the thread stack, so there's
- // lots of space, but the linker doesn't know. Hide the call from
- // the linker analysis by using an indirect call.
- CBZ g, needm
-
- MOVD g_m(g), R8
- MOVD R8, savedm-8(SP)
- B havem
-
-needm:
- MOVD g, savedm-8(SP) // g is zero, so is m.
- MOVD $runtime·needAndBindM(SB), R0
- BL (R0)
-
- // Set m->g0->sched.sp = SP, so that if a panic happens
- // during the function we are about to execute, it will
- // have a valid SP to run on the g0 stack.
- // The next few lines (after the havem label)
- // will save this SP onto the stack and then write
- // the same SP back to m->sched.sp. That seems redundant,
- // but if an unrecovered panic happens, unwindm will
- // restore the g->sched.sp from the stack location
- // and then systemstack will try to use it. If we don't set it here,
- // that restored SP will be uninitialized (typically 0) and
- // will not be usable.
- MOVD g_m(g), R8
- MOVD m_g0(R8), R3
- MOVD RSP, R0
- MOVD R0, (g_sched+gobuf_sp)(R3)
- MOVD R29, (g_sched+gobuf_bp)(R3)
-
-havem:
- // Now there's a valid m, and we're running on its m->g0.
- // Save current m->g0->sched.sp on stack and then set it to SP.
- // Save current sp in m->g0->sched.sp in preparation for
- // switch back to m->curg stack.
- // NOTE: unwindm knows that the saved g->sched.sp is at 16(RSP) aka savedsp-16(SP).
- // Beware that the frame size is actually 32+16.
- MOVD m_g0(R8), R3
- MOVD (g_sched+gobuf_sp)(R3), R4
- MOVD R4, savedsp-16(SP)
- MOVD RSP, R0
- MOVD R0, (g_sched+gobuf_sp)(R3)
-
- // Switch to m->curg stack and call runtime.cgocallbackg.
- // Because we are taking over the execution of m->curg
- // but *not* resuming what had been running, we need to
- // save that information (m->curg->sched) so we can restore it.
- // We can restore m->curg->sched.sp easily, because calling
- // runtime.cgocallbackg leaves SP unchanged upon return.
- // To save m->curg->sched.pc, we push it onto the curg stack and
- // open a frame the same size as cgocallback's g0 frame.
- // Once we switch to the curg stack, the pushed PC will appear
- // to be the return PC of cgocallback, so that the traceback
- // will seamlessly trace back into the earlier calls.
- MOVD m_curg(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
- MOVD (g_sched+gobuf_pc)(g), R5
- MOVD R5, -48(R4)
- MOVD (g_sched+gobuf_bp)(g), R5
- MOVD R5, -56(R4)
- // Gather our arguments into registers.
- MOVD fn+0(FP), R1
- MOVD frame+8(FP), R2
- MOVD ctxt+16(FP), R3
- MOVD $-48(R4), R0 // maintain 16-byte SP alignment
- MOVD R0, RSP // switch stack
- MOVD R1, 8(RSP)
- MOVD R2, 16(RSP)
- MOVD R3, 24(RSP)
- MOVD $runtime·cgocallbackg(SB), R0
- CALL (R0) // indirect call to bypass nosplit check. We're on a different stack now.
-
- // Restore g->sched (== m->curg->sched) from saved values.
- MOVD 0(RSP), R5
- MOVD R5, (g_sched+gobuf_pc)(g)
- MOVD RSP, R4
- ADD $48, R4, R4
- MOVD R4, (g_sched+gobuf_sp)(g)
-
- // Switch back to m->g0's stack and restore m->g0->sched.sp.
- // (Unlike m->curg, the g0 goroutine never uses sched.pc,
- // so we do not have to restore it.)
- MOVD g_m(g), R8
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R0
- MOVD R0, RSP
- MOVD savedsp-16(SP), R4
- MOVD R4, (g_sched+gobuf_sp)(g)
-
- // If the m on entry was nil, we called needm above to borrow an m,
- // 1. for the duration of the call on non-pthread platforms,
- // 2. or the duration of the C thread alive on pthread platforms.
- // If the m on entry wasn't nil,
- // 1. the thread might be a Go thread,
- // 2. or it wasn't the first call from a C thread on pthread platforms,
- // since then we skip dropm to reuse the m in the first call.
- MOVD savedm-8(SP), R6
- CBNZ R6, droppedm
-
- // Skip dropm to reuse it in the next call, when a pthread key has been created.
- MOVD _cgo_pthread_key_created(SB), R6
- // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
- CBZ R6, dropm
- MOVD (R6), R6
- CBNZ R6, droppedm
-
-dropm:
- MOVD $runtime·dropm(SB), R0
- BL (R0)
-droppedm:
-
- // Done!
- RET
-
-// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
-// Must obey the gcc calling convention.
-TEXT _cgo_topofstack(SB),NOSPLIT,$24
- // g (R28) and REGTMP (R27) might be clobbered by load_g. They
- // are callee-save in the gcc calling convention, so save them.
- MOVD R27, savedR27-8(SP)
- MOVD g, saveG-16(SP)
-
- BL runtime·load_g(SB)
- MOVD g_m(g), R0
- MOVD m_curg(R0), R0
- MOVD (g_stack+stack_hi)(R0), R0
-
- MOVD saveG-16(SP), g
- MOVD savedR28-8(SP), R27
- RET
-
-// void setg(G*); set g. for use by needm.
-TEXT runtime·setg(SB), NOSPLIT, $0-8
- MOVD gg+0(FP), g
- // This only happens if iscgo, so jump straight to save_g
- BL runtime·save_g(SB)
- RET
-
-// void setg_gcc(G*); set g called from gcc
-TEXT setg_gcc<>(SB),NOSPLIT,$8
- MOVD R0, g
- MOVD R27, savedR27-8(SP)
- BL runtime·save_g(SB)
- MOVD savedR27-8(SP), R27
- RET
-
-TEXT runtime·emptyfunc(SB),0,$0-0
- RET
-
-TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
- MOVD ZR, R0
- MOVD (R0), R0
- UNDEF
-
-TEXT runtime·return0(SB), NOSPLIT, $0
- MOVW $0, R0
- RET
-
-// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
- MOVD R0, R0 // NOP
- BL runtime·goexit1(SB) // does not return
-
-// This is called from .init_array and follows the platform, not Go, ABI.
-TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
- SUB $0x10, RSP
- MOVD R27, 8(RSP) // The access to global variables below implicitly uses R27, which is callee-save
- MOVD runtime·lastmoduledatap(SB), R1
- MOVD R0, moduledata_next(R1)
- MOVD R0, runtime·lastmoduledatap(SB)
- MOVD 8(RSP), R27
- ADD $0x10, RSP
- RET
-
-TEXT ·checkASM(SB),NOSPLIT,$0-1
- MOVW $1, R3
- MOVB R3, ret+0(FP)
- RET
-
-// gcWriteBarrier informs the GC about heap pointer writes.
-//
-// gcWriteBarrier does NOT follow the Go ABI. It accepts the
-// number of bytes of buffer needed in R25, and returns a pointer
-// to the buffer space in R25.
-// It clobbers condition codes.
-// It does not clobber any general-purpose registers except R27,
-// but may clobber others (e.g., floating point registers)
-// The act of CALLing gcWriteBarrier will clobber R30 (LR).
-TEXT gcWriteBarrier<>(SB),NOSPLIT,$200
- // Save the registers clobbered by the fast path.
- STP (R0, R1), 184(RSP)
-retry:
- MOVD g_m(g), R0
- MOVD m_p(R0), R0
- MOVD (p_wbBuf+wbBuf_next)(R0), R1
- MOVD (p_wbBuf+wbBuf_end)(R0), R27
- // Increment wbBuf.next position.
- ADD R25, R1
- // Is the buffer full?
- CMP R27, R1
- BHI flush
- // Commit to the larger buffer.
- MOVD R1, (p_wbBuf+wbBuf_next)(R0)
- // Make return value (the original next position)
- SUB R25, R1, R25
- // Restore registers.
- LDP 184(RSP), (R0, R1)
- RET
-
-flush:
- // Save all general purpose registers since these could be
- // clobbered by wbBufFlush and were not saved by the caller.
- // R0 and R1 already saved
- STP (R2, R3), 1*8(RSP)
- STP (R4, R5), 3*8(RSP)
- STP (R6, R7), 5*8(RSP)
- STP (R8, R9), 7*8(RSP)
- STP (R10, R11), 9*8(RSP)
- STP (R12, R13), 11*8(RSP)
- STP (R14, R15), 13*8(RSP)
- // R16, R17 may be clobbered by linker trampoline
- // R18 is unused.
- STP (R19, R20), 15*8(RSP)
- STP (R21, R22), 17*8(RSP)
- STP (R23, R24), 19*8(RSP)
- STP (R25, R26), 21*8(RSP)
- // R27 is temp register.
- // R28 is g.
- // R29 is frame pointer (unused).
- // R30 is LR, which was saved by the prologue.
- // R31 is SP.
-
- CALL runtime·wbBufFlush(SB)
- LDP 1*8(RSP), (R2, R3)
- LDP 3*8(RSP), (R4, R5)
- LDP 5*8(RSP), (R6, R7)
- LDP 7*8(RSP), (R8, R9)
- LDP 9*8(RSP), (R10, R11)
- LDP 11*8(RSP), (R12, R13)
- LDP 13*8(RSP), (R14, R15)
- LDP 15*8(RSP), (R19, R20)
- LDP 17*8(RSP), (R21, R22)
- LDP 19*8(RSP), (R23, R24)
- LDP 21*8(RSP), (R25, R26)
- JMP retry
-
-TEXT runtime·gcWriteBarrier1(SB),NOSPLIT,$0
- MOVD $8, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier2(SB),NOSPLIT,$0
- MOVD $16, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier3(SB),NOSPLIT,$0
- MOVD $24, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier4(SB),NOSPLIT,$0
- MOVD $32, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier5(SB),NOSPLIT,$0
- MOVD $40, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier6(SB),NOSPLIT,$0
- MOVD $48, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier7(SB),NOSPLIT,$0
- MOVD $56, R25
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier8(SB),NOSPLIT,$0
- MOVD $64, R25
- JMP gcWriteBarrier<>(SB)
-
-DATA debugCallFrameTooLarge<>+0x00(SB)/20, $"call frame too large"
-GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below
-
-// debugCallV2 is the entry point for debugger-injected function
-// calls on running goroutines. It informs the runtime that a
-// debug call has been injected and creates a call frame for the
-// debugger to fill in.
-//
-// To inject a function call, a debugger should:
-// 1. Check that the goroutine is in state _Grunning and that
-// there are at least 288 bytes free on the stack.
-// 2. Set SP as SP-16.
-// 3. Store the current LR in (SP) (using the SP after step 2).
-// 4. Store the current PC in the LR register.
-// 5. Write the desired argument frame size at SP-16
-// 6. Save all machine registers (including flags and fpsimd registers)
-// so they can be restored later by the debugger.
-// 7. Set the PC to debugCallV2 and resume execution.
-//
-// If the goroutine is in state _Grunnable, then it's not generally
-// safe to inject a call because it may return out via other runtime
-// operations. Instead, the debugger should unwind the stack to find
-// the return to non-runtime code, add a temporary breakpoint there,
-// and inject the call once that breakpoint is hit.
-//
-// If the goroutine is in any other state, it's not safe to inject a call.
-//
-// This function communicates back to the debugger by setting R20 and
-// invoking BRK to raise a breakpoint signal. Note that the signal PC of
-// the signal triggered by the BRK instruction is the PC where the signal
-// is trapped, not the next PC, so to resume execution, the debugger needs
-// to set the signal PC to PC+4. See the comments in the implementation for
-// the protocol the debugger is expected to follow. InjectDebugCall in the
-// runtime tests demonstrates this protocol.
-//
-// The debugger must ensure that any pointers passed to the function
-// obey escape analysis requirements. Specifically, it must not pass
-// a stack pointer to an escaping argument. debugCallV2 cannot check
-// this invariant.
-//
-// This is ABIInternal because Go code injects its PC directly into new
-// goroutine stacks.
-TEXT runtime·debugCallV2(SB),NOSPLIT|NOFRAME,$0-0
- STP (R29, R30), -280(RSP)
- SUB $272, RSP, RSP
- SUB $8, RSP, R29
- // Save all registers that may contain pointers so they can be
- // conservatively scanned.
- //
- // We can't do anything that might clobber any of these
- // registers before this.
- STP (R27, g), (30*8)(RSP)
- STP (R25, R26), (28*8)(RSP)
- STP (R23, R24), (26*8)(RSP)
- STP (R21, R22), (24*8)(RSP)
- STP (R19, R20), (22*8)(RSP)
- STP (R16, R17), (20*8)(RSP)
- STP (R14, R15), (18*8)(RSP)
- STP (R12, R13), (16*8)(RSP)
- STP (R10, R11), (14*8)(RSP)
- STP (R8, R9), (12*8)(RSP)
- STP (R6, R7), (10*8)(RSP)
- STP (R4, R5), (8*8)(RSP)
- STP (R2, R3), (6*8)(RSP)
- STP (R0, R1), (4*8)(RSP)
-
- // Perform a safe-point check.
- MOVD R30, 8(RSP) // Caller's PC
- CALL runtime·debugCallCheck(SB)
- MOVD 16(RSP), R0
- CBZ R0, good
-
- // The safety check failed. Put the reason string at the top
- // of the stack.
- MOVD R0, 8(RSP)
- MOVD 24(RSP), R0
- MOVD R0, 16(RSP)
-
- // Set R20 to 8 and invoke BRK. The debugger should get the
- // reason a call can't be injected from SP+8 and resume execution.
- MOVD $8, R20
- BREAK
- JMP restore
-
-good:
- // Registers are saved and it's safe to make a call.
- // Open up a call frame, moving the stack if necessary.
- //
- // Once the frame is allocated, this will set R20 to 0 and
- // invoke BRK. The debugger should write the argument
- // frame for the call at SP+8, set up argument registers,
- // set the LR as the signal PC + 4, set the PC to the function
- // to call, set R26 to point to the closure (if a closure call),
- // and resume execution.
- //
- // If the function returns, this will set R20 to 1 and invoke
- // BRK. The debugger can then inspect any return value saved
- // on the stack at SP+8 and in registers. To resume execution,
- // the debugger should restore the LR from (SP).
- //
- // If the function panics, this will set R20 to 2 and invoke BRK.
- // The interface{} value of the panic will be at SP+8. The debugger
- // can inspect the panic value and resume execution again.
-#define DEBUG_CALL_DISPATCH(NAME,MAXSIZE) \
- CMP $MAXSIZE, R0; \
- BGT 5(PC); \
- MOVD $NAME(SB), R0; \
- MOVD R0, 8(RSP); \
- CALL runtime·debugCallWrap(SB); \
- JMP restore
-
- MOVD 256(RSP), R0 // the argument frame size
- DEBUG_CALL_DISPATCH(debugCall32<>, 32)
- DEBUG_CALL_DISPATCH(debugCall64<>, 64)
- DEBUG_CALL_DISPATCH(debugCall128<>, 128)
- DEBUG_CALL_DISPATCH(debugCall256<>, 256)
- DEBUG_CALL_DISPATCH(debugCall512<>, 512)
- DEBUG_CALL_DISPATCH(debugCall1024<>, 1024)
- DEBUG_CALL_DISPATCH(debugCall2048<>, 2048)
- DEBUG_CALL_DISPATCH(debugCall4096<>, 4096)
- DEBUG_CALL_DISPATCH(debugCall8192<>, 8192)
- DEBUG_CALL_DISPATCH(debugCall16384<>, 16384)
- DEBUG_CALL_DISPATCH(debugCall32768<>, 32768)
- DEBUG_CALL_DISPATCH(debugCall65536<>, 65536)
- // The frame size is too large. Report the error.
- MOVD $debugCallFrameTooLarge<>(SB), R0
- MOVD R0, 8(RSP)
- MOVD $20, R0
- MOVD R0, 16(RSP) // length of debugCallFrameTooLarge string
- MOVD $8, R20
- BREAK
- JMP restore
-
-restore:
- // Calls and failures resume here.
- //
- // Set R20 to 16 and invoke BRK. The debugger should restore
- // all registers except for PC and RSP and resume execution.
- MOVD $16, R20
- BREAK
- // We must not modify flags after this point.
-
- // Restore pointer-containing registers, which may have been
- // modified from the debugger's copy by stack copying.
- LDP (30*8)(RSP), (R27, g)
- LDP (28*8)(RSP), (R25, R26)
- LDP (26*8)(RSP), (R23, R24)
- LDP (24*8)(RSP), (R21, R22)
- LDP (22*8)(RSP), (R19, R20)
- LDP (20*8)(RSP), (R16, R17)
- LDP (18*8)(RSP), (R14, R15)
- LDP (16*8)(RSP), (R12, R13)
- LDP (14*8)(RSP), (R10, R11)
- LDP (12*8)(RSP), (R8, R9)
- LDP (10*8)(RSP), (R6, R7)
- LDP (8*8)(RSP), (R4, R5)
- LDP (6*8)(RSP), (R2, R3)
- LDP (4*8)(RSP), (R0, R1)
-
- LDP -8(RSP), (R29, R27)
- ADD $288, RSP, RSP // Add 16 more bytes, see saveSigContext
- MOVD -16(RSP), R30 // restore old lr
- JMP (R27)
-
-// runtime.debugCallCheck assumes that functions defined with the
-// DEBUG_CALL_FN macro are safe points to inject calls.
-#define DEBUG_CALL_FN(NAME,MAXSIZE) \
-TEXT NAME(SB),WRAPPER,$MAXSIZE-0; \
- NO_LOCAL_POINTERS; \
- MOVD $0, R20; \
- BREAK; \
- MOVD $1, R20; \
- BREAK; \
- RET
-DEBUG_CALL_FN(debugCall32<>, 32)
-DEBUG_CALL_FN(debugCall64<>, 64)
-DEBUG_CALL_FN(debugCall128<>, 128)
-DEBUG_CALL_FN(debugCall256<>, 256)
-DEBUG_CALL_FN(debugCall512<>, 512)
-DEBUG_CALL_FN(debugCall1024<>, 1024)
-DEBUG_CALL_FN(debugCall2048<>, 2048)
-DEBUG_CALL_FN(debugCall4096<>, 4096)
-DEBUG_CALL_FN(debugCall8192<>, 8192)
-DEBUG_CALL_FN(debugCall16384<>, 16384)
-DEBUG_CALL_FN(debugCall32768<>, 32768)
-DEBUG_CALL_FN(debugCall65536<>, 65536)
-
-// func debugCallPanicked(val interface{})
-TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16
- // Copy the panic value to the top of stack at SP+8.
- MOVD val_type+0(FP), R0
- MOVD R0, 8(RSP)
- MOVD val_data+8(FP), R0
- MOVD R0, 16(RSP)
- MOVD $2, R20
- BREAK
- RET
-
-// Note: these functions use a special calling convention to save generated code space.
-// Arguments are passed in registers, but the space for those arguments are allocated
-// in the caller's stack frame. These stubs write the args into that stack space and
-// then tail call to the corresponding runtime handler.
-// The tail call makes these stubs disappear in backtraces.
-//
-// Defined as ABIInternal since the compiler generates ABIInternal
-// calls to it directly and it does not use the stack-based Go ABI.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
- JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
- JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
- MOVD R1, R0
- MOVD R2, R1
- JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
- MOVD R1, R0
- MOVD R2, R1
- JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
- MOVD R1, R0
- MOVD R2, R1
- JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
- MOVD R1, R0
- MOVD R2, R1
- JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
- MOVD R2, R0
- MOVD R3, R1
- JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
- MOVD R2, R0
- MOVD R3, R1
- JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
- MOVD R2, R0
- MOVD R3, R1
- JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
- MOVD R2, R0
- MOVD R3, R1
- JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
- MOVD R1, R0
- MOVD R2, R1
- JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
- MOVD R1, R0
- MOVD R2, R1
- JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSlice3CU(SB)
-TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
- MOVD R2, R0
- MOVD R3, R1
- JMP runtime·goPanicSliceConvert(SB)
-
-TEXT ·getfp(SB),NOSPLIT|NOFRAME,$0
- MOVD R29, R0
- RET
diff --git a/contrib/go/_std_1.22/src/runtime/asm_loong64.s b/contrib/go/_std_1.22/src/runtime/asm_loong64.s
deleted file mode 100644
index 586bd23ed478..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asm_loong64.s
+++ /dev/null
@@ -1,1032 +0,0 @@
-// Copyright 2022 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.
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "funcdata.h"
-#include "textflag.h"
-
-#define REGCTXT R29
-
-TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
- // R3 = stack; R4 = argc; R5 = argv
-
- ADDV $-24, R3
- MOVW R4, 8(R3) // argc
- MOVV R5, 16(R3) // argv
-
- // create istack out of the given (operating system) stack.
- // _cgo_init may update stackguard.
- MOVV $runtime·g0(SB), g
- MOVV $(-64*1024), R30
- ADDV R30, R3, R19
- MOVV R19, g_stackguard0(g)
- MOVV R19, g_stackguard1(g)
- MOVV R19, (g_stack+stack_lo)(g)
- MOVV R3, (g_stack+stack_hi)(g)
-
- // if there is a _cgo_init, call it using the gcc ABI.
- MOVV _cgo_init(SB), R25
- BEQ R25, nocgo
-
- MOVV R0, R7 // arg 3: not used
- MOVV R0, R6 // arg 2: not used
- MOVV $setg_gcc<>(SB), R5 // arg 1: setg
- MOVV g, R4 // arg 0: G
- JAL (R25)
-
-nocgo:
- // update stackguard after _cgo_init
- MOVV (g_stack+stack_lo)(g), R19
- ADDV $const_stackGuard, R19
- MOVV R19, g_stackguard0(g)
- MOVV R19, g_stackguard1(g)
-
- // set the per-goroutine and per-mach "registers"
- MOVV $runtime·m0(SB), R19
-
- // save m->g0 = g0
- MOVV g, m_g0(R19)
- // save m0 to g0->m
- MOVV R19, g_m(g)
-
- JAL runtime·check(SB)
-
- // args are already prepared
- JAL runtime·args(SB)
- JAL runtime·osinit(SB)
- JAL runtime·schedinit(SB)
-
- // create a new goroutine to start program
- MOVV $runtime·mainPC(SB), R19 // entry
- ADDV $-16, R3
- MOVV R19, 8(R3)
- MOVV R0, 0(R3)
- JAL runtime·newproc(SB)
- ADDV $16, R3
-
- // start this M
- JAL runtime·mstart(SB)
-
- MOVV R0, 1(R0)
- RET
-
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
-GLOBL runtime·mainPC(SB),RODATA,$8
-
-TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
- BREAK
- RET
-
-TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
- RET
-
-TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
- JAL runtime·mstart0(SB)
- RET // not reached
-
-// func cputicks() int64
-TEXT runtime·cputicks(SB),NOSPLIT,$0-8
- RDTIMED R0, R4
- MOVV R4, ret+0(FP)
- RET
-
-/*
- * go-routine
- */
-
-// void gogo(Gobuf*)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
- MOVV buf+0(FP), R4
- MOVV gobuf_g(R4), R5
- MOVV 0(R5), R0 // make sure g != nil
- JMP gogo<>(SB)
-
-TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
- MOVV R5, g
- JAL runtime·save_g(SB)
-
- MOVV gobuf_sp(R4), R3
- MOVV gobuf_lr(R4), R1
- MOVV gobuf_ret(R4), R19
- MOVV gobuf_ctxt(R4), REGCTXT
- MOVV R0, gobuf_sp(R4)
- MOVV R0, gobuf_ret(R4)
- MOVV R0, gobuf_lr(R4)
- MOVV R0, gobuf_ctxt(R4)
- MOVV gobuf_pc(R4), R6
- JMP (R6)
-
-// void mcall(fn func(*g))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return. It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R4, REGCTXT
-#else
- MOVV fn+0(FP), REGCTXT
-#endif
-
- // Save caller state in g->sched
- MOVV R3, (g_sched+gobuf_sp)(g)
- MOVV R1, (g_sched+gobuf_pc)(g)
- MOVV R0, (g_sched+gobuf_lr)(g)
-
- // Switch to m->g0 & its stack, call fn.
- MOVV g, R4 // arg = g
- MOVV g_m(g), R20
- MOVV m_g0(R20), g
- JAL runtime·save_g(SB)
- BNE g, R4, 2(PC)
- JMP runtime·badmcall(SB)
- MOVV 0(REGCTXT), R20 // code pointer
- MOVV (g_sched+gobuf_sp)(g), R3 // sp = m->g0->sched.sp
- ADDV $-16, R3
- MOVV R4, 8(R3)
- MOVV R0, 0(R3)
- JAL (R20)
- JMP runtime·badmcall2(SB)
-
-// systemstack_switch is a dummy routine that systemstack leaves at the bottom
-// of the G stack. We need to distinguish the routine that
-// lives at the bottom of the G stack from the one that lives
-// at the top of the system stack because the one at the top of
-// the system stack terminates the stack walk (see topofstack()).
-TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
- UNDEF
- JAL (R1) // make sure this function is not leaf
- RET
-
-// func systemstack(fn func())
-TEXT runtime·systemstack(SB), NOSPLIT, $0-8
- MOVV fn+0(FP), R19 // R19 = fn
- MOVV R19, REGCTXT // context
- MOVV g_m(g), R4 // R4 = m
-
- MOVV m_gsignal(R4), R5 // R5 = gsignal
- BEQ g, R5, noswitch
-
- MOVV m_g0(R4), R5 // R5 = g0
- BEQ g, R5, noswitch
-
- MOVV m_curg(R4), R6
- BEQ g, R6, switch
-
- // Bad: g is not gsignal, not g0, not curg. What is it?
- // Hide call from linker nosplit analysis.
- MOVV $runtime·badsystemstack(SB), R7
- JAL (R7)
- JAL runtime·abort(SB)
-
-switch:
- // save our state in g->sched. Pretend to
- // be systemstack_switch if the G stack is scanned.
- JAL gosave_systemstack_switch<>(SB)
-
- // switch to g0
- MOVV R5, g
- JAL runtime·save_g(SB)
- MOVV (g_sched+gobuf_sp)(g), R19
- MOVV R19, R3
-
- // call target function
- MOVV 0(REGCTXT), R6 // code pointer
- JAL (R6)
-
- // switch back to g
- MOVV g_m(g), R4
- MOVV m_curg(R4), g
- JAL runtime·save_g(SB)
- MOVV (g_sched+gobuf_sp)(g), R3
- MOVV R0, (g_sched+gobuf_sp)(g)
- RET
-
-noswitch:
- // already on m stack, just call directly
- // Using a tail call here cleans up tracebacks since we won't stop
- // at an intermediate systemstack.
- MOVV 0(REGCTXT), R4 // code pointer
- MOVV 0(R3), R1 // restore LR
- ADDV $8, R3
- JMP (R4)
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-// Caller has already loaded:
-// loong64: R31: LR
-//
-// The traceback routines see morestack on a g0 as being
-// the top of a stack (for example, morestack calling newstack
-// calling the scheduler calling newm calling gc), so we must
-// record an argument size. For that purpose, it has no arguments.
-TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
- // Cannot grow scheduler stack (m->g0).
- MOVV g_m(g), R7
- MOVV m_g0(R7), R8
- BNE g, R8, 3(PC)
- JAL runtime·badmorestackg0(SB)
- JAL runtime·abort(SB)
-
- // Cannot grow signal stack (m->gsignal).
- MOVV m_gsignal(R7), R8
- BNE g, R8, 3(PC)
- JAL runtime·badmorestackgsignal(SB)
- JAL runtime·abort(SB)
-
- // Called from f.
- // Set g->sched to context in f.
- MOVV R3, (g_sched+gobuf_sp)(g)
- MOVV R1, (g_sched+gobuf_pc)(g)
- MOVV R31, (g_sched+gobuf_lr)(g)
- MOVV REGCTXT, (g_sched+gobuf_ctxt)(g)
-
- // Called from f.
- // Set m->morebuf to f's caller.
- MOVV R31, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
- MOVV R3, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
- MOVV g, (m_morebuf+gobuf_g)(R7)
-
- // Call newstack on m->g0's stack.
- MOVV m_g0(R7), g
- JAL runtime·save_g(SB)
- MOVV (g_sched+gobuf_sp)(g), R3
- // Create a stack frame on g0 to call newstack.
- MOVV R0, -8(R3) // Zero saved LR in frame
- ADDV $-8, R3
- JAL runtime·newstack(SB)
-
- // Not reached, but make sure the return PC from the call to newstack
- // is still in this function, and not the beginning of the next.
- UNDEF
-
-TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
- // Force SPWRITE. This function doesn't actually write SP,
- // but it is called with a special calling convention where
- // the caller doesn't save LR on stack but passes it as a
- // register (R5), and the unwinder currently doesn't understand.
- // Make it SPWRITE to stop unwinding. (See issue 54332)
- MOVV R3, R3
-
- MOVV R0, REGCTXT
- JMP runtime·morestack(SB)
-
-// reflectcall: call a function with the given argument list
-// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
-// we don't have variable-sized frames, so we use a small number
-// of constant-sized-frame functions to encode a few bits of size in the pc.
-// Caution: ugly multiline assembly macros in your future!
-
-#define DISPATCH(NAME,MAXSIZE) \
- MOVV $MAXSIZE, R30; \
- SGTU R19, R30, R30; \
- BNE R30, 3(PC); \
- MOVV $NAME(SB), R4; \
- JMP (R4)
-// Note: can't just "BR NAME(SB)" - bad inlining results.
-
-TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
- MOVWU frameSize+32(FP), R19
- DISPATCH(runtime·call32, 32)
- DISPATCH(runtime·call64, 64)
- DISPATCH(runtime·call128, 128)
- DISPATCH(runtime·call256, 256)
- DISPATCH(runtime·call512, 512)
- DISPATCH(runtime·call1024, 1024)
- DISPATCH(runtime·call2048, 2048)
- DISPATCH(runtime·call4096, 4096)
- DISPATCH(runtime·call8192, 8192)
- DISPATCH(runtime·call16384, 16384)
- DISPATCH(runtime·call32768, 32768)
- DISPATCH(runtime·call65536, 65536)
- DISPATCH(runtime·call131072, 131072)
- DISPATCH(runtime·call262144, 262144)
- DISPATCH(runtime·call524288, 524288)
- DISPATCH(runtime·call1048576, 1048576)
- DISPATCH(runtime·call2097152, 2097152)
- DISPATCH(runtime·call4194304, 4194304)
- DISPATCH(runtime·call8388608, 8388608)
- DISPATCH(runtime·call16777216, 16777216)
- DISPATCH(runtime·call33554432, 33554432)
- DISPATCH(runtime·call67108864, 67108864)
- DISPATCH(runtime·call134217728, 134217728)
- DISPATCH(runtime·call268435456, 268435456)
- DISPATCH(runtime·call536870912, 536870912)
- DISPATCH(runtime·call1073741824, 1073741824)
- MOVV $runtime·badreflectcall(SB), R4
- JMP (R4)
-
-#define CALLFN(NAME,MAXSIZE) \
-TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
- NO_LOCAL_POINTERS; \
- /* copy arguments to stack */ \
- MOVV arg+16(FP), R4; \
- MOVWU argsize+24(FP), R5; \
- MOVV R3, R12; \
- ADDV $8, R12; \
- ADDV R12, R5; \
- BEQ R12, R5, 6(PC); \
- MOVBU (R4), R6; \
- ADDV $1, R4; \
- MOVBU R6, (R12); \
- ADDV $1, R12; \
- JMP -5(PC); \
- /* set up argument registers */ \
- MOVV regArgs+40(FP), R25; \
- JAL ·unspillArgs(SB); \
- /* call function */ \
- MOVV f+8(FP), REGCTXT; \
- MOVV (REGCTXT), R25; \
- PCDATA $PCDATA_StackMapIndex, $0; \
- JAL (R25); \
- /* copy return values back */ \
- MOVV regArgs+40(FP), R25; \
- JAL ·spillArgs(SB); \
- MOVV argtype+0(FP), R7; \
- MOVV arg+16(FP), R4; \
- MOVWU n+24(FP), R5; \
- MOVWU retoffset+28(FP), R6; \
- ADDV $8, R3, R12; \
- ADDV R6, R12; \
- ADDV R6, R4; \
- SUBVU R6, R5; \
- JAL callRet<>(SB); \
- RET
-
-// callRet copies return values back at the end of call*. This is a
-// separate function so it can allocate stack space for the arguments
-// to reflectcallmove. It does not follow the Go ABI; it expects its
-// arguments in registers.
-TEXT callRet<>(SB), NOSPLIT, $40-0
- NO_LOCAL_POINTERS
- MOVV R7, 8(R3)
- MOVV R4, 16(R3)
- MOVV R12, 24(R3)
- MOVV R5, 32(R3)
- MOVV R25, 40(R3)
- JAL runtime·reflectcallmove(SB)
- RET
-
-CALLFN(·call16, 16)
-CALLFN(·call32, 32)
-CALLFN(·call64, 64)
-CALLFN(·call128, 128)
-CALLFN(·call256, 256)
-CALLFN(·call512, 512)
-CALLFN(·call1024, 1024)
-CALLFN(·call2048, 2048)
-CALLFN(·call4096, 4096)
-CALLFN(·call8192, 8192)
-CALLFN(·call16384, 16384)
-CALLFN(·call32768, 32768)
-CALLFN(·call65536, 65536)
-CALLFN(·call131072, 131072)
-CALLFN(·call262144, 262144)
-CALLFN(·call524288, 524288)
-CALLFN(·call1048576, 1048576)
-CALLFN(·call2097152, 2097152)
-CALLFN(·call4194304, 4194304)
-CALLFN(·call8388608, 8388608)
-CALLFN(·call16777216, 16777216)
-CALLFN(·call33554432, 33554432)
-CALLFN(·call67108864, 67108864)
-CALLFN(·call134217728, 134217728)
-CALLFN(·call268435456, 268435456)
-CALLFN(·call536870912, 536870912)
-CALLFN(·call1073741824, 1073741824)
-
-TEXT runtime·procyield(SB),NOSPLIT,$0-0
- RET
-
-// Save state of caller into g->sched.
-// but using fake PC from systemstack_switch.
-// Must only be called from functions with no locals ($0)
-// or else unwinding from systemstack_switch is incorrect.
-// Smashes R19.
-TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
- MOVV $runtime·systemstack_switch(SB), R19
- ADDV $8, R19
- MOVV R19, (g_sched+gobuf_pc)(g)
- MOVV R3, (g_sched+gobuf_sp)(g)
- MOVV R0, (g_sched+gobuf_lr)(g)
- MOVV R0, (g_sched+gobuf_ret)(g)
- // Assert ctxt is zero. See func save.
- MOVV (g_sched+gobuf_ctxt)(g), R19
- BEQ R19, 2(PC)
- JAL runtime·abort(SB)
- RET
-
-// func asmcgocall(fn, arg unsafe.Pointer) int32
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.go for more details.
-TEXT ·asmcgocall(SB),NOSPLIT,$0-20
- MOVV fn+0(FP), R25
- MOVV arg+8(FP), R4
-
- MOVV R3, R12 // save original stack pointer
- MOVV g, R13
-
- // Figure out if we need to switch to m->g0 stack.
- // We get called to create new OS threads too, and those
- // come in on the m->g0 stack already.
- MOVV g_m(g), R5
- MOVV m_gsignal(R5), R6
- BEQ R6, g, g0
- MOVV m_g0(R5), R6
- BEQ R6, g, g0
-
- JAL gosave_systemstack_switch<>(SB)
- MOVV R6, g
- JAL runtime·save_g(SB)
- MOVV (g_sched+gobuf_sp)(g), R3
-
- // Now on a scheduling stack (a pthread-created stack).
-g0:
- // Save room for two of our pointers.
- ADDV $-16, R3
- MOVV R13, 0(R3) // save old g on stack
- MOVV (g_stack+stack_hi)(R13), R13
- SUBVU R12, R13
- MOVV R13, 8(R3) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
- JAL (R25)
-
- // Restore g, stack pointer. R4 is return value.
- MOVV 0(R3), g
- JAL runtime·save_g(SB)
- MOVV (g_stack+stack_hi)(g), R5
- MOVV 8(R3), R6
- SUBVU R6, R5
- MOVV R5, R3
-
- MOVW R4, ret+16(FP)
- RET
-
-// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
-// See cgocall.go for more details.
-TEXT ·cgocallback(SB),NOSPLIT,$24-24
- NO_LOCAL_POINTERS
-
- // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
- // It is used to dropm while thread is exiting.
- MOVV fn+0(FP), R5
- BNE R5, loadg
- // Restore the g from frame.
- MOVV frame+8(FP), g
- JMP dropm
-
-loadg:
- // Load m and g from thread-local storage.
- MOVB runtime·iscgo(SB), R19
- BEQ R19, nocgo
- JAL runtime·load_g(SB)
-nocgo:
-
- // If g is nil, Go did not create the current thread,
- // or if this thread never called into Go on pthread platforms.
- // Call needm to obtain one for temporary use.
- // In this case, we're running on the thread stack, so there's
- // lots of space, but the linker doesn't know. Hide the call from
- // the linker analysis by using an indirect call.
- BEQ g, needm
-
- MOVV g_m(g), R12
- MOVV R12, savedm-8(SP)
- JMP havem
-
-needm:
- MOVV g, savedm-8(SP) // g is zero, so is m.
- MOVV $runtime·needAndBindM(SB), R4
- JAL (R4)
-
- // Set m->sched.sp = SP, so that if a panic happens
- // during the function we are about to execute, it will
- // have a valid SP to run on the g0 stack.
- // The next few lines (after the havem label)
- // will save this SP onto the stack and then write
- // the same SP back to m->sched.sp. That seems redundant,
- // but if an unrecovered panic happens, unwindm will
- // restore the g->sched.sp from the stack location
- // and then systemstack will try to use it. If we don't set it here,
- // that restored SP will be uninitialized (typically 0) and
- // will not be usable.
- MOVV g_m(g), R12
- MOVV m_g0(R12), R19
- MOVV R3, (g_sched+gobuf_sp)(R19)
-
-havem:
- // Now there's a valid m, and we're running on its m->g0.
- // Save current m->g0->sched.sp on stack and then set it to SP.
- // Save current sp in m->g0->sched.sp in preparation for
- // switch back to m->curg stack.
- // NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
- MOVV m_g0(R12), R19
- MOVV (g_sched+gobuf_sp)(R19), R13
- MOVV R13, savedsp-24(SP) // must match frame size
- MOVV R3, (g_sched+gobuf_sp)(R19)
-
- // Switch to m->curg stack and call runtime.cgocallbackg.
- // Because we are taking over the execution of m->curg
- // but *not* resuming what had been running, we need to
- // save that information (m->curg->sched) so we can restore it.
- // We can restore m->curg->sched.sp easily, because calling
- // runtime.cgocallbackg leaves SP unchanged upon return.
- // To save m->curg->sched.pc, we push it onto the stack.
- // This has the added benefit that it looks to the traceback
- // routine like cgocallbackg is going to return to that
- // PC (because the frame we allocate below has the same
- // size as cgocallback_gofunc's frame declared above)
- // so that the traceback will seamlessly trace back into
- // the earlier calls.
- MOVV m_curg(R12), g
- JAL runtime·save_g(SB)
- MOVV (g_sched+gobuf_sp)(g), R13 // prepare stack as R13
- MOVV (g_sched+gobuf_pc)(g), R4
- MOVV R4, -(24+8)(R13) // "saved LR"; must match frame size
- MOVV fn+0(FP), R5
- MOVV frame+8(FP), R6
- MOVV ctxt+16(FP), R7
- MOVV $-(24+8)(R13), R3
- MOVV R5, 8(R3)
- MOVV R6, 16(R3)
- MOVV R7, 24(R3)
- JAL runtime·cgocallbackg(SB)
-
- // Restore g->sched (== m->curg->sched) from saved values.
- MOVV 0(R3), R4
- MOVV R4, (g_sched+gobuf_pc)(g)
- MOVV $(24+8)(R3), R13 // must match frame size
- MOVV R13, (g_sched+gobuf_sp)(g)
-
- // Switch back to m->g0's stack and restore m->g0->sched.sp.
- // (Unlike m->curg, the g0 goroutine never uses sched.pc,
- // so we do not have to restore it.)
- MOVV g_m(g), R12
- MOVV m_g0(R12), g
- JAL runtime·save_g(SB)
- MOVV (g_sched+gobuf_sp)(g), R3
- MOVV savedsp-24(SP), R13 // must match frame size
- MOVV R13, (g_sched+gobuf_sp)(g)
-
- // If the m on entry was nil, we called needm above to borrow an m,
- // 1. for the duration of the call on non-pthread platforms,
- // 2. or the duration of the C thread alive on pthread platforms.
- // If the m on entry wasn't nil,
- // 1. the thread might be a Go thread,
- // 2. or it wasn't the first call from a C thread on pthread platforms,
- // since then we skip dropm to resue the m in the first call.
- MOVV savedm-8(SP), R12
- BNE R12, droppedm
-
- // Skip dropm to reuse it in the next call, when a pthread key has been created.
- MOVV _cgo_pthread_key_created(SB), R12
- // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
- BEQ R12, dropm
- MOVV (R12), R12
- BNE R12, droppedm
-
-dropm:
- MOVV $runtime·dropm(SB), R4
- JAL (R4)
-droppedm:
-
- // Done!
- RET
-
-// void setg(G*); set g. for use by needm.
-TEXT runtime·setg(SB), NOSPLIT, $0-8
- MOVV gg+0(FP), g
- // This only happens if iscgo, so jump straight to save_g
- JAL runtime·save_g(SB)
- RET
-
-// void setg_gcc(G*); set g called from gcc with g in R19
-TEXT setg_gcc<>(SB),NOSPLIT,$0-0
- MOVV R19, g
- JAL runtime·save_g(SB)
- RET
-
-TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
- MOVW (R0), R0
- UNDEF
-
-// AES hashing not implemented for loong64
-TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
- JMP runtime·memhashFallback(SB)
-TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·strhashFallback(SB)
-TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·memhash32Fallback(SB)
-TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·memhash64Fallback(SB)
-
-TEXT runtime·return0(SB), NOSPLIT, $0
- MOVW $0, R19
- RET
-
-// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
-// Must obey the gcc calling convention.
-TEXT _cgo_topofstack(SB),NOSPLIT,$16
- // g (R22) and REGTMP (R30) might be clobbered by load_g. They
- // are callee-save in the gcc calling convention, so save them.
- MOVV R30, savedREGTMP-16(SP)
- MOVV g, savedG-8(SP)
-
- JAL runtime·load_g(SB)
- MOVV g_m(g), R19
- MOVV m_curg(R19), R19
- MOVV (g_stack+stack_hi)(R19), R4 // return value in R4
-
- MOVV savedG-8(SP), g
- MOVV savedREGTMP-16(SP), R30
- RET
-
-// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
- NOOP
- JAL runtime·goexit1(SB) // does not return
- // traceback from goexit1 must hit code range of goexit
- NOOP
-
-// This is called from .init_array and follows the platform, not Go, ABI.
-TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
- ADDV $-0x10, R3
- MOVV R30, 8(R3) // The access to global variables below implicitly uses R30, which is callee-save
- MOVV runtime·lastmoduledatap(SB), R12
- MOVV R4, moduledata_next(R12)
- MOVV R4, runtime·lastmoduledatap(SB)
- MOVV 8(R3), R30
- ADDV $0x10, R3
- RET
-
-TEXT ·checkASM(SB),NOSPLIT,$0-1
- MOVW $1, R19
- MOVB R19, ret+0(FP)
- RET
-
-#ifdef GOEXPERIMENT_regabiargs
-// spillArgs stores return values from registers to a *internal/abi.RegArgs in R25.
-TEXT ·spillArgs(SB),NOSPLIT,$0-0
- MOVV R4, (0*8)(R25)
- MOVV R5, (1*8)(R25)
- MOVV R6, (2*8)(R25)
- MOVV R7, (3*8)(R25)
- MOVV R8, (4*8)(R25)
- MOVV R9, (5*8)(R25)
- MOVV R10, (6*8)(R25)
- MOVV R11, (7*8)(R25)
- MOVV R12, (8*8)(R25)
- MOVV R13, (9*8)(R25)
- MOVV R14, (10*8)(R25)
- MOVV R15, (11*8)(R25)
- MOVV R16, (12*8)(R25)
- MOVV R17, (13*8)(R25)
- MOVV R18, (14*8)(R25)
- MOVV R19, (15*8)(R25)
- MOVD F0, (16*8)(R25)
- MOVD F1, (17*8)(R25)
- MOVD F2, (18*8)(R25)
- MOVD F3, (19*8)(R25)
- MOVD F4, (20*8)(R25)
- MOVD F5, (21*8)(R25)
- MOVD F6, (22*8)(R25)
- MOVD F7, (23*8)(R25)
- MOVD F8, (24*8)(R25)
- MOVD F9, (25*8)(R25)
- MOVD F10, (26*8)(R25)
- MOVD F11, (27*8)(R25)
- MOVD F12, (28*8)(R25)
- MOVD F13, (29*8)(R25)
- MOVD F14, (30*8)(R25)
- MOVD F15, (31*8)(R25)
- RET
-
-// unspillArgs loads args into registers from a *internal/abi.RegArgs in R25.
-TEXT ·unspillArgs(SB),NOSPLIT,$0-0
- MOVV (0*8)(R25), R4
- MOVV (1*8)(R25), R5
- MOVV (2*8)(R25), R6
- MOVV (3*8)(R25), R7
- MOVV (4*8)(R25), R8
- MOVV (5*8)(R25), R9
- MOVV (6*8)(R25), R10
- MOVV (7*8)(R25), R11
- MOVV (8*8)(R25), R12
- MOVV (9*8)(R25), R13
- MOVV (10*8)(R25), R14
- MOVV (11*8)(R25), R15
- MOVV (12*8)(R25), R16
- MOVV (13*8)(R25), R17
- MOVV (14*8)(R25), R18
- MOVV (15*8)(R25), R19
- MOVD (16*8)(R25), F0
- MOVD (17*8)(R25), F1
- MOVD (18*8)(R25), F2
- MOVD (19*8)(R25), F3
- MOVD (20*8)(R25), F4
- MOVD (21*8)(R25), F5
- MOVD (22*8)(R25), F6
- MOVD (23*8)(R25), F7
- MOVD (24*8)(R25), F8
- MOVD (25*8)(R25), F9
- MOVD (26*8)(R25), F10
- MOVD (27*8)(R25), F11
- MOVD (28*8)(R25), F12
- MOVD (29*8)(R25), F13
- MOVD (30*8)(R25), F14
- MOVD (31*8)(R25), F15
- RET
-#else
-TEXT ·spillArgs(SB),NOSPLIT,$0-0
- RET
-
-TEXT ·unspillArgs(SB),NOSPLIT,$0-0
- RET
-#endif
-
-// gcWriteBarrier informs the GC about heap pointer writes.
-//
-// gcWriteBarrier does NOT follow the Go ABI. It accepts the
-// number of bytes of buffer needed in R29, and returns a pointer
-// to the buffer space in R29.
-// It clobbers R30 (the linker temp register).
-// The act of CALLing gcWriteBarrier will clobber R1 (LR).
-// It does not clobber any other general-purpose registers,
-// but may clobber others (e.g., floating point registers).
-TEXT gcWriteBarrier<>(SB),NOSPLIT,$216
- // Save the registers clobbered by the fast path.
- MOVV R19, 208(R3)
- MOVV R13, 216(R3)
-retry:
- MOVV g_m(g), R19
- MOVV m_p(R19), R19
- MOVV (p_wbBuf+wbBuf_next)(R19), R13
- MOVV (p_wbBuf+wbBuf_end)(R19), R30 // R30 is linker temp register
- // Increment wbBuf.next position.
- ADDV R29, R13
- // Is the buffer full?
- BLTU R30, R13, flush
- // Commit to the larger buffer.
- MOVV R13, (p_wbBuf+wbBuf_next)(R19)
- // Make return value (the original next position)
- SUBV R29, R13, R29
- // Restore registers.
- MOVV 208(R3), R19
- MOVV 216(R3), R13
- RET
-
-flush:
- // Save all general purpose registers since these could be
- // clobbered by wbBufFlush and were not saved by the caller.
- MOVV R27, 8(R3)
- MOVV R28, 16(R3)
- // R1 is LR, which was saved by the prologue.
- MOVV R2, 24(R3)
- // R3 is SP.
- MOVV R4, 32(R3)
- MOVV R5, 40(R3)
- MOVV R6, 48(R3)
- MOVV R7, 56(R3)
- MOVV R8, 64(R3)
- MOVV R9, 72(R3)
- MOVV R10, 80(R3)
- MOVV R11, 88(R3)
- MOVV R12, 96(R3)
- // R13 already saved
- MOVV R14, 104(R3)
- MOVV R15, 112(R3)
- MOVV R16, 120(R3)
- MOVV R17, 128(R3)
- MOVV R18, 136(R3)
- // R19 already saved
- MOVV R20, 144(R3)
- MOVV R21, 152(R3)
- // R22 is g.
- MOVV R23, 160(R3)
- MOVV R24, 168(R3)
- MOVV R25, 176(R3)
- MOVV R26, 184(R3)
- // R27 already saved
- // R28 already saved.
- MOVV R29, 192(R3)
- // R30 is tmp register.
- MOVV R31, 200(R3)
-
- CALL runtime·wbBufFlush(SB)
-
- MOVV 8(R3), R27
- MOVV 16(R3), R28
- MOVV 24(R3), R2
- MOVV 32(R3), R4
- MOVV 40(R3), R5
- MOVV 48(R3), R6
- MOVV 56(R3), R7
- MOVV 64(R3), R8
- MOVV 72(R3), R9
- MOVV 80(R3), R10
- MOVV 88(R3), R11
- MOVV 96(R3), R12
- MOVV 104(R3), R14
- MOVV 112(R3), R15
- MOVV 120(R3), R16
- MOVV 128(R3), R17
- MOVV 136(R3), R18
- MOVV 144(R3), R20
- MOVV 152(R3), R21
- MOVV 160(R3), R23
- MOVV 168(R3), R24
- MOVV 176(R3), R25
- MOVV 184(R3), R26
- MOVV 192(R3), R29
- MOVV 200(R3), R31
- JMP retry
-
-TEXT runtime·gcWriteBarrier1(SB),NOSPLIT,$0
- MOVV $8, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier2(SB),NOSPLIT,$0
- MOVV $16, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier3(SB),NOSPLIT,$0
- MOVV $24, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier4(SB),NOSPLIT,$0
- MOVV $32, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier5(SB),NOSPLIT,$0
- MOVV $40, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier6(SB),NOSPLIT,$0
- MOVV $48, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier7(SB),NOSPLIT,$0
- MOVV $56, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier8(SB),NOSPLIT,$0
- MOVV $64, R29
- JMP gcWriteBarrier<>(SB)
-
-// Note: these functions use a special calling convention to save generated code space.
-// Arguments are passed in registers, but the space for those arguments are allocated
-// in the caller's stack frame. These stubs write the args into that stack space and
-// then tail call to the corresponding runtime handler.
-// The tail call makes these stubs disappear in backtraces.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R20, R4
- MOVV R21, R5
-#else
- MOVV R20, x+0(FP)
- MOVV R21, y+8(FP)
-#endif
- JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R20, R4
- MOVV R21, R5
-#else
- MOVV R20, x+0(FP)
- MOVV R21, y+8(FP)
-#endif
- JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R21, R4
- MOVV R23, R5
-#else
- MOVV R21, x+0(FP)
- MOVV R23, y+8(FP)
-#endif
- JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R21, R4
- MOVV R23, R5
-#else
- MOVV R21, x+0(FP)
- MOVV R23, y+8(FP)
-#endif
- JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R21, R4
- MOVV R23, R5
-#else
- MOVV R21, x+0(FP)
- MOVV R23, y+8(FP)
-#endif
- JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R21, R4
- MOVV R23, R5
-#else
- MOVV R21, x+0(FP)
- MOVV R23, y+8(FP)
-#endif
- JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R20, R4
- MOVV R21, R5
-#else
- MOVV R20, x+0(FP)
- MOVV R21, y+8(FP)
-#endif
- JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R20, R4
- MOVV R21, R5
-#else
- MOVV R20, x+0(FP)
- MOVV R21, y+8(FP)
-#endif
- JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R23, R4
- MOVV R24, R5
-#else
- MOVV R23, x+0(FP)
- MOVV R24, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R23, R4
- MOVV R24, R5
-#else
- MOVV R23, x+0(FP)
- MOVV R24, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R23, R4
- MOVV R24, R5
-#else
- MOVV R23, x+0(FP)
- MOVV R24, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R23, R4
- MOVV R24, R5
-#else
- MOVV R23, x+0(FP)
- MOVV R24, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R21, R4
- MOVV R23, R5
-#else
- MOVV R21, x+0(FP)
- MOVV R23, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R21, R4
- MOVV R23, R5
-#else
- MOVV R21, x+0(FP)
- MOVV R23, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R20, R4
- MOVV R21, R5
-#else
- MOVV R20, x+0(FP)
- MOVV R21, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R20, R4
- MOVV R21, R5
-#else
- MOVV R20, x+0(FP)
- MOVV R21, y+8(FP)
-#endif
- JMP runtime·goPanicSlice3CU(SB)
-TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
-#ifdef GOEXPERIMENT_regabiargs
- MOVV R23, R4
- MOVV R24, R5
-#else
- MOVV R23, x+0(FP)
- MOVV R24, y+8(FP)
-#endif
- JMP runtime·goPanicSliceConvert(SB)
diff --git a/contrib/go/_std_1.22/src/runtime/asm_ppc64x.s b/contrib/go/_std_1.22/src/runtime/asm_ppc64x.s
deleted file mode 100644
index ff9b736430cc..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asm_ppc64x.s
+++ /dev/null
@@ -1,1618 +0,0 @@
-// Copyright 2014 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.
-
-//go:build ppc64 || ppc64le
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "funcdata.h"
-#include "textflag.h"
-#include "asm_ppc64x.h"
-
-#ifdef GOOS_aix
-#define cgoCalleeStackSize 48
-#else
-#define cgoCalleeStackSize 32
-#endif
-
-TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
- // R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
-
- // initialize essential registers
- BL runtime·reginit(SB)
-
- SUB $(FIXED_FRAME+16), R1
- MOVD R2, 24(R1) // stash the TOC pointer away again now we've created a new frame
- MOVW R3, FIXED_FRAME+0(R1) // argc
- MOVD R4, FIXED_FRAME+8(R1) // argv
-
- // create istack out of the given (operating system) stack.
- // _cgo_init may update stackguard.
- MOVD $runtime·g0(SB), g
- BL runtime·save_g(SB)
- MOVD $(-64*1024), R31
- ADD R31, R1, R3
- MOVD R3, g_stackguard0(g)
- MOVD R3, g_stackguard1(g)
- MOVD R3, (g_stack+stack_lo)(g)
- MOVD R1, (g_stack+stack_hi)(g)
-
- // If there is a _cgo_init, call it using the gcc ABI.
- MOVD _cgo_init(SB), R12
- CMP R0, R12
- BEQ nocgo
-
-#ifdef GO_PPC64X_HAS_FUNCDESC
- // Load the real entry address from the first slot of the function descriptor.
- MOVD 8(R12), R2
- MOVD (R12), R12
-#endif
- MOVD R12, CTR // r12 = "global function entry point"
- MOVD R13, R5 // arg 2: TLS base pointer
- MOVD $setg_gcc<>(SB), R4 // arg 1: setg
- MOVD g, R3 // arg 0: G
- // C functions expect 32 (48 for AIX) bytes of space on caller
- // stack frame and a 16-byte aligned R1
- MOVD R1, R14 // save current stack
- SUB $cgoCalleeStackSize, R1 // reserve the callee area
- RLDCR $0, R1, $~15, R1 // 16-byte align
- BL (CTR) // may clobber R0, R3-R12
- MOVD R14, R1 // restore stack
-#ifndef GOOS_aix
- MOVD 24(R1), R2
-#endif
- XOR R0, R0 // fix R0
-
-nocgo:
- // update stackguard after _cgo_init
- MOVD (g_stack+stack_lo)(g), R3
- ADD $const_stackGuard, R3
- MOVD R3, g_stackguard0(g)
- MOVD R3, g_stackguard1(g)
-
- // set the per-goroutine and per-mach "registers"
- MOVD $runtime·m0(SB), R3
-
- // save m->g0 = g0
- MOVD g, m_g0(R3)
- // save m0 to g0->m
- MOVD R3, g_m(g)
-
- BL runtime·check(SB)
-
- // args are already prepared
- BL runtime·args(SB)
- BL runtime·osinit(SB)
- BL runtime·schedinit(SB)
-
- // create a new goroutine to start program
- MOVD $runtime·mainPC(SB), R3 // entry
- MOVDU R3, -8(R1)
- MOVDU R0, -8(R1)
- MOVDU R0, -8(R1)
- MOVDU R0, -8(R1)
- MOVDU R0, -8(R1)
- BL runtime·newproc(SB)
- ADD $(8+FIXED_FRAME), R1
-
- // start this M
- BL runtime·mstart(SB)
- // Prevent dead-code elimination of debugCallV2, which is
- // intended to be called by debuggers.
-#ifdef GOARCH_ppc64le
- MOVD $runtime·debugCallV2(SB), R31
-#endif
- MOVD R0, 0(R0)
- RET
-
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
-GLOBL runtime·mainPC(SB),RODATA,$8
-
-TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
- TW $31, R0, R0
- RET
-
-TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
- RET
-
-// Any changes must be reflected to runtime/cgo/gcc_aix_ppc64.S:.crosscall_ppc64
-TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
- // crosscall_ppc64 and crosscall2 need to reginit, but can't
- // get at the 'runtime.reginit' symbol.
- BR runtime·reginit(SB)
-
-TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
- // set R0 to zero, it's expected by the toolchain
- XOR R0, R0
- RET
-
-TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
- BL runtime·mstart0(SB)
- RET // not reached
-
-/*
- * go-routine
- */
-
-// void gogo(Gobuf*)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
- MOVD buf+0(FP), R5
- MOVD gobuf_g(R5), R6
- MOVD 0(R6), R4 // make sure g != nil
- BR gogo<>(SB)
-
-TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
- MOVD R6, g
- BL runtime·save_g(SB)
-
- MOVD gobuf_sp(R5), R1
- MOVD gobuf_lr(R5), R31
-#ifndef GOOS_aix
- MOVD 24(R1), R2 // restore R2
-#endif
- MOVD R31, LR
- MOVD gobuf_ret(R5), R3
- MOVD gobuf_ctxt(R5), R11
- MOVD R0, gobuf_sp(R5)
- MOVD R0, gobuf_ret(R5)
- MOVD R0, gobuf_lr(R5)
- MOVD R0, gobuf_ctxt(R5)
- CMP R0, R0 // set condition codes for == test, needed by stack split
- MOVD gobuf_pc(R5), R12
- MOVD R12, CTR
- BR (CTR)
-
-// void mcall(fn func(*g))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return. It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
- // Save caller state in g->sched
- // R11 should be safe across save_g??
- MOVD R3, R11
- MOVD R1, (g_sched+gobuf_sp)(g)
- MOVD LR, R31
- MOVD R31, (g_sched+gobuf_pc)(g)
- MOVD R0, (g_sched+gobuf_lr)(g)
-
- // Switch to m->g0 & its stack, call fn.
- MOVD g, R3
- MOVD g_m(g), R8
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- CMP g, R3
- BNE 2(PC)
- BR runtime·badmcall(SB)
- MOVD 0(R11), R12 // code pointer
- MOVD R12, CTR
- MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp
- // Don't need to do anything special for regabiargs here
- // R3 is g; stack is set anyway
- MOVDU R3, -8(R1)
- MOVDU R0, -8(R1)
- MOVDU R0, -8(R1)
- MOVDU R0, -8(R1)
- MOVDU R0, -8(R1)
- BL (CTR)
- MOVD 24(R1), R2
- BR runtime·badmcall2(SB)
-
-// systemstack_switch is a dummy routine that systemstack leaves at the bottom
-// of the G stack. We need to distinguish the routine that
-// lives at the bottom of the G stack from the one that lives
-// at the top of the system stack because the one at the top of
-// the system stack terminates the stack walk (see topofstack()).
-TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
- // We have several undefs here so that 16 bytes past
- // $runtime·systemstack_switch lies within them whether or not the
- // instructions that derive r2 from r12 are there.
- UNDEF
- UNDEF
- UNDEF
- BL (LR) // make sure this function is not leaf
- RET
-
-// func systemstack(fn func())
-TEXT runtime·systemstack(SB), NOSPLIT, $0-8
- MOVD fn+0(FP), R3 // R3 = fn
- MOVD R3, R11 // context
- MOVD g_m(g), R4 // R4 = m
-
- MOVD m_gsignal(R4), R5 // R5 = gsignal
- CMP g, R5
- BEQ noswitch
-
- MOVD m_g0(R4), R5 // R5 = g0
- CMP g, R5
- BEQ noswitch
-
- MOVD m_curg(R4), R6
- CMP g, R6
- BEQ switch
-
- // Bad: g is not gsignal, not g0, not curg. What is it?
- // Hide call from linker nosplit analysis.
- MOVD $runtime·badsystemstack(SB), R12
- MOVD R12, CTR
- BL (CTR)
- BL runtime·abort(SB)
-
-switch:
- // save our state in g->sched. Pretend to
- // be systemstack_switch if the G stack is scanned.
- BL gosave_systemstack_switch<>(SB)
-
- // switch to g0
- MOVD R5, g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R1
-
- // call target function
- MOVD 0(R11), R12 // code pointer
- MOVD R12, CTR
- BL (CTR)
-
- // restore TOC pointer. It seems unlikely that we will use systemstack
- // to call a function defined in another module, but the results of
- // doing so would be so confusing that it's worth doing this.
- MOVD g_m(g), R3
- MOVD m_curg(R3), g
- MOVD (g_sched+gobuf_sp)(g), R3
-#ifndef GOOS_aix
- MOVD 24(R3), R2
-#endif
- // switch back to g
- MOVD g_m(g), R3
- MOVD m_curg(R3), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R1
- MOVD R0, (g_sched+gobuf_sp)(g)
- RET
-
-noswitch:
- // already on m stack, just call directly
- // On other arches we do a tail call here, but it appears to be
- // impossible to tail call a function pointer in shared mode on
- // ppc64 because the caller is responsible for restoring the TOC.
- MOVD 0(R11), R12 // code pointer
- MOVD R12, CTR
- BL (CTR)
-#ifndef GOOS_aix
- MOVD 24(R1), R2
-#endif
- RET
-
-// func switchToCrashStack0(fn func())
-TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-8
- MOVD R3, R11 // context register
- MOVD g_m(g), R3 // curm
-
- // set g to gcrash
- MOVD $runtime·gcrash(SB), g // g = &gcrash
- CALL runtime·save_g(SB) // clobbers R31
- MOVD R3, g_m(g) // g.m = curm
- MOVD g, m_g0(R3) // curm.g0 = g
-
- // switch to crashstack
- MOVD (g_stack+stack_hi)(g), R3
- SUB $(4*8), R3
- MOVD R3, R1
-
- // call target function
- MOVD 0(R11), R12 // code pointer
- MOVD R12, CTR
- BL (CTR)
-
- // should never return
- CALL runtime·abort(SB)
- UNDEF
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-// Caller has already loaded:
-// R3: framesize, R4: argsize, R5: LR
-//
-// The traceback routines see morestack on a g0 as being
-// the top of a stack (for example, morestack calling newstack
-// calling the scheduler calling newm calling gc), so we must
-// record an argument size. For that purpose, it has no arguments.
-TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
- // Called from f.
- // Set g->sched to context in f.
- MOVD R1, (g_sched+gobuf_sp)(g)
- MOVD LR, R8
- MOVD R8, (g_sched+gobuf_pc)(g)
- MOVD R5, (g_sched+gobuf_lr)(g)
- MOVD R11, (g_sched+gobuf_ctxt)(g)
-
- // Cannot grow scheduler stack (m->g0).
- MOVD g_m(g), R7
- MOVD m_g0(R7), R8
- CMP g, R8
- BNE 3(PC)
- BL runtime·badmorestackg0(SB)
- BL runtime·abort(SB)
-
- // Cannot grow signal stack (m->gsignal).
- MOVD m_gsignal(R7), R8
- CMP g, R8
- BNE 3(PC)
- BL runtime·badmorestackgsignal(SB)
- BL runtime·abort(SB)
-
- // Called from f.
- // Set m->morebuf to f's caller.
- MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
- MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
- MOVD g, (m_morebuf+gobuf_g)(R7)
-
- // Call newstack on m->g0's stack.
- MOVD m_g0(R7), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R1
- MOVDU R0, -(FIXED_FRAME+0)(R1) // create a call frame on g0
- BL runtime·newstack(SB)
-
- // Not reached, but make sure the return PC from the call to newstack
- // is still in this function, and not the beginning of the next.
- UNDEF
-
-TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
- // Force SPWRITE. This function doesn't actually write SP,
- // but it is called with a special calling convention where
- // the caller doesn't save LR on stack but passes it as a
- // register (R5), and the unwinder currently doesn't understand.
- // Make it SPWRITE to stop unwinding. (See issue 54332)
- // Use OR R0, R1 instead of MOVD R1, R1 as the MOVD instruction
- // has a special affect on Power8,9,10 by lowering the thread
- // priority and causing a slowdown in execution time
-
- OR R0, R1
- MOVD R0, R11
- BR runtime·morestack(SB)
-
-// reflectcall: call a function with the given argument list
-// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
-// we don't have variable-sized frames, so we use a small number
-// of constant-sized-frame functions to encode a few bits of size in the pc.
-// Caution: ugly multiline assembly macros in your future!
-
-#define DISPATCH(NAME,MAXSIZE) \
- MOVD $MAXSIZE, R31; \
- CMP R3, R31; \
- BGT 4(PC); \
- MOVD $NAME(SB), R12; \
- MOVD R12, CTR; \
- BR (CTR)
-// Note: can't just "BR NAME(SB)" - bad inlining results.
-
-TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
- MOVWZ frameSize+32(FP), R3
- DISPATCH(runtime·call16, 16)
- DISPATCH(runtime·call32, 32)
- DISPATCH(runtime·call64, 64)
- DISPATCH(runtime·call128, 128)
- DISPATCH(runtime·call256, 256)
- DISPATCH(runtime·call512, 512)
- DISPATCH(runtime·call1024, 1024)
- DISPATCH(runtime·call2048, 2048)
- DISPATCH(runtime·call4096, 4096)
- DISPATCH(runtime·call8192, 8192)
- DISPATCH(runtime·call16384, 16384)
- DISPATCH(runtime·call32768, 32768)
- DISPATCH(runtime·call65536, 65536)
- DISPATCH(runtime·call131072, 131072)
- DISPATCH(runtime·call262144, 262144)
- DISPATCH(runtime·call524288, 524288)
- DISPATCH(runtime·call1048576, 1048576)
- DISPATCH(runtime·call2097152, 2097152)
- DISPATCH(runtime·call4194304, 4194304)
- DISPATCH(runtime·call8388608, 8388608)
- DISPATCH(runtime·call16777216, 16777216)
- DISPATCH(runtime·call33554432, 33554432)
- DISPATCH(runtime·call67108864, 67108864)
- DISPATCH(runtime·call134217728, 134217728)
- DISPATCH(runtime·call268435456, 268435456)
- DISPATCH(runtime·call536870912, 536870912)
- DISPATCH(runtime·call1073741824, 1073741824)
- MOVD $runtime·badreflectcall(SB), R12
- MOVD R12, CTR
- BR (CTR)
-
-#define CALLFN(NAME,MAXSIZE) \
-TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
- NO_LOCAL_POINTERS; \
- /* copy arguments to stack */ \
- MOVD stackArgs+16(FP), R3; \
- MOVWZ stackArgsSize+24(FP), R4; \
- MOVD R1, R5; \
- CMP R4, $8; \
- BLT tailsetup; \
- /* copy 8 at a time if possible */ \
- ADD $(FIXED_FRAME-8), R5; \
- SUB $8, R3; \
-top: \
- MOVDU 8(R3), R7; \
- MOVDU R7, 8(R5); \
- SUB $8, R4; \
- CMP R4, $8; \
- BGE top; \
- /* handle remaining bytes */ \
- CMP $0, R4; \
- BEQ callfn; \
- ADD $7, R3; \
- ADD $7, R5; \
- BR tail; \
-tailsetup: \
- CMP $0, R4; \
- BEQ callfn; \
- ADD $(FIXED_FRAME-1), R5; \
- SUB $1, R3; \
-tail: \
- MOVBU 1(R3), R6; \
- MOVBU R6, 1(R5); \
- SUB $1, R4; \
- CMP $0, R4; \
- BGT tail; \
-callfn: \
- /* call function */ \
- MOVD f+8(FP), R11; \
-#ifdef GOOS_aix \
- /* AIX won't trigger a SIGSEGV if R11 = nil */ \
- /* So it manually triggers it */ \
- CMP R0, R11 \
- BNE 2(PC) \
- MOVD R0, 0(R0) \
-#endif \
- MOVD regArgs+40(FP), R20; \
- BL runtime·unspillArgs(SB); \
- MOVD (R11), R12; \
- MOVD R12, CTR; \
- PCDATA $PCDATA_StackMapIndex, $0; \
- BL (CTR); \
-#ifndef GOOS_aix \
- MOVD 24(R1), R2; \
-#endif \
- /* copy return values back */ \
- MOVD regArgs+40(FP), R20; \
- BL runtime·spillArgs(SB); \
- MOVD stackArgsType+0(FP), R7; \
- MOVD stackArgs+16(FP), R3; \
- MOVWZ stackArgsSize+24(FP), R4; \
- MOVWZ stackRetOffset+28(FP), R6; \
- ADD $FIXED_FRAME, R1, R5; \
- ADD R6, R5; \
- ADD R6, R3; \
- SUB R6, R4; \
- BL callRet<>(SB); \
- RET
-
-// callRet copies return values back at the end of call*. This is a
-// separate function so it can allocate stack space for the arguments
-// to reflectcallmove. It does not follow the Go ABI; it expects its
-// arguments in registers.
-TEXT callRet<>(SB), NOSPLIT, $40-0
- NO_LOCAL_POINTERS
- MOVD R7, FIXED_FRAME+0(R1)
- MOVD R3, FIXED_FRAME+8(R1)
- MOVD R5, FIXED_FRAME+16(R1)
- MOVD R4, FIXED_FRAME+24(R1)
- MOVD R20, FIXED_FRAME+32(R1)
- BL runtime·reflectcallmove(SB)
- RET
-
-CALLFN(·call16, 16)
-CALLFN(·call32, 32)
-CALLFN(·call64, 64)
-CALLFN(·call128, 128)
-CALLFN(·call256, 256)
-CALLFN(·call512, 512)
-CALLFN(·call1024, 1024)
-CALLFN(·call2048, 2048)
-CALLFN(·call4096, 4096)
-CALLFN(·call8192, 8192)
-CALLFN(·call16384, 16384)
-CALLFN(·call32768, 32768)
-CALLFN(·call65536, 65536)
-CALLFN(·call131072, 131072)
-CALLFN(·call262144, 262144)
-CALLFN(·call524288, 524288)
-CALLFN(·call1048576, 1048576)
-CALLFN(·call2097152, 2097152)
-CALLFN(·call4194304, 4194304)
-CALLFN(·call8388608, 8388608)
-CALLFN(·call16777216, 16777216)
-CALLFN(·call33554432, 33554432)
-CALLFN(·call67108864, 67108864)
-CALLFN(·call134217728, 134217728)
-CALLFN(·call268435456, 268435456)
-CALLFN(·call536870912, 536870912)
-CALLFN(·call1073741824, 1073741824)
-
-TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4
- MOVW cycles+0(FP), R7
- // POWER does not have a pause/yield instruction equivalent.
- // Instead, we can lower the program priority by setting the
- // Program Priority Register prior to the wait loop and set it
- // back to default afterwards. On Linux, the default priority is
- // medium-low. For details, see page 837 of the ISA 3.0.
- OR R1, R1, R1 // Set PPR priority to low
-again:
- SUB $1, R7
- CMP $0, R7
- BNE again
- OR R6, R6, R6 // Set PPR priority back to medium-low
- RET
-
-// Save state of caller into g->sched,
-// but using fake PC from systemstack_switch.
-// Must only be called from functions with no locals ($0)
-// or else unwinding from systemstack_switch is incorrect.
-// Smashes R31.
-TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
- MOVD $runtime·systemstack_switch(SB), R31
- ADD $16, R31 // get past prologue (including r2-setting instructions when they're there)
- MOVD R31, (g_sched+gobuf_pc)(g)
- MOVD R1, (g_sched+gobuf_sp)(g)
- MOVD R0, (g_sched+gobuf_lr)(g)
- MOVD R0, (g_sched+gobuf_ret)(g)
- // Assert ctxt is zero. See func save.
- MOVD (g_sched+gobuf_ctxt)(g), R31
- CMP R0, R31
- BEQ 2(PC)
- BL runtime·abort(SB)
- RET
-
-#ifdef GOOS_aix
-#define asmcgocallSaveOffset cgoCalleeStackSize + 8
-#else
-#define asmcgocallSaveOffset cgoCalleeStackSize
-#endif
-
-// func asmcgocall_no_g(fn, arg unsafe.Pointer)
-// Call fn(arg) aligned appropriately for the gcc ABI.
-// Called on a system stack, and there may be no g yet (during needm).
-TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-16
- MOVD fn+0(FP), R3
- MOVD arg+8(FP), R4
-
- MOVD R1, R15
- SUB $(asmcgocallSaveOffset+8), R1
- RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI
- MOVD R15, asmcgocallSaveOffset(R1)
-
- MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?)
-
- // This is a "global call", so put the global entry point in r12
- MOVD R3, R12
-
-#ifdef GO_PPC64X_HAS_FUNCDESC
- // Load the real entry address from the first slot of the function descriptor.
- MOVD 8(R12), R2
- MOVD (R12), R12
-#endif
- MOVD R12, CTR
- MOVD R4, R3 // arg in r3
- BL (CTR)
-
- // C code can clobber R0, so set it back to 0. F27-F31 are
- // callee save, so we don't need to recover those.
- XOR R0, R0
-
- MOVD asmcgocallSaveOffset(R1), R1 // Restore stack pointer.
-#ifndef GOOS_aix
- MOVD 24(R1), R2
-#endif
-
- RET
-
-// func asmcgocall(fn, arg unsafe.Pointer) int32
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.go for more details.
-TEXT ·asmcgocall(SB),NOSPLIT,$0-20
- MOVD fn+0(FP), R3
- MOVD arg+8(FP), R4
-
- MOVD R1, R7 // save original stack pointer
- CMP $0, g
- BEQ nosave
- MOVD g, R5
-
- // Figure out if we need to switch to m->g0 stack.
- // We get called to create new OS threads too, and those
- // come in on the m->g0 stack already. Or we might already
- // be on the m->gsignal stack.
- MOVD g_m(g), R8
- MOVD m_gsignal(R8), R6
- CMP R6, g
- BEQ nosave
- MOVD m_g0(R8), R6
- CMP R6, g
- BEQ nosave
-
- BL gosave_systemstack_switch<>(SB)
- MOVD R6, g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R1
-
- // Now on a scheduling stack (a pthread-created stack).
-#ifdef GOOS_aix
- // Create a fake LR to improve backtrace.
- MOVD $runtime·asmcgocall(SB), R6
- MOVD R6, 16(R1)
- // AIX also saves one argument on the stack.
- SUB $8, R1
-#endif
- // Save room for two of our pointers, plus the callee
- // save area that lives on the caller stack.
- SUB $(asmcgocallSaveOffset+16), R1
- RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI
- MOVD R5, (asmcgocallSaveOffset+8)(R1) // save old g on stack
- MOVD (g_stack+stack_hi)(R5), R5
- SUB R7, R5
- MOVD R5, asmcgocallSaveOffset(R1) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
-#ifdef GOOS_aix
- MOVD R7, 0(R1) // Save frame pointer to allow manual backtrace with gdb
-#else
- MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?)
-#endif
- // This is a "global call", so put the global entry point in r12
- MOVD R3, R12
-
-#ifdef GO_PPC64X_HAS_FUNCDESC
- // Load the real entry address from the first slot of the function descriptor.
- MOVD 8(R12), R2
- MOVD (R12), R12
-#endif
- MOVD R12, CTR
- MOVD R4, R3 // arg in r3
- BL (CTR)
-
- // Reinitialise zero value register.
- XOR R0, R0
-
- // Restore g, stack pointer, toc pointer.
- // R3 is errno, so don't touch it
- MOVD (asmcgocallSaveOffset+8)(R1), g
- MOVD (g_stack+stack_hi)(g), R5
- MOVD asmcgocallSaveOffset(R1), R6
- SUB R6, R5
-#ifndef GOOS_aix
- MOVD 24(R5), R2
-#endif
- MOVD R5, R1
- BL runtime·save_g(SB)
-
- MOVW R3, ret+16(FP)
- RET
-
-nosave:
- // Running on a system stack, perhaps even without a g.
- // Having no g can happen during thread creation or thread teardown.
- // This code is like the above sequence but without saving/restoring g
- // and without worrying about the stack moving out from under us
- // (because we're on a system stack, not a goroutine stack).
- // The above code could be used directly if already on a system stack,
- // but then the only path through this code would be a rare case.
- // Using this code for all "already on system stack" calls exercises it more,
- // which should help keep it correct.
-
- SUB $(asmcgocallSaveOffset+8), R1
- RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI
- MOVD R7, asmcgocallSaveOffset(R1) // Save original stack pointer.
-
- MOVD R3, R12 // fn
-#ifdef GO_PPC64X_HAS_FUNCDESC
- // Load the real entry address from the first slot of the function descriptor.
- MOVD 8(R12), R2
- MOVD (R12), R12
-#endif
- MOVD R12, CTR
- MOVD R4, R3 // arg
- BL (CTR)
-
- // Reinitialise zero value register.
- XOR R0, R0
-
- MOVD asmcgocallSaveOffset(R1), R1 // Restore stack pointer.
-#ifndef GOOS_aix
- MOVD 24(R1), R2
-#endif
- MOVW R3, ret+16(FP)
- RET
-
-// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
-// See cgocall.go for more details.
-TEXT ·cgocallback(SB),NOSPLIT,$24-24
- NO_LOCAL_POINTERS
-
- // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
- // It is used to dropm while thread is exiting.
- MOVD fn+0(FP), R5
- CMP R5, $0
- BNE loadg
- // Restore the g from frame.
- MOVD frame+8(FP), g
- BR dropm
-
-loadg:
- // Load m and g from thread-local storage.
-#ifndef GOOS_openbsd
- MOVBZ runtime·iscgo(SB), R3
- CMP R3, $0
- BEQ nocgo
-#endif
- BL runtime·load_g(SB)
-nocgo:
-
- // If g is nil, Go did not create the current thread,
- // or if this thread never called into Go on pthread platforms.
- // Call needm to obtain one for temporary use.
- // In this case, we're running on the thread stack, so there's
- // lots of space, but the linker doesn't know. Hide the call from
- // the linker analysis by using an indirect call.
- CMP g, $0
- BEQ needm
-
- MOVD g_m(g), R8
- MOVD R8, savedm-8(SP)
- BR havem
-
-needm:
- MOVD g, savedm-8(SP) // g is zero, so is m.
- MOVD $runtime·needAndBindM(SB), R12
- MOVD R12, CTR
- BL (CTR)
-
- // Set m->sched.sp = SP, so that if a panic happens
- // during the function we are about to execute, it will
- // have a valid SP to run on the g0 stack.
- // The next few lines (after the havem label)
- // will save this SP onto the stack and then write
- // the same SP back to m->sched.sp. That seems redundant,
- // but if an unrecovered panic happens, unwindm will
- // restore the g->sched.sp from the stack location
- // and then systemstack will try to use it. If we don't set it here,
- // that restored SP will be uninitialized (typically 0) and
- // will not be usable.
- MOVD g_m(g), R8
- MOVD m_g0(R8), R3
- MOVD R1, (g_sched+gobuf_sp)(R3)
-
-havem:
- // Now there's a valid m, and we're running on its m->g0.
- // Save current m->g0->sched.sp on stack and then set it to SP.
- // Save current sp in m->g0->sched.sp in preparation for
- // switch back to m->curg stack.
- // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
- MOVD m_g0(R8), R3
- MOVD (g_sched+gobuf_sp)(R3), R4
- MOVD R4, savedsp-24(SP) // must match frame size
- MOVD R1, (g_sched+gobuf_sp)(R3)
-
- // Switch to m->curg stack and call runtime.cgocallbackg.
- // Because we are taking over the execution of m->curg
- // but *not* resuming what had been running, we need to
- // save that information (m->curg->sched) so we can restore it.
- // We can restore m->curg->sched.sp easily, because calling
- // runtime.cgocallbackg leaves SP unchanged upon return.
- // To save m->curg->sched.pc, we push it onto the curg stack and
- // open a frame the same size as cgocallback's g0 frame.
- // Once we switch to the curg stack, the pushed PC will appear
- // to be the return PC of cgocallback, so that the traceback
- // will seamlessly trace back into the earlier calls.
- MOVD m_curg(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
- MOVD (g_sched+gobuf_pc)(g), R5
- MOVD R5, -(24+FIXED_FRAME)(R4) // "saved LR"; must match frame size
- // Gather our arguments into registers.
- MOVD fn+0(FP), R5
- MOVD frame+8(FP), R6
- MOVD ctxt+16(FP), R7
- MOVD $-(24+FIXED_FRAME)(R4), R1 // switch stack; must match frame size
- MOVD R5, FIXED_FRAME+0(R1)
- MOVD R6, FIXED_FRAME+8(R1)
- MOVD R7, FIXED_FRAME+16(R1)
-
- MOVD $runtime·cgocallbackg(SB), R12
- MOVD R12, CTR
- CALL (CTR) // indirect call to bypass nosplit check. We're on a different stack now.
-
- // Restore g->sched (== m->curg->sched) from saved values.
- MOVD 0(R1), R5
- MOVD R5, (g_sched+gobuf_pc)(g)
- MOVD $(24+FIXED_FRAME)(R1), R4 // must match frame size
- MOVD R4, (g_sched+gobuf_sp)(g)
-
- // Switch back to m->g0's stack and restore m->g0->sched.sp.
- // (Unlike m->curg, the g0 goroutine never uses sched.pc,
- // so we do not have to restore it.)
- MOVD g_m(g), R8
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R1
- MOVD savedsp-24(SP), R4 // must match frame size
- MOVD R4, (g_sched+gobuf_sp)(g)
-
- // If the m on entry was nil, we called needm above to borrow an m,
- // 1. for the duration of the call on non-pthread platforms,
- // 2. or the duration of the C thread alive on pthread platforms.
- // If the m on entry wasn't nil,
- // 1. the thread might be a Go thread,
- // 2. or it wasn't the first call from a C thread on pthread platforms,
- // since then we skip dropm to reuse the m in the first call.
- MOVD savedm-8(SP), R6
- CMP R6, $0
- BNE droppedm
-
- // Skip dropm to reuse it in the next call, when a pthread key has been created.
- MOVD _cgo_pthread_key_created(SB), R6
- // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
- CMP R6, $0
- BEQ dropm
- MOVD (R6), R6
- CMP R6, $0
- BNE droppedm
-
-dropm:
- MOVD $runtime·dropm(SB), R12
- MOVD R12, CTR
- BL (CTR)
-droppedm:
-
- // Done!
- RET
-
-// void setg(G*); set g. for use by needm.
-TEXT runtime·setg(SB), NOSPLIT, $0-8
- MOVD gg+0(FP), g
- // This only happens if iscgo, so jump straight to save_g
- BL runtime·save_g(SB)
- RET
-
-#ifdef GO_PPC64X_HAS_FUNCDESC
-DEFINE_PPC64X_FUNCDESC(setg_gcc<>, _setg_gcc<>)
-TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
-#else
-TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
-#endif
- // The standard prologue clobbers R31, which is callee-save in
- // the C ABI, so we have to use $-8-0 and save LR ourselves.
- MOVD LR, R4
- // Also save g and R31, since they're callee-save in C ABI
- MOVD R31, R5
- MOVD g, R6
-
- MOVD R3, g
- BL runtime·save_g(SB)
-
- MOVD R6, g
- MOVD R5, R31
- MOVD R4, LR
- RET
-
-TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
- MOVW (R0), R0
- UNDEF
-
-#define TBR 268
-
-// int64 runtime·cputicks(void)
-TEXT runtime·cputicks(SB),NOSPLIT,$0-8
- MOVD SPR(TBR), R3
- MOVD R3, ret+0(FP)
- RET
-
-// spillArgs stores return values from registers to a *internal/abi.RegArgs in R20.
-TEXT runtime·spillArgs(SB),NOSPLIT,$0-0
- MOVD R3, 0(R20)
- MOVD R4, 8(R20)
- MOVD R5, 16(R20)
- MOVD R6, 24(R20)
- MOVD R7, 32(R20)
- MOVD R8, 40(R20)
- MOVD R9, 48(R20)
- MOVD R10, 56(R20)
- MOVD R14, 64(R20)
- MOVD R15, 72(R20)
- MOVD R16, 80(R20)
- MOVD R17, 88(R20)
- FMOVD F1, 96(R20)
- FMOVD F2, 104(R20)
- FMOVD F3, 112(R20)
- FMOVD F4, 120(R20)
- FMOVD F5, 128(R20)
- FMOVD F6, 136(R20)
- FMOVD F7, 144(R20)
- FMOVD F8, 152(R20)
- FMOVD F9, 160(R20)
- FMOVD F10, 168(R20)
- FMOVD F11, 176(R20)
- FMOVD F12, 184(R20)
- RET
-
-// unspillArgs loads args into registers from a *internal/abi.RegArgs in R20.
-TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0
- MOVD 0(R20), R3
- MOVD 8(R20), R4
- MOVD 16(R20), R5
- MOVD 24(R20), R6
- MOVD 32(R20), R7
- MOVD 40(R20), R8
- MOVD 48(R20), R9
- MOVD 56(R20), R10
- MOVD 64(R20), R14
- MOVD 72(R20), R15
- MOVD 80(R20), R16
- MOVD 88(R20), R17
- FMOVD 96(R20), F1
- FMOVD 104(R20), F2
- FMOVD 112(R20), F3
- FMOVD 120(R20), F4
- FMOVD 128(R20), F5
- FMOVD 136(R20), F6
- FMOVD 144(R20), F7
- FMOVD 152(R20), F8
- FMOVD 160(R20), F9
- FMOVD 168(R20), F10
- FMOVD 176(R20), F11
- FMOVD 184(R20), F12
- RET
-
-// AES hashing not implemented for ppc64
-TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
- JMP runtime·memhashFallback(SB)
-TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·strhashFallback(SB)
-TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·memhash32Fallback(SB)
-TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·memhash64Fallback(SB)
-
-TEXT runtime·return0(SB), NOSPLIT, $0
- MOVW $0, R3
- RET
-
-// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
-// Must obey the gcc calling convention.
-#ifdef GOOS_aix
-// On AIX, _cgo_topofstack is defined in runtime/cgo, because it must
-// be a longcall in order to prevent trampolines from ld.
-TEXT __cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
-#else
-TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
-#endif
- // g (R30) and R31 are callee-save in the C ABI, so save them
- MOVD g, R4
- MOVD R31, R5
- MOVD LR, R6
-
- BL runtime·load_g(SB) // clobbers g (R30), R31
- MOVD g_m(g), R3
- MOVD m_curg(R3), R3
- MOVD (g_stack+stack_hi)(R3), R3
-
- MOVD R4, g
- MOVD R5, R31
- MOVD R6, LR
- RET
-
-// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-//
-// When dynamically linking Go, it can be returned to from a function
-// implemented in a different module and so needs to reload the TOC pointer
-// from the stack (although this function declares that it does not set up x-a
-// frame, newproc1 does in fact allocate one for goexit and saves the TOC
-// pointer in the correct place).
-// goexit+_PCQuantum is halfway through the usual global entry point prologue
-// that derives r2 from r12 which is a bit silly, but not harmful.
-TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
- MOVD 24(R1), R2
- BL runtime·goexit1(SB) // does not return
- // traceback from goexit1 must hit code range of goexit
- MOVD R0, R0 // NOP
-
-// prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
-// module containing runtime) to the frame that goexit will execute in when
-// the goroutine exits. It's implemented in assembly mainly because that's the
-// easiest way to get access to R2.
-TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
- MOVD sp+0(FP), R3
- MOVD R2, 24(R3)
- RET
-
-TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
- ADD $-8, R1
- MOVD R31, 0(R1)
- MOVD runtime·lastmoduledatap(SB), R4
- MOVD R3, moduledata_next(R4)
- MOVD R3, runtime·lastmoduledatap(SB)
- MOVD 0(R1), R31
- ADD $8, R1
- RET
-
-TEXT ·checkASM(SB),NOSPLIT,$0-1
- MOVW $1, R3
- MOVB R3, ret+0(FP)
- RET
-
-// gcWriteBarrier informs the GC about heap pointer writes.
-//
-// gcWriteBarrier does NOT follow the Go ABI. It accepts the
-// number of bytes of buffer needed in R29, and returns a pointer
-// to the buffer space in R29.
-// It clobbers condition codes.
-// It does not clobber R0 through R17 (except special registers),
-// but may clobber any other register, *including* R31.
-TEXT gcWriteBarrier<>(SB),NOSPLIT,$120
- // The standard prologue clobbers R31.
- // We use R18, R19, and R31 as scratch registers.
-retry:
- MOVD g_m(g), R18
- MOVD m_p(R18), R18
- MOVD (p_wbBuf+wbBuf_next)(R18), R19
- MOVD (p_wbBuf+wbBuf_end)(R18), R31
- // Increment wbBuf.next position.
- ADD R29, R19
- // Is the buffer full?
- CMPU R31, R19
- BLT flush
- // Commit to the larger buffer.
- MOVD R19, (p_wbBuf+wbBuf_next)(R18)
- // Make return value (the original next position)
- SUB R29, R19, R29
- RET
-
-flush:
- // Save registers R0 through R15 since these were not saved by the caller.
- // We don't save all registers on ppc64 because it takes too much space.
- MOVD R20, (FIXED_FRAME+0)(R1)
- MOVD R21, (FIXED_FRAME+8)(R1)
- // R0 is always 0, so no need to spill.
- // R1 is SP.
- // R2 is SB.
- MOVD R3, (FIXED_FRAME+16)(R1)
- MOVD R4, (FIXED_FRAME+24)(R1)
- MOVD R5, (FIXED_FRAME+32)(R1)
- MOVD R6, (FIXED_FRAME+40)(R1)
- MOVD R7, (FIXED_FRAME+48)(R1)
- MOVD R8, (FIXED_FRAME+56)(R1)
- MOVD R9, (FIXED_FRAME+64)(R1)
- MOVD R10, (FIXED_FRAME+72)(R1)
- // R11, R12 may be clobbered by external-linker-inserted trampoline
- // R13 is REGTLS
- MOVD R14, (FIXED_FRAME+80)(R1)
- MOVD R15, (FIXED_FRAME+88)(R1)
- MOVD R16, (FIXED_FRAME+96)(R1)
- MOVD R17, (FIXED_FRAME+104)(R1)
- MOVD R29, (FIXED_FRAME+112)(R1)
-
- CALL runtime·wbBufFlush(SB)
-
- MOVD (FIXED_FRAME+0)(R1), R20
- MOVD (FIXED_FRAME+8)(R1), R21
- MOVD (FIXED_FRAME+16)(R1), R3
- MOVD (FIXED_FRAME+24)(R1), R4
- MOVD (FIXED_FRAME+32)(R1), R5
- MOVD (FIXED_FRAME+40)(R1), R6
- MOVD (FIXED_FRAME+48)(R1), R7
- MOVD (FIXED_FRAME+56)(R1), R8
- MOVD (FIXED_FRAME+64)(R1), R9
- MOVD (FIXED_FRAME+72)(R1), R10
- MOVD (FIXED_FRAME+80)(R1), R14
- MOVD (FIXED_FRAME+88)(R1), R15
- MOVD (FIXED_FRAME+96)(R1), R16
- MOVD (FIXED_FRAME+104)(R1), R17
- MOVD (FIXED_FRAME+112)(R1), R29
- JMP retry
-
-TEXT runtime·gcWriteBarrier1(SB),NOSPLIT,$0
- MOVD $8, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier2(SB),NOSPLIT,$0
- MOVD $16, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier3(SB),NOSPLIT,$0
- MOVD $24, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier4(SB),NOSPLIT,$0
- MOVD $32, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier5(SB),NOSPLIT,$0
- MOVD $40, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier6(SB),NOSPLIT,$0
- MOVD $48, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier7(SB),NOSPLIT,$0
- MOVD $56, R29
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier8(SB),NOSPLIT,$0
- MOVD $64, R29
- JMP gcWriteBarrier<>(SB)
-
-DATA debugCallFrameTooLarge<>+0x00(SB)/20, $"call frame too large"
-GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below
-
-// debugCallV2 is the entry point for debugger-injected function
-// calls on running goroutines. It informs the runtime that a
-// debug call has been injected and creates a call frame for the
-// debugger to fill in.
-//
-// To inject a function call, a debugger should:
-// 1. Check that the goroutine is in state _Grunning and that
-// there are at least 320 bytes free on the stack.
-// 2. Set SP as SP-32.
-// 3. Store the current LR in (SP) (using the SP after step 2).
-// 4. Store the current PC in the LR register.
-// 5. Write the desired argument frame size at SP-32
-// 6. Save all machine registers (including flags and floating point registers)
-// so they can be restored later by the debugger.
-// 7. Set the PC to debugCallV2 and resume execution.
-//
-// If the goroutine is in state _Grunnable, then it's not generally
-// safe to inject a call because it may return out via other runtime
-// operations. Instead, the debugger should unwind the stack to find
-// the return to non-runtime code, add a temporary breakpoint there,
-// and inject the call once that breakpoint is hit.
-//
-// If the goroutine is in any other state, it's not safe to inject a call.
-//
-// This function communicates back to the debugger by setting R20 and
-// invoking TW to raise a breakpoint signal. Note that the signal PC of
-// the signal triggered by the TW instruction is the PC where the signal
-// is trapped, not the next PC, so to resume execution, the debugger needs
-// to set the signal PC to PC+4. See the comments in the implementation for
-// the protocol the debugger is expected to follow. InjectDebugCall in the
-// runtime tests demonstrates this protocol.
-// The debugger must ensure that any pointers passed to the function
-// obey escape analysis requirements. Specifically, it must not pass
-// a stack pointer to an escaping argument. debugCallV2 cannot check
-// this invariant.
-//
-// This is ABIInternal because Go code injects its PC directly into new
-// goroutine stacks.
-#ifdef GOARCH_ppc64le
-TEXT runtime·debugCallV2(SB), NOSPLIT|NOFRAME, $0-0
- // save scratch register R31 first
- MOVD R31, -184(R1)
- MOVD 0(R1), R31
- // save caller LR
- MOVD R31, -304(R1)
- MOVD -32(R1), R31
- // save argument frame size
- MOVD R31, -192(R1)
- MOVD LR, R31
- MOVD R31, -320(R1)
- ADD $-320, R1
- // save all registers that can contain pointers
- // and the CR register
- MOVW CR, R31
- MOVD R31, 8(R1)
- MOVD R2, 24(R1)
- MOVD R3, 56(R1)
- MOVD R4, 64(R1)
- MOVD R5, 72(R1)
- MOVD R6, 80(R1)
- MOVD R7, 88(R1)
- MOVD R8, 96(R1)
- MOVD R9, 104(R1)
- MOVD R10, 112(R1)
- MOVD R11, 120(R1)
- MOVD R12, 144(R1)
- MOVD R13, 152(R1)
- MOVD R14, 160(R1)
- MOVD R15, 168(R1)
- MOVD R16, 176(R1)
- MOVD R17, 184(R1)
- MOVD R18, 192(R1)
- MOVD R19, 200(R1)
- MOVD R20, 208(R1)
- MOVD R21, 216(R1)
- MOVD R22, 224(R1)
- MOVD R23, 232(R1)
- MOVD R24, 240(R1)
- MOVD R25, 248(R1)
- MOVD R26, 256(R1)
- MOVD R27, 264(R1)
- MOVD R28, 272(R1)
- MOVD R29, 280(R1)
- MOVD g, 288(R1)
- MOVD LR, R31
- MOVD R31, 32(R1)
- CALL runtime·debugCallCheck(SB)
- MOVD 40(R1), R22
- XOR R0, R0
- CMP R22, R0
- BEQ good
- MOVD 48(R1), R22
- MOVD $8, R20
- TW $31, R0, R0
-
- BR restore
-
-good:
-#define DEBUG_CALL_DISPATCH(NAME,MAXSIZE) \
- MOVD $MAXSIZE, R23; \
- CMP R26, R23; \
- BGT 5(PC); \
- MOVD $NAME(SB), R26; \
- MOVD R26, 32(R1); \
- CALL runtime·debugCallWrap(SB); \
- BR restore
-
- // the argument frame size
- MOVD 128(R1), R26
-
- DEBUG_CALL_DISPATCH(debugCall32<>, 32)
- DEBUG_CALL_DISPATCH(debugCall64<>, 64)
- DEBUG_CALL_DISPATCH(debugCall128<>, 128)
- DEBUG_CALL_DISPATCH(debugCall256<>, 256)
- DEBUG_CALL_DISPATCH(debugCall512<>, 512)
- DEBUG_CALL_DISPATCH(debugCall1024<>, 1024)
- DEBUG_CALL_DISPATCH(debugCall2048<>, 2048)
- DEBUG_CALL_DISPATCH(debugCall4096<>, 4096)
- DEBUG_CALL_DISPATCH(debugCall8192<>, 8192)
- DEBUG_CALL_DISPATCH(debugCall16384<>, 16384)
- DEBUG_CALL_DISPATCH(debugCall32768<>, 32768)
- DEBUG_CALL_DISPATCH(debugCall65536<>, 65536)
- // The frame size is too large. Report the error.
- MOVD $debugCallFrameTooLarge<>(SB), R22
- MOVD R22, 32(R1)
- MOVD $20, R22
- // length of debugCallFrameTooLarge string
- MOVD R22, 40(R1)
- MOVD $8, R20
- TW $31, R0, R0
- BR restore
-restore:
- MOVD $16, R20
- TW $31, R0, R0
- // restore all registers that can contain
- // pointers including CR
- MOVD 8(R1), R31
- MOVW R31, CR
- MOVD 24(R1), R2
- MOVD 56(R1), R3
- MOVD 64(R1), R4
- MOVD 72(R1), R5
- MOVD 80(R1), R6
- MOVD 88(R1), R7
- MOVD 96(R1), R8
- MOVD 104(R1), R9
- MOVD 112(R1), R10
- MOVD 120(R1), R11
- MOVD 144(R1), R12
- MOVD 152(R1), R13
- MOVD 160(R1), R14
- MOVD 168(R1), R15
- MOVD 176(R1), R16
- MOVD 184(R1), R17
- MOVD 192(R1), R18
- MOVD 200(R1), R19
- MOVD 208(R1), R20
- MOVD 216(R1), R21
- MOVD 224(R1), R22
- MOVD 232(R1), R23
- MOVD 240(R1), R24
- MOVD 248(R1), R25
- MOVD 256(R1), R26
- MOVD 264(R1), R27
- MOVD 272(R1), R28
- MOVD 280(R1), R29
- MOVD 288(R1), g
- MOVD 16(R1), R31
- // restore old LR
- MOVD R31, LR
- // restore caller PC
- MOVD 0(R1), CTR
- MOVD 136(R1), R31
- // Add 32 bytes more to compensate for SP change in saveSigContext
- ADD $352, R1
- JMP (CTR)
-#endif
-#define DEBUG_CALL_FN(NAME,MAXSIZE) \
-TEXT NAME(SB),WRAPPER,$MAXSIZE-0; \
- NO_LOCAL_POINTERS; \
- MOVD $0, R20; \
- TW $31, R0, R0 \
- MOVD $1, R20; \
- TW $31, R0, R0 \
- RET
-DEBUG_CALL_FN(debugCall32<>, 32)
-DEBUG_CALL_FN(debugCall64<>, 64)
-DEBUG_CALL_FN(debugCall128<>, 128)
-DEBUG_CALL_FN(debugCall256<>, 256)
-DEBUG_CALL_FN(debugCall512<>, 512)
-DEBUG_CALL_FN(debugCall1024<>, 1024)
-DEBUG_CALL_FN(debugCall2048<>, 2048)
-DEBUG_CALL_FN(debugCall4096<>, 4096)
-DEBUG_CALL_FN(debugCall8192<>, 8192)
-DEBUG_CALL_FN(debugCall16384<>, 16384)
-DEBUG_CALL_FN(debugCall32768<>, 32768)
-DEBUG_CALL_FN(debugCall65536<>, 65536)
-
-#ifdef GOARCH_ppc64le
-// func debugCallPanicked(val interface{})
-TEXT runtime·debugCallPanicked(SB),NOSPLIT,$32-16
- // Copy the panic value to the top of stack at SP+32.
- MOVD val_type+0(FP), R31
- MOVD R31, 32(R1)
- MOVD val_data+8(FP), R31
- MOVD R31, 40(R1)
- MOVD $2, R20
- TW $31, R0, R0
- RET
-#endif
-// Note: these functions use a special calling convention to save generated code space.
-// Arguments are passed in registers, but the space for those arguments are allocated
-// in the caller's stack frame. These stubs write the args into that stack space and
-// then tail call to the corresponding runtime handler.
-// The tail call makes these stubs disappear in backtraces.
-TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
- JMP runtime·goPanicIndex(SB)
-TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
- JMP runtime·goPanicIndexU(SB)
-TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
- MOVD R4, R3
- MOVD R5, R4
- JMP runtime·goPanicSliceAlen(SB)
-TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
- MOVD R4, R3
- MOVD R5, R4
- JMP runtime·goPanicSliceAlenU(SB)
-TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
- MOVD R4, R3
- MOVD R5, R4
- JMP runtime·goPanicSliceAcap(SB)
-TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
- MOVD R4, R3
- MOVD R5, R4
- JMP runtime·goPanicSliceAcapU(SB)
-TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSliceB(SB)
-TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSliceBU(SB)
-TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
- MOVD R5, R3
- MOVD R6, R4
- JMP runtime·goPanicSlice3Alen(SB)
-TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
- MOVD R5, R3
- MOVD R6, R4
- JMP runtime·goPanicSlice3AlenU(SB)
-TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
- MOVD R5, R3
- MOVD R6, R4
- JMP runtime·goPanicSlice3Acap(SB)
-TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
- MOVD R5, R3
- MOVD R6, R4
- JMP runtime·goPanicSlice3AcapU(SB)
-TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
- MOVD R4, R3
- MOVD R5, R4
- JMP runtime·goPanicSlice3B(SB)
-TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
- MOVD R4, R3
- MOVD R5, R4
- JMP runtime·goPanicSlice3BU(SB)
-TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSlice3C(SB)
-TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
- JMP runtime·goPanicSlice3CU(SB)
-TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
- MOVD R5, R3
- MOVD R6, R4
- JMP runtime·goPanicSliceConvert(SB)
-
-// These functions are used when internal linking cgo with external
-// objects compiled with the -Os on gcc. They reduce prologue/epilogue
-// size by deferring preservation of callee-save registers to a shared
-// function. These are defined in PPC64 ELFv2 2.3.3 (but also present
-// in ELFv1)
-//
-// These appear unused, but the linker will redirect calls to functions
-// like _savegpr0_14 or _restgpr1_14 to runtime.elf_savegpr0 or
-// runtime.elf_restgpr1 with an appropriate offset based on the number
-// register operations required when linking external objects which
-// make these calls. For GPR/FPR saves, the minimum register value is
-// 14, for VR it is 20.
-//
-// These are only used when linking such cgo code internally. Note, R12
-// and R0 may be used in different ways than regular ELF compliant
-// functions.
-TEXT runtime·elf_savegpr0(SB),NOSPLIT|NOFRAME,$0
- // R0 holds the LR of the caller's caller, R1 holds save location
- MOVD R14, -144(R1)
- MOVD R15, -136(R1)
- MOVD R16, -128(R1)
- MOVD R17, -120(R1)
- MOVD R18, -112(R1)
- MOVD R19, -104(R1)
- MOVD R20, -96(R1)
- MOVD R21, -88(R1)
- MOVD R22, -80(R1)
- MOVD R23, -72(R1)
- MOVD R24, -64(R1)
- MOVD R25, -56(R1)
- MOVD R26, -48(R1)
- MOVD R27, -40(R1)
- MOVD R28, -32(R1)
- MOVD R29, -24(R1)
- MOVD g, -16(R1)
- MOVD R31, -8(R1)
- MOVD R0, 16(R1)
- RET
-TEXT runtime·elf_restgpr0(SB),NOSPLIT|NOFRAME,$0
- // R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
- MOVD -144(R1), R14
- MOVD -136(R1), R15
- MOVD -128(R1), R16
- MOVD -120(R1), R17
- MOVD -112(R1), R18
- MOVD -104(R1), R19
- MOVD -96(R1), R20
- MOVD -88(R1), R21
- MOVD -80(R1), R22
- MOVD -72(R1), R23
- MOVD -64(R1), R24
- MOVD -56(R1), R25
- MOVD -48(R1), R26
- MOVD -40(R1), R27
- MOVD -32(R1), R28
- MOVD -24(R1), R29
- MOVD -16(R1), g
- MOVD -8(R1), R31
- MOVD 16(R1), R0 // Load and return to saved LR
- MOVD R0, LR
- RET
-TEXT runtime·elf_savegpr1(SB),NOSPLIT|NOFRAME,$0
- // R12 holds the save location
- MOVD R14, -144(R12)
- MOVD R15, -136(R12)
- MOVD R16, -128(R12)
- MOVD R17, -120(R12)
- MOVD R18, -112(R12)
- MOVD R19, -104(R12)
- MOVD R20, -96(R12)
- MOVD R21, -88(R12)
- MOVD R22, -80(R12)
- MOVD R23, -72(R12)
- MOVD R24, -64(R12)
- MOVD R25, -56(R12)
- MOVD R26, -48(R12)
- MOVD R27, -40(R12)
- MOVD R28, -32(R12)
- MOVD R29, -24(R12)
- MOVD g, -16(R12)
- MOVD R31, -8(R12)
- RET
-TEXT runtime·elf_restgpr1(SB),NOSPLIT|NOFRAME,$0
- // R12 holds the save location
- MOVD -144(R12), R14
- MOVD -136(R12), R15
- MOVD -128(R12), R16
- MOVD -120(R12), R17
- MOVD -112(R12), R18
- MOVD -104(R12), R19
- MOVD -96(R12), R20
- MOVD -88(R12), R21
- MOVD -80(R12), R22
- MOVD -72(R12), R23
- MOVD -64(R12), R24
- MOVD -56(R12), R25
- MOVD -48(R12), R26
- MOVD -40(R12), R27
- MOVD -32(R12), R28
- MOVD -24(R12), R29
- MOVD -16(R12), g
- MOVD -8(R12), R31
- RET
-TEXT runtime·elf_savefpr(SB),NOSPLIT|NOFRAME,$0
- // R0 holds the LR of the caller's caller, R1 holds save location
- FMOVD F14, -144(R1)
- FMOVD F15, -136(R1)
- FMOVD F16, -128(R1)
- FMOVD F17, -120(R1)
- FMOVD F18, -112(R1)
- FMOVD F19, -104(R1)
- FMOVD F20, -96(R1)
- FMOVD F21, -88(R1)
- FMOVD F22, -80(R1)
- FMOVD F23, -72(R1)
- FMOVD F24, -64(R1)
- FMOVD F25, -56(R1)
- FMOVD F26, -48(R1)
- FMOVD F27, -40(R1)
- FMOVD F28, -32(R1)
- FMOVD F29, -24(R1)
- FMOVD F30, -16(R1)
- FMOVD F31, -8(R1)
- MOVD R0, 16(R1)
- RET
-TEXT runtime·elf_restfpr(SB),NOSPLIT|NOFRAME,$0
- // R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
- FMOVD -144(R1), F14
- FMOVD -136(R1), F15
- FMOVD -128(R1), F16
- FMOVD -120(R1), F17
- FMOVD -112(R1), F18
- FMOVD -104(R1), F19
- FMOVD -96(R1), F20
- FMOVD -88(R1), F21
- FMOVD -80(R1), F22
- FMOVD -72(R1), F23
- FMOVD -64(R1), F24
- FMOVD -56(R1), F25
- FMOVD -48(R1), F26
- FMOVD -40(R1), F27
- FMOVD -32(R1), F28
- FMOVD -24(R1), F29
- FMOVD -16(R1), F30
- FMOVD -8(R1), F31
- MOVD 16(R1), R0 // Load and return to saved LR
- MOVD R0, LR
- RET
-TEXT runtime·elf_savevr(SB),NOSPLIT|NOFRAME,$0
- // R0 holds the save location, R12 is clobbered
- MOVD $-192, R12
- STVX V20, (R0+R12)
- MOVD $-176, R12
- STVX V21, (R0+R12)
- MOVD $-160, R12
- STVX V22, (R0+R12)
- MOVD $-144, R12
- STVX V23, (R0+R12)
- MOVD $-128, R12
- STVX V24, (R0+R12)
- MOVD $-112, R12
- STVX V25, (R0+R12)
- MOVD $-96, R12
- STVX V26, (R0+R12)
- MOVD $-80, R12
- STVX V27, (R0+R12)
- MOVD $-64, R12
- STVX V28, (R0+R12)
- MOVD $-48, R12
- STVX V29, (R0+R12)
- MOVD $-32, R12
- STVX V30, (R0+R12)
- MOVD $-16, R12
- STVX V31, (R0+R12)
- RET
-TEXT runtime·elf_restvr(SB),NOSPLIT|NOFRAME,$0
- // R0 holds the save location, R12 is clobbered
- MOVD $-192, R12
- LVX (R0+R12), V20
- MOVD $-176, R12
- LVX (R0+R12), V21
- MOVD $-160, R12
- LVX (R0+R12), V22
- MOVD $-144, R12
- LVX (R0+R12), V23
- MOVD $-128, R12
- LVX (R0+R12), V24
- MOVD $-112, R12
- LVX (R0+R12), V25
- MOVD $-96, R12
- LVX (R0+R12), V26
- MOVD $-80, R12
- LVX (R0+R12), V27
- MOVD $-64, R12
- LVX (R0+R12), V28
- MOVD $-48, R12
- LVX (R0+R12), V29
- MOVD $-32, R12
- LVX (R0+R12), V30
- MOVD $-16, R12
- LVX (R0+R12), V31
- RET
diff --git a/contrib/go/_std_1.22/src/runtime/asm_s390x.s b/contrib/go/_std_1.22/src/runtime/asm_s390x.s
deleted file mode 100644
index a8e1424bf181..000000000000
--- a/contrib/go/_std_1.22/src/runtime/asm_s390x.s
+++ /dev/null
@@ -1,951 +0,0 @@
-// Copyright 2016 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.
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "funcdata.h"
-#include "textflag.h"
-
-// _rt0_s390x_lib is common startup code for s390x systems when
-// using -buildmode=c-archive or -buildmode=c-shared. The linker will
-// arrange to invoke this function as a global constructor (for
-// c-archive) or when the shared library is loaded (for c-shared).
-// We expect argc and argv to be passed in the usual C ABI registers
-// R2 and R3.
-TEXT _rt0_s390x_lib(SB), NOSPLIT|NOFRAME, $0
- STMG R6, R15, 48(R15)
- MOVD R2, _rt0_s390x_lib_argc<>(SB)
- MOVD R3, _rt0_s390x_lib_argv<>(SB)
-
- // Save R6-R15 in the register save area of the calling function.
- STMG R6, R15, 48(R15)
-
- // Allocate 80 bytes on the stack.
- MOVD $-80(R15), R15
-
- // Save F8-F15 in our stack frame.
- FMOVD F8, 16(R15)
- FMOVD F9, 24(R15)
- FMOVD F10, 32(R15)
- FMOVD F11, 40(R15)
- FMOVD F12, 48(R15)
- FMOVD F13, 56(R15)
- FMOVD F14, 64(R15)
- FMOVD F15, 72(R15)
-
- // Synchronous initialization.
- MOVD $runtime·libpreinit(SB), R1
- BL R1
-
- // Create a new thread to finish Go runtime initialization.
- MOVD _cgo_sys_thread_create(SB), R1
- CMP R1, $0
- BEQ nocgo
- MOVD $_rt0_s390x_lib_go(SB), R2
- MOVD $0, R3
- BL R1
- BR restore
-
-nocgo:
- MOVD $0x800000, R1 // stacksize
- MOVD R1, 0(R15)
- MOVD $_rt0_s390x_lib_go(SB), R1
- MOVD R1, 8(R15) // fn
- MOVD $runtime·newosproc(SB), R1
- BL R1
-
-restore:
- // Restore F8-F15 from our stack frame.
- FMOVD 16(R15), F8
- FMOVD 24(R15), F9
- FMOVD 32(R15), F10
- FMOVD 40(R15), F11
- FMOVD 48(R15), F12
- FMOVD 56(R15), F13
- FMOVD 64(R15), F14
- FMOVD 72(R15), F15
- MOVD $80(R15), R15
-
- // Restore R6-R15.
- LMG 48(R15), R6, R15
- RET
-
-// _rt0_s390x_lib_go initializes the Go runtime.
-// This is started in a separate thread by _rt0_s390x_lib.
-TEXT _rt0_s390x_lib_go(SB), NOSPLIT|NOFRAME, $0
- MOVD _rt0_s390x_lib_argc<>(SB), R2
- MOVD _rt0_s390x_lib_argv<>(SB), R3
- MOVD $runtime·rt0_go(SB), R1
- BR R1
-
-DATA _rt0_s390x_lib_argc<>(SB)/8, $0
-GLOBL _rt0_s390x_lib_argc<>(SB), NOPTR, $8
-DATA _rt0_s90x_lib_argv<>(SB)/8, $0
-GLOBL _rt0_s390x_lib_argv<>(SB), NOPTR, $8
-
-TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
- // R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer
- // C TLS base pointer in AR0:AR1
-
- // initialize essential registers
- XOR R0, R0
-
- SUB $24, R15
- MOVW R2, 8(R15) // argc
- MOVD R3, 16(R15) // argv
-
- // create istack out of the given (operating system) stack.
- // _cgo_init may update stackguard.
- MOVD $runtime·g0(SB), g
- MOVD R15, R11
- SUB $(64*1024), R11
- MOVD R11, g_stackguard0(g)
- MOVD R11, g_stackguard1(g)
- MOVD R11, (g_stack+stack_lo)(g)
- MOVD R15, (g_stack+stack_hi)(g)
-
- // if there is a _cgo_init, call it using the gcc ABI.
- MOVD _cgo_init(SB), R11
- CMPBEQ R11, $0, nocgo
- MOVW AR0, R4 // (AR0 << 32 | AR1) is the TLS base pointer; MOVD is translated to EAR
- SLD $32, R4, R4
- MOVW AR1, R4 // arg 2: TLS base pointer
- MOVD $setg_gcc<>(SB), R3 // arg 1: setg
- MOVD g, R2 // arg 0: G
- // C functions expect 160 bytes of space on caller stack frame
- // and an 8-byte aligned stack pointer
- MOVD R15, R9 // save current stack (R9 is preserved in the Linux ABI)
- SUB $160, R15 // reserve 160 bytes
- MOVD $~7, R6
- AND R6, R15 // 8-byte align
- BL R11 // this call clobbers volatile registers according to Linux ABI (R0-R5, R14)
- MOVD R9, R15 // restore stack
- XOR R0, R0 // zero R0
-
-nocgo:
- // update stackguard after _cgo_init
- MOVD (g_stack+stack_lo)(g), R2
- ADD $const_stackGuard, R2
- MOVD R2, g_stackguard0(g)
- MOVD R2, g_stackguard1(g)
-
- // set the per-goroutine and per-mach "registers"
- MOVD $runtime·m0(SB), R2
-
- // save m->g0 = g0
- MOVD g, m_g0(R2)
- // save m0 to g0->m
- MOVD R2, g_m(g)
-
- BL runtime·check(SB)
-
- // argc/argv are already prepared on stack
- BL runtime·args(SB)
- BL runtime·checkS390xCPU(SB)
- BL runtime·osinit(SB)
- BL runtime·schedinit(SB)
-
- // create a new goroutine to start program
- MOVD $runtime·mainPC(SB), R2 // entry
- SUB $16, R15
- MOVD R2, 8(R15)
- MOVD $0, 0(R15)
- BL runtime·newproc(SB)
- ADD $16, R15
-
- // start this M
- BL runtime·mstart(SB)
-
- MOVD $0, 1(R0)
- RET
-
-DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
-GLOBL runtime·mainPC(SB),RODATA,$8
-
-TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
- BRRK
- RET
-
-TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
- RET
-
-TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
- CALL runtime·mstart0(SB)
- RET // not reached
-
-/*
- * go-routine
- */
-
-// void gogo(Gobuf*)
-// restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
- MOVD buf+0(FP), R5
- MOVD gobuf_g(R5), R6
- MOVD 0(R6), R7 // make sure g != nil
- BR gogo<>(SB)
-
-TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
- MOVD R6, g
- BL runtime·save_g(SB)
-
- MOVD 0(g), R4
- MOVD gobuf_sp(R5), R15
- MOVD gobuf_lr(R5), LR
- MOVD gobuf_ret(R5), R3
- MOVD gobuf_ctxt(R5), R12
- MOVD $0, gobuf_sp(R5)
- MOVD $0, gobuf_ret(R5)
- MOVD $0, gobuf_lr(R5)
- MOVD $0, gobuf_ctxt(R5)
- CMP R0, R0 // set condition codes for == test, needed by stack split
- MOVD gobuf_pc(R5), R6
- BR (R6)
-
-// void mcall(fn func(*g))
-// Switch to m->g0's stack, call fn(g).
-// Fn must never return. It should gogo(&g->sched)
-// to keep running g.
-TEXT runtime·mcall(SB), NOSPLIT, $-8-8
- // Save caller state in g->sched
- MOVD R15, (g_sched+gobuf_sp)(g)
- MOVD LR, (g_sched+gobuf_pc)(g)
- MOVD $0, (g_sched+gobuf_lr)(g)
-
- // Switch to m->g0 & its stack, call fn.
- MOVD g, R3
- MOVD g_m(g), R8
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- CMP g, R3
- BNE 2(PC)
- BR runtime·badmcall(SB)
- MOVD fn+0(FP), R12 // context
- MOVD 0(R12), R4 // code pointer
- MOVD (g_sched+gobuf_sp)(g), R15 // sp = m->g0->sched.sp
- SUB $16, R15
- MOVD R3, 8(R15)
- MOVD $0, 0(R15)
- BL (R4)
- BR runtime·badmcall2(SB)
-
-// systemstack_switch is a dummy routine that systemstack leaves at the bottom
-// of the G stack. We need to distinguish the routine that
-// lives at the bottom of the G stack from the one that lives
-// at the top of the system stack because the one at the top of
-// the system stack terminates the stack walk (see topofstack()).
-TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
- UNDEF
- BL (LR) // make sure this function is not leaf
- RET
-
-// func systemstack(fn func())
-TEXT runtime·systemstack(SB), NOSPLIT, $0-8
- MOVD fn+0(FP), R3 // R3 = fn
- MOVD R3, R12 // context
- MOVD g_m(g), R4 // R4 = m
-
- MOVD m_gsignal(R4), R5 // R5 = gsignal
- CMPBEQ g, R5, noswitch
-
- MOVD m_g0(R4), R5 // R5 = g0
- CMPBEQ g, R5, noswitch
-
- MOVD m_curg(R4), R6
- CMPBEQ g, R6, switch
-
- // Bad: g is not gsignal, not g0, not curg. What is it?
- // Hide call from linker nosplit analysis.
- MOVD $runtime·badsystemstack(SB), R3
- BL (R3)
- BL runtime·abort(SB)
-
-switch:
- // save our state in g->sched. Pretend to
- // be systemstack_switch if the G stack is scanned.
- BL gosave_systemstack_switch<>(SB)
-
- // switch to g0
- MOVD R5, g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R15
-
- // call target function
- MOVD 0(R12), R3 // code pointer
- BL (R3)
-
- // switch back to g
- MOVD g_m(g), R3
- MOVD m_curg(R3), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R15
- MOVD $0, (g_sched+gobuf_sp)(g)
- RET
-
-noswitch:
- // already on m stack, just call directly
- // Using a tail call here cleans up tracebacks since we won't stop
- // at an intermediate systemstack.
- MOVD 0(R12), R3 // code pointer
- MOVD 0(R15), LR // restore LR
- ADD $8, R15
- BR (R3)
-
-/*
- * support for morestack
- */
-
-// Called during function prolog when more stack is needed.
-// Caller has already loaded:
-// R3: framesize, R4: argsize, R5: LR
-//
-// The traceback routines see morestack on a g0 as being
-// the top of a stack (for example, morestack calling newstack
-// calling the scheduler calling newm calling gc), so we must
-// record an argument size. For that purpose, it has no arguments.
-TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
- // Cannot grow scheduler stack (m->g0).
- MOVD g_m(g), R7
- MOVD m_g0(R7), R8
- CMPBNE g, R8, 3(PC)
- BL runtime·badmorestackg0(SB)
- BL runtime·abort(SB)
-
- // Cannot grow signal stack (m->gsignal).
- MOVD m_gsignal(R7), R8
- CMP g, R8
- BNE 3(PC)
- BL runtime·badmorestackgsignal(SB)
- BL runtime·abort(SB)
-
- // Called from f.
- // Set g->sched to context in f.
- MOVD R15, (g_sched+gobuf_sp)(g)
- MOVD LR, R8
- MOVD R8, (g_sched+gobuf_pc)(g)
- MOVD R5, (g_sched+gobuf_lr)(g)
- MOVD R12, (g_sched+gobuf_ctxt)(g)
-
- // Called from f.
- // Set m->morebuf to f's caller.
- MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
- MOVD R15, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
- MOVD g, (m_morebuf+gobuf_g)(R7)
-
- // Call newstack on m->g0's stack.
- MOVD m_g0(R7), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R15
- // Create a stack frame on g0 to call newstack.
- MOVD $0, -8(R15) // Zero saved LR in frame
- SUB $8, R15
- BL runtime·newstack(SB)
-
- // Not reached, but make sure the return PC from the call to newstack
- // is still in this function, and not the beginning of the next.
- UNDEF
-
-TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
- // Force SPWRITE. This function doesn't actually write SP,
- // but it is called with a special calling convention where
- // the caller doesn't save LR on stack but passes it as a
- // register (R5), and the unwinder currently doesn't understand.
- // Make it SPWRITE to stop unwinding. (See issue 54332)
- MOVD R15, R15
-
- MOVD $0, R12
- BR runtime·morestack(SB)
-
-// reflectcall: call a function with the given argument list
-// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
-// we don't have variable-sized frames, so we use a small number
-// of constant-sized-frame functions to encode a few bits of size in the pc.
-// Caution: ugly multiline assembly macros in your future!
-
-#define DISPATCH(NAME,MAXSIZE) \
- MOVD $MAXSIZE, R4; \
- CMP R3, R4; \
- BGT 3(PC); \
- MOVD $NAME(SB), R5; \
- BR (R5)
-// Note: can't just "BR NAME(SB)" - bad inlining results.
-
-TEXT ·reflectcall(SB), NOSPLIT, $-8-48
- MOVWZ frameSize+32(FP), R3
- DISPATCH(runtime·call16, 16)
- DISPATCH(runtime·call32, 32)
- DISPATCH(runtime·call64, 64)
- DISPATCH(runtime·call128, 128)
- DISPATCH(runtime·call256, 256)
- DISPATCH(runtime·call512, 512)
- DISPATCH(runtime·call1024, 1024)
- DISPATCH(runtime·call2048, 2048)
- DISPATCH(runtime·call4096, 4096)
- DISPATCH(runtime·call8192, 8192)
- DISPATCH(runtime·call16384, 16384)
- DISPATCH(runtime·call32768, 32768)
- DISPATCH(runtime·call65536, 65536)
- DISPATCH(runtime·call131072, 131072)
- DISPATCH(runtime·call262144, 262144)
- DISPATCH(runtime·call524288, 524288)
- DISPATCH(runtime·call1048576, 1048576)
- DISPATCH(runtime·call2097152, 2097152)
- DISPATCH(runtime·call4194304, 4194304)
- DISPATCH(runtime·call8388608, 8388608)
- DISPATCH(runtime·call16777216, 16777216)
- DISPATCH(runtime·call33554432, 33554432)
- DISPATCH(runtime·call67108864, 67108864)
- DISPATCH(runtime·call134217728, 134217728)
- DISPATCH(runtime·call268435456, 268435456)
- DISPATCH(runtime·call536870912, 536870912)
- DISPATCH(runtime·call1073741824, 1073741824)
- MOVD $runtime·badreflectcall(SB), R5
- BR (R5)
-
-#define CALLFN(NAME,MAXSIZE) \
-TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
- NO_LOCAL_POINTERS; \
- /* copy arguments to stack */ \
- MOVD stackArgs+16(FP), R4; \
- MOVWZ stackArgsSize+24(FP), R5; \
- MOVD $stack-MAXSIZE(SP), R6; \
-loopArgs: /* copy 256 bytes at a time */ \
- CMP R5, $256; \
- BLT tailArgs; \
- SUB $256, R5; \
- MVC $256, 0(R4), 0(R6); \
- MOVD $256(R4), R4; \
- MOVD $256(R6), R6; \
- BR loopArgs; \
-tailArgs: /* copy remaining bytes */ \
- CMP R5, $0; \
- BEQ callFunction; \
- SUB $1, R5; \
- EXRL $callfnMVC<>(SB), R5; \
-callFunction: \
- MOVD f+8(FP), R12; \
- MOVD (R12), R8; \
- PCDATA $PCDATA_StackMapIndex, $0; \
- BL (R8); \
- /* copy return values back */ \
- MOVD stackArgsType+0(FP), R7; \
- MOVD stackArgs+16(FP), R6; \
- MOVWZ stackArgsSize+24(FP), R5; \
- MOVD $stack-MAXSIZE(SP), R4; \
- MOVWZ stackRetOffset+28(FP), R1; \
- ADD R1, R4; \
- ADD R1, R6; \
- SUB R1, R5; \
- BL callRet<>(SB); \
- RET
-
-// callRet copies return values back at the end of call*. This is a
-// separate function so it can allocate stack space for the arguments
-// to reflectcallmove. It does not follow the Go ABI; it expects its
-// arguments in registers.
-TEXT callRet<>(SB), NOSPLIT, $40-0
- MOVD R7, 8(R15)
- MOVD R6, 16(R15)
- MOVD R4, 24(R15)
- MOVD R5, 32(R15)
- MOVD $0, 40(R15)
- BL runtime·reflectcallmove(SB)
- RET
-
-CALLFN(·call16, 16)
-CALLFN(·call32, 32)
-CALLFN(·call64, 64)
-CALLFN(·call128, 128)
-CALLFN(·call256, 256)
-CALLFN(·call512, 512)
-CALLFN(·call1024, 1024)
-CALLFN(·call2048, 2048)
-CALLFN(·call4096, 4096)
-CALLFN(·call8192, 8192)
-CALLFN(·call16384, 16384)
-CALLFN(·call32768, 32768)
-CALLFN(·call65536, 65536)
-CALLFN(·call131072, 131072)
-CALLFN(·call262144, 262144)
-CALLFN(·call524288, 524288)
-CALLFN(·call1048576, 1048576)
-CALLFN(·call2097152, 2097152)
-CALLFN(·call4194304, 4194304)
-CALLFN(·call8388608, 8388608)
-CALLFN(·call16777216, 16777216)
-CALLFN(·call33554432, 33554432)
-CALLFN(·call67108864, 67108864)
-CALLFN(·call134217728, 134217728)
-CALLFN(·call268435456, 268435456)
-CALLFN(·call536870912, 536870912)
-CALLFN(·call1073741824, 1073741824)
-
-// Not a function: target for EXRL (execute relative long) instruction.
-TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0
- MVC $1, 0(R4), 0(R6)
-
-TEXT runtime·procyield(SB),NOSPLIT,$0-0
- RET
-
-// Save state of caller into g->sched,
-// but using fake PC from systemstack_switch.
-// Must only be called from functions with no locals ($0)
-// or else unwinding from systemstack_switch is incorrect.
-// Smashes R1.
-TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
- MOVD $runtime·systemstack_switch(SB), R1
- ADD $16, R1 // get past prologue
- MOVD R1, (g_sched+gobuf_pc)(g)
- MOVD R15, (g_sched+gobuf_sp)(g)
- MOVD $0, (g_sched+gobuf_lr)(g)
- MOVD $0, (g_sched+gobuf_ret)(g)
- // Assert ctxt is zero. See func save.
- MOVD (g_sched+gobuf_ctxt)(g), R1
- CMPBEQ R1, $0, 2(PC)
- BL runtime·abort(SB)
- RET
-
-// func asmcgocall(fn, arg unsafe.Pointer) int32
-// Call fn(arg) on the scheduler stack,
-// aligned appropriately for the gcc ABI.
-// See cgocall.go for more details.
-TEXT ·asmcgocall(SB),NOSPLIT,$0-20
- // R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer
- // C TLS base pointer in AR0:AR1
- MOVD fn+0(FP), R3
- MOVD arg+8(FP), R4
-
- MOVD R15, R2 // save original stack pointer
- MOVD g, R5
-
- // Figure out if we need to switch to m->g0 stack.
- // We get called to create new OS threads too, and those
- // come in on the m->g0 stack already. Or we might already
- // be on the m->gsignal stack.
- MOVD g_m(g), R6
- MOVD m_gsignal(R6), R7
- CMPBEQ R7, g, g0
- MOVD m_g0(R6), R7
- CMPBEQ R7, g, g0
- BL gosave_systemstack_switch<>(SB)
- MOVD R7, g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R15
-
- // Now on a scheduling stack (a pthread-created stack).
-g0:
- // Save room for two of our pointers, plus 160 bytes of callee
- // save area that lives on the caller stack.
- SUB $176, R15
- MOVD $~7, R6
- AND R6, R15 // 8-byte alignment for gcc ABI
- MOVD R5, 168(R15) // save old g on stack
- MOVD (g_stack+stack_hi)(R5), R5
- SUB R2, R5
- MOVD R5, 160(R15) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
- MOVD $0, 0(R15) // clear back chain pointer (TODO can we give it real back trace information?)
- MOVD R4, R2 // arg in R2
- BL R3 // can clobber: R0-R5, R14, F0-F3, F5, F7-F15
-
- XOR R0, R0 // set R0 back to 0.
- // Restore g, stack pointer.
- MOVD 168(R15), g
- BL runtime·save_g(SB)
- MOVD (g_stack+stack_hi)(g), R5
- MOVD 160(R15), R6
- SUB R6, R5
- MOVD R5, R15
-
- MOVW R2, ret+16(FP)
- RET
-
-// cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
-// See cgocall.go for more details.
-TEXT ·cgocallback(SB),NOSPLIT,$24-24
- NO_LOCAL_POINTERS
-
- // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
- // It is used to dropm while thread is exiting.
- MOVD fn+0(FP), R1
- CMPBNE R1, $0, loadg
- // Restore the g from frame.
- MOVD frame+8(FP), g
- BR dropm
-
-loadg:
- // Load m and g from thread-local storage.
- MOVB runtime·iscgo(SB), R3
- CMPBEQ R3, $0, nocgo
- BL runtime·load_g(SB)
-
-nocgo:
- // If g is nil, Go did not create the current thread,
- // or if this thread never called into Go on pthread platforms.
- // Call needm to obtain one for temporary use.
- // In this case, we're running on the thread stack, so there's
- // lots of space, but the linker doesn't know. Hide the call from
- // the linker analysis by using an indirect call.
- CMPBEQ g, $0, needm
-
- MOVD g_m(g), R8
- MOVD R8, savedm-8(SP)
- BR havem
-
-needm:
- MOVD g, savedm-8(SP) // g is zero, so is m.
- MOVD $runtime·needAndBindM(SB), R3
- BL (R3)
-
- // Set m->sched.sp = SP, so that if a panic happens
- // during the function we are about to execute, it will
- // have a valid SP to run on the g0 stack.
- // The next few lines (after the havem label)
- // will save this SP onto the stack and then write
- // the same SP back to m->sched.sp. That seems redundant,
- // but if an unrecovered panic happens, unwindm will
- // restore the g->sched.sp from the stack location
- // and then systemstack will try to use it. If we don't set it here,
- // that restored SP will be uninitialized (typically 0) and
- // will not be usable.
- MOVD g_m(g), R8
- MOVD m_g0(R8), R3
- MOVD R15, (g_sched+gobuf_sp)(R3)
-
-havem:
- // Now there's a valid m, and we're running on its m->g0.
- // Save current m->g0->sched.sp on stack and then set it to SP.
- // Save current sp in m->g0->sched.sp in preparation for
- // switch back to m->curg stack.
- // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
- MOVD m_g0(R8), R3
- MOVD (g_sched+gobuf_sp)(R3), R4
- MOVD R4, savedsp-24(SP) // must match frame size
- MOVD R15, (g_sched+gobuf_sp)(R3)
-
- // Switch to m->curg stack and call runtime.cgocallbackg.
- // Because we are taking over the execution of m->curg
- // but *not* resuming what had been running, we need to
- // save that information (m->curg->sched) so we can restore it.
- // We can restore m->curg->sched.sp easily, because calling
- // runtime.cgocallbackg leaves SP unchanged upon return.
- // To save m->curg->sched.pc, we push it onto the curg stack and
- // open a frame the same size as cgocallback's g0 frame.
- // Once we switch to the curg stack, the pushed PC will appear
- // to be the return PC of cgocallback, so that the traceback
- // will seamlessly trace back into the earlier calls.
- MOVD m_curg(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
- MOVD (g_sched+gobuf_pc)(g), R5
- MOVD R5, -(24+8)(R4) // "saved LR"; must match frame size
- // Gather our arguments into registers.
- MOVD fn+0(FP), R1
- MOVD frame+8(FP), R2
- MOVD ctxt+16(FP), R3
- MOVD $-(24+8)(R4), R15 // switch stack; must match frame size
- MOVD R1, 8(R15)
- MOVD R2, 16(R15)
- MOVD R3, 24(R15)
- BL runtime·cgocallbackg(SB)
-
- // Restore g->sched (== m->curg->sched) from saved values.
- MOVD 0(R15), R5
- MOVD R5, (g_sched+gobuf_pc)(g)
- MOVD $(24+8)(R15), R4 // must match frame size
- MOVD R4, (g_sched+gobuf_sp)(g)
-
- // Switch back to m->g0's stack and restore m->g0->sched.sp.
- // (Unlike m->curg, the g0 goroutine never uses sched.pc,
- // so we do not have to restore it.)
- MOVD g_m(g), R8
- MOVD m_g0(R8), g
- BL runtime·save_g(SB)
- MOVD (g_sched+gobuf_sp)(g), R15
- MOVD savedsp-24(SP), R4 // must match frame size
- MOVD R4, (g_sched+gobuf_sp)(g)
-
- // If the m on entry was nil, we called needm above to borrow an m,
- // 1. for the duration of the call on non-pthread platforms,
- // 2. or the duration of the C thread alive on pthread platforms.
- // If the m on entry wasn't nil,
- // 1. the thread might be a Go thread,
- // 2. or it wasn't the first call from a C thread on pthread platforms,
- // since then we skip dropm to reuse the m in the first call.
- MOVD savedm-8(SP), R6
- CMPBNE R6, $0, droppedm
-
- // Skip dropm to reuse it in the next call, when a pthread key has been created.
- MOVD _cgo_pthread_key_created(SB), R6
- // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
- CMPBEQ R6, $0, dropm
- MOVD (R6), R6
- CMPBNE R6, $0, droppedm
-
-dropm:
- MOVD $runtime·dropm(SB), R3
- BL (R3)
-droppedm:
-
- // Done!
- RET
-
-// void setg(G*); set g. for use by needm.
-TEXT runtime·setg(SB), NOSPLIT, $0-8
- MOVD gg+0(FP), g
- // This only happens if iscgo, so jump straight to save_g
- BL runtime·save_g(SB)
- RET
-
-// void setg_gcc(G*); set g in C TLS.
-// Must obey the gcc calling convention.
-TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
- // The standard prologue clobbers LR (R14), which is callee-save in
- // the C ABI, so we have to use NOFRAME and save LR ourselves.
- MOVD LR, R1
- // Also save g, R10, and R11 since they're callee-save in C ABI
- MOVD R10, R3
- MOVD g, R4
- MOVD R11, R5
-
- MOVD R2, g
- BL runtime·save_g(SB)
-
- MOVD R5, R11
- MOVD R4, g
- MOVD R3, R10
- MOVD R1, LR
- RET
-
-TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
- MOVW (R0), R0
- UNDEF
-
-// int64 runtime·cputicks(void)
-TEXT runtime·cputicks(SB),NOSPLIT,$0-8
- // The TOD clock on s390 counts from the year 1900 in ~250ps intervals.
- // This means that since about 1972 the msb has been set, making the
- // result of a call to STORE CLOCK (stck) a negative number.
- // We clear the msb to make it positive.
- STCK ret+0(FP) // serialises before and after call
- MOVD ret+0(FP), R3 // R3 will wrap to 0 in the year 2043
- SLD $1, R3
- SRD $1, R3
- MOVD R3, ret+0(FP)
- RET
-
-// AES hashing not implemented for s390x
-TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
- JMP runtime·memhashFallback(SB)
-TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·strhashFallback(SB)
-TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·memhash32Fallback(SB)
-TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
- JMP runtime·memhash64Fallback(SB)
-
-TEXT runtime·return0(SB), NOSPLIT, $0
- MOVW $0, R3
- RET
-
-// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
-// Must obey the gcc calling convention.
-TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
- // g (R13), R10, R11 and LR (R14) are callee-save in the C ABI, so save them
- MOVD g, R1
- MOVD R10, R3
- MOVD LR, R4
- MOVD R11, R5
-
- BL runtime·load_g(SB) // clobbers g (R13), R10, R11
- MOVD g_m(g), R2
- MOVD m_curg(R2), R2
- MOVD (g_stack+stack_hi)(R2), R2
-
- MOVD R1, g
- MOVD R3, R10
- MOVD R4, LR
- MOVD R5, R11
- RET
-
-// The top-most function running on a goroutine
-// returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
- BYTE $0x07; BYTE $0x00; // 2-byte nop
- BL runtime·goexit1(SB) // does not return
- // traceback from goexit1 must hit code range of goexit
- BYTE $0x07; BYTE $0x00; // 2-byte nop
-
-TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
- // Stores are already ordered on s390x, so this is just a
- // compile barrier.
- RET
-
-// This is called from .init_array and follows the platform, not Go, ABI.
-// We are overly conservative. We could only save the registers we use.
-// However, since this function is only called once per loaded module
-// performance is unimportant.
-TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
- // Save R6-R15 in the register save area of the calling function.
- // Don't bother saving F8-F15 as we aren't doing any calls.
- STMG R6, R15, 48(R15)
-
- // append the argument (passed in R2, as per the ELF ABI) to the
- // moduledata linked list.
- MOVD runtime·lastmoduledatap(SB), R1
- MOVD R2, moduledata_next(R1)
- MOVD R2, runtime·lastmoduledatap(SB)
-
- // Restore R6-R15.
- LMG 48(R15), R6, R15
- RET
-
-TEXT ·checkASM(SB),NOSPLIT,$0-1
- MOVB $1, ret+0(FP)
- RET
-
-// gcWriteBarrier informs the GC about heap pointer writes.
-//
-// gcWriteBarrier does NOT follow the Go ABI. It accepts the
-// number of bytes of buffer needed in R9, and returns a pointer
-// to the buffer space in R9.
-// It clobbers R10 (the temp register) and R1 (used by PLT stub).
-// It does not clobber any other general-purpose registers,
-// but may clobber others (e.g., floating point registers).
-TEXT gcWriteBarrier<>(SB),NOSPLIT,$96
- // Save the registers clobbered by the fast path.
- MOVD R4, 96(R15)
-retry:
- MOVD g_m(g), R1
- MOVD m_p(R1), R1
- // Increment wbBuf.next position.
- MOVD R9, R4
- ADD (p_wbBuf+wbBuf_next)(R1), R4
- // Is the buffer full?
- MOVD (p_wbBuf+wbBuf_end)(R1), R10
- CMPUBGT R4, R10, flush
- // Commit to the larger buffer.
- MOVD R4, (p_wbBuf+wbBuf_next)(R1)
- // Make return value (the original next position)
- SUB R9, R4, R9
- // Restore registers.
- MOVD 96(R15), R4
- RET
-
-flush:
- // Save all general purpose registers since these could be
- // clobbered by wbBufFlush and were not saved by the caller.
- STMG R2, R3, 8(R15)
- MOVD R0, 24(R15)
- // R1 already saved.
- // R4 already saved.
- STMG R5, R12, 32(R15) // save R5 - R12
- // R13 is g.
- // R14 is LR.
- // R15 is SP.
-
- CALL runtime·wbBufFlush(SB)
-
- LMG 8(R15), R2, R3 // restore R2 - R3
- MOVD 24(R15), R0 // restore R0
- LMG 32(R15), R5, R12 // restore R5 - R12
- JMP retry
-
-TEXT runtime·gcWriteBarrier1(SB),NOSPLIT,$0
- MOVD $8, R9
- JMP gcWriteBarrier<>(SB)
-TEXT runtime·gcWriteBarrier2