[vm] Extract runtime offsets as JSON
Print constants as JSON in runtime/vm/compiler/offsets_extractor.cc instead of generating C++ declarations. tools/run_offsets_extractor.dart reads JSON and generates C++ declarations (runtime/vm/compiler/runtime_offsets_extracted.h). This would allow us to have different output formats in future (e.g. C++ and Dart). TEST=dart tools/run_offsets_extractor.dart Change-Id: Ib8576766ae8cc21583b5a7b27998fd88b733b3a1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/443140 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
35ec2eac8d
commit
c237ac8e23
@@ -18,39 +18,38 @@
|
||||
#include "vm/timeline.h"
|
||||
|
||||
#if defined(PRODUCT)
|
||||
#define PRODUCT_DEF "defined(PRODUCT)"
|
||||
#define PRODUCT_DEF "true"
|
||||
#else
|
||||
#define PRODUCT_DEF "!defined(PRODUCT)"
|
||||
#define PRODUCT_DEF "false"
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_ARCH_ARM)
|
||||
#define ARCH_DEF_CPU "defined(TARGET_ARCH_ARM)"
|
||||
#define ARCH_DEF_CPU "arm"
|
||||
#elif defined(TARGET_ARCH_X64)
|
||||
#define ARCH_DEF_CPU "defined(TARGET_ARCH_X64)"
|
||||
#define ARCH_DEF_CPU "x64"
|
||||
#elif defined(TARGET_ARCH_IA32)
|
||||
#define ARCH_DEF_CPU "defined(TARGET_ARCH_IA32)"
|
||||
#define ARCH_DEF_CPU "ia32"
|
||||
#elif defined(TARGET_ARCH_ARM64)
|
||||
#define ARCH_DEF_CPU "defined(TARGET_ARCH_ARM64)"
|
||||
#define ARCH_DEF_CPU "arm64"
|
||||
#elif defined(TARGET_ARCH_RISCV32)
|
||||
#define ARCH_DEF_CPU "defined(TARGET_ARCH_RISCV32)"
|
||||
#define ARCH_DEF_CPU "riscv32"
|
||||
#elif defined(TARGET_ARCH_RISCV64)
|
||||
#define ARCH_DEF_CPU "defined(TARGET_ARCH_RISCV64)"
|
||||
#define ARCH_DEF_CPU "riscv64"
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
||||
#if defined(DART_COMPRESSED_POINTERS)
|
||||
#define COMPRESSED_DEF "defined(DART_COMPRESSED_POINTERS)"
|
||||
#define COMPRESSED_DEF "true"
|
||||
#else
|
||||
#define COMPRESSED_DEF "!defined(DART_COMPRESSED_POINTERS)"
|
||||
#define COMPRESSED_DEF "false"
|
||||
#endif
|
||||
|
||||
#define PREPROCESSOR_CONDITION \
|
||||
"#if " PRODUCT_DEF " && " ARCH_DEF_CPU " && " COMPRESSED_DEF
|
||||
|
||||
#define PREPROCESSOR_CONDITION_END \
|
||||
"#endif // " PRODUCT_DEF " && \n // " ARCH_DEF_CPU \
|
||||
" && \n // " COMPRESSED_DEF
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
#define AOT_DEF "true"
|
||||
#else
|
||||
#define AOT_DEF "false"
|
||||
#endif
|
||||
|
||||
namespace dart {
|
||||
|
||||
@@ -73,100 +72,57 @@ class OffsetsExtractor : public AllStatic {
|
||||
#define PRINT_ARRAY_SIZEOF(Class, Name, ElementOffset)
|
||||
#define PRINT_PAYLOAD_SIZEOF(Class, Name, HeaderSize)
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#define PRINT_FIELD_OFFSET(Class, Name) \
|
||||
std::cout << "static constexpr dart::compiler::target::word AOT_" #Class \
|
||||
"_" #Name " = 0x" \
|
||||
<< Class::Name() << ";\n";
|
||||
std::cout << "{\"kind\": \"value\"," \
|
||||
" \"class\": \"" #Class "\", \"name\": \"" #Name \
|
||||
"\", \"value\": \"" \
|
||||
<< Class::Name() << "\"},\n";
|
||||
|
||||
#define PRINT_ARRAY_LAYOUT(Class, Name) \
|
||||
std::cout << "static constexpr dart::compiler::target::word AOT_" #Class \
|
||||
"_elements_start_offset = 0x" \
|
||||
<< Class::ArrayTraits::elements_start_offset() << ";\n"; \
|
||||
std::cout << "static constexpr dart::compiler::target::word AOT_" #Class \
|
||||
"_element_size = 0x" \
|
||||
<< Class::ArrayTraits::kElementSize << ";\n";
|
||||
std::cout << "{\"kind\": \"array\"," \
|
||||
" \"class\": \"" #Class "\", \"startOffset\": \"" \
|
||||
<< Class::ArrayTraits::elements_start_offset() \
|
||||
<< "\", \"elemSize\": \"" << Class::ArrayTraits::kElementSize \
|
||||
<< "\"},\n";
|
||||
|
||||
#define PRINT_SIZEOF(Class, Name, What) \
|
||||
std::cout << "static constexpr dart::compiler::target::word AOT_" #Class \
|
||||
"_" #Name " = 0x" \
|
||||
<< sizeof(What) << ";\n";
|
||||
std::cout << "{\"kind\": \"value\"," \
|
||||
" \"class\": \"" #Class "\", \"name\": \"" #Name \
|
||||
"\", \"value\": \"" \
|
||||
<< sizeof(What) << "\"},\n";
|
||||
|
||||
#define PRINT_RANGE(Class, Name, Type, First, Last, Filter) \
|
||||
{ \
|
||||
auto filter = Filter; \
|
||||
bool comma = false; \
|
||||
std::cout << "static constexpr dart::compiler::target::word AOT_" #Class \
|
||||
"_" #Name "[] = {"; \
|
||||
std::cout << "{\"kind\": \"range\"," \
|
||||
" \"class\": \"" #Class "\", \"name\": \"" #Name \
|
||||
"\", \"values\": ["; \
|
||||
for (intptr_t i = static_cast<intptr_t>(First); \
|
||||
i <= static_cast<intptr_t>(Last); i++) { \
|
||||
auto v = static_cast<Type>(i); \
|
||||
std::cout << (comma ? ", " : ""); \
|
||||
if (filter(v)) { \
|
||||
std::cout << "0x" << Class::Name(v); \
|
||||
std::cout << "\"" << Class::Name(v) << "\""; \
|
||||
} else { \
|
||||
std::cout << "-1"; \
|
||||
std::cout << "\"-1\""; \
|
||||
} \
|
||||
comma = true; \
|
||||
} \
|
||||
std::cout << "};\n"; \
|
||||
std::cout << "]},\n"; \
|
||||
}
|
||||
|
||||
#define PRINT_CONSTANT(Class, Name) \
|
||||
std::cout << "static constexpr dart::compiler::target::word AOT_" #Class \
|
||||
"_" #Name " = 0x" \
|
||||
<< Class::Name << ";\n";
|
||||
std::cout << "{\"kind\": \"value\"," \
|
||||
" \"class\": \"" #Class "\", \"name\": \"" #Name \
|
||||
"\", \"value\": \"" \
|
||||
<< Class::Name << "\"},\n";
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
AOT_OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT, PRINT_SIZEOF,
|
||||
PRINT_ARRAY_SIZEOF, PRINT_PAYLOAD_SIZEOF, PRINT_RANGE,
|
||||
PRINT_CONSTANT)
|
||||
|
||||
#else // defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#define PRINT_FIELD_OFFSET(Class, Name) \
|
||||
std::cout << "static constexpr dart::compiler::target::word " #Class \
|
||||
"_" #Name " = 0x" \
|
||||
<< Class::Name() << ";\n";
|
||||
|
||||
#define PRINT_ARRAY_LAYOUT(Class, Name) \
|
||||
std::cout << "static constexpr dart::compiler::target::word " #Class \
|
||||
"_elements_start_offset = 0x" \
|
||||
<< Class::ArrayTraits::elements_start_offset() << ";\n"; \
|
||||
std::cout << "static constexpr dart::compiler::target::word " #Class \
|
||||
"_element_size = 0x" \
|
||||
<< Class::ArrayTraits::kElementSize << ";\n";
|
||||
|
||||
#define PRINT_SIZEOF(Class, Name, What) \
|
||||
std::cout << "static constexpr dart::compiler::target::word " #Class \
|
||||
"_" #Name " = 0x" \
|
||||
<< sizeof(What) << ";\n";
|
||||
|
||||
#define PRINT_RANGE(Class, Name, Type, First, Last, Filter) \
|
||||
{ \
|
||||
auto filter = Filter; \
|
||||
bool comma = false; \
|
||||
std::cout << "static constexpr dart::compiler::target::word " #Class \
|
||||
"_" #Name "[] = {"; \
|
||||
for (intptr_t i = static_cast<intptr_t>(First); \
|
||||
i <= static_cast<intptr_t>(Last); i++) { \
|
||||
auto v = static_cast<Type>(i); \
|
||||
std::cout << (comma ? ", " : ""); \
|
||||
if (filter(v)) { \
|
||||
std::cout << "0x" << Class::Name(v); \
|
||||
} else { \
|
||||
std::cout << "-1"; \
|
||||
} \
|
||||
comma = true; \
|
||||
} \
|
||||
std::cout << "};\n"; \
|
||||
}
|
||||
|
||||
#define PRINT_CONSTANT(Class, Name) \
|
||||
std::cout << "static constexpr dart::compiler::target::word " #Class \
|
||||
"_" #Name " = 0x" \
|
||||
<< Class::Name << ";\n";
|
||||
|
||||
JIT_OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT, PRINT_SIZEOF,
|
||||
PRINT_ARRAY_SIZEOF, PRINT_PAYLOAD_SIZEOF, PRINT_RANGE,
|
||||
PRINT_CONSTANT)
|
||||
@@ -190,10 +146,17 @@ class OffsetsExtractor : public AllStatic {
|
||||
} // namespace dart
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::cout << std::hex << PREPROCESSOR_CONDITION << std::endl;
|
||||
std::cout << "{\n";
|
||||
std::cout << "\"product\": " PRODUCT_DEF ",\n";
|
||||
std::cout << "\"arch\": \"" ARCH_DEF_CPU "\",\n";
|
||||
std::cout << "\"compressed\": " COMPRESSED_DEF ",\n";
|
||||
std::cout << "\"aot\": " AOT_DEF ",\n";
|
||||
std::cout << "\"offsets\": [\n";
|
||||
#if !defined(TARGET_ARCH_IA32) || !defined(DART_PRECOMPILED_RUNTIME)
|
||||
dart::OffsetsExtractor::DumpOffsets();
|
||||
#endif
|
||||
std::cout << PREPROCESSOR_CONDITION_END << std::endl;
|
||||
std::cout << "{\"kind\": \"\"}\n"; // Terminate the list after comma.
|
||||
std::cout << "]\n";
|
||||
std::cout << "}\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,23 +3,14 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:convert' as convert show json;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:pool/pool.dart';
|
||||
|
||||
final pool = Pool(Platform.numberOfProcessors);
|
||||
|
||||
void main(List<String> args) async {
|
||||
final sdkRoot = Platform.script.resolve('../').toFilePath();
|
||||
Directory.current = Directory(sdkRoot);
|
||||
|
||||
final extractedOffsetsFile =
|
||||
'runtime/vm/compiler/runtime_offsets_extracted.h';
|
||||
|
||||
final old = File(extractedOffsetsFile).readAsStringSync();
|
||||
final header = old.substring(0, old.indexOf('\n#if '));
|
||||
final footer = old.substring(old.lastIndexOf('\n#endif '));
|
||||
|
||||
Future<void> buildOffsetsExtractor(List<String> args) async {
|
||||
// Build all configurations
|
||||
await forAllConfigurationsMode((
|
||||
String buildDir,
|
||||
@@ -38,27 +29,88 @@ void main(List<String> args) async {
|
||||
]);
|
||||
print('Building $buildDir - done');
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> runOffsetsExtractor() async {
|
||||
final (jit, aot) = await (
|
||||
forAllConfigurationsMode((String buildDir, _, __) async {
|
||||
return await run(['$buildDir/offsets_extractor']);
|
||||
}).then<String>((lines) => lines.join('\n')),
|
||||
}).then<String>((lines) => lines.join(',\n')),
|
||||
forAllConfigurationsMode((String buildDir, _, __) async {
|
||||
return await run(['$buildDir/offsets_extractor_aotruntime']);
|
||||
}).then<String>((lines) => lines.join('\n')),
|
||||
}).then<String>((lines) => lines.join(',\n')),
|
||||
).wait;
|
||||
|
||||
if (exitCode == 0) {
|
||||
final output = StringBuffer();
|
||||
output.writeln(header);
|
||||
output.writeln(jit);
|
||||
output.writeln(aot);
|
||||
output.writeln(footer);
|
||||
File(extractedOffsetsFile).writeAsStringSync(output.toString());
|
||||
print('Written $extractedOffsetsFile');
|
||||
print('Running `git cl format $extractedOffsetsFile');
|
||||
await run(['git', 'cl', 'format', extractedOffsetsFile]);
|
||||
final buf = StringBuffer();
|
||||
buf.writeln('[');
|
||||
buf.writeln(jit);
|
||||
buf.writeln(',');
|
||||
buf.writeln(aot);
|
||||
buf.writeln(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
String toCValue(Object? value) {
|
||||
final intValue = int.parse(value as String);
|
||||
if (intValue == -1) return '-1';
|
||||
return '0x${intValue.toRadixString(16)}';
|
||||
}
|
||||
|
||||
Future<void> writeCHeaderFile(List json) async {
|
||||
final extractedOffsetsFile =
|
||||
'runtime/vm/compiler/runtime_offsets_extracted.h';
|
||||
|
||||
final old = File(extractedOffsetsFile).readAsStringSync();
|
||||
final header = old.substring(0, old.indexOf('\n#if '));
|
||||
final footer = old.substring(old.lastIndexOf('\n#endif '));
|
||||
|
||||
final output = StringBuffer();
|
||||
output.writeln(header);
|
||||
for (final config in json) {
|
||||
final product = (config['product'] as bool) ? '' : '!';
|
||||
final productDef = '${product}defined(PRODUCT)';
|
||||
final arch = (config['arch'] as String).toUpperCase();
|
||||
final archDef = 'defined(TARGET_ARCH_$arch)';
|
||||
final compressed = (config['compressed'] as bool) ? '' : '!';
|
||||
final compressedDef = '${compressed}defined(DART_COMPRESSED_POINTERS)';
|
||||
final aot = (config['aot'] as bool) ? 'AOT_' : '';
|
||||
final prefix = 'static constexpr dart::compiler::target::word $aot';
|
||||
final offsets = config['offsets'] as List;
|
||||
output.writeln('#if $productDef && $archDef && $compressedDef');
|
||||
for (final offset in offsets) {
|
||||
final kind = offset['kind'] as String;
|
||||
switch (kind) {
|
||||
case 'value':
|
||||
final cls = offset['class'] as String;
|
||||
final name = offset['name'] as String;
|
||||
final value = toCValue(offset['value']);
|
||||
output.writeln('$prefix${cls}_$name = $value;');
|
||||
break;
|
||||
case 'array':
|
||||
final cls = offset['class'] as String;
|
||||
final startOffset = toCValue(offset['startOffset']);
|
||||
final elemSize = toCValue(offset['elemSize']);
|
||||
output.writeln('$prefix${cls}_elements_start_offset = $startOffset;');
|
||||
output.writeln('$prefix${cls}_element_size = $elemSize;');
|
||||
break;
|
||||
case 'range':
|
||||
final cls = offset['class'] as String;
|
||||
final name = offset['name'] as String;
|
||||
final values = (offset['values'] as List).map(toCValue).toList();
|
||||
output.writeln('$prefix${cls}_$name[] = {${values.join(', ')}};');
|
||||
break;
|
||||
}
|
||||
}
|
||||
output.writeln('#endif // $productDef &&');
|
||||
output.writeln(' // $archDef &&');
|
||||
output.writeln(' // $compressedDef');
|
||||
output.writeln();
|
||||
}
|
||||
output.writeln(footer);
|
||||
File(extractedOffsetsFile).writeAsStringSync(output.toString());
|
||||
print('Written $extractedOffsetsFile');
|
||||
print('Running `git cl format $extractedOffsetsFile');
|
||||
await run(['git', 'cl', 'format', extractedOffsetsFile]);
|
||||
}
|
||||
|
||||
Future<List<T>> forAllConfigurationsMode<T>(
|
||||
@@ -103,3 +155,22 @@ extension on String {
|
||||
String get capitalized => substring(0, 1).toUpperCase() + substring(1);
|
||||
String get upper => toUpperCase();
|
||||
}
|
||||
|
||||
void main(List<String> args) async {
|
||||
final sdkRoot = Platform.script.resolve('../').toFilePath();
|
||||
Directory.current = Directory(sdkRoot);
|
||||
|
||||
await buildOffsetsExtractor(args);
|
||||
if (exitCode != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final text = await runOffsetsExtractor();
|
||||
if (exitCode != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final json = convert.json.decode(text) as List;
|
||||
|
||||
await writeCHeaderFile(json);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user