From c885bdde1d22f1078c0a26f861a5f1e461bc82fb Mon Sep 17 00:00:00 2001 From: Samir Jindel Date: Sun, 27 Oct 2019 18:18:29 +0000 Subject: [PATCH] [vm] DBC is obsolete. Remove dead code. Change-Id: Ica33af158cca53c8e951e4b2582de83660e8a60d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121851 Commit-Queue: Samir Jindel Reviewed-by: Martin Kustermann --- .../FfiBoringssl/dart/FfiBoringssl.dart | 3 - benchmarks/FfiCall/dart/FfiCall.dart | 2 - benchmarks/FfiMemory/dart/FfiMemory.dart | 3 - pkg/pkg.status | 2 +- pkg/smith/lib/configuration.dart | 4 - .../test/data/standalone_2_vm.status | 10 - pkg/status_file/test/data/vm.status | 17 +- .../lib/src/compiler_configuration.dart | 3 +- pkg/test_runner/lib/src/options.dart | 5 +- .../lib/src/runtime_configuration.dart | 2 - pkg/vm/lib/bytecode/dbc.dart | 2 +- pkg/vm/lib/bytecode/gen_bytecode.dart | 3 - .../test/get_cpu_samples_rpc_test.dart | 2 +- runtime/BUILD.gn | 3 - runtime/bin/ffi_test/ffi_test_functions.cc | 2 +- runtime/docs/compiler/exceptions.md | 10 +- runtime/include/dart_api.h | 2 +- runtime/lib/ffi.cc | 126 +- runtime/lib/ffi.h | 76 - .../breakpoint_two_args_checked_test.dart | 2 +- .../get_cpu_profile_timeline_rpc_test.dart | 2 +- .../service/get_cpu_samples_rpc_test.dart | 2 +- .../tests/service/get_object_rpc_test.dart | 2 +- .../observatory/tests/service/service.status | 15 - .../tests/service/service_kernel.status | 11 +- runtime/platform/globals.h | 12 +- runtime/runtime_args.gni | 2 +- runtime/tests/vm/vm.status | 34 +- runtime/tools/run_clang_tidy.dart | 6 - runtime/vm/clustered_snapshot.cc | 22 +- runtime/vm/code_descriptors.h | 3 +- runtime/vm/code_patcher.cc | 4 +- runtime/vm/code_patcher.h | 17 +- runtime/vm/code_patcher_dbc.cc | 114 - .../vm/compiler/aot/aot_call_specializer.cc | 2 - runtime/vm/compiler/aot/precompiler.cc | 9 +- runtime/vm/compiler/aot/precompiler.h | 6 +- runtime/vm/compiler/asm_intrinsifier.cc | 4 - runtime/vm/compiler/asm_intrinsifier.h | 5 - runtime/vm/compiler/asm_intrinsifier_dbc.cc | 36 - runtime/vm/compiler/assembler/assembler.cc | 2 - runtime/vm/compiler/assembler/assembler.h | 2 - .../vm/compiler/assembler/assembler_dbc.cc | 127 - runtime/vm/compiler/assembler/assembler_dbc.h | 106 - .../compiler/assembler/assembler_dbc_test.cc | 2857 ----------- .../vm/compiler/assembler/disassembler_dbc.cc | 243 - .../compiler/assembler/disassembler_test.cc | 4 +- runtime/vm/compiler/backend/flow_graph.cc | 22 - .../compiler/backend/flow_graph_compiler.cc | 67 +- .../vm/compiler/backend/flow_graph_compiler.h | 55 +- .../backend/flow_graph_compiler_dbc.cc | 483 -- runtime/vm/compiler/backend/il.cc | 230 +- runtime/vm/compiler/backend/il.h | 49 - runtime/vm/compiler/backend/il_dbc.cc | 2122 -------- runtime/vm/compiler/backend/il_test_helper.cc | 3 +- runtime/vm/compiler/backend/inliner.cc | 9 +- runtime/vm/compiler/backend/linearscan.cc | 130 +- runtime/vm/compiler/backend/linearscan.h | 4 - runtime/vm/compiler/backend/locations.cc | 28 - runtime/vm/compiler/backend/locations.h | 45 - .../vm/compiler/backend/locations_helpers.h | 2 - .../backend/locations_helpers_test.cc | 4 - runtime/vm/compiler/backend/loops_test.cc | 5 - .../compiler/backend/typed_data_aot_test.cc | 4 +- runtime/vm/compiler/compiler_sources.gni | 19 - runtime/vm/compiler/ffi.cc | 133 +- runtime/vm/compiler/ffi.h | 54 - runtime/vm/compiler/ffi_dbc_trampoline.h | 28 - .../ffi_dbc_trampoline_x64_linux_mac.S | 77 - .../frontend/bytecode_flow_graph_builder.cc | 4 - .../frontend/kernel_binary_flowgraph.cc | 6 - runtime/vm/compiler/frontend/kernel_to_il.cc | 22 - runtime/vm/compiler/graph_intrinsifier.cc | 5 +- runtime/vm/compiler/graph_intrinsifier.h | 15 - runtime/vm/compiler/intrinsifier.cc | 12 +- runtime/vm/compiler/jit/compiler.cc | 3 +- runtime/vm/compiler/offsets_extractor.cc | 4 - runtime/vm/compiler/relocation.cc | 6 +- runtime/vm/compiler/relocation.h | 6 +- runtime/vm/compiler/runtime_api.cc | 4 - runtime/vm/compiler/runtime_api.h | 4 - .../vm/compiler/runtime_offsets_extracted.h | 579 --- runtime/vm/compiler/runtime_offsets_list.h | 75 +- runtime/vm/compiler/stub_code_compiler.h | 4 +- runtime/vm/compiler/stub_code_compiler_dbc.cc | 143 - runtime/vm/constants.h | 8 - runtime/vm/constants_dbc.cc | 25 - runtime/vm/constants_dbc.h | 1161 ----- runtime/vm/constants_kbc.h | 2 +- runtime/vm/cpu.h | 2 - runtime/vm/cpu_dbc.cc | 49 - runtime/vm/cpu_dbc.h | 46 - runtime/vm/cpu_test.cc | 2 - runtime/vm/dart.cc | 21 +- runtime/vm/dart_api_impl.cc | 10 - runtime/vm/dart_api_impl.h | 5 +- runtime/vm/dart_entry.cc | 9 +- runtime/vm/debugger.cc | 18 +- runtime/vm/debugger.h | 8 - runtime/vm/debugger_dbc.cc | 109 - runtime/vm/deferred_objects.h | 4 - runtime/vm/deopt_instructions.cc | 39 - runtime/vm/deopt_instructions.h | 38 +- runtime/vm/elf.cc | 1 - runtime/vm/exceptions.cc | 8 - runtime/vm/ffi_callback_trampolines.cc | 4 +- runtime/vm/ffi_callback_trampolines.h | 4 +- runtime/vm/flag_list.h | 12 +- runtime/vm/gdb_helpers.cc | 2 - runtime/vm/globals.h | 6 - runtime/vm/heap/pages.cc | 6 +- runtime/vm/instructions.h | 6 +- runtime/vm/instructions_dbc.cc | 206 - runtime/vm/instructions_dbc.h | 134 - runtime/vm/interpreter.cc | 9 +- runtime/vm/isolate.cc | 7 +- runtime/vm/isolate.h | 4 +- runtime/vm/kernel_isolate.cc | 8 +- runtime/vm/malloc_hooks_test.cc | 2 +- runtime/vm/native_arguments.h | 5 +- runtime/vm/native_entry.cc | 24 +- runtime/vm/object.cc | 5 - runtime/vm/object.h | 9 - runtime/vm/object_dbc_test.cc | 48 - runtime/vm/object_reload.cc | 4 - runtime/vm/os_android.cc | 8 +- runtime/vm/os_fuchsia.cc | 8 +- runtime/vm/os_linux.cc | 3 +- runtime/vm/os_macos.cc | 2 - runtime/vm/os_win.cc | 6 +- runtime/vm/profiler.cc | 19 +- runtime/vm/program_visitor.cc | 2 - runtime/vm/runtime_entry.cc | 87 +- runtime/vm/runtime_entry_dbc.cc | 30 - runtime/vm/simulator.h | 2 - runtime/vm/simulator_dbc.cc | 4249 ----------------- runtime/vm/simulator_dbc.h | 192 - runtime/vm/source_report.cc | 14 - runtime/vm/stack_frame.cc | 75 +- runtime/vm/stack_frame.h | 11 - runtime/vm/stack_frame_dbc.h | 100 - runtime/vm/stub_code.cc | 30 +- runtime/vm/stub_code.h | 2 +- runtime/vm/stub_code_list.h | 25 - runtime/vm/thread.cc | 2 +- runtime/vm/thread.h | 16 - runtime/vm/type_testing_stubs.cc | 10 +- runtime/vm/type_testing_stubs.h | 4 +- runtime/vm/unit_test.cc | 2 +- runtime/vm/unit_test.h | 27 +- runtime/vm/virtual_memory_posix.cc | 7 - runtime/vm/vm_sources.gni | 12 - tests/co19_2/co19_2-kernel.status | 13 +- tests/corelib_2/corelib_2.status | 5 +- tests/ffi/ffi.status | 3 - tests/lib_2/lib_2.status | 2 +- tests/lib_2/lib_2_kernel.status | 3 - .../standalone_2/io/test_extension_test.dart | 2 - tests/standalone_2/standalone_2_kernel.status | 4 +- tests/standalone_2/standalone_2_vm.status | 14 +- tools/bots/test_matrix.json | 24 +- tools/build.py | 7 +- tools/diff_results.dart | 1 - tools/gardening/lib/src/buildbot_data.dart | 24 - .../lib/src/results/configurations.dart | 4 - tools/gardening/lib/src/shard_data.dart | 12 - tools/generate_buildfiles.py | 2 +- tools/gn.py | 27 +- tools/run_offsets_extractor.sh | 2 - tools/test.dart | 4 - tools/utils.py | 4 - 171 files changed, 193 insertions(+), 15372 deletions(-) delete mode 100644 runtime/lib/ffi.h delete mode 100644 runtime/vm/code_patcher_dbc.cc delete mode 100644 runtime/vm/compiler/asm_intrinsifier_dbc.cc delete mode 100644 runtime/vm/compiler/assembler/assembler_dbc.cc delete mode 100644 runtime/vm/compiler/assembler/assembler_dbc.h delete mode 100644 runtime/vm/compiler/assembler/assembler_dbc_test.cc delete mode 100644 runtime/vm/compiler/assembler/disassembler_dbc.cc delete mode 100644 runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc delete mode 100644 runtime/vm/compiler/backend/il_dbc.cc delete mode 100644 runtime/vm/compiler/ffi_dbc_trampoline.h delete mode 100644 runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S delete mode 100644 runtime/vm/compiler/stub_code_compiler_dbc.cc delete mode 100644 runtime/vm/constants_dbc.cc delete mode 100644 runtime/vm/constants_dbc.h delete mode 100644 runtime/vm/cpu_dbc.cc delete mode 100644 runtime/vm/cpu_dbc.h delete mode 100644 runtime/vm/debugger_dbc.cc delete mode 100644 runtime/vm/instructions_dbc.cc delete mode 100644 runtime/vm/instructions_dbc.h delete mode 100644 runtime/vm/object_dbc_test.cc delete mode 100644 runtime/vm/runtime_entry_dbc.cc delete mode 100644 runtime/vm/simulator_dbc.cc delete mode 100644 runtime/vm/simulator_dbc.h delete mode 100644 runtime/vm/stack_frame_dbc.h diff --git a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart index c377b7f9f7c..104588eedd2 100644 --- a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart +++ b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart @@ -65,9 +65,6 @@ String hash(Pointer data, int length, Pointer hashAlgorithm) { // * Architecture: x64 // * 23000 - 52000000 us (without optimizations) // * 23000 - 30000 us (with optimizations) -// * Architecture: SimDBC64 -// * 23000 - 5500000 us (without optimizations) -// * 23000 - 30000 us (with optimizations) const int L = 1000; // Length of data in bytes. final hashAlgorithm = EVP_sha512(); diff --git a/benchmarks/FfiCall/dart/FfiCall.dart b/benchmarks/FfiCall/dart/FfiCall.dart index 68d66012746..a2857e4e82b 100644 --- a/benchmarks/FfiCall/dart/FfiCall.dart +++ b/benchmarks/FfiCall/dart/FfiCall.dart @@ -605,8 +605,6 @@ Pointer doCall20PointerUint8( // * CPU: Intel(R) Xeon(R) Gold 6154 // * Architecture: x64 // * 200 - 1100 us -// * Architecture: SimDBC64 -// * 2800 - 110000 us const N = 1000; class Uint8x01 extends BenchmarkBase { diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart index 9bfad25b628..50f84355126 100644 --- a/benchmarks/FfiMemory/dart/FfiMemory.dart +++ b/benchmarks/FfiMemory/dart/FfiMemory.dart @@ -203,9 +203,6 @@ int doLoadInt64Mint(Pointer pointer, int length) { // * Architecture: x64 // * 48000 - 125000 us (without optimizations) // * 14 - ??? us (expected with optimizations, on par with typed data) -// * Architecture: SimDBC64 -// * 52000 - 130000 us (without optimizations) -// * 300 - ??? us (expected with optimizations, on par with typed data) const N = 1000; class PointerInt8 extends BenchmarkBase { diff --git a/pkg/pkg.status b/pkg/pkg.status index 738bd38ce43..445692d9ad3 100644 --- a/pkg/pkg.status +++ b/pkg/pkg.status @@ -210,7 +210,7 @@ analyzer/test/src/task/strong/front_end_inference_test: Slow # Timeout. These tests do not run efficiently on our simulator or low-end # devices. -[ $runtime == vm && ($arch == armv6 || $arch == simarm || $arch == simarm64 || $arch == simarmv6 || $arch == simdbc64) ] +[ $runtime == vm && ($arch == armv6 || $arch == simarm || $arch == simarm64 || $arch == simarmv6) ] *: Skip [ $arch != x64 || $compiler != none || $mode != release || $runtime != vm ] diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart index 4332fb85b8b..be9c74c075a 100644 --- a/pkg/smith/lib/configuration.dart +++ b/pkg/smith/lib/configuration.dart @@ -567,8 +567,6 @@ class Architecture extends NamedEnum { static const simarm = Architecture._('simarm'); static const simarmv6 = Architecture._('simarmv6'); static const simarm64 = Architecture._('simarm64'); - static const simdbc = Architecture._('simdbc'); - static const simdbc64 = Architecture._('simdbc64'); static final List names = _all.keys.toList(); @@ -582,8 +580,6 @@ class Architecture extends NamedEnum { simarm, simarmv6, simarm64, - simdbc, - simdbc64 ], key: (architecture) => (architecture as Architecture).name); static Architecture find(String name) { diff --git a/pkg/status_file/test/data/standalone_2_vm.status b/pkg/status_file/test/data/standalone_2_vm.status index 2b859023038..d58085f65bc 100644 --- a/pkg/status_file/test/data/standalone_2_vm.status +++ b/pkg/status_file/test/data/standalone_2_vm.status @@ -24,16 +24,6 @@ io/socket_close_test: Pass, Timeout # Issue 28502: timeout. no_allow_absolute_addresses_test: SkipByDesign # Not supported. link_natives_lazily_test: SkipByDesign # Not supported. -[ $arch == simdbc || $arch == simdbc64 ] -full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet. - -link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives. - -no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers - -[ $arch == simdbc64 && $mode == debug && $checked ] -io/web_socket_test: Pass, RuntimeError # Issue 26814. - [ $system == windows ] verbose_gc_to_bmu_test: Skip io/process_sync_test: Pass, Timeout # Issue 24596 diff --git a/pkg/status_file/test/data/vm.status b/pkg/status_file/test/data/vm.status index f62053eb694..5db98f22f7b 100644 --- a/pkg/status_file/test/data/vm.status +++ b/pkg/status_file/test/data/vm.status @@ -47,11 +47,10 @@ cc/CorelibIsolateStartup: Skip # OOM crash can bring down the OS. dart/data_uri_spawn_test: Skip # TODO(zra): package:unittest is not in the image. cc/Read: Fail # TODO(zra): Investigate, ../../dart/runtime/bin/file_test.cc: 34: error: expected: !file->WriteByte(1) -# Profiler is completely disabled in SIMDBC builds. # On the simluator stack traces produced by the Profiler do not match # up with the real Dart stack trace and hence we don't get correct # symbol names. -[ $arch == simarm || $arch == simarmv6 || $arch == simarm64 || $arch == simdbc || $arch == simdbc64 ] +[ $arch == simarm || $arch == simarmv6 || $arch == simarm64 ] cc/Service_Profile: Skip cc/Profiler_AllocationSampleTest: Skip cc/Profiler_ArrayAllocation: Skip @@ -166,20 +165,6 @@ dart/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri [ $runtime == vm && $mode == product ] cc/DartAPI_IsolateSetCheckedMode: Fail,OK # Checked mode disabled in product mode. -[ $arch == simdbc || $arch == simdbc64 ] -cc/RegExp_ExternalOneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegExp_ExternalTwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegExp_OneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegExp_TwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. - -cc/GuardFieldConstructor2Test: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldConstructorTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldFinalListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldFinalVariableLengthListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldSimpleTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC - -cc/RegenerateAllocStubs: Skip # This test is meaningless for DBC as allocation stubs are not used. - [ $hot_reload || $hot_reload_rollback ] dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads. dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads. diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart index 731f5f0dfac..01389c4e2bd 100644 --- a/pkg/test_runner/lib/src/compiler_configuration.dart +++ b/pkg/test_runner/lib/src/compiler_configuration.dart @@ -85,8 +85,7 @@ abstract class CompilerConfiguration { case Compiler.dartk: case Compiler.dartkb: - if (configuration.architecture == Architecture.simdbc64 || - configuration.architecture == Architecture.simarm || + if (configuration.architecture == Architecture.simarm || configuration.architecture == Architecture.simarm64 || configuration.system == System.android) { return VMKernelCompilerConfiguration(configuration); diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart index 419fa81a28e..9064cb5e4e7 100644 --- a/pkg/test_runner/lib/src/options.dart +++ b/pkg/test_runner/lib/src/options.dart @@ -142,8 +142,7 @@ Allowed values are: all ia32, x64 arm, armv6, arm64, -simarm, simarmv6, simarm64, -simdbc, simdbc64, arm_x64''', +simarm, simarmv6, simarm64, arm_x64''', abbr: 'a', values: ['all']..addAll(Architecture.names), defaultsTo: Architecture.x64.name, @@ -687,7 +686,7 @@ compiler.''', // Expand architectures. var architectures = data["arch"] as String; if (architectures == "all") { - architectures = "ia32,x64,simarm,simarm64,simdbc64"; + architectures = "ia32,x64,simarm,simarm64"; } for (var architectureName in architectures.split(",")) { diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart index 839137568d6..5a2b45b641f 100644 --- a/pkg/test_runner/lib/src/runtime_configuration.dart +++ b/pkg/test_runner/lib/src/runtime_configuration.dart @@ -234,8 +234,6 @@ class DartVmRuntimeConfiguration extends RuntimeConfiguration { case Architecture.simarmv6: case Architecture.armv6: case Architecture.simarm64: - case Architecture.simdbc: - case Architecture.simdbc64: multiplier *= 4; break; } diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart index 33925898bf6..c9939f0f4a8 100644 --- a/pkg/vm/lib/bytecode/dbc.dart +++ b/pkg/vm/lib/bytecode/dbc.dart @@ -534,7 +534,7 @@ const Map BytecodeFormats = const { Encoding.k0, const [Operand.none, Operand.none, Operand.none]), }; -// Should match constant in runtime/vm/stack_frame_dbc.h. +// Should match constant in runtime/vm/stack_frame_kbc.h. const int kParamEndSlotFromFp = 4; enum SpecialIndex { diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart index 61f988a4389..6b1b0244728 100644 --- a/pkg/vm/lib/bytecode/gen_bytecode.dart +++ b/pkg/vm/lib/bytecode/gen_bytecode.dart @@ -1926,9 +1926,6 @@ class BytecodeGenerator extends RecursiveVisitor { // CheckStack must see a properly initialized context when stress-testing // stack trace collection. - // Also, simdbc doesn't support arguments descriptor SpecialDbcRegister as - // a source location for deopt info, so CheckStack should be generated - // after the code which uses arguments descriptor. asm.emitCheckStack(0); if (locals.hasFunctionTypeArgsVar && isClosure) { diff --git a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart index dcc8d9b46cd..de49353add1 100644 --- a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart +++ b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart @@ -54,7 +54,7 @@ var tests = [ var vmArgs = [ '--profiler=true', - '--profile-vm=false', // So this also works with DBC and KBC. + '--profile-vm=false', // So this also works with KBC. ]; main([args = const []]) async => diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index 2e65496ea34..1932df82beb 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -106,9 +106,6 @@ config("dart_arch_config") { defines += [ "TARGET_ARCH_X64" ] } else if (dart_target_arch == "ia32" || dart_target_arch == "x86") { defines += [ "TARGET_ARCH_IA32" ] - } else if (dart_target_arch == "dbc") { - defines += [ "TARGET_ARCH_DBC" ] - defines += [ "USING_SIMULATOR" ] } else { print("Invalid dart_target_arch: $dart_target_arch") assert(false) diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc index d0f4db35905..f673f13138e 100644 --- a/runtime/bin/ffi_test/ffi_test_functions.cc +++ b/runtime/bin/ffi_test/ffi_test_functions.cc @@ -564,7 +564,7 @@ DART_EXPORT void Regress37069(uint64_t a, Dart_ExecuteInternalCommand("gc-now", nullptr); } -#if !defined(HOST_OS_WINDOWS) && !defined(TARGET_ARCH_DBC) +#if !defined(HOST_OS_WINDOWS) DART_EXPORT void* UnprotectCodeOtherThread(void* isolate, std::condition_variable* var, std::mutex* mut) { diff --git a/runtime/docs/compiler/exceptions.md b/runtime/docs/compiler/exceptions.md index 222e5f8be64..6dd211dd647 100644 --- a/runtime/docs/compiler/exceptions.md +++ b/runtime/docs/compiler/exceptions.md @@ -81,12 +81,4 @@ catch block entry. See `ExceptionHandlerFinder::{GetCatchEntryMovesFromDeopt, Ex Constructing `CatchEntryMoves` dynamically from deoptimization instructions allows to avoid unnecessary duplication of the metadata and save memory: as deoptimization environments contain all information necessary for constructing -correct stack state. - -IMPORTANT: There is a subtle difference between DBC and other architectures with -respect to catch block entry state. On normal architectures `Parameter(i)` at -catch entry would be associated with the same stack space that would be used to -store variable with index `i`. On DBC however at catch entry `Parameter(i)` -would be allocated to a separate scratch space at the very top of the register -space. See `FlowGraphAllocator::ProcessInitialDefinition` and -`FlowGraphCompiler::CatchEntryRegForVariable`. +correct stack state. \ No newline at end of file diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index fce7ee20d92..6dbd7034572 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3465,7 +3465,7 @@ DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SortClasses(); * permissions; the data piece may be loaded as read-only. * * - Requires the VM to have not been started with --precompilation. - * - Not supported when targeting IA32 or DBC. + * - Not supported when targeting IA32. * - The VM writing the snapshot and the VM reading the snapshot must be the * same version, must be built in the same DEBUG/RELEASE/PRODUCT mode, must * be targeting the same architecture, and must both be in checked mode or diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc index eb1ee9476de..355d1e31c4c 100644 --- a/runtime/lib/ffi.cc +++ b/runtime/lib/ffi.cc @@ -2,8 +2,6 @@ // 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. -#include "lib/ffi.h" - #include "include/dart_api.h" #include "platform/globals.h" #include "vm/bootstrap_natives.h" @@ -421,10 +419,7 @@ DEFINE_NATIVE_ENTRY(Ffi_asExternalTypedData, 0, 2) { } DEFINE_NATIVE_ENTRY(Ffi_nativeCallbackFunction, 1, 2) { -#if defined(TARGET_ARCH_DBC) - Exceptions::ThrowUnsupportedError( - "FFI callbacks are not yet supported on DBC."); -#elif defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) +#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) // Calls to this function are removed by the flow-graph builder in AOT. // See StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction(). UNREACHABLE(); @@ -495,7 +490,7 @@ DEFINE_NATIVE_ENTRY(Ffi_pointerFromFunction, 1, 1) { thread->SetFfiCallbackCode(function.FfiCallbackId(), code); uword entry_point = code.EntryPoint(); -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) if (NativeCallbackTrampolines::Enabled()) { entry_point = isolate->native_callback_trampolines()->TrampolineForId( function.FfiCallbackId()); @@ -505,121 +500,4 @@ DEFINE_NATIVE_ENTRY(Ffi_pointerFromFunction, 1, 1) { return Pointer::New(type_arg, entry_point); } -#if defined(TARGET_ARCH_DBC) - -void FfiMarshalledArguments::SetFunctionAddress(uint64_t value) const { - data_[kOffsetFunctionAddress] = value; -} - -static intptr_t ArgumentHostRegisterIndex(host::Register reg) { - for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) { - if (host::CallingConventions::ArgumentRegisters[i] == reg) { - return i; - } - } - UNREACHABLE(); -} - -void FfiMarshalledArguments::SetRegister(host::Register reg, - uint64_t value) const { - const intptr_t reg_index = ArgumentHostRegisterIndex(reg); - ASSERT(host::CallingConventions::ArgumentRegisters[reg_index] == reg); - const intptr_t index = kOffsetRegisters + reg_index; - data_[index] = value; -} - -void FfiMarshalledArguments::SetFpuRegister(host::FpuRegister reg, - uint64_t value) const { - const intptr_t fpu_index = static_cast(reg); - ASSERT(host::CallingConventions::FpuArgumentRegisters[fpu_index] == reg); - const intptr_t index = kOffsetFpuRegisters + fpu_index; - data_[index] = value; -} - -void FfiMarshalledArguments::SetNumStackSlots(intptr_t num_args) const { - data_[kOffsetNumStackSlots] = num_args; -} - -void FfiMarshalledArguments::SetAlignmentMask(uint64_t alignment_mask) const { - data_[kOffsetAlignmentMask] = alignment_mask; -} - -intptr_t FfiMarshalledArguments::GetNumStackSlots() const { - return data_[kOffsetNumStackSlots]; -} - -void FfiMarshalledArguments::SetStackSlotValue(intptr_t index, - uint64_t value) const { - ASSERT(0 <= index && index < GetNumStackSlots()); - data_[kOffsetStackSlotValues + index] = value; -} - -uint64_t* FfiMarshalledArguments::New( - const compiler::ffi::FfiSignatureDescriptor& signature, - const uint64_t* arg_values) { - const intptr_t num_stack_slots = signature.num_stack_slots(); - const uint64_t alignment_mask = ~(OS::ActivationFrameAlignment() - 1); - const intptr_t size = - FfiMarshalledArguments::kOffsetStackSlotValues + num_stack_slots; - uint64_t* data = Thread::Current()->GetFfiMarshalledArguments(size); - const auto& descr = FfiMarshalledArguments(data); - - descr.SetFunctionAddress(arg_values[compiler::ffi::kFunctionAddressRegister]); - const intptr_t num_args = signature.length(); - descr.SetNumStackSlots(num_stack_slots); - descr.SetAlignmentMask(alignment_mask); - for (int i = 0; i < num_args; i++) { - uint64_t arg_value = arg_values[compiler::ffi::kFirstArgumentRegister + i]; - HostLocation loc = signature.LocationAt(i); - // TODO(36809): For 32 bit, support pair locations. - if (loc.IsRegister()) { - descr.SetRegister(loc.reg(), arg_value); - } else if (loc.IsFpuRegister()) { - descr.SetFpuRegister(loc.fpu_reg(), arg_value); - } else { - ASSERT(loc.IsStackSlot() || loc.IsDoubleStackSlot()); - ASSERT(loc.stack_index() < num_stack_slots); - descr.SetStackSlotValue(loc.stack_index(), arg_value); - } - } - - return data; -} - -#if defined(DEBUG) -void FfiMarshalledArguments::Print() const { - OS::PrintErr("FfiMarshalledArguments data_ 0x%" Pp "\n", - reinterpret_cast(data_)); - OS::PrintErr(" 00 0x%016" Px64 " (function address, int result)\n", - data_[0]); - for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) { - const intptr_t index = kOffsetRegisters + i; - const char* result_str = i == 0 ? ", float result" : ""; - OS::PrintErr(" %02" Pd " 0x%016" Px64 " (%s%s)\n", index, data_[index], - RegisterNames::RegisterName( - host::CallingConventions::ArgumentRegisters[i]), - result_str); - } - for (intptr_t i = 0; i < host::CallingConventions::kNumFpuArgRegs; i++) { - const intptr_t index = kOffsetFpuRegisters + i; - OS::PrintErr(" %02" Pd " 0x%016" Px64 " (%s)\n", index, data_[index], - RegisterNames::FpuRegisterName( - host::CallingConventions::FpuArgumentRegisters[i])); - } - const intptr_t alignment_mask = data_[kOffsetAlignmentMask]; - OS::PrintErr(" %02" Pd " 0x%" Pp " (stack alignment mask)\n", - kOffsetAlignmentMask, alignment_mask); - const intptr_t num_stack_slots = data_[kOffsetNumStackSlots]; - OS::PrintErr(" %02" Pd " 0x%" Pp " (number of stack slots)\n", - kOffsetNumStackSlots, num_stack_slots); - for (intptr_t i = 0; i < num_stack_slots; i++) { - const intptr_t index = kOffsetStackSlotValues + i; - OS::PrintErr(" %02" Pd " 0x%016" Px64 " (stack slot %" Pd ")\n", index, - data_[index], i); - } -} -#endif // defined(DEBUG) - -#endif // defined(TARGET_ARCH_DBC) - } // namespace dart diff --git a/runtime/lib/ffi.h b/runtime/lib/ffi.h deleted file mode 100644 index 4cfa85561cf..00000000000 --- a/runtime/lib/ffi.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_LIB_FFI_H_ -#define RUNTIME_LIB_FFI_H_ - -#if defined(TARGET_ARCH_DBC) - -#include - -#include "vm/class_id.h" -#include "vm/compiler/backend/locations.h" -#include "vm/compiler/ffi.h" -#include "vm/object.h" -#include "vm/raw_object.h" - -namespace dart { - -// This structure contains all data required for an ffi call. -// It consists of the function address, all calling convention argument -// register values, argument fpu register values, number of stack arguments, -// and stack argument values. The generic DBC trampoline reads its arguments -// from this structure. -// -// Moreover, the DBC trampoline also stores the integer and floating point -// result registers in the first two slots when returning. -class FfiMarshalledArguments : public ValueObject { - public: - explicit FfiMarshalledArguments(uint64_t* data) : data_(data) {} - - // Copies ffi trampoline arguments (including target address) from stack into - // a signature agnostic data structure (FfiMarshalledArguments) using the - // signature and the stack address of the first argument. (Note that this - // only works on DBC as the stack grows upwards in DBC.) - static uint64_t* New(const compiler::ffi::FfiSignatureDescriptor& signature, - const uint64_t* arg_values); - - uint64_t IntResult() const { return data_[kOffsetIntResult]; } - uint64_t DoubleResult() const { return data_[kOffsetDoubleResult]; } - -#if defined(DEBUG) - void Print() const; -#endif - - private: - void SetFunctionAddress(uint64_t value) const; - void SetRegister(::dart::host::Register reg, uint64_t value) const; - void SetFpuRegister(::dart::host::FpuRegister reg, uint64_t value) const; - void SetAlignmentMask(uint64_t kOffsetAlignmentMask) const; - void SetNumStackSlots(intptr_t num_args) const; - intptr_t GetNumStackSlots() const; - void SetStackSlotValue(intptr_t index, uint64_t value) const; - - // TODO(36809): Replace this with uword. On 32 bit architecture, - // this should be 32 bits, as the DBC stack itself is 32 bits. - uint64_t* data_; - - static const intptr_t kOffsetFunctionAddress = 0; - static const intptr_t kOffsetRegisters = 1; - static const intptr_t kOffsetFpuRegisters = - kOffsetRegisters + ::dart::host::CallingConventions::kNumArgRegs; - static const intptr_t kOffsetAlignmentMask = - kOffsetFpuRegisters + ::dart::host::CallingConventions::kNumFpuArgRegs; - static const intptr_t kOffsetNumStackSlots = kOffsetAlignmentMask + 1; - static const intptr_t kOffsetStackSlotValues = kOffsetNumStackSlots + 1; - - static const intptr_t kOffsetIntResult = 0; - static const intptr_t kOffsetDoubleResult = 1; -}; - -} // namespace dart - -#endif // defined(TARGET_ARCH_DBC) - -#endif // RUNTIME_LIB_FFI_H_ diff --git a/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart b/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart index 66608054b61..8c218905093 100644 --- a/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart +++ b/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. // VMOptions=--verbose_debug -// This test is mostly interesting for DBC, which needs to patch two bytecodes +// This test was mostly interesting for DBC, which needed to patch two bytecodes // to create a breakpoint for fast Smi ops. import 'package:observatory/service_io.dart'; diff --git a/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart index a0d7f9e2e72..5b7d1ec8eb8 100644 --- a/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart +++ b/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart @@ -55,7 +55,7 @@ var tests = [ var vmArgs = [ '--profiler=true', - '--profile-vm=false', // So this also works with DBC and KBC. + '--profile-vm=false', // So this also works with KBC. ]; main(args) async => diff --git a/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart b/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart index aa55eb38996..542b476f4a6 100644 --- a/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart +++ b/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart @@ -55,7 +55,7 @@ var tests = [ var vmArgs = [ '--profiler=true', - '--profile-vm=false', // So this also works with DBC and KBC. + '--profile-vm=false', // So this also works with KBC. ]; main(args) async => diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart index de51a719728..ce8af6b69e7 100644 --- a/runtime/observatory/tests/service/get_object_rpc_test.dart +++ b/runtime/observatory/tests/service/get_object_rpc_test.dart @@ -895,7 +895,7 @@ var tests = [ } } if (!use_field_guards) { - return; // skip the test if guards are not enabled(like on simdbc64) + return; // skip the test if guards are not enabled } // Call eval to get a class id. diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status index ea1e417f2b8..a8f8dd499e6 100644 --- a/runtime/observatory/tests/service/service.status +++ b/runtime/observatory/tests/service/service.status @@ -46,21 +46,6 @@ async_scope_test: Pass, Slow [ $arch == simarm || $arch == simarm64 ] *: Pass, Slow -[ $arch == simdbc || $arch == simdbc64 ] -async_single_step_exception_test: RuntimeError # Issue 29218 -get_cpu_profile_timeline_rpc_test: SkipByDesign -implicit_getter_setter_test: RuntimeError # Field guards unimplemented. -next_through_catch_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975). -next_through_simple_async_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975). -next_through_simple_linear_2_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975). -step_through_function_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975). -step_through_getter_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975). - -[ $arch == simdbc || $arch == simdbc64 || $mode == debug ] -break_on_default_constructor_test: Pass, Slow -debugger_location_second_test: Pass, Slow -debugger_location_test: Pass, Slow - # All tests use dart:io [ $compiler == dart2js || $browser ] *: SkipByDesign diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status index 316e3f215e7..0037e6ef4e5 100644 --- a/runtime/observatory/tests/service/service_kernel.status +++ b/runtime/observatory/tests/service/service_kernel.status @@ -53,16 +53,9 @@ eval_regression_flutter20255_test: SkipSlow # Timeout get_vm_timeline_rpc_test: Pass, Slow rewind_optimized_out_test: SkipSlow # Timeout -[ $arch != simarm && $arch != simarm64 && $arch != simdbc && $compiler == dartk ] +[ $arch != simarm && $arch != simarm64 && $compiler == dartk ] complex_reload_test: RuntimeError -[ $arch == simdbc64 && $compiler == dartk ] -eval_test: RuntimeError, Timeout # Issue #34736 -evaluate_in_frame_rpc_test: RuntimeError, Timeout # Issue #34736 - -[ $arch == simdbc64 && $compiler == dartk && $mode == debug ] -eval_test: Pass, Slow - [ $compiler == dartkb && ($builder_tag == bytecode_interpreter || $builder_tag == bytecode_mixed) ] *: Skip # There are still timeouts in the interpreter and mixed modes which cause infra timeouts. @@ -122,7 +115,7 @@ step_through_setter_test: Skip # Issues 32137 and 32138. step_through_switch_test: Skip # Times out. Issue 32137. step_through_switch_with_continue_test: Skip # Times out. Issue 32137. -[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ] +[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ] add_breakpoint_rpc_kernel_test: RuntimeError # Issue #34736 async_generator_breakpoint_test: SkipByDesign # No incremental compiler available. bad_reload_test: Skip # Times out on sim architectures, also RuntimeError. diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h index 7e368fecfd4..9d4981f73eb 100644 --- a/runtime/platform/globals.h +++ b/runtime/platform/globals.h @@ -299,8 +299,7 @@ typedef simd128_value_t fpu_register_t; #endif #if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_X64) && \ - !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64) && \ - !defined(TARGET_ARCH_DBC) + !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64) // No target architecture specified pick the one matching the host architecture. #if defined(HOST_ARCH_ARM) #define TARGET_ARCH_ARM 1 @@ -319,12 +318,6 @@ typedef simd128_value_t fpu_register_t; #define TARGET_ARCH_IS_32_BIT 1 #elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64) #define TARGET_ARCH_IS_64_BIT 1 -#elif defined(TARGET_ARCH_DBC) -#if defined(ARCH_IS_32_BIT) -#define TARGET_ARCH_IS_32_BIT 1 -#else -#define TARGET_ARCH_IS_64_BIT 1 -#endif #else #error Automatic target architecture detection failed. #endif @@ -363,9 +356,6 @@ typedef simd128_value_t fpu_register_t; #define USING_SIMULATOR 1 #endif -#elif defined(TARGET_ARCH_DBC) -#define USING_SIMULATOR 1 - #else #error Unknown architecture. #endif diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni index 2d4ce24a5d2..f266ec0c08a 100644 --- a/runtime/runtime_args.gni +++ b/runtime/runtime_args.gni @@ -28,7 +28,7 @@ declare_args() { dart_runtime_mode = "develop" # Explicitly set the target architecture to use a simulator. - # Available options are: arm, arm64, x64, ia32, and dbc. + # Available options are: arm, arm64, x64, ia32. dart_target_arch = target_cpu # The optimization level to use for debug builds. Defaults to 0 for builds with diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status index 8863cc53eaa..73d6b6fa51c 100644 --- a/runtime/tests/vm/vm.status +++ b/runtime/tests/vm/vm.status @@ -82,7 +82,7 @@ dart/disassemble_determinism_test: Slow # Times out on slower bots. [ $arch == ia32 && $mode == debug && $system == windows ] dart/transferable_test: Skip # This is performance test and somehow debug win ia32 bot's performance is unpredictable -[ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $hot_reload && ($compiler == dartk || $compiler == dartkb) ] +[ $arch != simarm && $arch != simarm64 && $hot_reload && ($compiler == dartk || $compiler == dartkb) ] dart/data_uri_import_test/base64: Crash dart/data_uri_import_test/nocharset: Crash dart/data_uri_import_test/nomime: Crash @@ -122,7 +122,7 @@ dart/spawn_shutdown_test: SkipSlow [ $mode == debug && $system == windows ] dart/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot. -# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which +# Enabling of dartk for sim{arm,arm64} revelaed these test failures, which # are to be triaged. Isolate tests are skipped on purpose due to the usage of # batch mode. [ $mode == debug && ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ] @@ -169,13 +169,8 @@ cc/IsolateReload_LibraryLookup: Fail, Crash [ $checked && ($compiler == dartk || $compiler == dartkb) ] dart/redirection_type_shuffling_test/00: Pass # Works in --checked mode but not in --strong mode. -[ ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ] +[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ] dart/appjit*: SkipSlow # DFE too slow - -# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which -# are to be triaged. Isolate tests are skipped on purpose due to the usage of -# batch mode. -[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ] dart/data_uri_spawn_test: Skip # Please triage. dart/snapshot_version_test: RuntimeError # Please triage. @@ -186,17 +181,16 @@ dart/kernel_determinism_test: SkipSlow [ $arch == arm || $arch == arm64 || $builder_tag == crossword || $builder_tag == crossword_ast || $compiler != dartkp ] dart/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host). -[ $arch == arm || $arch == ia32 || $arch == simarm || $arch == simdbc || $arch == simdbc64 ] +[ $arch == arm || $arch == ia32 || $arch == simarm ] cc/GenKernelKernelCombined: SkipByDesign # No interpreter support. cc/GenKernelKernelLoadKernel: SkipByDesign # No interpreter support. cc/GenKernelKernelMaxRSS: SkipByDesign # No interpreter support. cc/GenKernelKernelReadAllBytecode: SkipByDesign # No interpreter support. -# Profiler is completely disabled in SIMDBC builds. # On the simluator stack traces produced by the Profiler do not match # up with the real Dart stack trace and hence we don't get correct # symbol names. -[ $arch == simarm || $arch == simarm64 || $arch == simarmv6 || $arch == simdbc || $arch == simdbc64 ] +[ $arch == simarm || $arch == simarm64 || $arch == simarmv6 ] cc/LargeMap: SkipByDesign cc/Profiler_AllocationSampleTest: SkipByDesign cc/Profiler_ArrayAllocation: SkipByDesign @@ -224,20 +218,8 @@ cc/Profiler_TrivialRecordAllocation: SkipByDesign cc/Profiler_TypedArrayAllocation: SkipByDesign cc/Service_Profile: SkipByDesign -[ $arch == simdbc || $arch == simdbc64 ] -cc/GuardFieldConstructor2Test: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldConstructorTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldFinalListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldFinalVariableLengthListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/GuardFieldSimpleTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC -cc/RegExp_ExternalOneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegExp_ExternalTwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegExp_OneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegExp_TwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch. -cc/RegenerateAllocStubs: SkipByDesign # This test is meaningless for DBC as allocation stubs are not used. - -[ $arch == simdbc || $arch == simdbc64 || $compiler == dartkb ] -dart/generic_field_invocation_test: SkipByDesign # DBC and KBC interpreters do not support --no_lazy_dispatchers +[ $compiler == dartkb ] +dart/generic_field_invocation_test: SkipByDesign # KBC interpreters do not support --no_lazy_dispatchers [ $builder_tag == bytecode_interpreter || $builder_tag == bytecode_mixed || $builder_tag == optimization_counter_threshold || $hot_reload || $hot_reload_rollback || $arch != arm && $arch != simarm && $arch != x64 || $compiler != dartk && $compiler != dartkb && $compiler != dartkp ] dart/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensible to when functions are optimized, so they are disabled on hotreload, optcounter and bytecode interpreter bots. @@ -267,7 +249,7 @@ dart/use_bare_instructions_flag_test: SkipByDesign # This test is for VM AOT onl # as that would involve running CFE (the front end) in simulator mode # to compile the URI file specified in spawnURI code. # These Isolate tests that use spawnURI are hence skipped on purpose. -[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ] +[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ] dart/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri dart/issue32950_test: SkipByDesign # uses spawnUri. diff --git a/runtime/tools/run_clang_tidy.dart b/runtime/tools/run_clang_tidy.dart index d165e77b899..5b18c617c88 100644 --- a/runtime/tools/run_clang_tidy.dart +++ b/runtime/tools/run_clang_tidy.dart @@ -80,23 +80,19 @@ final Set excludedFiles = Set.from([ 'runtime/platform/utils_win.h', 'runtime/vm/compiler/assembler/assembler_arm64.h', 'runtime/vm/compiler/assembler/assembler_arm.h', - 'runtime/vm/compiler/assembler/assembler_dbc.h', 'runtime/vm/compiler/assembler/assembler_ia32.h', 'runtime/vm/compiler/assembler/assembler_x64.h', 'runtime/vm/compiler/runtime_offsets_extracted.h', 'runtime/vm/constants_arm64.h', 'runtime/vm/constants_arm.h', - 'runtime/vm/constants_dbc.h', 'runtime/vm/constants_ia32.h', 'runtime/vm/constants_x64.h', 'runtime/vm/cpu_arm64.h', 'runtime/vm/cpu_arm.h', - 'runtime/vm/cpu_dbc.h', 'runtime/vm/cpu_ia32.h', 'runtime/vm/cpu_x64.h', 'runtime/vm/instructions_arm64.h', 'runtime/vm/instructions_arm.h', - 'runtime/vm/instructions_dbc.h', 'runtime/vm/instructions_ia32.h', 'runtime/vm/instructions_x64.h', 'runtime/vm/os_thread_android.h', @@ -107,10 +103,8 @@ final Set excludedFiles = Set.from([ 'runtime/vm/regexp_assembler_bytecode_inl.h', 'runtime/vm/simulator_arm64.h', 'runtime/vm/simulator_arm.h', - 'runtime/vm/simulator_dbc.h', 'runtime/vm/stack_frame_arm64.h', 'runtime/vm/stack_frame_arm.h', - 'runtime/vm/stack_frame_dbc.h', 'runtime/vm/stack_frame_ia32.h', 'runtime/vm/stack_frame_x64.h', diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index 837ce8e8c44..c96f37c7557 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -27,8 +27,7 @@ namespace dart { -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \ - !defined(TARGET_ARCH_DBC) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) static void RelocateCodeObjects( bool is_vm, @@ -59,8 +58,7 @@ class RawCodeKeyValueTrait { typedef DirectChainedHashMap RawCodeSet; -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \ - // !defined(TARGET_ARCH_DBC) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) \ static RawObject* AllocateUninitialized(PageSpace* old_space, intptr_t size) { ASSERT(Utils::IsAligned(size, kObjectAlignment)); @@ -1723,7 +1721,6 @@ class ObjectPoolSerializationCluster : public SerializationCluster { RawObjectPool::Entry& entry = pool->ptr()->data()[j]; switch (ObjectPool::TypeBits::decode(entry_bits[j])) { case ObjectPool::EntryType::kTaggedObject: { -#if !defined(TARGET_ARCH_DBC) if ((entry.raw_obj_ == StubCode::CallNoScopeNative().raw()) || (entry.raw_obj_ == StubCode::CallAutoScopeNative().raw())) { // Natives can run while precompiling, becoming linked and @@ -1732,7 +1729,6 @@ class ObjectPoolSerializationCluster : public SerializationCluster { s->WriteElementRef(StubCode::CallBootstrapNative().raw(), j); break; } -#endif s->WriteElementRef(entry.raw_obj_, j); break; } @@ -1815,14 +1811,6 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster { entry.raw_value_ = static_cast(new_entry); break; } -#if defined(TARGET_ARCH_DBC) - case ObjectPool::EntryType::kNativeFunctionWrapper: { - // Read nothing. Initialize with the lazy link entry. - uword new_entry = NativeEntry::BootstrapNativeCallWrapperEntry(); - entry.raw_value_ = static_cast(new_entry); - break; - } -#endif default: UNREACHABLE(); } @@ -4733,8 +4721,7 @@ void Serializer::Serialize() { } intptr_t code_order_length = 0; -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \ - !defined(TARGET_ARCH_DBC) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) if (kind_ == Snapshot::kFullAOT) { auto code_objects = static_cast(clusters_by_cid_[kCodeCid]) @@ -4769,8 +4756,7 @@ void Serializer::Serialize() { (*code_objects)[i] = code_order[i]; } } -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \ - // !defined(TARGET_ARCH_DBC) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) intptr_t num_clusters = 0; for (intptr_t cid = 1; cid < num_cids_; cid++) { diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h index 923de559efe..07061897e35 100644 --- a/runtime/vm/code_descriptors.h +++ b/runtime/vm/code_descriptors.h @@ -76,8 +76,7 @@ class CompressedStackMapsIterator : public ValueObject { // returns false. bool Find(uint32_t pc_offset) { // We should never have an entry with a PC offset of 0 inside an - // non-empty CSM, so fail. (On DBC, a pc_offset of 0 can be provided - // to Find() if there's no stack map information for a given Code object.) + // non-empty CSM, so fail. if (pc_offset == 0) return false; do { if (current_pc_offset_ >= pc_offset) break; diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc index 71682313562..d711035fbc6 100644 --- a/runtime/vm/code_patcher.cc +++ b/runtime/vm/code_patcher.cc @@ -18,7 +18,7 @@ DEFINE_FLAG(bool, dual_map_code, true, "Dual map jitted code, RW and RX"); DEFINE_FLAG(bool, dual_map_code, false, "Dual map jitted code, RW and RX"); #endif // defined(DUAL_MAPPING_SUPPORTED) -#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC) +#if defined(TARGET_ARCH_IA32) WritableInstructionsScope::WritableInstructionsScope(uword address, intptr_t size) : address_(address), size_(size) { @@ -34,7 +34,7 @@ WritableInstructionsScope::~WritableInstructionsScope() { VirtualMemory::kReadExecute); } } -#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC) +#endif // defined(TARGET_ARCH_IA32) bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size) { // When breaking within generated code in GDB, it may overwrite individual diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h index ceacea62741..fa5c5213cae 100644 --- a/runtime/vm/code_patcher.h +++ b/runtime/vm/code_patcher.h @@ -19,7 +19,7 @@ class RawCode; class RawFunction; class RawObject; -#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC) +#if defined(TARGET_ARCH_IA32) // Stack-allocated class to create a scope where the specified region // [address, address + size] has write access enabled. This is used // when patching generated code. Access is reset to read-execute in @@ -34,7 +34,7 @@ class WritableInstructionsScope : public ValueObject { const uword address_; const intptr_t size_; }; -#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC) +#endif // defined(TARGET_ARCH_IA32) class CodePatcher : public AllStatic { public: @@ -83,27 +83,14 @@ class CodePatcher : public AllStatic { static RawCode* GetSwitchableCallTargetAt(uword return_address, const Code& caller_code); -#if defined(TARGET_ARCH_DBC) - static NativeFunctionWrapper GetNativeCallAt(uword return_address, - const Code& caller_code, - NativeFunction* target); -#else static RawCode* GetNativeCallAt(uword return_address, const Code& caller_code, NativeFunction* target); -#endif -#if defined(TARGET_ARCH_DBC) - static void PatchNativeCallAt(uword return_address, - const Code& caller_code, - NativeFunction target, - NativeFunctionWrapper trampoline); -#else static void PatchNativeCallAt(uword return_address, const Code& caller_code, NativeFunction target, const Code& trampoline); -#endif static intptr_t GetSubtypeTestCachePoolIndex(uword return_address); }; diff --git a/runtime/vm/code_patcher_dbc.cc b/runtime/vm/code_patcher_dbc.cc deleted file mode 100644 index 93bc87a920d..00000000000 --- a/runtime/vm/code_patcher_dbc.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. -#if defined(TARGET_ARCH_DBC) - -#include "vm/code_patcher.h" - -#include "vm/compiler/backend/flow_graph_compiler.h" -#include "vm/instructions.h" -#include "vm/object.h" - -namespace dart { - -RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, - const Code& code) { - ASSERT(code.ContainsInstructionAt(return_address)); - CallPattern call(return_address, code); - return call.TargetCode(); -} - -void CodePatcher::PatchStaticCallAt(uword return_address, - const Code& code, - const Code& new_target) { - ASSERT(code.ContainsInstructionAt(return_address)); - CallPattern call(return_address, code); - call.SetTargetCode(new_target); -} - -void CodePatcher::InsertDeoptimizationCallAt(uword start) { - CallPattern::InsertDeoptCallAt(start); -} - -RawCode* CodePatcher::GetInstanceCallAt(uword return_address, - const Code& caller_code, - Object* cache) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - CallPattern call(return_address, caller_code); - if (cache != NULL) { - *cache = call.Data(); - } - return call.TargetCode(); -} - -void CodePatcher::PatchInstanceCallAt(uword return_address, - const Code& caller_code, - const Object& data, - const Code& target) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - CallPattern call(return_address, caller_code); - call.SetData(data); - call.SetTargetCode(target); -} - -RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(uword return_address, - const Code& caller_code, - ICData* ic_data_result) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - CallPattern static_call(return_address, caller_code); - ICData& ic_data = ICData::Handle(); - ic_data ^= static_call.Data(); - if (ic_data_result != NULL) { - *ic_data_result = ic_data.raw(); - } - return ic_data.GetTargetAt(0); -} - -void CodePatcher::PatchSwitchableCallAt(uword return_address, - const Code& caller_code, - const Object& data, - const Code& target) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - SwitchableCallPattern call(return_address, caller_code); - call.SetData(data); - call.SetTarget(target); -} - -RawCode* CodePatcher::GetSwitchableCallTargetAt(uword return_address, - const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - SwitchableCallPattern call(return_address, caller_code); - return call.target(); -} - -RawObject* CodePatcher::GetSwitchableCallDataAt(uword return_address, - const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - SwitchableCallPattern call(return_address, caller_code); - return call.data(); -} - -void CodePatcher::PatchNativeCallAt(uword return_address, - const Code& code, - NativeFunction target, - NativeFunctionWrapper trampoline) { - ASSERT(code.ContainsInstructionAt(return_address)); - NativeCallPattern call(return_address, code); - call.set_target(trampoline); - call.set_native_function(target); -} - -NativeFunctionWrapper CodePatcher::GetNativeCallAt(uword return_address, - const Code& caller_code, - NativeFunction* target) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); - NativeCallPattern call(return_address, caller_code); - *target = call.native_function(); - return call.target(); -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc index 12f61e23acb..65afe801ea5 100644 --- a/runtime/vm/compiler/aot/aot_call_specializer.cc +++ b/runtime/vm/compiler/aot/aot_call_specializer.cc @@ -601,7 +601,6 @@ bool AotCallSpecializer::TryOptimizeIntegerOperation(TemplateDartCall<0>* instr, return false; } -#ifndef TARGET_ARCH_DBC if (FlowGraphCompiler::SupportsUnboxedInt64()) { if (op_kind == Token::kNEGATE || op_kind == Token::kBIT_NOT) { left_value = PrepareStaticOpInput(left_value, kMintCid, instr); @@ -609,7 +608,6 @@ bool AotCallSpecializer::TryOptimizeIntegerOperation(TemplateDartCall<0>* instr, op_kind, left_value, DeoptId::kNone, Instruction::kNotSpeculative); } } -#endif } if (replacement != nullptr && !replacement->ComputeCanDeoptimize()) { diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 3b9e272f615..aaf5882fa3d 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -100,8 +100,7 @@ DEFINE_FLAG(bool, Precompiler* Precompiler::singleton_ = nullptr; -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) class PrecompileParsedFunctionHelper : public ValueObject { public: @@ -2055,7 +2054,7 @@ void Precompiler::BindStaticCalls() { void Precompiler::DedupUnlinkedCalls() { ASSERT(!I->compilation_allowed()); -#if !defined(TARGET_ARCH_DBC) + class UnlinkedCallDeduper { public: explicit UnlinkedCallDeduper(Zone* zone) @@ -2139,7 +2138,6 @@ void Precompiler::DedupUnlinkedCalls() { visitor.Visit(current); } } -#endif } void Precompiler::Obfuscate() { @@ -2962,8 +2960,7 @@ const char** Obfuscator::SerializeMap(Thread* thread) { return result; } -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - // !defined(TARGET_ARCH_IA32) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) } // namespace dart diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h index 47e4d9ebd4b..9cb24d247e5 100644 --- a/runtime/vm/compiler/aot/precompiler.h +++ b/runtime/vm/compiler/aot/precompiler.h @@ -346,8 +346,7 @@ class FunctionsTraits { typedef UnorderedHashSet UniqueFunctionsSet; -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) // ObfuscationMap maps Strings to Strings. class ObfuscationMapTraits { public: @@ -553,8 +552,7 @@ class Obfuscator { static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces) {} }; -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - // !defined(TARGET_ARCH_IA32) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) } // namespace dart diff --git a/runtime/vm/compiler/asm_intrinsifier.cc b/runtime/vm/compiler/asm_intrinsifier.cc index 6cc847a560a..0886fe4c187 100644 --- a/runtime/vm/compiler/asm_intrinsifier.cc +++ b/runtime/vm/compiler/asm_intrinsifier.cc @@ -12,8 +12,6 @@ namespace dart { namespace compiler { -#if !defined(TARGET_ARCH_DBC) - void AsmIntrinsifier::String_identityHash(Assembler* assembler, Label* normal_ir_body) { String_getHashCode(assembler, normal_ir_body); @@ -36,8 +34,6 @@ void AsmIntrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler, /*sticky=*/true); } -#endif // !defined(TARGET_ARCH_DBC) - } // namespace compiler } // namespace dart diff --git a/runtime/vm/compiler/asm_intrinsifier.h b/runtime/vm/compiler/asm_intrinsifier.h index 9f7e5d786c7..59b3f63f67e 100644 --- a/runtime/vm/compiler/asm_intrinsifier.h +++ b/runtime/vm/compiler/asm_intrinsifier.h @@ -42,11 +42,6 @@ class AsmIntrinsifier : public AllStatic { static void enum_name(Assembler* assembler, Label* normal_ir_body); ALL_INTRINSICS_LIST(DECLARE_FUNCTION) - // On DBC all intrinsics are handled the same way. -#if defined(TARGET_ARCH_DBC) - GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION) -#endif // defined(TARGET_ARCH_DBC) - #undef DECLARE_FUNCTION static void IntrinsifyRegExpExecuteMatch(Assembler* assembler, diff --git a/runtime/vm/compiler/asm_intrinsifier_dbc.cc b/runtime/vm/compiler/asm_intrinsifier_dbc.cc deleted file mode 100644 index cfb113054af..00000000000 --- a/runtime/vm/compiler/asm_intrinsifier_dbc.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. -#if defined(TARGET_ARCH_DBC) - -#define SHOULD_NOT_INCLUDE_RUNTIME - -#include "vm/class_id.h" -#include "vm/compiler/asm_intrinsifier.h" -#include "vm/compiler/assembler/assembler.h" -#include "vm/compiler/intrinsifier.h" - -namespace dart { -namespace compiler { - -DECLARE_FLAG(bool, interpret_irregexp); - -#define DEFINE_FUNCTION(class_name, test_function_name, enum_name, fp) \ - void AsmIntrinsifier::enum_name(Assembler* assembler, \ - Label* normal_ir_body) { \ - if (Simulator::IsSupportedIntrinsic(Simulator::k##enum_name##Intrinsic)) { \ - assembler->Intrinsic(Simulator::k##enum_name##Intrinsic); \ - } \ - assembler->Bind(normal_ir_body); \ - } - -ALL_INTRINSICS_LIST(DEFINE_FUNCTION) -GRAPH_INTRINSICS_LIST(DEFINE_FUNCTION) -#undef DEFINE_FUNCTION - -} // namespace compiler -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc index 6b5427d04ad..6cc1a58efbb 100644 --- a/runtime/vm/compiler/assembler/assembler.cc +++ b/runtime/vm/compiler/assembler/assembler.cc @@ -244,12 +244,10 @@ bool AssemblerBase::EmittingComments() { return FLAG_code_comments || FLAG_disassemble || FLAG_disassemble_optimized; } -#if !defined(TARGET_ARCH_DBC) void Assembler::Stop(const char* message) { Comment("Stop: %s", message); Breakpoint(); } -#endif intptr_t ObjIndexPair::Hashcode(Key key) { if (key.type() != ObjectPoolBuilderEntry::kTaggedObject) { diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h index 645728aba31..c5100dc2bd7 100644 --- a/runtime/vm/compiler/assembler/assembler.h +++ b/runtime/vm/compiler/assembler/assembler.h @@ -380,8 +380,6 @@ class AssemblerBase : public StackResource { #include "vm/compiler/assembler/assembler_arm.h" #elif defined(TARGET_ARCH_ARM64) #include "vm/compiler/assembler/assembler_arm64.h" -#elif defined(TARGET_ARCH_DBC) -#include "vm/compiler/assembler/assembler_dbc.h" #else #error Unknown architecture. #endif diff --git a/runtime/vm/compiler/assembler/assembler_dbc.cc b/runtime/vm/compiler/assembler/assembler_dbc.cc deleted file mode 100644 index fe6f47f9454..00000000000 --- a/runtime/vm/compiler/assembler/assembler_dbc.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" // NOLINT -#if defined(TARGET_ARCH_DBC) - -#define SHOULD_NOT_INCLUDE_RUNTIME - -#include "vm/compiler/assembler/assembler.h" -#include "vm/cpu.h" -#include "vm/longjump.h" -#include "vm/simulator.h" - -namespace dart { -DECLARE_FLAG(bool, check_code_pointer); -DECLARE_FLAG(bool, inline_alloc); - -namespace compiler { - -void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { - const uword end = data + length; - while (data < end) { - *reinterpret_cast(data) = SimulatorBytecode::kTrap; - data += sizeof(int32_t); - } -} - -#define DEFINE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2) \ - void Assembler::Name(PARAMS_##Signature) { \ - Emit(SimulatorBytecode::FENCODE_##Signature( \ - SimulatorBytecode::k##Name ENCODE_##Signature)); \ - } - -#define PARAMS_0 -#define PARAMS_A_D uintptr_t ra, uintptr_t rd -#define PARAMS_D uintptr_t rd -#define PARAMS_A_B_C uintptr_t ra, uintptr_t rb, uintptr_t rc -#define PARAMS_A_B_Y uintptr_t ra, uintptr_t rb, intptr_t ry -#define PARAMS_A uintptr_t ra -#define PARAMS_T intptr_t x -#define PARAMS_A_X uintptr_t ra, intptr_t x -#define PARAMS_X intptr_t x - -#define ENCODE_0 -#define ENCODE_A_D , ra, rd -#define ENCODE_D , 0, rd -#define ENCODE_A_B_C , ra, rb, rc -#define ENCODE_A_B_Y , ra, rb, ry -#define ENCODE_A , ra, 0 -#define ENCODE_T , x -#define ENCODE_A_X , ra, x -#define ENCODE_X , 0, x - -#define FENCODE_0 Encode -#define FENCODE_A_D Encode -#define FENCODE_D Encode -#define FENCODE_A_B_C Encode -#define FENCODE_A_B_Y Encode -#define FENCODE_A Encode -#define FENCODE_T EncodeSigned -#define FENCODE_A_X EncodeSigned -#define FENCODE_X EncodeSigned - -BYTECODES_LIST(DEFINE_EMIT) - -#undef DEFINE_EMIT - -void Assembler::Emit(int32_t value) { - AssemblerBuffer::EnsureCapacity ensured(&buffer_); - buffer_.Emit(value); -} - -static int32_t EncodeJump(int32_t relative_pc) { - return SimulatorBytecode::kJump | (relative_pc << 8); -} - -static int32_t OffsetToPC(int32_t offset) { - return offset >> 2; -} - -void Assembler::Jump(Label* label) { - if (label->IsBound()) { - Emit(EncodeJump(OffsetToPC(label->Position() - buffer_.Size()))); - } else { - const intptr_t position = buffer_.Size(); - Emit(label->position_); - label->LinkTo(position); - } -} - -void Assembler::Bind(Label* label) { - ASSERT(!label->IsBound()); - ASSERT(!label->IsBound()); - intptr_t bound_pc = buffer_.Size(); - while (label->IsLinked()) { - const int32_t position = label->Position(); - const int32_t next_position = buffer_.Load(position); - buffer_.Store(position, - EncodeJump(OffsetToPC(bound_pc - position))); - label->position_ = next_position; - } - label->BindTo(bound_pc); -} - -void Assembler::Stop(const char* message) { - // TODO(vegorov) support passing a message to the bytecode. - Emit(SimulatorBytecode::kTrap); -} - -void Assembler::PushConstant(const Object& obj) { - PushConstant(AddConstant(obj)); -} - -void Assembler::LoadConstant(uintptr_t ra, const Object& obj) { - LoadConstant(ra, AddConstant(obj)); -} - -intptr_t Assembler::AddConstant(const Object& obj) { - return object_pool_builder().FindObject( - NewZoneHandle(ThreadState::Current()->zone(), obj)); -} - -} // namespace compiler -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h deleted file mode 100644 index 0737026cc69..00000000000 --- a/runtime/vm/compiler/assembler/assembler_dbc.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_DBC_H_ -#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_DBC_H_ - -#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_H_ -#error Do not include assembler_dbc.h directly; use assembler.h instead. -#endif - -#include "platform/assert.h" -#include "platform/utils.h" -#include "vm/constants_dbc.h" -#include "vm/cpu.h" -#include "vm/hash_map.h" -#include "vm/simulator.h" - -namespace dart { - -namespace compiler { - -// Dummy declaration to make things compile. -class Address : public ValueObject { - private: - Address(); -}; - -class Assembler : public AssemblerBase { - public: - explicit Assembler(ObjectPoolBuilder* object_pool_builder, - bool use_far_branches = false) - : AssemblerBase(object_pool_builder) {} - ~Assembler() {} - - void Bind(Label* label); - void Jump(Label* label); - - // Misc. functionality - intptr_t prologue_offset() const { return 0; } - - void MonomorphicCheckedEntryJIT() {} - void MonomorphicCheckedEntryAOT() {} - - // Debugging and bringup support. - void Breakpoint() override { Stop("Breakpoint!"); } - void Stop(const char* message) override; - - static void InitializeMemoryWithBreakpoints(uword data, intptr_t length); - - static uword GetBreakInstructionFiller() { return SimulatorBytecode::kTrap; } - - static bool IsSafe(const Object& value) { return true; } - static bool IsSafeSmi(const Object& value) { return false; } - - enum CanBeSmi { - kValueIsNotSmi, - kValueCanBeSmi, - }; - - // Bytecodes. - -#define DECLARE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2) \ - void Name(PARAMS_##Signature); - -#define PARAMS_0 -#define PARAMS_A_D uintptr_t ra, uintptr_t rd -#define PARAMS_D uintptr_t rd -#define PARAMS_A_B_C uintptr_t ra, uintptr_t rb, uintptr_t rc -#define PARAMS_A_B_Y uintptr_t ra, uintptr_t rb, intptr_t ry -#define PARAMS_A uintptr_t ra -#define PARAMS_X intptr_t x -#define PARAMS_T intptr_t x -#define PARAMS_A_X uintptr_t ra, intptr_t x - - BYTECODES_LIST(DECLARE_EMIT) - -#undef PARAMS_0 -#undef PARAMS_A_D -#undef PARAMS_D -#undef PARAMS_A_B_C -#undef PARAMS_A_B_Y -#undef PARAMS_A -#undef PARAMS_X -#undef PARAMS_T -#undef PARAMS_A_X -#undef DECLARE_EMIT - - void Emit(int32_t value); - - void PushConstant(const Object& obj); - void LoadConstant(uintptr_t ra, const Object& obj); - - intptr_t AddConstant(const Object& obj); - - void Nop(intptr_t d) { Nop(0, d); } - - private: - DISALLOW_ALLOCATION(); - DISALLOW_COPY_AND_ASSIGN(Assembler); -}; - -} // namespace compiler -} // namespace dart - -#endif // RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_DBC_H_ diff --git a/runtime/vm/compiler/assembler/assembler_dbc_test.cc b/runtime/vm/compiler/assembler/assembler_dbc_test.cc deleted file mode 100644 index 562fb4c9513..00000000000 --- a/runtime/vm/compiler/assembler/assembler_dbc_test.cc +++ /dev/null @@ -1,2857 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#include "vm/compiler/assembler/assembler.h" -#include "vm/compiler/backend/locations.h" -#include "vm/compiler/compiler_state.h" -#include "vm/stack_frame.h" -#include "vm/symbols.h" -#include "vm/unit_test.h" - -namespace dart { -namespace compiler { - -static RawObject* ExecuteTest(const Code& code) { - const intptr_t kTypeArgsLen = 0; - const intptr_t kNumArgs = 0; - const Array& args_desc = - Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)); - const Array& args = Array::Handle(Array::New(0)); - Thread* thread = Thread::Current(); - TransitionToGenerated transition(thread); - return Simulator::Current()->Call(code, args_desc, args, thread); -} - -#define EXECUTE_TEST_CODE_INTPTR(code) \ - Smi::Value(Smi::RawCast(ExecuteTest(code))) -#define EXECUTE_TEST_CODE_BOOL(code) \ - (Bool::RawCast(ExecuteTest(code)) == Bool::True().raw()) -#define EXECUTE_TEST_CODE_OBJECT(code) Object::Handle(ExecuteTest(code)) -#define EXECUTE_TEST_CODE_DOUBLE(code) \ - bit_cast(ExecuteTest(code)) -#define EXECUTE_TEST_CODE_INTPTR_UNBOXED(code) \ - reinterpret_cast(ExecuteTest(code)) - -#define __ assembler-> - -static RawClass* CreateDummyClass(const String& class_name, - const Script& script) { - const Class& cls = Class::Handle(Class::New( - Library::Handle(), class_name, script, TokenPosition::kNoSource)); - cls.set_is_synthesized_class(); // Dummy class for testing. - return cls.raw(); -} - -static RawLibrary* CreateDummyLibrary(const String& library_name) { - return Library::New(library_name); -} - -static RawFunction* CreateFunction(const char* name) { - Thread* thread = Thread::Current(); - const String& class_name = String::Handle(Symbols::New(thread, "ownerClass")); - const String& lib_name = String::Handle(Symbols::New(thread, "ownerLibrary")); - const Script& script = Script::Handle(); - const Class& owner_class = - Class::Handle(CreateDummyClass(class_name, script)); - const Library& owner_library = Library::Handle(CreateDummyLibrary(lib_name)); - owner_class.set_library(owner_library); - const String& function_name = String::ZoneHandle(Symbols::New(thread, name)); - return Function::New(function_name, RawFunction::kRegularFunction, true, - false, false, false, false, owner_class, - TokenPosition::kMinSource); -} - -static void GenerateDummyCode(Assembler* assembler, const Object& result) { - __ PushConstant(result); - __ ReturnTOS(); -} - -static void MakeDummyInstanceCall(Assembler* assembler, const Object& result) { - // Make a dummy function. - ObjectPoolBuilder object_pool_builder; - Assembler _assembler_(&object_pool_builder); - GenerateDummyCode(&_assembler_, result); - const char* dummy_function_name = "dummy_instance_function"; - const Function& dummy_instance_function = - Function::Handle(CreateFunction(dummy_function_name)); - Code& code = Code::Handle(Code::FinalizeCodeAndNotify( - dummy_instance_function, nullptr, &_assembler_, - Code::PoolAttachment::kAttachPool)); - dummy_instance_function.AttachCode(code); - - // Make a dummy ICData. - const intptr_t kTypeArgsLen = 0; - const intptr_t kNumArgs = 2; - const Array& dummy_arguments_descriptor = - Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)); - const ICData& ic_data = ICData::Handle(ICData::New( - dummy_instance_function, String::Handle(dummy_instance_function.name()), - dummy_arguments_descriptor, DeoptId::kNone, 2, ICData::kInstance)); - - // Wire up the Function in the ICData. - GrowableArray cids(2); - cids.Add(kSmiCid); - cids.Add(kSmiCid); - ic_data.AddCheck(cids, dummy_instance_function); - - // For the non-Smi tests. - cids[0] = kMintCid; - ic_data.AddCheck(cids, dummy_instance_function); - ICData* call_ic_data = &ICData::ZoneHandle(ic_data.Original()); - - // Generate the instance call. - const intptr_t call_ic_data_kidx = __ AddConstant(*call_ic_data); - __ InstanceCall2(2, call_ic_data_kidx); -} - -ASSEMBLER_TEST_GENERATE(Simple, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(Simple, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(Nop, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ Nop(0); - __ Nop(0); - __ Nop(0); - __ Nop(0); - __ Nop(0); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(Nop, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// Called from assembler_test.cc. -// FP[-kParamEndSlotFromFp - 1]: growable array -// FP[-kParamEndSlotFromFp - 2]: value -ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { - __ Frame(2); - __ Move(0, -kParamEndSlotFromFp - 1); - __ Move(1, -kParamEndSlotFromFp - 2); - __ StoreField(0, GrowableObjectArray::data_offset() / target::kWordSize, 1); - __ Return(0); -} - -// - OneByteStringFromCharCode rA, rX -// -// Load the one-character symbol with the char code given by the Smi -// in FP[rX] into FP[rA]. -ASSEMBLER_TEST_GENERATE(OneByteStringFromCharCode, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::ZoneHandle(Smi::New(65))); - __ OneByteStringFromCharCode(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(OneByteStringFromCharCode, test) { - EXPECT_EQ(Symbols::New(Thread::Current(), "A"), - EXECUTE_TEST_CODE_OBJECT(test->code()).raw()); -} - -// - StringToCharCode rA, rX -// -// Load and smi-encode the single char code of the string in FP[rX] into -// FP[rA]. If the string's length is not 1, load smi -1 instead. -// -ASSEMBLER_TEST_GENERATE(StringToCharCode, assembler) { - __ Frame(2); - __ LoadConstant(0, String::ZoneHandle(String::New("A", Heap::kOld))); - __ StringToCharCode(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(StringToCharCode, test) { - EXPECT_EQ(65, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(StringToCharCodeIllegalLength, assembler) { - __ Frame(2); - __ LoadConstant(0, String::ZoneHandle(String::New("AAA", Heap::kOld))); - __ StringToCharCode(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(StringToCharCodeIllegalLength, test) { - EXPECT_EQ(-1, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS; -// GreaterThanTOS; -// -// Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are -// both smis and result of SP[0] SP[-1] is a smi - if this is true -// then pops operands and pushes result on the stack and skips the next -// instruction (which implements a slow path fallback). -ASSEMBLER_TEST_GENERATE(AddTOS, assembler) { - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ PushConstant(Smi::Handle(Smi::New(84))); - __ AddTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AddTOS, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(AddTOSOverflow, assembler) { - __ PushConstant(Smi::Handle(Smi::New(Smi::kMaxValue))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ AddTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AddTOSOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(AddTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ AddTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AddTOSNonSmi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(SubTOS, assembler) { - __ PushConstant(Smi::Handle(Smi::New(30))); - __ PushConstant(Smi::Handle(Smi::New(-12))); - __ SubTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(SubTOS, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(SubTOSOverflow, assembler) { - __ PushConstant(Smi::Handle(Smi::New(Smi::kMinValue))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ SubTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(SubTOSOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(SubTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ SubTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(SubTOSNonSmi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(MulTOS, assembler) { - __ PushConstant(Smi::Handle(Smi::New(-6))); - __ PushConstant(Smi::Handle(Smi::New(-7))); - __ MulTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(MulTOS, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(MulTOSOverflow, assembler) { - __ PushConstant(Smi::Handle(Smi::New(Smi::kMaxValue))); - __ PushConstant(Smi::Handle(Smi::New(-8))); - __ MulTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(MulTOSOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(MulTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ MulTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(MulTOSNonSmi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BitOrTOS, assembler) { - __ PushConstant(Smi::Handle(Smi::New(0x22))); - __ PushConstant(Smi::Handle(Smi::New(0x08))); - __ BitOrTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(BitOrTOS, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BitOrTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(0x08))); - __ BitOrTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(BitOrTOSNonSmi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BitAndTOS, assembler) { - __ PushConstant(Smi::Handle(Smi::New(0x2a))); - __ PushConstant(Smi::Handle(Smi::New(0xaa))); - __ BitAndTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(BitAndTOS, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BitAndTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(0x08))); - __ BitAndTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(BitAndTOSNonSmi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(EqualTOSTrue, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ EqualTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(EqualTOSTrue, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(EqualTOSFalse, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ EqualTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Bool::True()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(EqualTOSFalse, test) { - EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(EqualTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ EqualTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Bool::True()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(EqualTOSNonSmi, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(LessThanTOSTrue, assembler) { - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ LessThanTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(LessThanTOSTrue, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(LessThanTOSFalse, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ LessThanTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(LessThanTOSFalse, test) { - EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(LessThanTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ LessThanTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Bool::True()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(LessThanTOSNonSmi, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(GreaterThanTOSTrue, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ GreaterThanTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(GreaterThanTOSTrue, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(GreaterThanTOSFalse, assembler) { - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ GreaterThanTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(GreaterThanTOSFalse, test) { - EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(GreaterThanTOSNonSmi, assembler) { - const String& numstr = - String::Handle(String::New("9176543219876543210", Heap::kOld)); - __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld))); - __ PushConstant(Smi::Handle(Smi::New(-42))); - __ GreaterThanTOS(); - // Shouldn't be skipped. - MakeDummyInstanceCall(assembler, Bool::True()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(GreaterThanTOSNonSmi, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -// - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC -// -// Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC]. -// If these instructions can trigger a deoptimization, the following -// instruction should be Deopt. If no deoptimization should be triggered, -// the immediately following instruction is skipped. -ASSEMBLER_TEST_GENERATE(AddNoOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(20))); - __ LoadConstant(1, Smi::Handle(Smi::New(22))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Add(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(AddNoOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(AddOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue))); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Add(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(AddOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(SubNoOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(64))); - __ LoadConstant(1, Smi::Handle(Smi::New(22))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Sub(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(SubNoOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(SubOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue))); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Sub(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(SubOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(MulNoOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-6))); - __ LoadConstant(1, Smi::Handle(Smi::New(-7))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Mul(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(MulNoOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(MulOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue))); - __ LoadConstant(1, Smi::Handle(Smi::New(-8))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Mul(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(MulOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DivNoDeopt, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(27))); - __ LoadConstant(1, Smi::Handle(Smi::New(3))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Div(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DivNoDeopt, test) { - EXPECT_EQ(9, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DivZero, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(3))); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Div(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DivZero, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DivCornerCase, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Div(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DivCornerCase, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ModPosPos, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(4))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Mod(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ModPosPos, test) { - EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ModNegPos, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-42))); - __ LoadConstant(1, Smi::Handle(Smi::New(4))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Mod(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ModNegPos, test) { - EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ModPosNeg, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(-4))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Mod(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ModPosNeg, test) { - EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ModZero, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(3))); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Mod(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ModZero, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ShlNoDeopt, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(21))); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Shl(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ShlNoDeopt, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ShlOverflow, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue))); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Shl(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ShlOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ShlNegShift, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(21))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Shl(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ShlNegShift, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ShrNoDeopt, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(84))); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Shr(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(-42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ShrNoDeopt, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(ShrNegShift, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(21))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ Shr(2, 0, 1); - __ LoadConstant(2, Smi::Handle(Smi::New(42))); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(ShrNegShift, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - Neg rA , rD -// -// FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the -// immediately following instruction is skipped. -ASSEMBLER_TEST_GENERATE(NegPos, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Neg(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(NegPos, test) { - EXPECT_EQ(-42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(NegNeg, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(-42))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Neg(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(NegNeg, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(NegOverflow, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Neg(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(NegOverflow, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - BitOr, BitAnd, BitXor rA, rB, rC -// -// FP[rA] <- FP[rB] op FP[rC] -ASSEMBLER_TEST_GENERATE(BitOr, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(0x2))); - __ LoadConstant(1, Smi::Handle(Smi::New(0x28))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ BitOr(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BitOr, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BitAnd, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(0x2b))); - __ LoadConstant(1, Smi::Handle(Smi::New(0x6a))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ BitAnd(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BitAnd, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BitXor, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(0x37))); - __ LoadConstant(1, Smi::Handle(Smi::New(0x1d))); - __ LoadConstant(2, Smi::Handle(Smi::New(-1))); - __ BitXor(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BitXor, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - BitNot rA, rD -// -// FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi. -ASSEMBLER_TEST_GENERATE(BitNot, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(~42))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ BitNot(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(BitNot, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS -// -// Skips the next instruction unless the given condition holds. 'Num' -// variants perform number check while non-Num variants just compare -// RawObject pointers. -// -// Used to implement conditional jump: -// -// IfNeStrictTOS -// Jump T ;; jump if not equal -ASSEMBLER_TEST_GENERATE(IfNeStrictTOSTaken, assembler) { - Label branch_taken; - const Array& array1 = Array::Handle(Array::New(1, Heap::kOld)); - const Array& array2 = Array::Handle(Array::New(2, Heap::kOld)); - __ PushConstant(array1); - __ PushConstant(array2); - __ IfNeStrictTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeStrictTOSTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeStrictTOSNotTaken, assembler) { - Label branch_taken; - const Array& array1 = Array::Handle(Array::New(1, Heap::kOld)); - __ PushConstant(array1); - __ PushConstant(array1); - __ IfNeStrictTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeStrictTOSNotTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// TODO(zra): Also add tests that use Mint, Bignum. -ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSTaken, assembler) { - Label branch_taken; - __ PushConstant(Smi::Handle(Smi::New(-1))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ IfNeStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeStrictNumTOSTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSNotTaken, assembler) { - Label branch_taken; - __ PushConstant(Smi::Handle(Smi::New(1))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ IfNeStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeStrictNumTOSNotTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSTakenDouble, assembler) { - Label branch_taken; - __ PushConstant(Double::Handle(Double::New(-1.0, Heap::kOld))); - __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld))); - __ IfNeStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeStrictNumTOSTakenDouble, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSNotTakenDouble, assembler) { - Label branch_taken; - __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld))); - __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld))); - __ IfNeStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeStrictNumTOSNotTakenDouble, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqStrictTOSTaken, assembler) { - Label branch_taken; - const Array& array1 = Array::Handle(Array::New(1, Heap::kOld)); - __ PushConstant(array1); - __ PushConstant(array1); - __ IfEqStrictTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqStrictTOSTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqStrictTOSNotTaken, assembler) { - Label branch_taken; - const Array& array1 = Array::Handle(Array::New(1, Heap::kOld)); - const Array& array2 = Array::Handle(Array::New(2, Heap::kOld)); - __ PushConstant(array1); - __ PushConstant(array2); - __ IfEqStrictTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqStrictTOSNotTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// TODO(zra): Also add tests that use Mint, Bignum. -ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSTaken, assembler) { - Label branch_taken; - __ PushConstant(Smi::Handle(Smi::New(1))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ IfEqStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqStrictNumTOSTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSNotTaken, assembler) { - Label branch_taken; - __ PushConstant(Smi::Handle(Smi::New(-1))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ IfEqStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqStrictNumTOSNotTaken, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSTakenDouble, assembler) { - Label branch_taken; - __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld))); - __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld))); - __ IfEqStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqStrictNumTOSTakenDouble, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSNotTakenDouble, assembler) { - Label branch_taken; - __ PushConstant(Double::Handle(Double::New(-1.0, Heap::kOld))); - __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld))); - __ IfEqStrictNumTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqStrictNumTOSNotTakenDouble, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - BooleanNegateTOS -// -// SP[0] = !SP[0] -ASSEMBLER_TEST_GENERATE(BooleanNegateTOSTrue, assembler) { - __ PushConstant(Bool::True()); - __ BooleanNegateTOS(); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(BooleanNegateTOSTrue, test) { - EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BooleanNegateTOSFalse, assembler) { - __ PushConstant(Bool::False()); - __ BooleanNegateTOS(); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(BooleanNegateTOSFalse, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -// - AssertBoolean A -// -// Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0). -ASSEMBLER_TEST_GENERATE(AssertBooleanTrue, assembler) { - __ PushConstant(Bool::True()); - __ AssertBoolean(1); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AssertBooleanTrue, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(AssertBooleanFalse, assembler) { - __ PushConstant(Bool::False()); - __ AssertBoolean(1); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AssertBooleanFalse, test) { - EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(AssertBooleanNotNull, assembler) { - __ PushConstant(Bool::True()); - __ AssertBoolean(0); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AssertBooleanNotNull, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(AssertBooleanFail1, assembler) { - __ PushConstant(Smi::Handle(Smi::New(37))); - __ AssertBoolean(1); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AssertBooleanFail1, test) { - EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsError()); -} - -ASSEMBLER_TEST_GENERATE(AssertBooleanFail2, assembler) { - __ PushConstant(Object::null_object()); - __ AssertBoolean(0); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(AssertBooleanFail2, test) { - EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsError()); -} - -// - Drop1; DropR n; Drop n -// -// Drop 1 or n values from the stack, if instruction is DropR push the first -// dropped value to the stack; -ASSEMBLER_TEST_GENERATE(Drop1, assembler) { - __ PushConstant(Smi::Handle(Smi::New(0))); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ Drop1(); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(Drop1, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(Drop, assembler) { - __ PushConstant(Smi::Handle(Smi::New(0))); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ Drop(11); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(Drop, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DropR, assembler) { - __ PushConstant(Smi::Handle(Smi::New(0))); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(41))); - __ DropR(11); - __ AddTOS(); - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(DropR, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - Frame D -// -// Reserve and initialize with null space for D local variables. -ASSEMBLER_TEST_GENERATE(FrameInitialized1, assembler) { - __ Frame(1); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(FrameInitialized1, test) { - EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsNull()); -} - -ASSEMBLER_TEST_GENERATE(FrameInitialized, assembler) { - Label error; - __ PushConstant(Smi::Handle(Smi::New(42))); - __ Frame(4); - __ PushConstant(Object::null_object()); - __ IfNeStrictTOS(); - __ Jump(&error); - __ PushConstant(Object::null_object()); - __ IfNeStrictTOS(); - __ Jump(&error); - __ PushConstant(Object::null_object()); - __ IfNeStrictTOS(); - __ Jump(&error); - __ PushConstant(Object::null_object()); - __ IfNeStrictTOS(); - __ Jump(&error); - __ ReturnTOS(); - - // If a frame slot was not initialized to null. - __ Bind(&error); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(FrameInitialized, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - StoreLocal rX; PopLocal rX -// -// Store top of the stack into FP[rX] and pop it if needed. -// -// - Push rX -// -// Push FP[rX] to the stack. -ASSEMBLER_TEST_GENERATE(StoreLocalPush, assembler) { - __ Frame(1); - __ PushConstant(Smi::Handle(Smi::New(37))); - __ PushConstant(Smi::Handle(Smi::New(21))); - __ StoreLocal(0); - __ Push(0); - __ AddTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(StoreLocalPush, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(PopLocalPush, assembler) { - __ Frame(1); - __ PushConstant(Smi::Handle(Smi::New(21))); - __ PopLocal(0); - __ Push(0); - __ Push(0); - __ AddTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(PopLocalPush, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(LoadConstantPush, assembler) { - __ Frame(1); - __ LoadConstant(0, Smi::Handle(Smi::New(21))); - __ Push(0); - __ Push(0); - __ AddTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(LoadConstantPush, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - Move rA, rX -// -// FP[rA] <- FP[rX] -// Note: rX is signed so it can be used to address parameters which are -// at negative indices with respect to FP. -ASSEMBLER_TEST_GENERATE(MoveLocalLocal, assembler) { - __ Frame(2); - __ PushConstant(Smi::Handle(Smi::New(21))); - __ PopLocal(0); - __ Move(1, 0); - __ Push(0); - __ Push(1); - __ AddTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(MoveLocalLocal, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - Return R; ReturnTOS -// -// Return to the caller using either a value from the given register or a -// value from the top-of-stack as a result. -ASSEMBLER_TEST_GENERATE(Return1, assembler) { - __ Frame(1); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ StoreLocal(0); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(Return1, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(Return2, assembler) { - __ Frame(2); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ StoreLocal(1); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(Return2, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(Loop, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); - - Label loop_entry, error; - __ Bind(&loop_entry); - // Add 1 to FP[1]. - __ PushConstant(Smi::Handle(Smi::New(1))); - __ Push(1); - __ AddTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(-1))); - __ PopLocal(1); - - // Subtract 1 from FP[0]. - __ Push(0); - __ PushConstant(Smi::Handle(Smi::New(1))); - __ SubTOS(); - // Should be skipped. - MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(-1))); - - // Jump to loop_entry if FP[0] != 0. - __ StoreLocal(0); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ IfNeStrictNumTOS(); - __ Jump(&loop_entry); - - __ Return(1); - - __ Bind(&error); - __ LoadConstant(1, Smi::Handle(Smi::New(-42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(Loop, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - LoadClassIdTOS, LoadClassId rA, D -// -// LoadClassIdTOS loads the class id from the object at SP[0] and stores it -// to SP[0]. LoadClassId loads the class id from FP[rA] and stores it to -// FP[D]. -ASSEMBLER_TEST_GENERATE(LoadClassIdTOS, assembler) { - __ PushConstant(Smi::Handle(Smi::New(42))); - __ LoadClassIdTOS(); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(LoadClassIdTOS, test) { - EXPECT_EQ(kSmiCid, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(LoadClassId, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadClassId(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(LoadClassId, test) { - EXPECT_EQ(kSmiCid, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - CreateArrayTOS -// -// Allocate array of length SP[0] with type arguments SP[-1]. -ASSEMBLER_TEST_GENERATE(CreateArrayTOS, assembler) { - __ PushConstant(Object::null_object()); - __ PushConstant(Smi::Handle(Smi::New(10))); - __ CreateArrayTOS(); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(CreateArrayTOS, test) { - const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code()); - EXPECT(obj.IsArray()); - Array& array = Array::Handle(); - array ^= obj.raw(); - EXPECT_EQ(10, array.Length()); -} - -// - TestSmi rA, rD -// -// If FP[rA] & FP[rD] != 0, then skip the next instruction. FP[rA] and FP[rD] -// must be Smis. -ASSEMBLER_TEST_GENERATE(TestSmiTrue, assembler) { - Label branch_taken; - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(7))); - __ LoadConstant(1, Smi::Handle(Smi::New(3))); - __ TestSmi(0, 1); - __ Jump(&branch_taken); - __ PushConstant(Bool::True()); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(TestSmiTrue, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(TestSmiFalse, assembler) { - Label branch_taken; - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(8))); - __ LoadConstant(1, Smi::Handle(Smi::New(4))); - __ TestSmi(0, 1); - __ Jump(&branch_taken); - __ PushConstant(Bool::True()); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Bool::False()); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(TestSmiFalse, test) { - EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code())); -} - -// - TestCids rA, D -// -// The next D instructions must be Nops whose D field encodes a class id. If -// the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's -// A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found, -// jump to PC + N. -ASSEMBLER_TEST_GENERATE(TestCidsTrue, assembler) { - Label true_branch, no_match_branch; - __ Frame(2); - __ LoadConstant(0, Object::Handle(String::New("Hi", Heap::kOld))); - const intptr_t num_cases = 2; - __ TestCids(0, num_cases); - __ Nop(0, static_cast(kSmiCid)); // Smi => false - __ Nop(1, static_cast(kOneByteStringCid)); // String => true - __ Jump(&no_match_branch); - __ Jump(&true_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); // false branch - __ Return(1); - __ Bind(&true_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ Return(1); - __ Bind(&no_match_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(2))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(TestCidsTrue, test) { - EXPECT_EQ(1, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(TestCidsFalse, assembler) { - Label true_branch, no_match_branch; - __ Frame(2); - __ LoadConstant(0, Object::Handle(Smi::New(42))); - const intptr_t num_cases = 2; - __ TestCids(0, num_cases); - __ Nop(0, static_cast(kSmiCid)); // Smi => false - __ Nop(1, static_cast(kOneByteStringCid)); // String => true - __ Jump(&no_match_branch); - __ Jump(&true_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); // false branch - __ Return(1); - __ Bind(&true_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ Return(1); - __ Bind(&no_match_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(2))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(TestCidsFalse, test) { - EXPECT_EQ(0, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(TestCidsNoMatch, assembler) { - Label true_branch, no_match_branch; - __ Frame(2); - __ LoadConstant(0, Object::Handle(Array::New(1, Heap::kOld))); - const intptr_t num_cases = 2; - __ TestCids(0, num_cases); - __ Nop(0, static_cast(kSmiCid)); // Smi => false - __ Nop(1, static_cast(kOneByteStringCid)); // String => true - __ Jump(&no_match_branch); - __ Jump(&true_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); // false branch - __ Return(1); - __ Bind(&true_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(1))); - __ Return(1); - __ Bind(&no_match_branch); - __ LoadConstant(1, Smi::Handle(Smi::New(2))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(TestCidsNoMatch, test) { - EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - CheckSmi rA -// -// If FP[rA] is a Smi, then skip the next instruction. -ASSEMBLER_TEST_GENERATE(CheckSmiPass, assembler) { - __ Frame(1); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ LoadConstant(0, Smi::Handle(Smi::New(0))); - __ CheckSmi(0); - __ PushConstant(Smi::Handle(Smi::New(-1))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(CheckSmiPass, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(CheckSmiFail, assembler) { - __ Frame(1); - __ PushConstant(Smi::Handle(Smi::New(-1))); - __ LoadConstant(0, Bool::True()); - __ CheckSmi(0); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(CheckSmiFail, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - CheckClassId rA, D -// -// If the object at FP[rA]'s class id matches the class id in PP[D], then -// skip the following instruction. -ASSEMBLER_TEST_GENERATE(CheckClassIdSmiPass, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadClassId(1, 0); - __ CheckClassId(1, kSmiCid); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(CheckClassIdSmiPass, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(CheckClassIdNonSmiPass, assembler) { - __ Frame(2); - __ LoadConstant(0, Bool::True()); - __ LoadClassId(1, 0); - __ CheckClassId(1, kBoolCid); - __ LoadConstant(0, Bool::False()); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(CheckClassIdNonSmiPass, test) { - EXPECT(EXECUTE_TEST_CODE_BOOL(test->code())); -} - -ASSEMBLER_TEST_GENERATE(CheckClassIdFail, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadClassId(1, 0); - __ CheckClassId(1, kBoolCid); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(CheckClassIdFail, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - IfNull rA -// -// Cond is Eq or Ne. Skips the next instruction unless the given condition -// holds. -ASSEMBLER_TEST_GENERATE(IfEqNullNotNull, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ IfEqNull(0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(IfEqNullNotNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqNullIsNull, assembler) { - __ Frame(2); - __ LoadConstant(0, Object::null_object()); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ IfEqNull(0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(IfEqNullIsNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeNullIsNull, assembler) { - __ Frame(2); - __ LoadConstant(0, Object::null_object()); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ IfNeNull(0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(IfNeNullIsNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeNullNotNull, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ IfNeNull(0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(IfNeNullNotNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqNullTOSNotNull, assembler) { - Label branch_taken; - __ PushConstant(Smi::Handle(Smi::New(-1))); - __ IfEqNullTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqNullTOSNotNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfEqNullTOSIsNull, assembler) { - Label branch_taken; - __ PushConstant(Object::null_object()); - __ IfEqNullTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfEqNullTOSIsNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeNullTOSNotNull, assembler) { - Label branch_taken; - __ PushConstant(Smi::Handle(Smi::New(-1))); - __ IfNeNullTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeNullTOSNotNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfNeNullTOSIsNull, assembler) { - Label branch_taken; - __ PushConstant(Object::null_object()); - __ IfNeNullTOS(); - __ Jump(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(42))); - __ ReturnTOS(); - __ Bind(&branch_taken); - __ PushConstant(Smi::Handle(Smi::New(0))); - __ ReturnTOS(); -} - -ASSEMBLER_TEST_RUN(IfNeNullTOSIsNull, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - If rA, rD -// -// Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and -// unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt. -// Skips the next instruction unless FP[rA] FP[rD]. Assumes that -// FP[rA] and FP[rD] are Smis or unboxed doubles as indicated by . -ASSEMBLER_TEST_GENERATE(IfLeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(-5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfLe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfLeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfLeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(-5))); - __ IfLe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfLeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfLtTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(-5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfLt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfLtTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfLtFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(-5))); - __ IfLt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfLtFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfGeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(-5))); - __ IfGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfGeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfGeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(-5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfGeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfGtTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(-5))); - __ IfGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfGtTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfGtFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(-5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfGtFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -#if defined(ARCH_IS_64_BIT) -ASSEMBLER_TEST_GENERATE(IfDNeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDNe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDNeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDNeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDNe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDNeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDNeNan, assembler) { - const double not_a_number = bit_cast(0x7FF8000000000000LL); - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDNe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDNeNan, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDEqTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDEq(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDEqTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDEqFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDEq(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDEqFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDEqNan, assembler) { - const double not_a_number = bit_cast(0x7FF8000000000000LL); - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDEq(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDEqNan, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDLeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDLe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDLeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDLeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDLe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDLeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDLeNan, assembler) { - const double not_a_number = bit_cast(0x7FF8000000000000LL); - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDLe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDLeNan, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDLtTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDLt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDLtTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDLtFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDLt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDLtFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDLtNan, assembler) { - const double not_a_number = bit_cast(0x7FF8000000000000LL); - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDLt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDLtNan, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDGeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDGeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDGeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDGeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDGeNan, assembler) { - const double not_a_number = bit_cast(0x7FF8000000000000LL); - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDGeNan, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDGtTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDGtTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDGtFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDGtFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfDGtNan, assembler) { - const double not_a_number = bit_cast(0x7FF8000000000000LL); - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld))); - __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld))); - __ UnboxDouble(1, 1); - __ UnboxDouble(2, 2); - __ IfDGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfDGtNan, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} -#endif // defined(ARCH_IS_64_BIT) - -ASSEMBLER_TEST_GENERATE(IfULeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfULe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfULeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfULeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(5))); - __ IfULe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfULeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfULeNegTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(5))); - __ LoadConstant(2, Smi::Handle(Smi::New(-5))); - __ IfULe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfULeNegTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfULtTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfULt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfULtTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfULtFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(5))); - __ IfULt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfULtFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfUGeTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(5))); - __ IfUGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfUGeTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfUGeFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfUGe(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfUGeFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfUGtTrue, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ LoadConstant(1, Smi::Handle(Smi::New(100))); - __ LoadConstant(2, Smi::Handle(Smi::New(5))); - __ IfUGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfUGtTrue, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(IfUGtFalse, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(5))); - __ LoadConstant(2, Smi::Handle(Smi::New(100))); - __ IfUGt(1, 2); - __ LoadConstant(0, Smi::Handle(Smi::New(-1))); - __ Return(0); -} - -ASSEMBLER_TEST_RUN(IfUGtFalse, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - Min, Max rA, rB, rC -// -// FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are -// Smis. -ASSEMBLER_TEST_GENERATE(Min, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(500))); - __ Min(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(Min, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(Max, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ LoadConstant(1, Smi::Handle(Smi::New(5))); - __ Max(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(Max, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - UnboxInt32 rA, rB, C -// -// Unboxes the integer in FP[rB] into FP[rA]. If C == 1, the value may be -// truncated. If FP[rA] is successfully unboxed the following instruction is -// skipped. -ASSEMBLER_TEST_GENERATE(UnboxInt32NoTrunctateSuccess, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(1234))); - __ UnboxInt32(1, 0, /*may_truncate=*/0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxInt32NoTrunctateSuccess, test) { - EXPECT_EQ(1234, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxInt32NoTrunctateFail, assembler) { - __ Frame(2); - __ LoadConstant(0, Integer::Handle(Integer::New(Smi::kMaxValue + 1))); - __ UnboxInt32(1, 0, /*may_truncate=*/0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxInt32NoTrunctateFail, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxInt32TrunctateSuccess, assembler) { - __ Frame(2); - __ LoadConstant( - 0, Integer::Handle(Integer::New(static_cast(kMaxInt32) + 1))); - __ UnboxInt32(1, 0, /*may_truncate=*/1); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxInt32TrunctateSuccess, test) { - EXPECT_EQ(static_cast(kMaxInt32) + 1, - EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -// - BoxInt32 rA, rD -// -// Boxes the unboxed signed 32-bit integer in FP[rD] into FP[rA]. -ASSEMBLER_TEST_GENERATE(BoxInt32, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ UnboxInt32(1, 0, /*may_truncate=*/0); - __ Nop(0); // Unboxing succeeds. - __ BoxInt32(2, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BoxInt32, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - BoxUint32 rA, rD -// -// Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA]. -ASSEMBLER_TEST_GENERATE(BoxUint32, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ UnboxInt32(1, 0, /*may_truncate=*/0); - __ Nop(0); // Unboxing succeeds. - __ BoxUint32(2, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BoxUint32, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - UnboxInt64 rA, rD -// -// Unboxes the integer in FP[rD] into FP[rA]. -ASSEMBLER_TEST_GENERATE(UnboxInt64MaxMint, assembler) { - __ Frame(2); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64))); - __ UnboxInt64(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxInt64MaxMint, test) { - EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxInt64MinMint, assembler) { - __ Frame(2); - __ LoadConstant(0, Integer::Handle(Integer::New(kMinInt64))); - __ UnboxInt64(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxInt64MinMint, test) { - EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxInt64Smi, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ UnboxInt64(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxInt64Smi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -// - BoxInt64 rA, rD -// -// Boxes the unboxed signed 64-bit integer in FP[rD] into FP[rA]. If the -// value does not fit into a Smi the following instruction is skipped. (The -// following instruction should be a jump to a label after the slow path -// allocating a Mint box and writing into the Mint box.) -ASSEMBLER_TEST_GENERATE(BoxInt64Smi, assembler) { - __ Frame(3); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ UnboxInt64(1, 0); - __ BoxInt64(2, 1); - __ Nop(0); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BoxInt64Smi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(BoxInt64MintFails, assembler) { - Label done; - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64))); - __ UnboxInt64(1, 0); - __ BoxInt64(2, 1); // Boxing into Smi fails. - __ Jump(&done); - // Faking a slow path, with a different Mint value. - __ LoadConstant(2, Integer::Handle(Integer::New(kMaxInt64 - 42))); - __ Bind(&done); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(BoxInt64MintFails, test) { - const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code()); - EXPECT(obj.IsMint()); - EXPECT_EQ(kMaxInt64 - 42, Mint::Cast(obj).value()); -} - -ASSEMBLER_TEST_GENERATE(WriteIntoMint, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64))); - __ UnboxInt64(1, 0); - __ LoadConstant(2, Integer::Handle(Integer::New(kMaxInt64 - 42))); - __ WriteIntoMint(2, 1); // Transplant unboxed value into an existing box. - __ Return(2); -} - -ASSEMBLER_TEST_RUN(WriteIntoMint, test) { - const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code()); - EXPECT(obj.IsMint()); - EXPECT_EQ(kMaxInt64, Mint::Cast(obj).value()); -} - -// - UnboxedWidthExtender rA rB C -// -// Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed -// integer in FP[rA]. C contains SmallRepresentation which determines how -// the integer is extended. -ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Positive, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt8 + 0xFFFFFF00))); - __ UnboxInt64(1, 0); - // The lower bits contain 0x7F, overwrite the upper bits with 0. - __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Positive, test) { - EXPECT_EQ(static_cast(kMaxInt8), - kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Negative, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32))); - __ UnboxInt64(1, 0); - // The lower bits contain 0xFF, overwrite the upper bits with 1. - __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Negative, test) { - // least significant 32 bits set to 1. - EXPECT_EQ(kMaxUint32, - kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint8, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32))); - __ UnboxInt64(1, 0); - // The lower bits contain 0xFF, overwrite the upper bits with 0. - __ UnboxedWidthExtender(2, 1, kSmallUnboxedUint8); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint8, test) { - EXPECT_EQ(kMaxUint8, - kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Positive, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt16 + 0xFFFF0000))); - __ UnboxInt64(1, 0); - // The lower bits contain 0x7FFF, overwrite the upper bits with 0. - __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Positive, test) { - EXPECT_EQ(static_cast(kMaxInt16), - kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Negative, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32))); - __ UnboxInt64(1, 0); - // The lower bits contain 0xFFFF, overwrite the upper bits with 1. - __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Negative, test) { - // least significant 32 bits set to 1. - EXPECT_EQ(kMaxUint32, - kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint16, assembler) { - __ Frame(3); - __ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32))); - __ UnboxInt64(1, 0); - // The lower bits contain 0xFFFF, overwrite the upper bits with 0. - __ UnboxedWidthExtender(2, 1, kSmallUnboxedUint16); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint16, test) { - EXPECT_EQ(kMaxUint16, - kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code())); -} - -#if defined(ARCH_IS_64_BIT) -// - UnboxDouble rA, rD -// -// Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double. -// -// - CheckedUnboxDouble rA, rD -// -// Unboxes FP[rD] into FP[rA] and skips the following instruction unless -// FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a -// double. -ASSEMBLER_TEST_GENERATE(UnboxDouble, assembler) { - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld))); - __ UnboxDouble(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(UnboxDouble, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(CheckedUnboxDouble, assembler) { - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld))); - __ CheckedUnboxDouble(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(CheckedUnboxDouble, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(WriteIntoDouble, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld))); - __ UnboxDouble(1, 0); - __ LoadConstant(2, Double::Handle(Double::New(0.0, Heap::kOld))); - __ WriteIntoDouble(2, 1); // Transplant unboxed value into an existing box. - __ Return(2); -} - -ASSEMBLER_TEST_RUN(WriteIntoDouble, test) { - const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code()); - EXPECT(obj.IsDouble()); - EXPECT_EQ(42.0, Double::Cast(obj).value()); -} - -ASSEMBLER_TEST_GENERATE(CheckedUnboxSmi, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ CheckedUnboxDouble(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(0))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(CheckedUnboxSmi, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(CheckedUnboxFail, assembler) { - __ Frame(2); - __ LoadConstant(0, Bool::True()); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ CheckedUnboxDouble(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(CheckedUnboxFail, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -// - DAdd, DSub, DMul, DDiv rA, rB, rC -// -// Arithmetic operations on unboxed doubles. FP[rA] <- FP[rB] op FP[rC]. -ASSEMBLER_TEST_GENERATE(DAdd, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(41.0, Heap::kOld))); - __ LoadConstant(1, Double::Handle(Double::New(1.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ UnboxDouble(1, 1); - __ DAdd(2, 1, 0); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DAdd, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DSub, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(1.0, Heap::kOld))); - __ LoadConstant(1, Double::Handle(Double::New(43.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ UnboxDouble(1, 1); - __ DSub(2, 1, 0); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DSub, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DMul, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(6.0, Heap::kOld))); - __ LoadConstant(1, Double::Handle(Double::New(7.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ UnboxDouble(1, 1); - __ DMul(2, 1, 0); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DMul, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DDiv, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(2.0, Heap::kOld))); - __ LoadConstant(1, Double::Handle(Double::New(84.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ UnboxDouble(1, 1); - __ DDiv(2, 1, 0); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DDiv, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DNeg, assembler) { - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(-42.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ DNeg(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DNeg, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DSqrt, assembler) { - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(36.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ DSqrt(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DSqrt, test) { - EXPECT_EQ(6.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -// - SmiToDouble rA, rD -// -// Convert the Smi in FP[rD] to an unboxed double in FP[rA]. -// -// - DoubleToSmi rA, rD -// -// If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then -// this instruction does so, and skips the following instruction. Otherwise, -// the following instruction is not skipped. -ASSEMBLER_TEST_GENERATE(SmiToDouble, assembler) { - __ Frame(2); - __ LoadConstant(0, Smi::Handle(Smi::New(42))); - __ SmiToDouble(1, 0); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(SmiToDouble, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DoubleToSmi, assembler) { - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ UnboxDouble(0, 0); - __ DoubleToSmi(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DoubleToSmi, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DoubleToSmiNearMax, assembler) { - const double m = static_cast(Smi::kMaxValue - 1000); - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(m, Heap::kOld))); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ UnboxDouble(0, 0); - __ DoubleToSmi(0, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DoubleToSmiNearMax, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DoubleToSmiNearMin, assembler) { - const double m = static_cast(Smi::kMinValue); - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(m, Heap::kOld))); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ UnboxDouble(0, 0); - __ DoubleToSmi(0, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DoubleToSmiNearMin, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DoubleToSmiFailPos, assembler) { - const double pos_overflow = static_cast(Smi::kMaxValue + 1); - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(pos_overflow, Heap::kOld))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ UnboxDouble(0, 0); - __ DoubleToSmi(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DoubleToSmiFailPos, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DoubleToSmiFailNeg, assembler) { - const double neg_overflow = static_cast(Smi::kMinValue - 1000); - __ Frame(2); - __ LoadConstant(0, Double::Handle(Double::New(neg_overflow, Heap::kOld))); - __ LoadConstant(1, Smi::Handle(Smi::New(-1))); - __ UnboxDouble(0, 0); - __ DoubleToSmi(1, 0); - __ LoadConstant(1, Smi::Handle(Smi::New(42))); - __ Return(1); -} - -ASSEMBLER_TEST_RUN(DoubleToSmiFailNeg, test) { - EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DMin, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld))); - __ LoadConstant(1, Double::Handle(Double::New(500.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ UnboxDouble(1, 1); - __ DMin(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DMin, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -ASSEMBLER_TEST_GENERATE(DMax, assembler) { - __ Frame(3); - __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld))); - __ LoadConstant(1, Double::Handle(Double::New(5.0, Heap::kOld))); - __ UnboxDouble(0, 0); - __ UnboxDouble(1, 1); - __ DMax(2, 0, 1); - __ Return(2); -} - -ASSEMBLER_TEST_RUN(DMax, test) { - EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code())); -} - -#endif // defined(ARCH_IS_64_BIT) - -} // namespace compiler -} // namespace dart - -#endif // defined(TARGET_ARCH_DBC) diff --git a/runtime/vm/compiler/assembler/disassembler_dbc.cc b/runtime/vm/compiler/assembler/disassembler_dbc.cc deleted file mode 100644 index 7a15129a1b2..00000000000 --- a/runtime/vm/compiler/assembler/disassembler_dbc.cc +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/compiler/assembler/disassembler.h" - -#include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. -#if defined(TARGET_ARCH_DBC) - -#include "platform/assert.h" -#include "vm/constants_dbc.h" -#include "vm/cpu.h" -#include "vm/instructions.h" - -namespace dart { - -static const char* kOpcodeNames[] = { -#define BYTECODE_NAME(name, encoding, op1, op2, op3) #name, - BYTECODES_LIST(BYTECODE_NAME) -#undef BYTECODE_NAME -}; - -static const size_t kOpcodeCount = - sizeof(kOpcodeNames) / sizeof(kOpcodeNames[0]); - -typedef void (*BytecodeFormatter)(char* buffer, - intptr_t size, - uword pc, - uint32_t bc); -typedef void (*Fmt)(char** buf, intptr_t* size, uword pc, int32_t value); - -template -void FormatOperand(char** buf, - intptr_t* size, - const char* fmt, - ValueType value) { - intptr_t written = Utils::SNPrint(*buf, *size, fmt, value); - if (written < *size) { - *buf += written; - *size += written; - } else { - *size = -1; - } -} - -static void Fmt___(char** buf, intptr_t* size, uword pc, int32_t value) {} - -static void Fmttgt(char** buf, intptr_t* size, uword pc, int32_t value) { - FormatOperand(buf, size, "-> %" Px, pc + (value << 2)); -} - -static void Fmtlit(char** buf, intptr_t* size, uword pc, int32_t value) { - FormatOperand(buf, size, "k%d", value); -} - -static void Fmtreg(char** buf, intptr_t* size, uword pc, int32_t value) { - FormatOperand(buf, size, "r%d", value); -} - -static void Fmtxeg(char** buf, intptr_t* size, uword pc, int32_t value) { - if (value < 0) { - FormatOperand(buf, size, "FP[%d]", value); - } else { - Fmtreg(buf, size, pc, value); - } -} - -static void Fmtnum(char** buf, intptr_t* size, uword pc, int32_t value) { - FormatOperand(buf, size, "#%d", value); -} - -static void Apply(char** buf, - intptr_t* size, - uword pc, - Fmt fmt, - int32_t value, - const char* suffix) { - if (*size <= 0) { - return; - } - - fmt(buf, size, pc, value); - if (*size > 0) { - FormatOperand(buf, size, "%s", suffix); - } -} - -static void Format0(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) {} - -static void FormatT(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t x = static_cast(op) >> 8; - Apply(&buf, &size, pc, op1, x, ""); -} - -static void FormatA(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op & 0xFF00) >> 8; - Apply(&buf, &size, pc, op1, a, ""); -} - -static void FormatA_D(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op & 0xFF00) >> 8; - const int32_t bc = op >> 16; - Apply(&buf, &size, pc, op1, a, ", "); - Apply(&buf, &size, pc, op2, bc, ""); -} - -static void FormatA_X(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op & 0xFF00) >> 8; - const int32_t bc = static_cast(op) >> 16; - Apply(&buf, &size, pc, op1, a, ", "); - Apply(&buf, &size, pc, op2, bc, ""); -} - -static void FormatX(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t bc = static_cast(op) >> 16; - Apply(&buf, &size, pc, op1, bc, ""); -} - -static void FormatD(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t bc = op >> 16; - Apply(&buf, &size, pc, op1, bc, ""); -} - -static void FormatA_B_C(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op >> 8) & 0xFF; - const int32_t b = (op >> 16) & 0xFF; - const int32_t c = (op >> 24) & 0xFF; - Apply(&buf, &size, pc, op1, a, ", "); - Apply(&buf, &size, pc, op2, b, ", "); - Apply(&buf, &size, pc, op3, c, ""); -} - -static void FormatA_B_Y(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op >> 8) & 0xFF; - const int32_t b = (op >> 16) & 0xFF; - const int32_t y = static_cast((op >> 24) & 0xFF); - Apply(&buf, &size, pc, op1, a, ", "); - Apply(&buf, &size, pc, op2, b, ", "); - Apply(&buf, &size, pc, op3, y, ""); -} - -#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3) \ - static void Format##name(char* buf, intptr_t size, uword pc, uint32_t op) { \ - Format##encoding(buf, size, pc, op, Fmt##op1, Fmt##op2, Fmt##op3); \ - } -BYTECODES_LIST(BYTECODE_FORMATTER) -#undef BYTECODE_FORMATTER - -static const BytecodeFormatter kFormatters[] = { -#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3) &Format##name, - BYTECODES_LIST(BYTECODE_FORMATTER) -#undef BYTECODE_FORMATTER -}; - -void Disassembler::DecodeInstruction(char* hex_buffer, - intptr_t hex_size, - char* human_buffer, - intptr_t human_size, - int* out_instr_size, - const Code& code, - Object** object, - uword pc) { - const uint32_t instr = *reinterpret_cast(pc); - const uint8_t opcode = instr & 0xFF; - ASSERT(opcode < kOpcodeCount); - size_t name_size = - Utils::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]); - - human_buffer += name_size; - human_size -= name_size; - kFormatters[opcode](human_buffer, human_size, pc, instr); - - Utils::SNPrint(hex_buffer, hex_size, "%08x", instr); - if (out_instr_size) { - *out_instr_size = sizeof(uint32_t); - } - - *object = NULL; - if (!code.IsNull()) { - *object = &Object::Handle(); - if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) { - *object = NULL; - } - } -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/compiler/assembler/disassembler_test.cc b/runtime/vm/compiler/assembler/disassembler_test.cc index ff78bd24d88..6b0691f1368 100644 --- a/runtime/vm/compiler/assembler/disassembler_test.cc +++ b/runtime/vm/compiler/assembler/disassembler_test.cc @@ -9,9 +9,7 @@ namespace dart { -// TODO(vegorov) this test is disabled on DBC because there is no PopRegister -// method on DBC assembler. -#if !defined(PRODUCT) && !defined(TARGET_ARCH_DBC) +#if !defined(PRODUCT) ISOLATE_UNIT_TEST_CASE(Disassembler) { compiler::ObjectPoolBuilder object_pool_builder; diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc index ee19e39ee52..0c83b5564df 100644 --- a/runtime/vm/compiler/backend/flow_graph.cc +++ b/runtime/vm/compiler/backend/flow_graph.cc @@ -1216,28 +1216,6 @@ void FlowGraph::RenameRecursive( // Attach environment to the block entry. AttachEnvironment(block_entry, env); -#if defined(TARGET_ARCH_DBC) - // On DBC the exception/stacktrace variables are in special registers when - // entering the catch block. The only usage of those special registers is - // within the catch block. A possible lazy-deopt at the beginning of the - // catch does not need to move those around, since the registers will be - // up-to-date when arriving in the unoptimized code and unoptimized code will - // take care of moving them to appropriate slots. - if (CatchBlockEntryInstr* catch_entry = block_entry->AsCatchBlockEntry()) { - Environment* deopt_env = catch_entry->env(); - const LocalVariable* raw_exception_var = catch_entry->raw_exception_var(); - const LocalVariable* raw_stacktrace_var = catch_entry->raw_stacktrace_var(); - if (raw_exception_var != nullptr) { - Value* value = deopt_env->ValueAt(EnvIndex(raw_exception_var)); - value->BindToEnvironment(constant_null()); - } - if (raw_stacktrace_var != nullptr) { - Value* value = deopt_env->ValueAt(EnvIndex(raw_stacktrace_var)); - value->BindToEnvironment(constant_null()); - } - } -#endif // defined(TARGET_ARCH_DBC) - // 2. Process normal instructions. for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { Instruction* current = it.Current(); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index 1aaa25cce47..a3a7d8a3d78 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -520,8 +520,6 @@ void FlowGraphCompiler::EmitSourceLine(Instruction* instr) { line.ToCString()); } -#if !defined(TARGET_ARCH_DBC) - static bool IsPusher(Instruction* instr) { if (auto def = instr->AsDefinition()) { return def->HasTemp(); @@ -538,14 +536,10 @@ static bool IsPopper(Instruction* instr) { return false; } -#endif - bool FlowGraphCompiler::IsPeephole(Instruction* instr) const { -#if !defined(TARGET_ARCH_DBC) if (FLAG_enable_peephole && !is_optimizing()) { return IsPusher(instr) && IsPopper(instr->next()); } -#endif return false; } @@ -573,7 +567,7 @@ void FlowGraphCompiler::VisitBlocks() { continue; } -#if defined(DEBUG) && !defined(TARGET_ARCH_DBC) +#if defined(DEBUG) if (!is_optimizing()) { FrameStateClear(); } @@ -632,7 +626,7 @@ void FlowGraphCompiler::VisitBlocks() { EndCodeSourceRange(instr->token_pos()); } -#if defined(DEBUG) && !defined(TARGET_ARCH_DBC) +#if defined(DEBUG) if (!is_optimizing()) { FrameStateUpdateWith(instr); } @@ -640,7 +634,7 @@ void FlowGraphCompiler::VisitBlocks() { StatsEnd(instr); } -#if defined(DEBUG) && !defined(TARGET_ARCH_DBC) +#if defined(DEBUG) ASSERT(is_optimizing() || FrameStateIsSafeToCall()); #endif } @@ -860,15 +854,8 @@ void FlowGraphCompiler::RecordSafepoint(LocationSummary* locs, // spill_area_size but the second safepoint will truncate the bitmap and // append the live registers to it again. The bitmap produced by both calls // will be the same. -#if !defined(TARGET_ARCH_DBC) ASSERT(bitmap->Length() <= (spill_area_size + saved_registers_size)); bitmap->SetLength(spill_area_size); -#else - ASSERT(slow_path_argument_count == 0); - if (bitmap->Length() <= (spill_area_size + saved_registers_size)) { - bitmap->SetLength(Utils::Maximum(bitmap->Length(), spill_area_size)); - } -#endif ASSERT(slow_path_argument_count == 0 || !using_shared_stub); @@ -1038,23 +1025,6 @@ compiler::Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, return stub->entry_label(); } -#if defined(TARGET_ARCH_DBC) -void FlowGraphCompiler::EmitDeopt(intptr_t deopt_id, - ICData::DeoptReasonId reason, - uint32_t flags) { - ASSERT(is_optimizing()); - ASSERT(!intrinsic_mode()); - // The pending deoptimization environment may be changed after this deopt is - // emitted, so we need to make a copy. - Environment* env_copy = pending_deoptimization_env_->DeepCopy(zone()); - CompilerDeoptInfo* info = - new (zone()) CompilerDeoptInfo(deopt_id, reason, flags, env_copy); - deopt_infos_.Add(info); - assembler()->Deopt(0, /*is_eager =*/1); - info->set_pc_offset(assembler()->CodeSize()); -} -#endif // defined(TARGET_ARCH_DBC) - void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { ASSERT(exception_handlers_list_ != NULL); const ExceptionHandlers& handlers = ExceptionHandlers::Handle( @@ -1268,7 +1238,7 @@ bool FlowGraphCompiler::TryIntrinsifyHelper() { } break; } -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) case RawFunction::kMethodExtractor: { auto& extracted_method = Function::ZoneHandle( parsed_function().function().extracted_method_closure()); @@ -1285,7 +1255,7 @@ bool FlowGraphCompiler::TryIntrinsifyHelper() { SpecialStatsEnd(CombinedCodeStatistics::kTagIntrinsics); return true; } -#endif // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#endif // !defined(TARGET_ARCH_IA32) default: break; } @@ -1309,9 +1279,6 @@ bool FlowGraphCompiler::TryIntrinsifyHelper() { return complete; } -// DBC is very different from other architectures in how it performs instance -// and static calls because it does not use stubs. -#if !defined(TARGET_ARCH_DBC) void FlowGraphCompiler::GenerateCallWithDeopt(TokenPosition token_pos, intptr_t deopt_id, const Code& stub, @@ -1470,7 +1437,6 @@ void FlowGraphCompiler::GenerateListTypeCheck( CheckClassIds(class_id_reg, args, is_instance_lbl, &unknown); assembler()->Bind(&unknown); } -#endif // !defined(TARGET_ARCH_DBC) void FlowGraphCompiler::EmitComment(Instruction* instr) { if (!FLAG_support_il_printer || !FLAG_support_disassembler) { @@ -1484,8 +1450,6 @@ void FlowGraphCompiler::EmitComment(Instruction* instr) { #endif } -#if !defined(TARGET_ARCH_DBC) -// TODO(vegorov) enable edge-counters on DBC if we consider them beneficial. bool FlowGraphCompiler::NeedsEdgeCounter(BlockEntryInstr* block) { // Only emit an edge counter if there is not goto at the end of the block, // except for the entry block. @@ -1504,15 +1468,11 @@ static Register AllocateFreeRegister(bool* blocked_registers) { UNREACHABLE(); return kNoRegister; } -#endif void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { ASSERT(!is_optimizing()); instr->InitializeLocationSummary(zone(), false); // Not optimizing. -// No need to allocate registers based on LocationSummary on DBC as in -// unoptimized mode it's a stack based bytecode just like IR itself. -#if !defined(TARGET_ARCH_DBC) LocationSummary* locs = instr->locs(); bool blocked_registers[kNumberOfCpuRegisters]; @@ -1627,7 +1587,6 @@ void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { } locs->set_out(0, result_location); } -#endif // !defined(TARGET_ARCH_DBC) } static uword RegMaskBit(Register reg) { @@ -1744,7 +1703,6 @@ void ParallelMoveResolver::PerformMove(int index) { compiler_->EndCodeSourceRange(TokenPosition::kParallelMove); } -#if !defined(TARGET_ARCH_DBC) void ParallelMoveResolver::EmitMove(int index) { MoveOperands* const move = moves_[index]; const Location dst = move->dest(); @@ -1766,7 +1724,6 @@ void ParallelMoveResolver::EmitMove(int index) { #endif move->Eliminate(); } -#endif bool ParallelMoveResolver::IsScratchLocation(Location loc) { for (int i = 0; i < moves_.length(); ++i) { @@ -2062,9 +2019,6 @@ bool FlowGraphCompiler::LookupMethodFor(int class_id, return true; } -#if !defined(TARGET_ARCH_DBC) -// DBC emits calls very differently from other architectures due to its -// interpreted nature. void FlowGraphCompiler::EmitPolymorphicInstanceCall( const CallTargets& targets, const InstanceCallInstr& original_call, @@ -2380,12 +2334,8 @@ void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub( } #undef __ -#endif -#if defined(DEBUG) && !defined(TARGET_ARCH_DBC) -// TODO(vegorov) re-enable frame state tracking on DBC. It is -// currently disabled because it relies on LocationSummaries and -// we don't use them during unoptimized compilation on DBC. +#if defined(DEBUG) void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { ASSERT(!is_optimizing()); @@ -2450,9 +2400,8 @@ void FlowGraphCompiler::FrameStateClear() { ASSERT(!is_optimizing()); frame_state_.TruncateTo(0); } -#endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) +#endif // defined(DEBUG) -#if !defined(TARGET_ARCH_DBC) #define __ compiler->assembler()-> void ThrowErrorSlowPathCode::EmitNativeCode(FlowGraphCompiler* compiler) { @@ -2506,8 +2455,6 @@ void ThrowErrorSlowPathCode::EmitNativeCode(FlowGraphCompiler* compiler) { } #undef __ -#endif // !defined(TARGET_ARCH_DBC) - #endif // !defined(DART_PRECOMPILED_RUNTIME) } // namespace dart diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h index 5714a0a37d4..86374da910f 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.h +++ b/runtime/vm/compiler/backend/flow_graph_compiler.h @@ -167,9 +167,6 @@ class CompilerDeoptInfo : public ZoneAllocated { deopt_id_(deopt_id), reason_(reason), flags_(flags), -#if defined(TARGET_ARCH_DBC) - lazy_deopt_with_result_(false), -#endif deopt_env_(deopt_env) { ASSERT(deopt_env != NULL); } @@ -190,18 +187,6 @@ class CompilerDeoptInfo : public ZoneAllocated { uint32_t flags() const { return flags_; } const Environment* deopt_env() const { return deopt_env_; } -#if defined(TARGET_ARCH_DBC) - // On DBC calls return results on the stack but not all calls have a result. - // This needs to be taken into account when constructing lazy deoptimization - // environment. - // For calls with results we add a deopt instruction that would copy top - // of the stack from optimized frame to unoptimized frame effectively - // preserving the result of the call. - // For calls with no results we don't emit such instruction - because there - // is no result pushed by the return sequence. - void mark_lazy_deopt_with_result() { lazy_deopt_with_result_ = true; } -#endif - private: void EmitMaterializations(Environment* env, DeoptInfoBuilder* builder); @@ -212,9 +197,6 @@ class CompilerDeoptInfo : public ZoneAllocated { const intptr_t deopt_id_; const ICData::DeoptReasonId reason_; const uint32_t flags_; -#if defined(TARGET_ARCH_DBC) - bool lazy_deopt_with_result_; -#endif Environment* deopt_env_; DISALLOW_COPY_AND_ASSIGN(CompilerDeoptInfo); @@ -522,9 +504,6 @@ class FlowGraphCompiler : public ValueObject { const Register scratch_reg, compiler::Label* done); -// DBC emits calls very differently from all other architectures due to its -// interpreted nature. -#if !defined(TARGET_ARCH_DBC) void GenerateRuntimeCall(TokenPosition token_pos, intptr_t deopt_id, const RuntimeEntry& entry, @@ -683,7 +662,7 @@ class FlowGraphCompiler : public ValueObject { bool NeedsEdgeCounter(BlockEntryInstr* block); void EmitEdgeCounter(intptr_t edge_id); -#endif // !defined(TARGET_ARCH_DBC) + void RecordCatchEntryMoves(Environment* env = NULL, intptr_t try_index = kInvalidTryIndex); @@ -754,15 +733,6 @@ class FlowGraphCompiler : public ValueObject { ICData::DeoptReasonId reason, uint32_t flags = 0); -#if defined(TARGET_ARCH_DBC) - void EmitDeopt(intptr_t deopt_id, - ICData::DeoptReasonId reason, - uint32_t flags = 0); - - // If the cid does not fit in 16 bits, then this will cause a bailout. - uint16_t ToEmbeddableCid(intptr_t cid, Instruction* instruction); -#endif // defined(TARGET_ARCH_DBC) - CompilerDeoptInfo* AddDeoptIndexAtCall(intptr_t deopt_id); CompilerDeoptInfo* AddSlowPathDeoptInfo(intptr_t deopt_id, Environment* env); @@ -853,19 +823,6 @@ class FlowGraphCompiler : public ValueObject { Function* fn_return, bool* class_is_abstract_return = NULL); -#if defined(TARGET_ARCH_DBC) - enum CallResult { - kHasResult, - kNoResult, - }; - void RecordAfterCallHelper(TokenPosition token_pos, - intptr_t deopt_id, - intptr_t argument_count, - CallResult result, - LocationSummary* locs); - void RecordAfterCall(Instruction* instr, CallResult result); -#endif - // Returns new class-id bias. // // TODO(kustermann): We should move this code out of the [FlowGraphCompiler]! @@ -940,9 +897,6 @@ class FlowGraphCompiler : public ValueObject { void EmitTestAndCallLoadCid(Register class_id_reg); -// DBC handles type tests differently from all other architectures due -// to its interpreted nature. -#if !defined(TARGET_ARCH_DBC) // Type checking helper methods. void CheckClassIds(Register class_id_reg, const GrowableArray& class_ids, @@ -1008,8 +962,6 @@ class FlowGraphCompiler : public ValueObject { void GenerateMethodExtractorIntrinsic(const Function& extracted_method, intptr_t type_arguments_field_offset); -#endif // !defined(TARGET_ARCH_DBC) - void GenerateGetterIntrinsic(intptr_t offset); void GenerateSetterIntrinsic(intptr_t offset); @@ -1041,10 +993,7 @@ class FlowGraphCompiler : public ValueObject { return compressed_stackmaps_builder_; } -// TODO(vegorov) re-enable frame state tracking on DBC. It is -// currently disabled because it relies on LocationSummaries and -// we don't use them during unoptimized compilation on DBC. -#if defined(DEBUG) && !defined(TARGET_ARCH_DBC) +#if defined(DEBUG) void FrameStateUpdateWith(Instruction* instr); void FrameStatePush(Definition* defn); void FrameStatePop(intptr_t count); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc deleted file mode 100644 index fe42375b074..00000000000 --- a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. -#if defined(TARGET_ARCH_DBC) - -#include "vm/compiler/backend/flow_graph_compiler.h" - -#include "vm/compiler/backend/il_printer.h" -#include "vm/compiler/backend/locations.h" -#include "vm/compiler/jit/compiler.h" -#include "vm/cpu.h" -#include "vm/dart_entry.h" -#include "vm/deopt_instructions.h" -#include "vm/instructions.h" -#include "vm/object_store.h" -#include "vm/parser.h" -#include "vm/simulator.h" -#include "vm/stack_frame.h" -#include "vm/stub_code.h" -#include "vm/symbols.h" - -namespace dart { - -DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); -DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic."); -DEFINE_FLAG(bool, unbox_doubles, true, "Optimize double arithmetic."); -DECLARE_FLAG(bool, enable_simd_inline); -DECLARE_FLAG(charp, optimization_filter); - -void FlowGraphCompiler::ArchSpecificInitialization() {} - -FlowGraphCompiler::~FlowGraphCompiler() { - // BlockInfos are zone-allocated, so their destructors are not called. - // Verify the labels explicitly here. - for (int i = 0; i < block_info_.length(); ++i) { - ASSERT(!block_info_[i]->jump_label()->IsLinked()); - } -} - -bool FlowGraphCompiler::SupportsUnboxedDoubles() { -#if defined(ARCH_IS_64_BIT) - return true; -#else - // We use 64-bit wide stack slots to unbox doubles. - return false; -#endif -} - -bool FlowGraphCompiler::SupportsUnboxedInt64() { - return false; -} - -bool FlowGraphCompiler::SupportsUnboxedSimd128() { - return false; -} - -bool FlowGraphCompiler::SupportsHardwareDivision() { - return true; -} - -bool FlowGraphCompiler::CanConvertInt64ToDouble() { - return false; -} - -void FlowGraphCompiler::EnterIntrinsicMode() { - ASSERT(!intrinsic_mode()); - intrinsic_mode_ = true; -} - -void FlowGraphCompiler::ExitIntrinsicMode() { - ASSERT(intrinsic_mode()); - intrinsic_mode_ = false; -} - -RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, - DeoptInfoBuilder* builder, - const Array& deopt_table) { - if (deopt_env_ == NULL) { - ++builder->current_info_number_; - return TypedData::null(); - } - - intptr_t stack_height = compiler->StackSize(); - AllocateIncomingParametersRecursive(deopt_env_, &stack_height); - - intptr_t slot_ix = 0; - Environment* current = deopt_env_; - - // Emit all kMaterializeObject instructions describing objects to be - // materialized on the deoptimization as a prefix to the deoptimization info. - EmitMaterializations(deopt_env_, builder); - - // The real frame starts here. - builder->MarkFrameStart(); - - Zone* zone = compiler->zone(); - - builder->AddCallerFp(slot_ix++); - builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); - builder->AddPcMarker(Function::ZoneHandle(zone), slot_ix++); - builder->AddConstant(Function::ZoneHandle(zone), slot_ix++); - - // Emit all values that are needed for materialization as a part of the - // expression stack for the bottom-most frame. This guarantees that GC - // will be able to find them during materialization. - slot_ix = builder->EmitMaterializationArguments(slot_ix); - - if (lazy_deopt_with_result_) { - ASSERT(reason() == ICData::kDeoptAtCall); - builder->AddCopy( - NULL, - Location::StackSlot( - compiler::target::frame_layout.FrameSlotForVariableIndex( - -stack_height), - FPREG), - slot_ix++); - } - - // For the innermost environment, set outgoing arguments and the locals. - for (intptr_t i = current->Length() - 1; - i >= current->fixed_parameter_count(); i--) { - builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); - } - - builder->AddCallerFp(slot_ix++); - - Environment* previous = current; - current = current->outer(); - while (current != NULL) { - // For any outer environment the deopt id is that of the call instruction - // which is recorded in the outer environment. - builder->AddReturnAddress(current->function(), - DeoptId::ToDeoptAfter(current->deopt_id()), - slot_ix++); - - builder->AddPcMarker(previous->function(), slot_ix++); - builder->AddConstant(previous->function(), slot_ix++); - - // The values of outgoing arguments can be changed from the inlined call so - // we must read them from the previous environment. - for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { - builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), - slot_ix++); - } - - // Set the locals, note that outgoing arguments are not in the environment. - for (intptr_t i = current->Length() - 1; - i >= current->fixed_parameter_count(); i--) { - builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); - } - - builder->AddCallerFp(slot_ix++); - - // Iterate on the outer environment. - previous = current; - current = current->outer(); - } - // The previous pointer is now the outermost environment. - ASSERT(previous != NULL); - - // For the outermost environment, set caller PC. - builder->AddCallerPc(slot_ix++); - - builder->AddPcMarker(previous->function(), slot_ix++); - builder->AddConstant(previous->function(), slot_ix++); - - // For the outermost environment, set the incoming arguments. - for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { - builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); - } - - return builder->CreateDeoptInfo(deopt_table); -} - -void FlowGraphCompiler::RecordAfterCallHelper(TokenPosition token_pos, - intptr_t deopt_id, - intptr_t argument_count, - CallResult result, - LocationSummary* locs) { - RecordSafepoint(locs); - // Marks either the continuation point in unoptimized code or the - // deoptimization point in optimized code, after call. - const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id); - if (is_optimizing()) { - // Return/ReturnTOS instruction drops incoming arguments so - // we have to drop outgoing arguments from the innermost environment. - // On all other architectures caller drops outgoing arguments itself - // hence the difference. - pending_deoptimization_env_->DropArguments(argument_count); - CompilerDeoptInfo* info = AddDeoptIndexAtCall(deopt_id_after); - if (result == kHasResult) { - info->mark_lazy_deopt_with_result(); - } - // This descriptor is needed for exception handling in optimized code. - AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id_after, token_pos); - } else { - // Add deoptimization continuation point after the call and before the - // arguments are removed. - AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); - } -} - -void FlowGraphCompiler::RecordAfterCall(Instruction* instr, CallResult result) { - RecordAfterCallHelper(instr->token_pos(), instr->deopt_id(), - instr->ArgumentCount(), result, instr->locs()); -} - -void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, - intptr_t stub_ix) { - UNREACHABLE(); -} - -#define __ assembler()-> - -void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, - intptr_t deopt_id, - const AbstractType& dst_type, - const String& dst_name, - LocationSummary* locs) { - SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); - if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) { - test_cache = SubtypeTestCache::New(); - } else if (!dst_type.IsInstantiated() && - (dst_type.IsTypeParameter() || dst_type.IsType())) { - test_cache = SubtypeTestCache::New(); - } - - if (is_optimizing()) { - __ Push(locs->in(0).reg()); // Instance. - __ Push(locs->in(1).reg()); // Instantiator type arguments. - __ Push(locs->in(2).reg()); // Function type arguments. - } - __ PushConstant(dst_type); - __ PushConstant(dst_name); - - bool may_be_smi = false; - if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) { - const Class& type_class = Class::Handle(zone(), dst_type.type_class()); - if (type_class.NumTypeArguments() == 0) { - const Class& smi_class = Class::Handle(zone(), Smi::Class()); - may_be_smi = Class::IsSubtypeOf(smi_class, TypeArguments::Handle(zone()), - type_class, TypeArguments::Handle(zone()), - Heap::kOld); - } - } - __ AssertAssignable(may_be_smi ? 1 : 0, __ AddConstant(test_cache)); - - if (is_optimizing()) { - // Register allocator does not think that our first input (also used as - // output) needs to be kept alive across the call because that is how code - // is written on other platforms (where registers are always spilled across - // the call): inputs are consumed by operation and output is produced so - // neither are alive at the safepoint. - // We have to mark the slot alive manually to ensure that GC - // visits it. - locs->SetStackBit(locs->out(0).reg()); - } - AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); - const intptr_t kArgCount = 0; - RecordAfterCallHelper(token_pos, deopt_id, kArgCount, - FlowGraphCompiler::kHasResult, locs); - if (is_optimizing()) { - // Assert assignable keeps the instance on the stack as the result, - // all other arguments are popped. - ASSERT(locs->out(0).reg() == locs->in(0).reg()); - __ Drop1(); - } -} - -void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { - if (!is_optimizing()) { - Definition* defn = instr->AsDefinition(); - if ((defn != NULL) && (defn->tag() != Instruction::kPushArgument) && - (defn->tag() != Instruction::kStoreIndexed) && - (defn->tag() != Instruction::kStoreStaticField) && - (defn->tag() != Instruction::kStoreLocal) && - (defn->tag() != Instruction::kStoreInstanceField) && - (defn->tag() != Instruction::kDropTemps) && !defn->HasTemp()) { - __ Drop1(); - } - } -} - -void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) { - __ Move(0, -(1 + compiler::target::frame_layout.param_end_from_fp)); - ASSERT(offset % kWordSize == 0); - if (Utils::IsInt(8, offset / kWordSize)) { - __ LoadField(0, 0, offset / kWordSize); - } else { - __ LoadFieldExt(0, 0); - __ Nop(offset / kWordSize); - } - __ Return(0); -} - -void FlowGraphCompiler::GenerateSetterIntrinsic(intptr_t offset) { - __ Move(0, -(2 + compiler::target::frame_layout.param_end_from_fp)); - __ Move(1, -(1 + compiler::target::frame_layout.param_end_from_fp)); - ASSERT(offset % kWordSize == 0); - if (Utils::IsInt(8, offset / kWordSize)) { - __ StoreField(0, offset / kWordSize, 1); - } else { - __ StoreFieldExt(0, 1); - __ Nop(offset / kWordSize); - } - __ LoadConstant(0, Object::Handle()); - __ Return(0); -} - -void FlowGraphCompiler::EmitFrameEntry() { - const Function& function = parsed_function().function(); - const intptr_t num_fixed_params = function.num_fixed_parameters(); - const int num_locals = parsed_function().num_stack_locals(); - - if (CanOptimizeFunction() && function.IsOptimizable() && - (!is_optimizing() || may_reoptimize())) { - __ HotCheck(!is_optimizing(), GetOptimizationThreshold()); - } - - if (is_optimizing()) { - __ EntryOptimized(num_fixed_params, - flow_graph_.graph_entry()->spill_slot_count()); - } else { - __ Entry(num_locals); - } - - if (!is_optimizing()) { - if (parsed_function().has_arg_desc_var()) { - // TODO(kustermann): If dbc simulator put the args_desc_ into the - // _special_regs, we could replace these 3 with the MoveSpecial bytecode. - const intptr_t slot_index = - compiler::target::frame_layout.FrameSlotForVariable( - parsed_function().arg_desc_var()); - __ LoadArgDescriptor(); - __ StoreLocal(LocalVarIndex(0, slot_index)); - __ Drop(1); - } - } -} - -void FlowGraphCompiler::EmitPrologue() { - EmitFrameEntry(); -} - -void FlowGraphCompiler::CompileGraph() { - InitCompiler(); - VisitBlocks(); -} - -uint16_t FlowGraphCompiler::ToEmbeddableCid(intptr_t cid, - Instruction* instruction) { - if (!Utils::IsUint(16, cid)) { - instruction->Unsupported(this); - UNREACHABLE(); - } - return static_cast(cid); -} - -#undef __ -#define __ compiler_->assembler()-> - -void ParallelMoveResolver::EmitMove(int index) { - MoveOperands* move = moves_[index]; - const Location source = move->src(); - const Location destination = move->dest(); - if (source.IsStackSlot() && destination.IsRegister()) { - // Only allow access to the arguments (which have in the non-inverted stack - // positive indices). - ASSERT(source.base_reg() == FPREG); - ASSERT(source.stack_index() > - compiler::target::frame_layout.param_end_from_fp); - __ Move(destination.reg(), -source.stack_index()); - } else if (source.IsRegister() && destination.IsRegister()) { - __ Move(destination.reg(), source.reg()); - } else if (source.IsArgsDescRegister()) { - ASSERT(destination.IsRegister()); - __ LoadArgDescriptorOpt(destination.reg()); - } else if (source.IsExceptionRegister()) { - ASSERT(destination.IsRegister()); - __ MoveSpecial(destination.reg(), Simulator::kExceptionSpecialIndex); - } else if (source.IsStackTraceRegister()) { - ASSERT(destination.IsRegister()); - __ MoveSpecial(destination.reg(), Simulator::kStackTraceSpecialIndex); - } else if (source.IsConstant() && destination.IsRegister()) { - if (source.constant_instruction()->representation() == kUnboxedDouble) { - const Register result = destination.reg(); - const Object& constant = source.constant(); - if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) { - __ BitXor(result, result, result); - } else { - __ LoadConstant(result, constant); - __ UnboxDouble(result, result); - } - } else { - __ LoadConstant(destination.reg(), source.constant()); - } - } else { - compiler_->Bailout("Unsupported move"); - UNREACHABLE(); - } - - move->Eliminate(); -} - -void ParallelMoveResolver::EmitSwap(int index) { - MoveOperands* move = moves_[index]; - const Location source = move->src(); - const Location destination = move->dest(); - ASSERT(source.IsRegister() && destination.IsRegister()); - __ Swap(destination.reg(), source.reg()); - - // The swap of source and destination has executed a move from source to - // destination. - move->Eliminate(); - - // Any unperformed (including pending) move with a source of either - // this move's source or destination needs to have their source - // changed to reflect the state of affairs after the swap. - for (int i = 0; i < moves_.length(); ++i) { - const MoveOperands& other_move = *moves_[i]; - if (other_move.Blocks(source)) { - moves_[i]->set_src(destination); - } else if (other_move.Blocks(destination)) { - moves_[i]->set_src(source); - } - } -} - -void ParallelMoveResolver::MoveMemoryToMemory(const compiler::Address& dst, - const compiler::Address& src) { - UNREACHABLE(); -} - -// Do not call or implement this function. Instead, use the form below that -// uses an offset from the frame pointer instead of an Address. -void ParallelMoveResolver::Exchange(Register reg, - const compiler::Address& mem) { - UNREACHABLE(); -} - -// Do not call or implement this function. Instead, use the form below that -// uses offsets from the frame pointer instead of Addresses. -void ParallelMoveResolver::Exchange(const compiler::Address& mem1, - const compiler::Address& mem2) { - UNREACHABLE(); -} - -void ParallelMoveResolver::Exchange(Register reg, - Register base_reg, - intptr_t stack_offset) { - UNIMPLEMENTED(); -} - -void ParallelMoveResolver::Exchange(Register base_reg1, - intptr_t stack_offset1, - Register base_reg2, - intptr_t stack_offset2) { - UNIMPLEMENTED(); -} - -void ParallelMoveResolver::SpillScratch(Register reg) { - UNIMPLEMENTED(); -} - -void ParallelMoveResolver::RestoreScratch(Register reg) { - UNIMPLEMENTED(); -} - -void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { - UNIMPLEMENTED(); -} - -void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { - UNIMPLEMENTED(); -} - -#undef __ - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 7f7d3922b3d..1cbb6d718f4 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -47,7 +47,7 @@ DEFINE_FLAG(bool, "Generate special IC stubs for two args Smi operations"); DEFINE_FLAG(bool, unbox_numeric_fields, - !USING_DBC, + true, "Support unboxed double and float32x4 fields."); class SubclassFinder { @@ -2033,12 +2033,8 @@ bool BinarySmiOpInstr::ComputeCanDeoptimize() const { return RangeUtils::CanBeZero(right_range()); case Token::kTRUNCDIV: -#if defined(TARGET_ARCH_DBC) - return true; -#else return RangeUtils::CanBeZero(right_range()) || RangeUtils::Overlaps(right_range(), -1, -1); -#endif default: return can_overflow(); @@ -3140,10 +3136,7 @@ Definition* UnboxInt64Instr::Canonicalize(FlowGraph* flow_graph) { return replacement; } -// Currently we perform this only on 64-bit architectures and not on simdbc64 -// (on simdbc64 the [UnboxedConstantInstr] handling is only implemented for -// doubles and causes a bailout for everthing else) -#if !defined(TARGET_ARCH_DBC) + // Currently we perform this only on 64-bit architectures. if (compiler::target::kBitsPerWord == 64) { ConstantInstr* c = value()->definition()->AsConstant(); if (c != NULL && (c->value().IsSmi() || c->value().IsMint())) { @@ -3156,7 +3149,6 @@ Definition* UnboxInt64Instr::Canonicalize(FlowGraph* flow_graph) { return uc; } } -#endif // !defined(TARGET_ARCH_DBC) return this; } @@ -3877,13 +3869,9 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // TODO(kusterman): Remove duplicate between // {TargetEntryInstr,FunctionEntryInstr}::EmitNativeCode. if (!compiler->is_optimizing()) { -#if !defined(TARGET_ARCH_DBC) - // TODO(vegorov) re-enable edge counters on DBC if we consider them - // beneficial for the quality of the optimized bytecode. if (compiler->NeedsEdgeCounter(this)) { compiler->EmitEdgeCounter(preorder_number()); } -#endif // The deoptimization descriptor points after the edge counter code for // uniformity with ARM, where we can reuse pattern matching code that @@ -3959,13 +3947,9 @@ void FunctionEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { #endif if (!compiler->is_optimizing()) { -#if !defined(TARGET_ARCH_DBC) - // TODO(vegorov) re-enable edge counters on DBC if we consider them - // beneficial for the quality of the optimized bytecode. if (compiler->NeedsEdgeCounter(this)) { compiler->EmitEdgeCounter(preorder_number()); } -#endif // The deoptimization descriptor points after the edge counter code for // uniformity with ARM, where we can reuse pattern matching code that @@ -4092,7 +4076,6 @@ void ParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { -#if !defined(TARGET_ARCH_DBC) // The native entry frame has size -kExitLinkSlotFromFp. In order to access // the top of stack from above the entry frame, we add a constant to account // for the the two frame pointers and two return addresses of the entry frame. @@ -4103,14 +4086,10 @@ void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { const Location src = rebase.Rebase(loc_); NoTemporaryAllocator no_temp; compiler->EmitMove(dst, src, &no_temp); -#else - UNREACHABLE(); -#endif } LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone, bool opt) const { -#if !defined(TARGET_ARCH_DBC) ASSERT(opt); Location input = Location::Any(); if (representation() == kUnboxedInt64 && compiler::target::kWordSize < 8) { @@ -4123,9 +4102,6 @@ LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone, } return LocationSummary::Make(zone, /*num_inputs=*/0, input, LocationSummary::kNoCall); -#else - UNREACHABLE(); -#endif } bool ParallelMoveInstr::IsRedundant() const { @@ -4241,23 +4217,10 @@ LocationSummary* DropTempsInstr::MakeLocationSummary(Zone* zone, } void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { -#if defined(TARGET_ARCH_DBC) - // On DBC the action of poping the TOS value and then pushing it - // after all intermediates are poped is folded into a special - // bytecode (DropR). On other architectures this is handled by - // instruction prologue/epilogues. - ASSERT(!compiler->is_optimizing()); - if ((InputCount() != 0) && HasTemp()) { - __ DropR(num_temps()); - } else { - __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0)); - } -#else ASSERT(!compiler->is_optimizing()); // Assert that register assignment is correct. ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); __ Drop(num_temps()); -#endif // defined(TARGET_ARCH_DBC) } StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, @@ -4278,8 +4241,6 @@ LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, return MakeCallSummary(zone); } -// DBC does not use specialized inline cache stubs for smi operations. -#if !defined(TARGET_ARCH_DBC) static RawCode* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { if (!FLAG_two_args_smi_icd) { return Code::null(); @@ -4295,59 +4256,6 @@ static RawCode* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { return Code::null(); } } -#else -static void TryFastPathSmiOp(FlowGraphCompiler* compiler, - ICData* call_ic_data, - Token::Kind op_kind) { - if (!FLAG_two_args_smi_icd) { - return; - } - switch (op_kind) { - case Token::kADD: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ AddTOS(); - } - break; - case Token::kSUB: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ SubTOS(); - } - break; - case Token::kEQ: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ EqualTOS(); - } - break; - case Token::kLT: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ LessThanTOS(); - } - break; - case Token::kGT: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ GreaterThanTOS(); - } - break; - case Token::kBIT_AND: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ BitAndTOS(); - } - break; - case Token::kBIT_OR: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ BitOrTOS(); - } - break; - case Token::kMUL: - if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { - __ MulTOS(); - } - break; - default: - break; - } -} -#endif void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { Zone* zone = compiler->zone(); @@ -4369,7 +4277,6 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw()); } -#if !defined(TARGET_ARCH_DBC) if ((compiler->is_optimizing() || compiler->function().HasBytecode()) && HasICData()) { ASSERT(HasICData()); @@ -4404,46 +4311,6 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { *call_ic_data); } } -#else - ICData* original_ic_data = &ICData::ZoneHandle(call_ic_data->Original()); - - // Emit smi fast path instruction. If fast-path succeeds it skips the next - // instruction otherwise it falls through. Only attempt in unoptimized code - // because TryFastPathSmiOp will update original_ic_data. - if (!compiler->is_optimizing()) { - TryFastPathSmiOp(compiler, original_ic_data, token_kind()); - } - - const intptr_t call_ic_data_kidx = __ AddConstant(*original_ic_data); - switch (original_ic_data->NumArgsTested()) { - case 1: - if (compiler->is_optimizing()) { - __ InstanceCall1Opt(ArgumentCount(), call_ic_data_kidx); - } else { - __ InstanceCall1(ArgumentCount(), call_ic_data_kidx); - } - break; - case 2: - if (compiler->is_optimizing()) { - __ InstanceCall2Opt(ArgumentCount(), call_ic_data_kidx); - } else { - __ InstanceCall2(ArgumentCount(), call_ic_data_kidx); - } - break; - default: - UNIMPLEMENTED(); - break; - } - compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(), - token_pos()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -#endif // !defined(TARGET_ARCH_DBC) } bool InstanceCallInstr::MatchesCoreName(const String& name) { @@ -4563,9 +4430,6 @@ intptr_t PolymorphicInstanceCallInstr::CallCount() const { return targets().AggregateCallCount(); } -// DBC does not support optimizing compiler and thus doesn't emit -// PolymorphicInstanceCallInstr. -#if !defined(TARGET_ARCH_DBC) void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { ArgumentsInfo args_info(instance_call()->type_args_len(), instance_call()->ArgumentCount(), @@ -4574,7 +4438,6 @@ void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { targets_, *instance_call(), args_info, deopt_id(), instance_call()->token_pos(), locs(), complete(), total_call_count()); } -#endif RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType( const CallTargets& targets) { @@ -4718,7 +4581,6 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); } -#if !defined(TARGET_ARCH_DBC) ArgumentsInfo args_info(type_args_len(), ArgumentCount(), argument_names()); compiler->GenerateStaticCall(deopt_id(), token_pos(), function(), args_info, locs(), *call_ic_data, rebind_rule_, @@ -4731,30 +4593,6 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { ArgumentAt(0)); } } -#else - const Array& arguments_descriptor = Array::Handle( - zone, (ic_data() == NULL) ? GetArgumentsDescriptor() - : ic_data()->arguments_descriptor()); - const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor); - - compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(), - token_pos()); - if (compiler->is_optimizing()) { - __ PushConstant(function()); - __ StaticCall(ArgumentCount(), argdesc_kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - __ PopLocal(locs()->out(0).reg()); - } else { - const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data); - __ PushConstant(ic_data_kidx); - __ IndirectStaticCall(ArgumentCount(), argdesc_kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall, - deopt_id(), token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - } -#endif // !defined(TARGET_ARCH_DBC) } intptr_t AssertAssignableInstr::statistics_tag() const { @@ -4775,15 +4613,10 @@ intptr_t AssertAssignableInstr::statistics_tag() const { void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(), dst_name(), locs()); - -// DBC does not use LocationSummaries in the same way as other architectures. -#if !defined(TARGET_ARCH_DBC) ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); -#endif // !defined(TARGET_ARCH_DBC) } void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { -#if !defined(TARGET_ARCH_DBC) ASSERT(sub_type().IsFinalized()); ASSERT(super_type().IsFinalized()); @@ -4797,19 +4630,6 @@ void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { kSubtypeCheckRuntimeEntry, 5, locs()); __ Drop(5); -#else - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); // Instantiator type arguments. - __ Push(locs()->in(1).reg()); // Function type arguments. - } else { - // The 2 inputs are already on the expression stack. - } - __ PushConstant(sub_type()); - __ PushConstant(super_type()); - __ PushConstant(dst_name()); - __ AssertSubtype(); - -#endif } LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, @@ -4818,15 +4638,9 @@ LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, } void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { -#if !defined(TARGET_ARCH_DBC) __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_)); -#else - compiler->EmitDeopt(deopt_id(), deopt_reason_); -#endif } -#if !defined(TARGET_ARCH_DBC) - void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { compiler::Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, @@ -4924,8 +4738,6 @@ LocationSummary* CheckNullInstr::MakeLocationSummary(Zone* zone, return locs; } -#endif // !defined(TARGET_ARCH_DBC) - void CheckNullInstr::AddMetadataForRuntimeCall(CheckNullInstr* check_null, FlowGraphCompiler* compiler) { const String& function_name = check_null->function_name(); @@ -4935,8 +4747,6 @@ void CheckNullInstr::AddMetadataForRuntimeCall(CheckNullInstr* check_null, check_null->token_pos(), name_index); } -#if !defined(TARGET_ARCH_DBC) - void UnboxInstr::EmitLoadFromBoxWithDeopt(FlowGraphCompiler* compiler) { const intptr_t box_cid = BoxCid(); const Register box = locs()->in(0).reg(); @@ -5013,8 +4823,6 @@ void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } -#endif // !defined(TARGET_ARCH_DBC) - Environment* Environment::From(Zone* zone, const GrowableArray& definitions, intptr_t fixed_parameter_count, @@ -5158,16 +4966,13 @@ bool TestCidsInstr::AttributesEqual(Instruction* other) const { return true; } -#if !defined(TARGET_ARCH_DBC) static bool BindsToSmiConstant(Value* value) { return value->BindsToConstant() && value->BoundConstant().IsSmi(); } -#endif bool IfThenElseInstr::Supports(ComparisonInstr* comparison, Value* v1, Value* v2) { -#if !defined(TARGET_ARCH_DBC) bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); if (comparison->IsStrictCompare()) { // Strict comparison with number checks calls a stub and is not supported @@ -5180,9 +4985,6 @@ bool IfThenElseInstr::Supports(ComparisonInstr* comparison, return false; } return is_smi_result; -#else - return false; -#endif // !defined(TARGET_ARCH_DBC) } bool PhiInstr::IsRedundant() const { @@ -5546,8 +5348,6 @@ Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const { } } -#if !defined(TARGET_ARCH_DBC) - #define Z zone_ LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone, @@ -5631,34 +5431,8 @@ LocationSummary* NativeReturnInstr::MakeLocationSummary(Zone* zone, #undef Z -#else - -LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone, - bool is_optimizing) const { - LocationSummary* summary = - new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(), - /*num_temps=*/0, LocationSummary::kCall); - - summary->set_in( - TargetAddressIndex(), - Location::RegisterLocation(compiler::ffi::kFunctionAddressRegister)); - for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) { - summary->set_in(i, arg_locations_[i]); - } - summary->set_out(0, compiler::ffi::ResultLocation( - compiler::ffi::ResultHostRepresentation(signature_))); - - return summary; -} - -#endif // !defined(TARGET_ARCH_DBC) - Representation FfiCallInstr::representation() const { -#if !defined(TARGET_ARCH_DBC) return compiler::ffi::ResultRepresentation(signature_); -#else - return compiler::ffi::ResultHostRepresentation(signature_); -#endif // !defined(TARGET_ARCH_DBC) } // SIMD diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index 65a15cf8d4f..53d91557503 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -529,21 +529,11 @@ FOR_EACH_ABSTRACT_INSTRUCTION(FORWARD_DECLARATION) DECLARE_INSTRUCTION_NO_BACKEND(type) \ DECLARE_INSTRUCTION_BACKEND() -#if defined(TARGET_ARCH_DBC) -#define DECLARE_COMPARISON_METHODS \ - virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing) \ - const; \ - virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, \ - BranchLabels labels); \ - virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler, \ - BranchLabels labels); -#else #define DECLARE_COMPARISON_METHODS \ virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing) \ const; \ virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, \ BranchLabels labels); -#endif #define DECLARE_COMPARISON_INSTRUCTION(type) \ DECLARE_INSTRUCTION_NO_BACKEND(type) \ @@ -1077,18 +1067,11 @@ class Instruction : public ZoneAllocated { // instead. Location::Kind RegisterKindForResult() const { const Representation rep = representation(); -#if !defined(TARGET_ARCH_DBC) if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) || (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) || (rep == kUnboxedFloat64x2)) { return Location::kFpuRegister; } -#else - // DBC supports only unboxed doubles and does not have distinguished FPU - // registers. - ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) && - (rep != kUnboxedFloat64x2)); -#endif return Location::kRegister; } @@ -2968,15 +2951,6 @@ class ComparisonInstr : public Definition { virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, BranchLabels labels) = 0; -#if defined(TARGET_ARCH_DBC) - // On the DBC platform EmitNativeCode needs to know ahead of time what - // 'Condition' will be returned by EmitComparisonCode. This call must return - // the same result as EmitComparisonCode, but should not emit any - // instructions. - virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler, - BranchLabels labels) = 0; -#endif - // Emits code that generates 'true' or 'false', depending on the comparison. // This implementation will call EmitComparisonCode. If EmitComparisonCode // does not use the labels (merely returning a condition) then EmitNativeCode @@ -6054,10 +6028,6 @@ class BoxInstr : public TemplateDefinition<1, NoThrow, Pure> { SetInputAt(0, value); } -#if defined(TARGET_ARCH_DBC) - void EmitAllocateBox(FlowGraphCompiler* compiler); -#endif - private: intptr_t ValueOffset() const { return Boxing::ValueOffset(from_representation()); @@ -6798,14 +6768,6 @@ class CheckedSmiComparisonInstr : public TemplateComparison<2, Throws> { virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, BranchLabels labels); -#if defined(TARGET_ARCH_DBC) - virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler, - BranchLabels labels) { - UNREACHABLE(); - return INVALID_CONDITION; - } -#endif - virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right); private: @@ -8645,17 +8607,6 @@ class Environment : public ZoneAllocated { // from the copy. Environment* DeepCopy(Zone* zone, intptr_t length) const; -#if defined(TARGET_ARCH_DBC) - // Return/ReturnTOS instruction drops incoming arguments so - // we have to drop outgoing arguments from the innermost environment. - // On all other architectures caller drops outgoing arguments itself - // hence the difference. - // Note: this method can only be used at the code generation stage because - // it mutates environment in unsafe way (e.g. does not update def-use - // chains). - void DropArguments(intptr_t argc); -#endif - private: friend class ShallowIterator; friend class compiler::BlockBuilder; // For Environment constructor. diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc deleted file mode 100644 index bd859e9d38e..00000000000 --- a/runtime/vm/compiler/backend/il_dbc.cc +++ /dev/null @@ -1,2122 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. -#if defined(TARGET_ARCH_DBC) - -#include "vm/compiler/backend/il.h" - -#include "vm/compiler/backend/flow_graph.h" -#include "vm/compiler/backend/flow_graph_compiler.h" -#include "vm/compiler/backend/locations.h" -#include "vm/compiler/backend/range_analysis.h" -#include "vm/compiler/jit/compiler.h" -#include "vm/cpu.h" -#include "vm/dart_entry.h" -#include "vm/object_store.h" -#include "vm/parser.h" -#include "vm/simulator.h" -#include "vm/stack_frame.h" -#include "vm/stub_code.h" -#include "vm/symbols.h" - -#define __ compiler->assembler()-> - -namespace dart { - -DECLARE_FLAG(bool, emit_edge_counters); -DECLARE_FLAG(int, optimization_counter_threshold); - -// List of instructions that are still unimplemented by DBC backend. -#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \ - M(BinaryInt32Op) \ - M(BinaryUint32Op) \ - M(CheckCondition) \ - M(DoubleToInteger) \ - M(ExtractNthOutput) \ - M(GuardFieldClass) \ - M(GuardFieldLength) \ - M(GuardFieldType) \ - M(IfThenElse) \ - M(Int32ToDouble) \ - M(LoadCodeUnits) \ - M(ShiftUint32Op) \ - M(SpeculativeShiftUint32Op) \ - M(TruncDivMod) \ - M(UnaryUint32Op) \ - M(IntConverter) - -// List of instructions that are not used by DBC. -// Things we aren't planning to implement for DBC: -// - Unboxed SIMD, -// - Unboxed Mint, -// - Optimized RegExps, -// - Precompilation. -#define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ - M(CaseInsensitiveCompare) \ - M(GenericCheckBound) \ - M(IndirectGoto) \ - M(Int64ToDouble) \ - M(BinaryInt64Op) \ - M(ShiftInt64Op) \ - M(SpeculativeShiftInt64Op) \ - M(UnaryInt64Op) \ - M(CheckedSmiOp) \ - M(CheckedSmiComparison) \ - M(SimdOp) \ - M(NativeReturn) - -// Location summaries actually are not used by the unoptimizing DBC compiler -// because we don't allocate any registers. -static LocationSummary* CreateLocationSummary( - Zone* zone, - intptr_t num_inputs, - Location output = Location::NoLocation(), - LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall, - intptr_t num_temps = 0) { - LocationSummary* locs = - new (zone) LocationSummary(zone, num_inputs, num_temps, contains_call); - ASSERT(contains_call == LocationSummary::kNoCall || - num_inputs <= kMaxNumberOfFixedInputRegistersUsedByIL); - for (intptr_t i = 0; i < num_inputs; i++) { - locs->set_in(i, (contains_call == LocationSummary::kNoCall) - ? Location::RequiresRegister() - : Location::RegisterLocation(i)); - } - for (intptr_t i = 0; i < num_temps; i++) { - locs->set_temp(i, Location::RequiresRegister()); - } - if (!output.IsInvalid()) { - // For instructions that call we default to returning result in R0. - locs->set_out(0, output); - } - return locs; -} - -#define DEFINE_MAKE_LOCATION_SUMMARY(Name, ...) \ - LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ - const { \ - return CreateLocationSummary(zone, __VA_ARGS__); \ - } - -#define EMIT_NATIVE_CODE(Name, ...) \ - DEFINE_MAKE_LOCATION_SUMMARY(Name, __VA_ARGS__); \ - void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) - -#define DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ - LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ - const { \ - if (!opt) UNIMPLEMENTED(); \ - return NULL; \ - } - -#define DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name) \ - LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ - const { \ - UNREACHABLE(); \ - return NULL; \ - } - -#define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ - void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ - UNIMPLEMENTED(); \ - } - -#define DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name) \ - void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ - UNREACHABLE(); \ - } - -#define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ - void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ - UNIMPLEMENTED(); \ - } \ - Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*, \ - BranchLabels) { \ - UNIMPLEMENTED(); \ - return NEXT_IS_TRUE; \ - } - -#define DEFINE_UNIMPLEMENTED(Name) \ - DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name) \ - DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) - -FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) - -#undef DEFINE_UNIMPLEMENTED - -#define DEFINE_UNREACHABLE(Name) \ - DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name) \ - DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name) - -FOR_EACH_UNREACHABLE_INSTRUCTION(DEFINE_UNREACHABLE) - -#undef DEFINE_UNREACHABLE - -// Only used in AOT compilation. -DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(CheckedSmiComparison) - -EMIT_NATIVE_CODE(InstanceOf, - 3, - Location::SameAsFirstInput(), - LocationSummary::kCall) { - SubtypeTestCache& test_cache = SubtypeTestCache::Handle(); - if (!type().IsVoidType() && type().IsInstantiated()) { - test_cache = SubtypeTestCache::New(); - } - - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); // Value. - __ Push(locs()->in(1).reg()); // Instantiator type arguments. - __ Push(locs()->in(2).reg()); // Function type arguments. - } - - __ PushConstant(type()); - __ PushConstant(test_cache); - __ InstanceOf(); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -} - -DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable, - 3, - Location::SameAsFirstInput(), - LocationSummary::kCall); - -DEFINE_MAKE_LOCATION_SUMMARY(AssertSubtype, - 2, - Location::NoLocation(), - LocationSummary::kCall); - -EMIT_NATIVE_CODE(AssertBoolean, - 1, - Location::SameAsFirstInput(), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); - } - __ AssertBoolean(0); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - if (compiler->is_optimizing()) { - __ Drop1(); - } -} - -EMIT_NATIVE_CODE(PolymorphicInstanceCall, - 0, - Location::RegisterLocation(0), - LocationSummary::kCall) { - const Array& arguments_descriptor = - Array::Handle(instance_call()->GetArgumentsDescriptor()); - const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor); - - // Push the target onto the stack. - const intptr_t length = targets_.length(); - if (!Utils::IsUint(8, length)) { - Unsupported(compiler); - UNREACHABLE(); - } - bool using_ranges = false; - for (intptr_t i = 0; i < length; i++) { - if (!targets_[i].IsSingleCid()) { - using_ranges = true; - break; - } - } - - if (using_ranges) { - __ PushPolymorphicInstanceCallByRange( - instance_call()->ArgumentCountWithoutTypeArgs(), length); - } else { - __ PushPolymorphicInstanceCall( - instance_call()->ArgumentCountWithoutTypeArgs(), length); - } - for (intptr_t i = 0; i < length; i++) { - const Function& target = *targets_.TargetAt(i)->target; - - __ Nop(compiler->ToEmbeddableCid(targets_[i].cid_start, this)); - if (using_ranges) { - __ Nop(compiler->ToEmbeddableCid(1 + targets_[i].Extent(), this)); - } - __ Nop(__ AddConstant(target)); - } - compiler->EmitDeopt(deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail, - 0); - - // Call the function. - __ StaticCall(instance_call()->ArgumentCount(), argdesc_kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - instance_call()->token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - __ PopLocal(locs()->out(0).reg()); -} - -EMIT_NATIVE_CODE(LoadIndexedUnsafe, 1, Location::RegisterLocation(0)) { - ASSERT(base_reg() == FPREG); - - ASSERT(offset_ % kWordSize == 0); - const intptr_t slot_offset = offset_ / kWordSize; - ASSERT(Utils::IsInt(8, slot_offset)); - - if (compiler->is_optimizing()) { - const Register index = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - __ LoadFpRelativeSlotOpt(result, index, slot_offset); - } else { - __ LoadFpRelativeSlot(slot_offset); - } -} - -EMIT_NATIVE_CODE(StoreIndexedUnsafe, 2, Location::RegisterLocation(0)) { - ASSERT(base_reg() == FPREG); - - ASSERT(offset_ % kWordSize == 0); - const intptr_t slot_offset = offset_ / kWordSize; - ASSERT(Utils::IsInt(8, slot_offset)); - - if (compiler->is_optimizing()) { - const Register index = locs()->in(kIndexPos).reg(); - const Register value = locs()->in(kValuePos).reg(); - __ StoreFpRelativeSlotOpt(value, index, slot_offset); - } else { - __ StoreFpRelativeSlot(slot_offset); - } -} - -EMIT_NATIVE_CODE(TailCall, - 1, - Location::NoLocation(), - LocationSummary::kNoCall, - 1) { - if (compiler->is_optimizing()) { - const Register arg_desc = locs()->in(0).reg(); - const Register temp = locs()->temp(0).reg(); - __ LoadConstant(temp, code()); - __ TailCallOpt(arg_desc, temp); - } else { - __ PushConstant(code()); - __ TailCall(); - } -} - -EMIT_NATIVE_CODE(Stop, 0) { - __ Stop(message()); -} - -EMIT_NATIVE_CODE(CheckStackOverflow, - 0, - Location::NoLocation(), - LocationSummary::kCall) { - if (compiler->ForceSlowPathForStackOverflow()) { - __ CheckStackAlwaysExit(); - } else { - __ CheckStack(); - } - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult); -} - -EMIT_NATIVE_CODE(PushArgument, 1) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); - } -} - -EMIT_NATIVE_CODE(LoadLocal, 0) { - ASSERT(!compiler->is_optimizing()); - const intptr_t slot_index = - compiler::target::frame_layout.FrameSlotForVariable(&local()); - __ Push(LocalVarIndex(0, slot_index)); -} - -EMIT_NATIVE_CODE(StoreLocal, 0) { - ASSERT(!compiler->is_optimizing()); - const intptr_t slot_index = - compiler::target::frame_layout.FrameSlotForVariable(&local()); - if (HasTemp()) { - __ StoreLocal(LocalVarIndex(0, slot_index)); - } else { - __ PopLocal(LocalVarIndex(0, slot_index)); - } -} - -EMIT_NATIVE_CODE(LoadClassId, 1, Location::RequiresRegister()) { - if (compiler->is_optimizing()) { - __ LoadClassId(locs()->out(0).reg(), locs()->in(0).reg()); - } else { - __ LoadClassIdTOS(); - } -} - -EMIT_NATIVE_CODE(Constant, 0, Location::RequiresRegister()) { - if (compiler->is_optimizing()) { - if (locs()->out(0).IsRegister()) { - __ LoadConstant(locs()->out(0).reg(), value()); - } - } else { - __ PushConstant(value()); - } -} - -EMIT_NATIVE_CODE(UnboxedConstant, 0, Location::RequiresRegister()) { - // The register allocator drops constant definitions that have no uses. - if (locs()->out(0).IsInvalid()) { - return; - } - if (representation_ != kUnboxedDouble) { - Unsupported(compiler); - UNREACHABLE(); - } - const Register result = locs()->out(0).reg(); - if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { - __ BitXor(result, result, result); - } else { - __ LoadConstant(result, value()); - __ UnboxDouble(result, result); - } -} - -EMIT_NATIVE_CODE(Return, 1) { - if (compiler->is_optimizing()) { - __ Return(locs()->in(0).reg()); - } else { - __ ReturnTOS(); - } -} - -LocationSummary* StoreStaticFieldInstr::MakeLocationSummary( - - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 1; - const intptr_t kNumTemps = 1; - LocationSummary* locs = new (zone) - LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - for (intptr_t i = 0; i < kNumInputs; i++) { - locs->set_in(i, Location::RequiresRegister()); - } - for (intptr_t i = 0; i < kNumTemps; i++) { - locs->set_temp(i, Location::RequiresRegister()); - } - return locs; -} - -void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler->is_optimizing()) { - __ LoadConstant(locs()->temp(0).reg(), - Field::ZoneHandle(field().Original())); - __ StoreField(locs()->temp(0).reg(), - Field::static_value_offset() / kWordSize, - locs()->in(0).reg()); - } else { - const intptr_t kidx = __ AddConstant(field()); - __ StoreStaticTOS(kidx); - } -} - -EMIT_NATIVE_CODE(LoadStaticField, 1, Location::RequiresRegister()) { - if (compiler->is_optimizing()) { - __ LoadField(locs()->out(0).reg(), locs()->in(0).reg(), - Field::static_value_offset() / kWordSize); - } else { - const intptr_t kidx = __ AddConstant(StaticField()); - __ PushStatic(kidx); - } -} - -EMIT_NATIVE_CODE(InitStaticField, - 1, - Location::NoLocation(), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); - __ InitStaticTOS(); - } else { - __ InitStaticTOS(); - } - compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult); -} - -EMIT_NATIVE_CODE(ClosureCall, - 1, - Location::RegisterLocation(0), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); - } - - const Array& arguments_descriptor = - Array::ZoneHandle(GetArgumentsDescriptor()); - const intptr_t argdesc_kidx = - compiler->assembler()->AddConstant(arguments_descriptor); - __ StaticCall(ArgumentCount(), argdesc_kidx); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -} - -static void EmitBranchOnCondition(FlowGraphCompiler* compiler, - Condition true_condition, - BranchLabels labels) { - if (true_condition == NEXT_IS_TRUE) { - // NEXT_IS_TRUE indicates that the preceeding test expects the true case - // to be in the subsequent instruction, which it skips if the test fails. - __ Jump(labels.true_label); - if (labels.fall_through != labels.false_label) { - // The preceeding Jump instruction will be skipped if the test fails. - // If we aren't falling through to the false case, then we have to do - // a Jump to it here. - __ Jump(labels.false_label); - } - } else { - ASSERT(true_condition == NEXT_IS_FALSE); - // NEXT_IS_FALSE indicates that the preceeding test has been flipped and - // expects the false case to be in the subsequent instruction, which it - // skips if the test succeeds. - __ Jump(labels.false_label); - if (labels.fall_through != labels.true_label) { - // The preceeding Jump instruction will be skipped if the test succeeds. - // If we aren't falling through to the true case, then we have to do - // a Jump to it here. - __ Jump(labels.true_label); - } - } -} - -Condition StrictCompareInstr::GetNextInstructionCondition( - FlowGraphCompiler* compiler, - BranchLabels labels) { - return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE - : NEXT_IS_FALSE; -} - -Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels) { - ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT)); - - Token::Kind comparison; - Condition condition; - if (labels.fall_through == labels.false_label) { - condition = NEXT_IS_TRUE; - comparison = kind(); - } else { - // Flip comparison to save a jump. - condition = NEXT_IS_FALSE; - comparison = - (kind() == Token::kEQ_STRICT) ? Token::kNE_STRICT : Token::kEQ_STRICT; - } - - if (!compiler->is_optimizing()) { - const SimulatorBytecode::Opcode eq_op = - needs_number_check() ? SimulatorBytecode::kIfEqStrictNumTOS - : SimulatorBytecode::kIfEqStrictTOS; - const SimulatorBytecode::Opcode ne_op = - needs_number_check() ? SimulatorBytecode::kIfNeStrictNumTOS - : SimulatorBytecode::kIfNeStrictTOS; - __ Emit(comparison == Token::kEQ_STRICT ? eq_op : ne_op); - } else { - const SimulatorBytecode::Opcode eq_op = - needs_number_check() ? SimulatorBytecode::kIfEqStrictNum - : SimulatorBytecode::kIfEqStrict; - const SimulatorBytecode::Opcode ne_op = - needs_number_check() ? SimulatorBytecode::kIfNeStrictNum - : SimulatorBytecode::kIfNeStrict; - __ Emit(SimulatorBytecode::Encode( - (comparison == Token::kEQ_STRICT) ? eq_op : ne_op, locs()->in(0).reg(), - locs()->in(1).reg())); - } - - if (needs_number_check() && token_pos().IsReal()) { - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id_, - token_pos()); - } - - return condition; -} - -DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare, - 2, - Location::RequiresRegister(), - needs_number_check() ? LocationSummary::kCall - : LocationSummary::kNoCall) - -void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, - BranchInstr* branch) { - BranchLabels labels = compiler->CreateBranchLabels(branch); - Condition true_condition = EmitComparisonCode(compiler, labels); - if (true_condition != INVALID_CONDITION) { - EmitBranchOnCondition(compiler, true_condition, labels); - } -} - -void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - compiler::Label is_true, is_false; - BranchLabels labels = {&is_true, &is_false, &is_false}; - Condition true_condition = - this->GetNextInstructionCondition(compiler, labels); - if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() || - is_true.IsLinked() || is_false.IsLinked()) { - Condition actual_condition = EmitComparisonCode(compiler, labels); - ASSERT(actual_condition == true_condition); - if (true_condition != INVALID_CONDITION) { - EmitBranchOnCondition(compiler, true_condition, labels); - } - compiler::Label done; - __ Bind(&is_false); - __ PushConstant(Bool::False()); - __ Jump(&done); - __ Bind(&is_true); - __ PushConstant(Bool::True()); - __ Bind(&done); - } else { - const Register result = this->locs()->out(0).reg(); - bool next_is_true = true_condition == NEXT_IS_TRUE; - __ LoadConstant(result, Bool::Get(!next_is_true)); - Condition actual_condition = EmitComparisonCode(compiler, labels); - ASSERT(actual_condition == true_condition); - // Although we have a condition to branch on, the comparison code may also - // have contained a direct branch to one of the labels, so they may need to - // be bound. - if (next_is_true && is_true.IsLinked()) { - __ Bind(&is_true); - } else if (!next_is_true && is_false.IsLinked()) { - __ Bind(&is_false); - } - // This instruction is conditionally skipped by EmitComparisonCode. - __ LoadConstant(result, Bool::Get(next_is_true)); - // If the other label is linked we need to bind it and emit code that loads - // the correct boolean. - if ((next_is_true && is_false.IsLinked()) || - (!next_is_true && is_true.IsLinked())) { - compiler::Label done; - __ Jump(&done); - __ Bind(next_is_true ? &is_false : &is_true); - __ LoadConstant(result, Bool::Get(!next_is_true)); - __ Bind(&done); - } - } -} - -LocationSummary* BranchInstr::MakeLocationSummary( - - Zone* zone, - bool opt) const { - comparison()->InitializeLocationSummary(zone, opt); - if (!comparison()->HasLocs()) { - return NULL; - } - // Branches don't produce a result. - comparison()->locs()->set_out(0, Location::NoLocation()); - return comparison()->locs(); -} - -void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - comparison()->EmitBranchCode(compiler, this); -} - -EMIT_NATIVE_CODE(Goto, 0) { - if (!compiler->is_optimizing()) { - // Add a deoptimization descriptor for deoptimizing instructions that - // may be inserted before this instruction. - compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), - TokenPosition::kNoSource); - } - if (HasParallelMove()) { - compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); - } - // We can fall through if the successor is the next block in the list. - // Otherwise, we need a jump. - if (!compiler->CanFallThroughTo(successor())) { - __ Jump(compiler->GetJumpLabel(successor())); - } -} - -Condition TestSmiInstr::GetNextInstructionCondition(FlowGraphCompiler* compiler, - BranchLabels labels) { - ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); - return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE; -} - -Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels) { - ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); - Register left = locs()->in(0).reg(); - Register right = locs()->in(1).reg(); - __ TestSmi(left, right); - return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE; -} - -DEFINE_MAKE_LOCATION_SUMMARY(TestSmi, - 2, - Location::RequiresRegister(), - LocationSummary::kNoCall) - -Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels) { - ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); - const Register value = locs()->in(0).reg(); - const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; - - const ZoneGrowableArray& data = cid_results(); - const intptr_t num_cases = data.length() / 2; - ASSERT(num_cases <= 255); - __ TestCids(value, num_cases); - - bool result = false; - for (intptr_t i = 0; i < data.length(); i += 2) { - const intptr_t test_cid = data[i]; - result = data[i + 1] == true_result; - __ Nop(result ? 1 : 0, compiler->ToEmbeddableCid(test_cid, this)); - } - - // No match found, deoptimize or default action. - if (CanDeoptimize()) { - compiler->EmitDeopt(deopt_id(), ICData::kDeoptTestCids, - licm_hoisted_ ? ICData::kHoisted : 0); - } else { - // If the cid is not in the list, jump to the opposite label from the cids - // that are in the list. These must be all the same (see asserts in the - // constructor). - compiler::Label* target = result ? labels.false_label : labels.true_label; - __ Jump(target); - } - - return NEXT_IS_TRUE; -} - -Condition TestCidsInstr::GetNextInstructionCondition( - FlowGraphCompiler* compiler, - BranchLabels labels) { - return NEXT_IS_TRUE; -} - -DEFINE_MAKE_LOCATION_SUMMARY(TestCids, - 1, - Location::RequiresRegister(), - LocationSummary::kNoCall) - -EMIT_NATIVE_CODE(CreateArray, - 2, - Location::RequiresRegister(), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - const Register length = locs()->in(kLengthPos).reg(); - const Register type_arguments = locs()->in(kElementTypePos).reg(); - const Register out = locs()->out(0).reg(); - __ CreateArrayOpt(out, length, type_arguments); - __ Push(type_arguments); - __ Push(length); - __ CreateArrayTOS(); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - __ PopLocal(out); - } else { - __ CreateArrayTOS(); - compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); - } -} - -EMIT_NATIVE_CODE(StoreIndexed, - 3, - Location::NoLocation(), - LocationSummary::kNoCall, - 1) { - if (!compiler->is_optimizing()) { - ASSERT(class_id() == kArrayCid); - __ StoreIndexedTOS(); - return; - } - const Register array = locs()->in(kArrayPos).reg(); - const Register index = locs()->in(kIndexPos).reg(); - const Register value = locs()->in(kValuePos).reg(); - const Register temp = locs()->temp(0).reg(); - switch (class_id()) { - case kArrayCid: - __ StoreIndexed(array, index, value); - break; - case kTypedDataUint8ArrayCid: - case kTypedDataInt8ArrayCid: - case kExternalOneByteStringCid: - case kExternalTypedDataUint8ArrayCid: - ASSERT(index_scale() == 1); - if (IsExternal()) { - __ StoreIndexedUntaggedUint8(array, index, value); - } else { - __ StoreIndexedUint8(array, index, value); - } - break; - case kOneByteStringCid: - ASSERT(index_scale() == 1); - __ StoreIndexedOneByteString(array, index, value); - break; - case kTypedDataInt32ArrayCid: - case kTypedDataUint32ArrayCid: { - if (IsExternal()) { - if (index_scale() == 1) { - __ StoreIndexedUntaggedUint32(array, index, value); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ StoreIndexedUntaggedUint32(array, temp, value); - } - } else { - if (index_scale() == 1) { - __ StoreIndexedUint32(array, index, value); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ StoreIndexedUint32(array, temp, value); - } - } - break; - } - case kTypedDataFloat32ArrayCid: - if (IsExternal()) { - if (index_scale() == 1) { - __ StoreIndexedUntaggedFloat32(array, index, value); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ StoreIndexedUntaggedFloat32(array, temp, value); - } - } else { - if (index_scale() == 1) { - __ StoreIndexedFloat32(array, index, value); - } else if (index_scale() == 4) { - __ StoreIndexed4Float32(array, index, value); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ StoreIndexedFloat32(array, temp, value); - } - } - break; - case kTypedDataFloat64ArrayCid: - if (IsExternal()) { - if (index_scale() == 1) { - __ StoreIndexedUntaggedFloat64(array, index, value); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ StoreIndexedUntaggedFloat64(array, temp, value); - } - } else { - if (index_scale() == 1) { - __ StoreIndexedFloat64(array, index, value); - } else if (index_scale() == 8) { - __ StoreIndexed8Float64(array, index, value); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ StoreIndexedFloat64(array, temp, value); - } - } - break; - default: - Unsupported(compiler); - UNREACHABLE(); - break; - } -} - -EMIT_NATIVE_CODE(LoadIndexed, - 2, - Location::RequiresRegister(), - LocationSummary::kNoCall, - 1) { - if (compiler->is_optimizing()) { - ASSERT(compiler->is_optimizing()); - const Register array = locs()->in(0).reg(); - const Register index = locs()->in(1).reg(); - const Register temp = locs()->temp(0).reg(); - const Register result = locs()->out(0).reg(); - switch (class_id()) { - case kArrayCid: - case kImmutableArrayCid: - __ LoadIndexed(result, array, index); - break; - case kTypedDataUint8ArrayCid: - case kTypedDataUint8ClampedArrayCid: - case kExternalOneByteStringCid: - case kExternalTypedDataUint8ArrayCid: - case kExternalTypedDataUint8ClampedArrayCid: - ASSERT(index_scale() == 1); - if (IsExternal()) { - __ LoadIndexedUntaggedUint8(result, array, index); - } else { - __ LoadIndexedUint8(result, array, index); - } - break; - case kTypedDataInt8ArrayCid: - ASSERT(index_scale() == 1); - if (IsExternal()) { - __ LoadIndexedUntaggedInt8(result, array, index); - } else { - __ LoadIndexedInt8(result, array, index); - } - break; - case kOneByteStringCid: - ASSERT(index_scale() == 1); - __ LoadIndexedOneByteString(result, array, index); - break; - case kTwoByteStringCid: - if (index_scale() != 2) { - // TODO(zra): Fix-up index. - Unsupported(compiler); - UNREACHABLE(); - } - if (IsExternal()) { - Unsupported(compiler); - UNREACHABLE(); - } - __ LoadIndexedTwoByteString(result, array, index); - break; - case kTypedDataInt32ArrayCid: - ASSERT(representation() == kUnboxedInt32); - if (IsExternal()) { - if (index_scale() == 1) { - __ LoadIndexedUntaggedInt32(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedUntaggedInt32(result, array, temp); - } - } else { - if (index_scale() == 1) { - __ LoadIndexedInt32(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedInt32(result, array, temp); - } - } - break; - case kTypedDataUint32ArrayCid: - ASSERT(representation() == kUnboxedUint32); - if (IsExternal()) { - if (index_scale() == 1) { - __ LoadIndexedUntaggedUint32(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedUntaggedUint32(result, array, temp); - } - } else { - if (index_scale() == 1) { - __ LoadIndexedUint32(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedUint32(result, array, temp); - } - } - break; - case kTypedDataFloat32ArrayCid: - if (IsExternal()) { - if (index_scale() == 1) { - __ LoadIndexedUntaggedFloat32(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedUntaggedFloat32(result, array, temp); - } - } else { - if (index_scale() == 1) { - __ LoadIndexedFloat32(result, array, index); - } else if (index_scale() == 4) { - __ LoadIndexed4Float32(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedFloat32(result, array, temp); - } - } - break; - case kTypedDataFloat64ArrayCid: - if (IsExternal()) { - if (index_scale() == 1) { - __ LoadIndexedUntaggedFloat64(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedUntaggedFloat64(result, array, temp); - } - } else { - if (index_scale() == 1) { - __ LoadIndexedFloat64(result, array, index); - } else if (index_scale() == 8) { - __ LoadIndexed8Float64(result, array, index); - } else { - __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale())); - __ LoadIndexedFloat64(result, array, temp); - } - } - break; - default: - Unsupported(compiler); - UNREACHABLE(); - break; - } - } else { - switch (class_id()) { - case kArrayCid: - case kImmutableArrayCid: - __ LoadIndexedTOS(); - break; - default: - Unsupported(compiler); - UNREACHABLE(); - break; - } - } -} - -EMIT_NATIVE_CODE(StringInterpolate, - 1, - Location::RegisterLocation(0), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); - } - const intptr_t kTypeArgsLen = 0; - const intptr_t kArgumentCount = 1; - const Array& arguments_descriptor = Array::Handle(ArgumentsDescriptor::New( - kTypeArgsLen, kArgumentCount, Object::null_array())); - __ PushConstant(CallFunction()); - const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor); - __ StaticCall(kArgumentCount, argdesc_kidx); - // Note: can't use RecordAfterCall here because - // StringInterpolateInstr::ArgumentCount() is 0. However - // internally it does a call with 1 argument which needs to - // be reflected in the lazy deoptimization environment. - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCallHelper(token_pos(), deopt_id(), kArgumentCount, - FlowGraphCompiler::kHasResult, locs()); - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -} - -void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - const Representation result_rep = - compiler::ffi::ResultHostRepresentation(signature_); - // TODO(36809): In 32 bit we'll need a result location as well. - const TypedData& signature_descriptor = - TypedData::Handle(compiler::ffi::FfiSignatureDescriptor::New( - *arg_host_locations_, result_rep)); - - const intptr_t sigdesc_kidx = __ AddConstant(signature_descriptor); - - __ FfiCall(sigdesc_kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCallHelper(token_pos(), deopt_id(), 0, - FlowGraphCompiler::kHasResult, locs()); -} - -EMIT_NATIVE_CODE(NativeCall, - 0, - Location::NoLocation(), - LocationSummary::kCall) { - SetupNative(); - - const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); - - NativeFunctionWrapper trampoline; - NativeFunction function; - if (link_lazily()) { - trampoline = &NativeEntry::BootstrapNativeCallWrapper; - function = reinterpret_cast(&NativeEntry::LinkNativeCall); - } else { - if (is_bootstrap_native()) { - trampoline = &NativeEntry::BootstrapNativeCallWrapper; - } else if (is_auto_scope()) { - trampoline = &NativeEntry::AutoScopeNativeCallWrapper; - } else { - trampoline = &NativeEntry::NoScopeNativeCallWrapper; - } - function = native_c_function(); - } - - const compiler::ExternalLabel trampoline_label( - reinterpret_cast(trampoline)); - const intptr_t trampoline_kidx = - __ object_pool_builder().FindNativeFunctionWrapper( - &trampoline_label, ObjectPool::Patchability::kPatchable); - const compiler::ExternalLabel label(reinterpret_cast(function)); - const intptr_t target_kidx = __ object_pool_builder().FindNativeFunction( - &label, ObjectPool::Patchability::kPatchable); - const intptr_t argc_tag_kidx = - __ object_pool_builder().FindImmediate(static_cast(argc_tag)); - __ NativeCall(trampoline_kidx, target_kidx, argc_tag_kidx); - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); -} - -EMIT_NATIVE_CODE(OneByteStringFromCharCode, - 1, - Location::RequiresRegister(), - LocationSummary::kNoCall) { - ASSERT(compiler->is_optimizing()); - const Register char_code = locs()->in(0).reg(); // Char code is a smi. - const Register result = locs()->out(0).reg(); - __ OneByteStringFromCharCode(result, char_code); -} - -EMIT_NATIVE_CODE(StringToCharCode, - 1, - Location::RequiresRegister(), - LocationSummary::kNoCall) { - ASSERT(cid_ == kOneByteStringCid); - const Register str = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); // Result char code is a smi. - __ StringToCharCode(result, str); -} - -EMIT_NATIVE_CODE(AllocateObject, - 0, - Location::RequiresRegister(), - LocationSummary::kCall) { - if (ArgumentCount() == 1) { - // Allocate with type arguments. - if (compiler->is_optimizing()) { - // If we're optimizing, try a streamlined fastpath. - const intptr_t instance_size = cls().instance_size(); - Isolate* isolate = Isolate::Current(); - if (Heap::IsAllocatableInNewSpace(instance_size) && - !cls().TraceAllocation(isolate)) { - uint32_t tags = 0; - tags = RawObject::SizeTag::update(instance_size, tags); - ASSERT(cls().id() != kIllegalCid); - tags = RawObject::ClassIdTag::update(cls().id(), tags); - if (Smi::IsValid(tags)) { - const intptr_t tags_kidx = - __ AddConstant(Smi::Handle(Smi::New(tags))); - __ AllocateTOpt(locs()->out(0).reg(), tags_kidx); - __ Nop(cls().type_arguments_field_offset()); - } - } - __ PushConstant(cls()); - __ AllocateT(); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - compiler->RecordSafepoint(locs()); - __ PopLocal(locs()->out(0).reg()); - } else { - __ PushConstant(cls()); - __ AllocateT(); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - compiler->RecordSafepoint(locs()); - } - } else if (compiler->is_optimizing()) { - // If we're optimizing, try a streamlined fastpath. - const intptr_t instance_size = cls().instance_size(); - Isolate* isolate = Isolate::Current(); - if (Heap::IsAllocatableInNewSpace(instance_size) && - !cls().TraceAllocation(isolate)) { - uword tags = 0; - tags = RawObject::SizeTag::update(instance_size, tags); - ASSERT(cls().id() != kIllegalCid); - tags = RawObject::ClassIdTag::update(cls().id(), tags); - // tags also has the initial zero hash code on 64 bit. - if (Smi::IsValid(tags)) { - const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags))); - __ AllocateOpt(locs()->out(0).reg(), tags_kidx); - } - } - const intptr_t kidx = __ AddConstant(cls()); - __ Allocate(kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - compiler->RecordSafepoint(locs()); - __ PopLocal(locs()->out(0).reg()); - } else { - const intptr_t kidx = __ AddConstant(cls()); - __ Allocate(kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - compiler->RecordSafepoint(locs()); - } -} - -EMIT_NATIVE_CODE(StoreInstanceField, 2) { - ASSERT(OffsetInBytes() > 0); // Field is finalized and points after header. - ASSERT(OffsetInBytes() % kWordSize == 0); - if (compiler->is_optimizing()) { - const Register value = locs()->in(1).reg(); - const Register instance = locs()->in(0).reg(); - if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) { - __ StoreField(instance, OffsetInBytes() / kWordSize, value); - } else { - __ StoreFieldExt(instance, value); - __ Nop(OffsetInBytes() / kWordSize); - } - } else { - __ StoreFieldTOS(OffsetInBytes() / kWordSize); - } -} - -EMIT_NATIVE_CODE(LoadField, 1, Location::RequiresRegister()) { - ASSERT(OffsetInBytes() % kWordSize == 0); - if (compiler->is_optimizing()) { - const Register result = locs()->out(0).reg(); - const Register instance = locs()->in(0).reg(); - if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) { - __ LoadField(result, instance, OffsetInBytes() / kWordSize); - } else { - __ LoadFieldExt(result, instance); - __ Nop(OffsetInBytes() / kWordSize); - } - } else { - __ LoadFieldTOS(OffsetInBytes() / kWordSize); - } -} - -EMIT_NATIVE_CODE(LoadUntagged, 1, Location::RequiresRegister()) { - const Register obj = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - if (object()->definition()->representation() == kUntagged) { - __ LoadUntagged(result, obj, offset() / kWordSize); - } else { - ASSERT(object()->definition()->representation() == kTagged); - __ LoadField(result, obj, offset() / kWordSize); - } -} - -EMIT_NATIVE_CODE(StoreUntagged, 1, Location::RequiresRegister()) { - const Register obj = locs()->in(0).reg(); - const Register value = locs()->out(0).reg(); - const auto offset_in_words = offset() / kWordSize; - if (object()->definition()->representation() == kUntagged) { - __ StoreUntagged(obj, offset_in_words, value); - } else { - ASSERT(object()->definition()->representation() == kTagged); - __ StoreField(obj, offset_in_words, value); - } -} - -EMIT_NATIVE_CODE(BooleanNegate, 1, Location::RequiresRegister()) { - if (compiler->is_optimizing()) { - __ BooleanNegate(locs()->out(0).reg(), locs()->in(0).reg()); - } else { - __ BooleanNegateTOS(); - } -} - -EMIT_NATIVE_CODE(AllocateContext, - 0, - Location::RequiresRegister(), - LocationSummary::kCall) { - ASSERT(!compiler->is_optimizing()); - __ AllocateContext(num_context_variables()); - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); -} - -EMIT_NATIVE_CODE(AllocateUninitializedContext, - 0, - Location::RequiresRegister(), - LocationSummary::kCall) { - ASSERT(compiler->is_optimizing()); - __ AllocateUninitializedContext(locs()->out(0).reg(), - num_context_variables()); - __ AllocateContext(num_context_variables()); - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - __ PopLocal(locs()->out(0).reg()); -} - -EMIT_NATIVE_CODE(CloneContext, - 1, - Location::RequiresRegister(), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); - } - __ CloneContext(); - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -} - -EMIT_NATIVE_CODE(CatchBlockEntry, 0) { - __ Bind(compiler->GetJumpLabel(this)); - compiler->AddExceptionHandler( - catch_try_index(), try_index(), compiler->assembler()->CodeSize(), - is_generated(), catch_handler_types_, needs_stacktrace()); - // On lazy deoptimization we patch the optimized code here to enter the - // deoptimization stub. - const intptr_t deopt_id = DeoptId::ToDeoptAfter(GetDeoptId()); - if (compiler->is_optimizing()) { - compiler->AddDeoptIndexAtCall(deopt_id); - } else { - compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, - TokenPosition::kNoSource); - } - if (HasParallelMove()) { - compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); - } - __ SetFrame(compiler->StackSize()); - - if (!compiler->is_optimizing()) { - if (raw_exception_var_ != nullptr) { - __ MoveSpecial( - LocalVarIndex(0, compiler::target::frame_layout.FrameSlotForVariable( - raw_exception_var_)), - Simulator::kExceptionSpecialIndex); - } - if (raw_stacktrace_var_ != nullptr) { - __ MoveSpecial( - LocalVarIndex(0, compiler::target::frame_layout.FrameSlotForVariable( - raw_stacktrace_var_)), - Simulator::kStackTraceSpecialIndex); - } - } -} - -EMIT_NATIVE_CODE(Throw, 0, Location::NoLocation(), LocationSummary::kCall) { - __ Throw(0); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult); - __ Trap(); -} - -EMIT_NATIVE_CODE(ReThrow, 0, Location::NoLocation(), LocationSummary::kCall) { - compiler->SetNeedsStackTrace(catch_try_index()); - __ Throw(1); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult); - __ Trap(); -} - -EMIT_NATIVE_CODE(InstantiateType, - 2, - Location::RequiresRegister(), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); // Instantiator type arguments. - __ Push(locs()->in(1).reg()); // Function type arguments. - } - __ InstantiateType(__ AddConstant(type())); - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -} - -EMIT_NATIVE_CODE(InstantiateTypeArguments, - 2, - Location::RequiresRegister(), - LocationSummary::kCall) { - if (compiler->is_optimizing()) { - __ Push(locs()->in(0).reg()); // Instantiator type arguments. - __ Push(locs()->in(1).reg()); // Function type arguments. - } - __ InstantiateTypeArgumentsTOS( - type_arguments().IsRawWhenInstantiatedFromRaw(type_arguments().Length()), - __ AddConstant(type_arguments())); - compiler->RecordSafepoint(locs()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(), - token_pos()); - if (compiler->is_optimizing()) { - __ PopLocal(locs()->out(0).reg()); - } -} - -void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { -#ifdef PRODUCT - UNREACHABLE(); -#else - __ DebugStep(); - compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); -#endif -} - -void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - BlockEntryInstr* entry = normal_entry(); - if (entry != nullptr) { - if (!compiler->CanFallThroughTo(entry)) { - FATAL("Checked function entry must have no offset"); - } - } else { - entry = osr_entry(); - if (!compiler->CanFallThroughTo(entry)) { - __ Jump(compiler->GetJumpLabel(entry)); - } - } -} - -LocationSummary* Instruction::MakeCallSummary(Zone* zone) { - LocationSummary* result = - new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); - // TODO(vegorov) support allocating out registers for calls. - // Currently we require them to be fixed. - ASSERT(0 < kMaxNumberOfFixedInputRegistersUsedByIL); - result->set_out(0, Location::RegisterLocation(0)); - return result; -} - -Representation LoadIndexedInstr::representation() const { - switch (class_id_) { - case kArrayCid: - case kImmutableArrayCid: - return kTagged; - case kOneByteStringCid: - case kTwoByteStringCid: - case kTypedDataInt8ArrayCid: - case kTypedDataUint8ArrayCid: - case kTypedDataUint8ClampedArrayCid: - case kExternalOneByteStringCid: - case kExternalTypedDataUint8ArrayCid: - case kExternalTypedDataUint8ClampedArrayCid: - return kUnboxedIntPtr; - case kTypedDataInt32ArrayCid: - return kUnboxedInt32; - case kTypedDataUint32ArrayCid: - return kUnboxedUint32; - case kTypedDataFloat32ArrayCid: - case kTypedDataFloat64ArrayCid: - return kUnboxedDouble; - case kTypedDataInt32x4ArrayCid: - return kUnboxedInt32x4; - case kTypedDataFloat32x4ArrayCid: - return kUnboxedFloat32x4; - case kTypedDataFloat64x2ArrayCid: - return kUnboxedFloat64x2; - - // These are unsupported on DBC and will cause a bailout during - // EmitNativeCode. - case kTypedDataInt16ArrayCid: - case kTypedDataUint16ArrayCid: - case kExternalTwoByteStringCid: - return kUnboxedIntPtr; - - default: - UNREACHABLE(); - return kTagged; - } -} - -Representation StoreIndexedInstr::RequiredInputRepresentation( - intptr_t idx) const { - // Array can be a Dart object or a pointer to external data. - if (idx == 0) { - return kNoRepresentation; // Flexible input representation. - } - if (idx == 1) { - return kTagged; // Index is a smi. - } - ASSERT(idx == 2); - switch (class_id_) { - case kArrayCid: - return kTagged; - case kOneByteStringCid: - case kTypedDataInt8ArrayCid: - case kTypedDataUint8ArrayCid: - case kExternalOneByteStringCid: - case kExternalTypedDataUint8ArrayCid: - return kUnboxedIntPtr; - case kTypedDataInt32ArrayCid: - return kUnboxedInt32; - case kTypedDataUint32ArrayCid: - return kUnboxedUint32; - case kTypedDataFloat32ArrayCid: - case kTypedDataFloat64ArrayCid: - return kUnboxedDouble; - case kTypedDataFloat32x4ArrayCid: - return kUnboxedFloat32x4; - case kTypedDataInt32x4ArrayCid: - return kUnboxedInt32x4; - case kTypedDataFloat64x2ArrayCid: - return kUnboxedFloat64x2; - - // These are unsupported on DBC and will cause a bailout during - // EmitNativeCode. - case kTypedDataUint8ClampedArrayCid: - case kExternalTypedDataUint8ClampedArrayCid: - case kTypedDataInt16ArrayCid: - case kTypedDataUint16ArrayCid: - return kUnboxedIntPtr; - default: - UNREACHABLE(); - return kTagged; - } -} - -void Environment::DropArguments(intptr_t argc) { -#if defined(DEBUG) - // Check that we are in the backend - register allocation has been run. - ASSERT((Length() == 0) || (locations_ != nullptr)); - - // Check that we are only dropping a valid number of instructions from the - // environment. - ASSERT(argc <= values_.length()); -#endif - values_.TruncateTo(values_.length() - argc); -} - -EMIT_NATIVE_CODE(CheckSmi, 1) { - __ CheckSmi(locs()->in(0).reg()); - compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckSmi, - licm_hoisted_ ? ICData::kHoisted : 0); -} - -EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) { - const Register left = locs()->in(0).reg(); - const Register right = locs()->in(1).reg(); - __ CheckEitherNonSmi(left, right); - compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp, - licm_hoisted_ ? ICData::kHoisted : 0); -} - -EMIT_NATIVE_CODE(CheckClassId, 1) { - if (cids_.IsSingleCid()) { - __ CheckClassId(locs()->in(0).reg(), - compiler->ToEmbeddableCid(cids_.cid_start, this)); - } else { - __ CheckClassIdRange(locs()->in(0).reg(), - compiler->ToEmbeddableCid(cids_.cid_start, this)); - __ Nop(compiler->ToEmbeddableCid(cids_.Extent(), this)); - } - compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass); -} - -EMIT_NATIVE_CODE(CheckClass, 1) { - const Register value = locs()->in(0).reg(); - if (IsNullCheck()) { - ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); - if (IsDeoptIfNull()) { - __ IfEqNull(value); - } else { - __ IfNeNull(value); - } - } else { - ASSERT(!cids_.IsMonomorphic() || !cids_.HasClassId(kSmiCid)); - const intptr_t may_be_smi = cids_.HasClassId(kSmiCid) ? 1 : 0; - bool is_bit_test = false; - intptr_t cid_mask = 0; - if (IsBitTest()) { - cid_mask = ComputeCidMask(); - is_bit_test = Smi::IsValid(cid_mask); - } - if (is_bit_test) { - intptr_t min = cids_.ComputeLowestCid(); - __ CheckBitTest(value, may_be_smi); - __ Nop(compiler->ToEmbeddableCid(min, this)); - __ Nop(__ AddConstant(Smi::Handle(Smi::New(cid_mask)))); - } else { - bool using_ranges = false; - int smi_adjustment = 0; - int length = cids_.length(); - for (intptr_t i = 0; i < length; i++) { - if (!cids_[i].IsSingleCid()) { - using_ranges = true; - } else if (cids_[i].cid_start == kSmiCid) { - ASSERT(cids_[i].cid_end == kSmiCid); // We are in the else clause. - ASSERT(smi_adjustment == 0); - smi_adjustment = 1; - } - } - - if (!Utils::IsUint(8, length)) { - Unsupported(compiler); - UNREACHABLE(); - } - if (using_ranges) { - __ CheckCidsByRange(value, may_be_smi, (length - smi_adjustment) * 2); - } else { - __ CheckCids(value, may_be_smi, length - smi_adjustment); - } - for (intptr_t i = 0; i < length; i++) { - intptr_t cid_start = cids_[i].cid_start; - intptr_t cid_end = cids_[i].cid_end; - if (cid_start == kSmiCid && cid_end == kSmiCid) { - ASSERT(smi_adjustment == 1); - continue; - } - __ Nop(compiler->ToEmbeddableCid(cid_start, this)); - if (using_ranges) { - __ Nop(compiler->ToEmbeddableCid(1 + cids_[i].Extent(), this)); - } - } - } - } - compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass, - licm_hoisted_ ? ICData::kHoisted : 0); -} - -EMIT_NATIVE_CODE(CheckNull, 1) { - if (compiler->is_optimizing()) { - const Register value = locs()->in(0).reg(); - __ IfEqNull(value); - } else { - __ IfEqNullTOS(); - } - __ NullError(); - CheckNullInstr::AddMetadataForRuntimeCall(this, compiler); -} - -EMIT_NATIVE_CODE(BinarySmiOp, 2, Location::RequiresRegister()) { - if (compiler->is_optimizing()) { - const Register left = locs()->in(0).reg(); - const Register right = locs()->in(1).reg(); - const Register out = locs()->out(0).reg(); - const bool can_deopt = CanDeoptimize(); - bool needs_nop = false; - switch (op_kind()) { - case Token::kADD: - __ Add(out, left, right); - needs_nop = true; - break; - case Token::kSUB: - __ Sub(out, left, right); - needs_nop = true; - break; - case Token::kMUL: - __ Mul(out, left, right); - needs_nop = true; - break; - case Token::kTRUNCDIV: - ASSERT(can_deopt); - __ Div(out, left, right); - break; - case Token::kBIT_AND: - ASSERT(!can_deopt); - __ BitAnd(out, left, right); - break; - case Token::kBIT_OR: - ASSERT(!can_deopt); - __ BitOr(out, left, right); - break; - case Token::kBIT_XOR: - ASSERT(!can_deopt); - __ BitXor(out, left, right); - break; - case Token::kMOD: - __ Mod(out, left, right); - needs_nop = true; - break; - case Token::kSHR: - __ Shr(out, left, right); - needs_nop = true; - break; - case Token::kSHL: - __ Shl(out, left, right); - needs_nop = true; - break; - default: - UNREACHABLE(); - } - if (can_deopt) { - compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinarySmiOp); - } else if (needs_nop) { - __ Nop(0); - } - } else { - switch (op_kind()) { - case Token::kADD: - __ SmiAddTOS(); - break; - case Token::kSUB: - __ SmiSubTOS(); - break; - case Token::kMUL: - __ SmiMulTOS(); - break; - case Token::kBIT_AND: - __ SmiBitAndTOS(); - break; - default: - UNIMPLEMENTED(); - } - } -} - -EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) { - switch (op_kind()) { - case Token::kNEGATE: { - __ Neg(locs()->out(0).reg(), locs()->in(0).reg()); - compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp); - break; - } - case Token::kBIT_NOT: - __ BitNot(locs()->out(0).reg(), locs()->in(0).reg()); - break; - default: - UNREACHABLE(); - break; - } -} - -void BoxInstr::EmitAllocateBox(FlowGraphCompiler* compiler) { - const Register out = locs()->out(0).reg(); - const Class& box_class = compiler->BoxClassFor(from_representation()); - const intptr_t instance_size = box_class.instance_size(); - Isolate* isolate = Isolate::Current(); - ASSERT(Heap::IsAllocatableInNewSpace(instance_size)); - if (!box_class.TraceAllocation(isolate)) { - uword tags = 0; - tags = RawObject::SizeTag::update(instance_size, tags); - tags = RawObject::ClassIdTag::update(box_class.id(), tags); - // tags also has the initial zero hash code on 64 bit. - if (Smi::IsValid(tags)) { - const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags))); - __ AllocateOpt(out, tags_kidx); - } - } - const intptr_t kidx = __ AddConstant(box_class); - __ Allocate(kidx); - compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone, - token_pos()); - compiler->RecordSafepoint(locs()); - __ PopLocal(out); -} - -EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) { - ASSERT(from_representation() == kUnboxedDouble || - from_representation() == kUnboxedFloat); - const Register value = locs()->in(0).reg(); - const Register out = locs()->out(0).reg(); - if (from_representation() == kUnboxedFloat) { - __ FloatToDouble(value, value); - } - EmitAllocateBox(compiler); - __ WriteIntoDouble(out, value); -} - -EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) { - if (representation() == kUnboxedInt64) { - EmitLoadInt64FromBoxOrSmi(compiler); - return; - } - ASSERT(representation() == kUnboxedDouble || - representation() == kUnboxedFloat); - const intptr_t value_cid = value()->Type()->ToCid(); - const intptr_t box_cid = BoxCid(); - const Register box = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - if (value_cid == box_cid || - (speculative_mode() == kNotSpeculative && value_cid != kSmiCid)) { - __ UnboxDouble(result, box); - } else if (CanConvertSmi() && (value_cid == kSmiCid)) { - __ SmiToDouble(result, box); - } else if ((value()->Type()->ToNullableCid() == box_cid) && - value()->Type()->is_nullable()) { - __ IfEqNull(box); - ASSERT(CanDeoptimize()); - compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass); - __ UnboxDouble(result, box); - } else { - __ CheckedUnboxDouble(result, box); - ASSERT(CanDeoptimize()); - compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass); - } - if (representation() == kUnboxedFloat) { - __ DoubleToFloat(result, result); - } -} - -EMIT_NATIVE_CODE(UnboxInteger32, 1, Location::RequiresRegister()) { -#if defined(ARCH_IS_64_BIT) - const Register out = locs()->out(0).reg(); - const Register value = locs()->in(0).reg(); - const bool may_truncate = is_truncating() || !CanDeoptimize(); - __ UnboxInt32(out, value, may_truncate); - if (CanDeoptimize()) { - compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptUnboxInteger); - } else { - __ Nop(0); - } -#else - Unsupported(compiler); - UNREACHABLE(); -#endif // defined(ARCH_IS_64_BIT) -} - -EMIT_NATIVE_CODE(BoxInteger32, 1, Location::RequiresRegister()) { -#if defined(ARCH_IS_64_BIT) - const Register out = locs()->out(0).reg(); - const Register value = locs()->in(0).reg(); - if (from_representation() == kUnboxedInt32) { - __ BoxInt32(out, value); - } else { - ASSERT(from_representation() == kUnboxedUint32); - __ BoxUint32(out, value); - } -#else - Unsupported(compiler); - UNREACHABLE(); -#endif // defined(ARCH_IS_64_BIT) -} - -EMIT_NATIVE_CODE(BoxInt64, 1, Location::RequiresRegister()) { -#if defined(ARCH_IS_64_BIT) - compiler::Label done; - const Register value = locs()->in(0).reg(); - const Register out = locs()->out(0).reg(); - __ BoxInt64(out, value); - __ Jump(&done); - EmitAllocateBox(compiler); - __ WriteIntoMint(out, value); - __ Bind(&done); -#else - Unsupported(compiler); - UNREACHABLE(); -#endif // defined(ARCH_IS_64_BIT) -} - -void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) { -#if defined(ARCH_IS_64_BIT) - const Register out = locs()->out(0).reg(); - const Register value = locs()->in(0).reg(); - __ UnboxInt64(out, value); -#else - Unsupported(compiler); - UNREACHABLE(); -#endif // defined(ARCH_IS_64_BIT) -} - -EMIT_NATIVE_CODE(UnboxedWidthExtender, 1, Location::RequiresRegister()) { - const Register out = locs()->out(0).reg(); - const Register value = locs()->in(0).reg(); - __ UnboxedWidthExtender(out, value, from_representation()); -} - -EMIT_NATIVE_CODE(DoubleToSmi, 1, Location::RequiresRegister()) { - const Register value = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - __ DoubleToSmi(result, value); - compiler->EmitDeopt(deopt_id(), ICData::kDeoptDoubleToSmi); -} - -EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) { - const Register value = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - __ SmiToDouble(result, value); -} - -EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) { - const Register left = locs()->in(0).reg(); - const Register right = locs()->in(1).reg(); - const Register result = locs()->out(0).reg(); - switch (op_kind()) { - case Token::kADD: - __ DAdd(result, left, right); - break; - case Token::kSUB: - __ DSub(result, left, right); - break; - case Token::kMUL: - __ DMul(result, left, right); - break; - case Token::kDIV: - __ DDiv(result, left, right); - break; - default: - UNREACHABLE(); - } -} - -Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels) { - ASSERT(compiler->is_optimizing()); - const Register value = locs()->in(0).reg(); - switch (op_kind()) { - case MethodRecognizer::kDouble_getIsNaN: - __ DoubleIsNaN(value); - break; - case MethodRecognizer::kDouble_getIsInfinite: - __ DoubleIsInfinite(value); - break; - default: - UNREACHABLE(); - } - const bool is_negated = kind() != Token::kEQ; - return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE; -} - -Condition DoubleTestOpInstr::GetNextInstructionCondition( - FlowGraphCompiler* compiler, - BranchLabels labels) { - const bool is_negated = kind() != Token::kEQ; - return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE; -} - -DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister()) - -EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) { - const Register value = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - __ DNeg(result, value); -} - -EMIT_NATIVE_CODE(MathUnary, 1, Location::RequiresRegister()) { - const Register value = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - if (kind() == MathUnaryInstr::kSqrt) { - __ DSqrt(result, value); - } else if (kind() == MathUnaryInstr::kDoubleSquare) { - __ DMul(result, value, value); - } else { - Unsupported(compiler); - UNREACHABLE(); - } -} - -EMIT_NATIVE_CODE(DoubleToDouble, 1, Location::RequiresRegister()) { - const Register in = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - switch (recognized_kind()) { - case MethodRecognizer::kDoubleTruncate: - __ DTruncate(result, in); - break; - case MethodRecognizer::kDoubleFloor: - __ DFloor(result, in); - break; - case MethodRecognizer::kDoubleCeil: - __ DCeil(result, in); - break; - default: - UNREACHABLE(); - } -} - -EMIT_NATIVE_CODE(DoubleToFloat, 1, Location::RequiresRegister()) { - const Register in = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - __ DoubleToFloat(result, in); -} - -EMIT_NATIVE_CODE(FloatToDouble, 1, Location::RequiresRegister()) { - const Register in = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - __ FloatToDouble(result, in); -} - -EMIT_NATIVE_CODE(InvokeMathCFunction, - InputCount(), - Location::RequiresRegister()) { - const Register left = locs()->in(0).reg(); - const Register result = locs()->out(0).reg(); - if (recognized_kind() == MethodRecognizer::kMathDoublePow) { - const Register right = locs()->in(1).reg(); - __ DPow(result, left, right); - } else if (recognized_kind() == MethodRecognizer::kDoubleMod) { - const Register right = locs()->in(1).reg(); - __ DMod(result, left, right); - } else if (recognized_kind() == MethodRecognizer::kMathSin) { - __ DSin(result, left); - } else if (recognized_kind() == MethodRecognizer::kMathCos) { - __ DCos(result, left); - } else { - Unsupported(compiler); - UNREACHABLE(); - } -} - -EMIT_NATIVE_CODE(MathMinMax, 2, Location::RequiresRegister()) { - ASSERT((op_kind() == MethodRecognizer::kMathMin) || - (op_kind() == MethodRecognizer::kMathMax)); - const Register left = locs()->in(0).reg(); - const Register right = locs()->in(1).reg(); - const Register result = locs()->out(0).reg(); - if (result_cid() == kDoubleCid) { - if (op_kind() == MethodRecognizer::kMathMin) { - __ DMin(result, left, right); - } else { - __ DMax(result, left, right); - } - } else { - ASSERT(result_cid() == kSmiCid); - if (op_kind() == MethodRecognizer::kMathMin) { - __ Min(result, left, right); - } else { - __ Max(result, left, right); - } - } -} - -static SimulatorBytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) { - switch (kind) { - case Token::kEQ: - return SimulatorBytecode::kIfEqStrict; - case Token::kNE: - return SimulatorBytecode::kIfNeStrict; - case Token::kLT: - return SimulatorBytecode::kIfLt; - case Token::kGT: - return SimulatorBytecode::kIfGt; - case Token::kLTE: - return SimulatorBytecode::kIfLe; - case Token::kGTE: - return SimulatorBytecode::kIfGe; - default: - UNREACHABLE(); - return SimulatorBytecode::kTrap; - } -} - -static SimulatorBytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) { - switch (kind) { - case Token::kEQ: - return SimulatorBytecode::kIfDEq; - case Token::kNE: - return SimulatorBytecode::kIfDNe; - case Token::kLT: - return SimulatorBytecode::kIfDLt; - case Token::kGT: - return SimulatorBytecode::kIfDGt; - case Token::kLTE: - return SimulatorBytecode::kIfDLe; - case Token::kGTE: - return SimulatorBytecode::kIfDGe; - default: - UNREACHABLE(); - return SimulatorBytecode::kTrap; - } -} - -static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, - LocationSummary* locs, - Token::Kind kind, - BranchLabels labels) { - Token::Kind comparison = kind; - Condition condition = NEXT_IS_TRUE; - if (labels.fall_through != labels.false_label) { - // If we aren't falling through to the false label, we can save a Jump - // instruction in the case that the true case is the fall through by - // negating the sense of the test such that the instruction following the - // test is the Jump to the false label. In the case where both labels are - // null we don't negate the sense of the test. - condition = NEXT_IS_FALSE; - comparison = Token::NegateComparison(kind); - } - if (compiler->is_optimizing()) { - const Register left = locs->in(0).reg(); - const Register right = locs->in(1).reg(); - __ Emit(SimulatorBytecode::Encode(OpcodeForSmiCondition(comparison), left, - right)); - return condition; - } else { - switch (kind) { - case Token::kEQ: - __ IfEqStrictTOS(); - break; - case Token::kNE: - __ IfNeStrictTOS(); - break; - case Token::kLT: - __ IfSmiLtTOS(); - break; - case Token::kLTE: - __ IfSmiLeTOS(); - break; - case Token::kGT: - __ IfSmiGtTOS(); - break; - case Token::kGTE: - __ IfSmiGeTOS(); - break; - default: - UNIMPLEMENTED(); - } - return condition; - } -} - -static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, - LocationSummary* locs, - Token::Kind kind) { - const Register left = locs->in(0).reg(); - const Register right = locs->in(1).reg(); - Token::Kind comparison = kind; - // For double comparisons we can't flip the condition like with smi - // comparisons because of NaN which will compare false for all except != - // operations. - // TODO(fschneider): Change the block order instead in DBC so that the - // false block in always the fall-through block. - Condition condition = NEXT_IS_TRUE; - __ Emit(SimulatorBytecode::Encode(OpcodeForDoubleCondition(comparison), left, - right)); - return condition; -} - -Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels) { - if (operation_cid() == kSmiCid) { - return EmitSmiComparisonOp(compiler, locs(), kind(), labels); - } else { - ASSERT(operation_cid() == kDoubleCid); - return EmitDoubleComparisonOp(compiler, locs(), kind()); - } -} - -Condition EqualityCompareInstr::GetNextInstructionCondition( - FlowGraphCompiler* compiler, - BranchLabels labels) { - if (operation_cid() == kSmiCid) { - return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE - : NEXT_IS_TRUE; - } else { - ASSERT(operation_cid() == kDoubleCid); - return NEXT_IS_TRUE; - } -} - -DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister()); - -Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels) { - if (operation_cid() == kSmiCid) { - return EmitSmiComparisonOp(compiler, locs(), kind(), labels); - } else { - ASSERT(operation_cid() == kDoubleCid); - return EmitDoubleComparisonOp(compiler, locs(), kind()); - } -} - -Condition RelationalOpInstr::GetNextInstructionCondition( - FlowGraphCompiler* compiler, - BranchLabels labels) { - if (operation_cid() == kSmiCid) { - return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE - : NEXT_IS_TRUE; - } else { - ASSERT(operation_cid() == kDoubleCid); - return NEXT_IS_TRUE; - } -} - -DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister()) - -EMIT_NATIVE_CODE(CheckArrayBound, 2) { - const Register length = locs()->in(kLengthPos).reg(); - const Register index = locs()->in(kIndexPos).reg(); - const intptr_t index_cid = this->index()->Type()->ToCid(); - if (index_cid != kSmiCid) { - __ CheckSmi(index); - compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckArrayBound, - (generalized_ ? ICData::kGeneralized : 0) | - (licm_hoisted_ ? ICData::kHoisted : 0)); - } - __ IfULe(length, index); - compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckArrayBound, - (generalized_ ? ICData::kGeneralized : 0) | - (licm_hoisted_ ? ICData::kHoisted : 0)); -} - -void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - UNREACHABLE(); -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc index 9570fc9bac2..82094ea9df2 100644 --- a/runtime/vm/compiler/backend/il_test_helper.cc +++ b/runtime/vm/compiler/backend/il_test_helper.cc @@ -131,8 +131,7 @@ void TestPipeline::CompileGraphAndAttachFunction() { SpeculativeInliningPolicy speculative_policy(/*enable_blacklist=*/false); -#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) || \ - defined(TARGET_ARCH_DBC) +#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) const bool use_far_branches = false; #else const bool use_far_branches = true; diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc index d171a713b5c..52e3cac2410 100644 --- a/runtime/vm/compiler/backend/inliner.cc +++ b/runtime/vm/compiler/backend/inliner.cc @@ -1032,8 +1032,7 @@ class CallSiteInliner : public ValueObject { #endif CalleeGraphValidator::Validate(callee_graph); } -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) if (FLAG_precompiled_mode) { callee_graph->PopulateWithICData(parsed_function->function()); } @@ -1128,8 +1127,7 @@ class CallSiteInliner : public ValueObject { // TODO(fschneider): Improve suppression of speculative inlining. // Deopt-ids overlap between caller and callee. if (FLAG_precompiled_mode) { -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) AotCallSpecializer call_specializer(inliner_->precompiler_, callee_graph, inliner_->speculative_policy_); @@ -1140,8 +1138,7 @@ class CallSiteInliner : public ValueObject { CompilerPass::RunInliningPipeline(CompilerPass::kAOT, &state); #else UNREACHABLE(); -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - // !defined(TARGET_ARCH_IA32) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) } else { JitCallSpecializer call_specializer(callee_graph, inliner_->speculative_policy_); diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc index efce8fa7797..7635384f45b 100644 --- a/runtime/vm/compiler/backend/linearscan.cc +++ b/runtime/vm/compiler/backend/linearscan.cc @@ -140,9 +140,7 @@ FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph, // TODO(fschneider): Handle saving and restoring these registers when // generating intrinsic code. if (intrinsic_mode) { -#if !defined(TARGET_ARCH_DBC) blocked_cpu_registers_[ARGS_DESC_REG] = true; -#endif #if !defined(TARGET_ARCH_IA32) // Need to preserve CODE_REG to be able to store the PC marker @@ -186,15 +184,6 @@ void SSALivenessAnalysis::ComputeInitialSets() { // Initialize location summary for instruction. current->InitializeLocationSummary(zone(), true); // opt -#if defined(TARGET_ARCH_DBC) - // TODO(vegorov) remove this once we have ported all necessary - // instructions to DBC. - if (!current->HasLocs()) { - const char* msg = "SSALivenessAnalysis::ComputeInitialSets"; - NOT_IN_PRODUCT(msg = current->ToCString()); - graph_entry_->parsed_function().Bailout("SSALivenessAnalysis", msg); - } -#endif LocationSummary* locs = current->locs(); #if defined(DEBUG) @@ -453,10 +442,6 @@ void FlowGraphAllocator::BlockLocation(Location loc, intptr_t to) { if (loc.IsRegister()) { BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_); -#if defined(TARGET_ARCH_DBC) - last_used_register_ = - Utils::Maximum(last_used_register_, loc.register_code()); -#endif } else if (loc.IsFpuRegister()) { BlockRegisterLocation(loc, from, to, blocked_fpu_registers_, fpu_regs_); } else { @@ -690,7 +675,7 @@ void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn, SplitInitialDefinitionAt(range, block->lifetime_position() + 1); ConvertAllUses(range); - // On non-DBC we'll have exception/stacktrace in a register and need to + // We have exception/stacktrace in a register and need to // ensure this register is not available for register allocation during // the [CatchBlockEntry] to ensure it's not overwritten. if (loc.IsRegister()) { @@ -698,40 +683,6 @@ void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn, block->lifetime_position() + 1); } return; -#if defined(TARGET_ARCH_DBC) - } else if (ParameterInstr* param = defn->AsParameter()) { - intptr_t slot_index = param->index(); - AssignSafepoints(defn, range); - range->finger()->Initialize(range); - slot_index = kNumberOfCpuRegisters - 1 - slot_index; - if (slot_index < kMaxNumberOfFixedInputRegistersUsedByIL) { - // We ran out of registers for the catch block parameters. - // Bail out to unoptimized code - flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "CATCH"); - UNREACHABLE(); - } - range->set_assigned_location(Location::RegisterLocation(slot_index)); - SplitInitialDefinitionAt(range, block->lifetime_position() + 2); - ConvertAllUses(range); - BlockLocation(Location::RegisterLocation(slot_index), 0, kMaxPosition); - return; - } else if (ConstantInstr* constant = defn->AsConstant()) { - ASSERT(constant != NULL); - range->set_assigned_location(Location::Constant(constant)); - range->set_spill_slot(Location::Constant(constant)); - AssignSafepoints(defn, range); - range->finger()->Initialize(range); - UsePosition* use = - range->finger()->FirstRegisterBeneficialUse(block->start_pos()); - if (use != NULL) { - LiveRange* tail = SplitBetween(range, block->start_pos(), use->pos()); - // Parameters and constants are tagged, so allocated to CPU registers. - ASSERT(constant->representation() == kTagged); - CompleteRange(tail, Location::kRegister); - } - ConvertAllUses(range); - return; -#endif // defined(TARGET_ARCH_DBC) } } @@ -749,17 +700,6 @@ void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn, slot_index = flow_graph_.num_direct_parameters() - 1 - slot_index; } -#if defined(TARGET_ARCH_DBC) - ASSERT(param->base_reg() == FPREG); - if (slot_index >= 0) { - AssignSafepoints(defn, range); - range->finger()->Initialize(range); - range->set_assigned_location(Location::RegisterLocation(slot_index)); - SplitInitialDefinitionAt(range, kNormalEntryPos); - ConvertAllUses(range); - return; - } -#endif // defined(TARGET_ARCH_DBC) if (param->base_reg() == FPREG) { slot_index = compiler::target::frame_layout.FrameSlotForVariableIndex(-slot_index); @@ -774,11 +714,7 @@ void FlowGraphAllocator::ProcessInitialDefinition(Definition* defn, SpecialParameterInstr* param = defn->AsSpecialParameter(); ASSERT(param->kind() == SpecialParameterInstr::kArgDescriptor); Location loc; -#if defined(TARGET_ARCH_DBC) - loc = LocationArgumentsDescriptorLocation(); -#else loc = Location::RegisterLocation(ARGS_DESC_REG); -#endif // defined(TARGET_ARCH_DBC) range->set_assigned_location(loc); if (loc.IsRegister()) { AssignSafepoints(defn, range); @@ -1438,9 +1374,6 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, } // Block all allocatable registers for calls. -// Note that on DBC registers are always essentially spilled so -// we don't need to block anything. -#if !defined(TARGET_ARCH_DBC) if (locs->always_calls() && !locs->callee_safe_call()) { // Expected shape of live range: // @@ -1490,7 +1423,6 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, } #endif } -#endif if (locs->can_call()) { safepoints_.Add(current); @@ -1971,14 +1903,6 @@ void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { } void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { -#if defined(TARGET_ARCH_DBC) - // There is no need to support spilling on DBC because we have a lot of - // registers and registers and spill-slots have the same performance - // characteristics. - flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "SPILL"); - UNREACHABLE(); -#endif - ASSERT(range->spill_slot().IsInvalid()); // Compute range start and end. @@ -2319,10 +2243,6 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) { registers_[candidate]->Add(unallocated); unallocated->set_assigned_location(MakeRegisterLocation(candidate)); -#if defined(TARGET_ARCH_DBC) - last_used_register_ = Utils::Maximum(last_used_register_, candidate); -#endif - return true; } @@ -2510,9 +2430,6 @@ void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, registers_[reg]->Add(unallocated); unallocated->set_assigned_location(MakeRegisterLocation(reg)); -#if defined(TARGET_ARCH_DBC) - last_used_register_ = Utils::Maximum(last_used_register_, reg); -#endif } bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, @@ -2595,16 +2512,10 @@ void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { if (loc.IsMachineRegister()) { for (SafepointPosition* safepoint = range->first_safepoint(); safepoint != NULL; safepoint = safepoint->next()) { -#if !defined(TARGET_ARCH_DBC) if (!safepoint->locs()->always_calls()) { ASSERT(safepoint->locs()->can_call()); safepoint->locs()->live_registers()->Add(loc, range->representation()); } -#else - if (range->representation() == kTagged) { - safepoint->locs()->SetStackBit(loc.reg()); - } -#endif // !defined(TARGET_ARCH_DBC) } } } @@ -2984,10 +2895,6 @@ void FlowGraphAllocator::AllocateRegisters() { NumberInstructions(); -#if defined(TARGET_ARCH_DBC) - last_used_register_ = -1; -#endif - BuildLiveRanges(); if (FLAG_print_ssa_liveranges) { @@ -3011,16 +2918,6 @@ void FlowGraphAllocator::AllocateRegisters() { PrepareForAllocation(Location::kRegister, kNumberOfCpuRegisters, unallocated_cpu_, cpu_regs_, blocked_cpu_registers_); AllocateUnallocatedRanges(); -#if defined(TARGET_ARCH_DBC) - const intptr_t last_used_cpu_register = last_used_register_; - last_used_register_ = -1; -#endif - -#if defined(TARGET_ARCH_DBC) - // Spilling is unsupported on DBC. - ASSERT(spill_slots_.length() == 0); - cpu_spill_slot_count_ = 0; -#else // GraphEntryInstr::fixed_slot_count() stack slots are reserved for catch // entries. When allocating a spill slot, AllocateSpillSlotFor() accounts for // these reserved slots and allocates spill slots on top of them. @@ -3028,24 +2925,13 @@ void FlowGraphAllocator::AllocateRegisters() { // slots for catch entries in the spill area. cpu_spill_slot_count_ = Utils::Maximum( spill_slots_.length(), flow_graph_.graph_entry()->fixed_slot_count()); -#endif spill_slots_.Clear(); quad_spill_slots_.Clear(); untagged_spill_slots_.Clear(); PrepareForAllocation(Location::kFpuRegister, kNumberOfFpuRegisters, unallocated_xmm_, fpu_regs_, blocked_fpu_registers_); -#if defined(TARGET_ARCH_DBC) - // For DBC all registers should have been allocated in the first pass. - ASSERT(unallocated_.is_empty()); -#endif - AllocateUnallocatedRanges(); -#if defined(TARGET_ARCH_DBC) - const intptr_t last_used_fpu_register = last_used_register_; - ASSERT(last_used_fpu_register == -1); // Not supported right now. -#endif - ResolveControlFlow(); GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); @@ -3053,20 +2939,6 @@ void FlowGraphAllocator::AllocateRegisters() { intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor; entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count); -#if defined(TARGET_ARCH_DBC) - // Spilling is unsupported on DBC. - if (entry->spill_slot_count() != 0) { - UNREACHABLE(); - } - - // We store number of used DBC registers in the spill slot count to avoid - // introducing a separate field. It has roughly the same meaning: - // number of used registers determines how big of a frame to reserve for - // this function on DBC stack. - entry->set_spill_slot_count((last_used_cpu_register + 1) + - (last_used_fpu_register + 1)); -#endif - if (FLAG_print_ssa_liveranges) { const Function& function = flow_graph_.function(); diff --git a/runtime/vm/compiler/backend/linearscan.h b/runtime/vm/compiler/backend/linearscan.h index 9655f32d1c3..8b774cc1237 100644 --- a/runtime/vm/compiler/backend/linearscan.h +++ b/runtime/vm/compiler/backend/linearscan.h @@ -295,10 +295,6 @@ class FlowGraphAllocator : public ValueObject { intptr_t number_of_registers_; -#if defined(TARGET_ARCH_DBC) - intptr_t last_used_register_; -#endif - // Per register lists of allocated live ranges. Contain only those // ranges that can be affected by future allocation decisions. // Those live ranges that end before the start of the current live range are diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc index 210cd37ab9d..1db7fd7b160 100644 --- a/runtime/vm/compiler/backend/locations.cc +++ b/runtime/vm/compiler/backend/locations.cc @@ -141,12 +141,9 @@ Location LocationAnyOrConstant(Value* value) { : Location::Any(); } -// DBC does not have an notion of 'address' in its instruction set. -#if !defined(TARGET_ARCH_DBC) compiler::Address LocationToStackSlotAddress(Location loc) { return compiler::Address(loc.base_reg(), loc.ToStackSlotOffset()); } -#endif template intptr_t TemplateLocation::ToStackSlotOffset() const { @@ -189,19 +186,6 @@ const char* TemplateLocation::Name() const { return "0"; } UNREACHABLE(); -#if TARGET_ARCH_DBC - case kSpecialDbcRegister: - switch (payload()) { - case kArgsDescriptorReg: - return "ArgDescReg"; - case kExceptionReg: - return "ExceptionReg"; - case kStackTraceReg: - return "StackTraceReg"; - default: - UNREACHABLE(); - } -#endif default: if (IsConstant()) { return "C"; @@ -269,27 +253,15 @@ TemplateLocation::Copy() const { } Location LocationArgumentsDescriptorLocation() { -#ifdef TARGET_ARCH_DBC - return Location(Location::kSpecialDbcRegister, Location::kArgsDescriptorReg); -#else return Location::RegisterLocation(ARGS_DESC_REG); -#endif } Location LocationExceptionLocation() { -#ifdef TARGET_ARCH_DBC - return Location(Location::kSpecialDbcRegister, Location::kExceptionReg); -#else return Location::RegisterLocation(kExceptionObjectReg); -#endif } Location LocationStackTraceLocation() { -#ifdef TARGET_ARCH_DBC - return Location(Location::kSpecialDbcRegister, Location::kStackTraceReg); -#else return Location::RegisterLocation(kStackTraceObjectReg); -#endif } Location LocationRemapForSlowPath(Location loc, diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h index b6e7777ef38..e0731f4777e 100644 --- a/runtime/vm/compiler/backend/locations.h +++ b/runtime/vm/compiler/backend/locations.h @@ -94,14 +94,6 @@ class TemplateLocation : public ValueObject { static const uword kLocationTagMask = 0x3; public: -#if defined(TARGET_ARCH_DBC) - enum SpecialDbcRegister{ - kArgsDescriptorReg, - kExceptionReg, - kStackTraceReg, - }; -#endif - // Constant payload can overlap with kind field so Kind values // have to be chosen in a way that their last 2 bits are never // the same as kConstantTag or kPairLocationTag. @@ -137,12 +129,6 @@ class TemplateLocation : public ValueObject { // FpuRegister location represents a fixed fpu register. Payload contains // its code. kFpuRegister = 12, - -#ifdef TARGET_ARCH_DBC - // We use this to signify a special `Location` where the different - // [SpecialDbcRegister]s can be found on DBC. - kSpecialDbcRegister = 15, -#endif }; TemplateLocation() : value_(kInvalidLocation) { @@ -169,12 +155,6 @@ class TemplateLocation : public ValueObject { COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kConstantTag); COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag); -#ifdef TARGET_ARCH_DBC - COMPILE_ASSERT((kSpecialDbcRegister & kLocationTagMask) != kConstantTag); - COMPILE_ASSERT((kSpecialDbcRegister & kLocationTagMask) != - kPairLocationTag); -#endif - // Verify tags and tagmask. COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag); @@ -295,22 +275,6 @@ class TemplateLocation : public ValueObject { bool IsFpuRegister() const { return kind() == kFpuRegister; } -#ifdef TARGET_ARCH_DBC - bool IsArgsDescRegister() const { - return IsSpecialDbcRegister(kArgsDescriptorReg); - } - bool IsExceptionRegister() const { - return IsSpecialDbcRegister(kExceptionReg); - } - bool IsStackTraceRegister() const { - return IsSpecialDbcRegister(kStackTraceReg); - } - - bool IsSpecialDbcRegister(SpecialDbcRegister reg) const { - return kind() == kSpecialDbcRegister && payload() == reg; - } -#endif - FpuRegister fpu_reg() const { ASSERT(IsFpuRegister()); return static_cast(payload()); @@ -493,11 +457,8 @@ Location LocationRemapForSlowPath(Location loc, intptr_t* cpu_reg_slots, intptr_t* fpu_reg_slots); -// DBC does not have an notion of 'address' in its instruction set. -#if !defined(TARGET_ARCH_DBC) // Return a memory operand for stack slot locations. compiler::Address LocationToStackSlotAddress(Location loc); -#endif template class TemplatePairLocation : public ZoneAllocated { @@ -608,7 +569,6 @@ class RegisterSet : public ValueObject { #endif } -#if !defined(TARGET_ARCH_DBC) void AddAllArgumentRegisters() { // All (native) arguments are passed on the stack in IA32. #if !defined(TARGET_ARCH_IA32) @@ -626,7 +586,6 @@ class RegisterSet : public ValueObject { } #endif } -#endif void Add(Location loc, Representation rep = kTagged) { if (loc.IsRegister()) { @@ -785,12 +744,8 @@ class LocationSummary : public ZoneAllocated { void set_out(intptr_t index, Location loc) { ASSERT(index == 0); -// DBC calls are different from call on other architectures so this -// assert doesn't make sense. -#if !defined(TARGET_ARCH_DBC) ASSERT(!always_calls() || (loc.IsMachineRegister() || loc.IsInvalid() || loc.IsPairLocation())); -#endif output_location_ = loc; } diff --git a/runtime/vm/compiler/backend/locations_helpers.h b/runtime/vm/compiler/backend/locations_helpers.h index 481fbdb27a1..5e7969a358f 100644 --- a/runtime/vm/compiler/backend/locations_helpers.h +++ b/runtime/vm/compiler/backend/locations_helpers.h @@ -430,8 +430,6 @@ void InvokeEmitter( #include "vm/compiler/backend/locations_helpers_arm.h" #elif defined(TARGET_ARCH_ARM64) -#elif defined(TARGET_ARCH_DBC) - #else #error Unknown architecture. #endif diff --git a/runtime/vm/compiler/backend/locations_helpers_test.cc b/runtime/vm/compiler/backend/locations_helpers_test.cc index ed7950611dc..aaf3805053d 100644 --- a/runtime/vm/compiler/backend/locations_helpers_test.cc +++ b/runtime/vm/compiler/backend/locations_helpers_test.cc @@ -9,8 +9,6 @@ namespace dart { -#if !defined(TARGET_ARCH_DBC) - #define Reg(index) (static_cast(index)) #define Fpu(index) (static_cast(index)) @@ -233,6 +231,4 @@ INSTRUCTION_TEST(FixedTemp, EXPECT_EQ(Fpu(3), Fpu(temp)); } -#endif // !defined(TARGET_ARCH_DBC) - } // namespace dart diff --git a/runtime/vm/compiler/backend/loops_test.cc b/runtime/vm/compiler/backend/loops_test.cc index b2b2e237e1c..3898334c104 100644 --- a/runtime/vm/compiler/backend/loops_test.cc +++ b/runtime/vm/compiler/backend/loops_test.cc @@ -368,7 +368,6 @@ ISOLATE_UNIT_TEST_CASE(NonStrictConditionUp) { EXPECT_STREQ(expected, ComputeInduction(thread, script_chars)); } -#ifndef TARGET_ARCH_DBC ISOLATE_UNIT_TEST_CASE(NonStrictConditionUpWrap) { const char* script_chars = R"( @@ -392,7 +391,6 @@ ISOLATE_UNIT_TEST_CASE(NonStrictConditionUpWrap) { " ]\n"; EXPECT_STREQ(expected, ComputeInduction(thread, script_chars)); } -#endif ISOLATE_UNIT_TEST_CASE(NonStrictConditionDown) { const char* script_chars = @@ -413,7 +411,6 @@ ISOLATE_UNIT_TEST_CASE(NonStrictConditionDown) { EXPECT_STREQ(expected, ComputeInduction(thread, script_chars)); } -#ifndef TARGET_ARCH_DBC ISOLATE_UNIT_TEST_CASE(NonStrictConditionDownWrap) { const char* script_chars = R"( @@ -438,8 +435,6 @@ ISOLATE_UNIT_TEST_CASE(NonStrictConditionDownWrap) { EXPECT_STREQ(expected, ComputeInduction(thread, script_chars)); } -#endif - ISOLATE_UNIT_TEST_CASE(NotEqualConditionUp) { const char* script_chars = R"( diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc index 65156bf4e06..3d1a906fa2c 100644 --- a/runtime/vm/compiler/backend/typed_data_aot_test.cc +++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc @@ -13,7 +13,7 @@ namespace dart { -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) +#if defined(DART_PRECOMPILER) // This test asserts that we are inlining accesses to typed data interfaces // (e.g. Uint8List) if there are no instantiated 3rd party classes. @@ -445,6 +445,6 @@ ISOLATE_UNIT_TEST_CASE(IRTest_TypedDataAOT_FunctionalIndexError) { } } -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) +#endif // defined(DART_PRECOMPILER) } // namespace dart diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni index d1a5b77d776..7188785fb27 100644 --- a/runtime/vm/compiler/compiler_sources.gni +++ b/runtime/vm/compiler/compiler_sources.gni @@ -13,7 +13,6 @@ compiler_sources = [ "asm_intrinsifier.h", "asm_intrinsifier_arm.cc", "asm_intrinsifier_arm64.cc", - "asm_intrinsifier_dbc.cc", "asm_intrinsifier_ia32.cc", "asm_intrinsifier_x64.cc", "assembler/assembler.cc", @@ -22,8 +21,6 @@ compiler_sources = [ "assembler/assembler_arm.h", "assembler/assembler_arm64.cc", "assembler/assembler_arm64.h", - "assembler/assembler_dbc.cc", - "assembler/assembler_dbc.h", "assembler/assembler_ia32.cc", "assembler/assembler_ia32.h", "assembler/assembler_x64.cc", @@ -32,7 +29,6 @@ compiler_sources = [ "assembler/disassembler.h", "assembler/disassembler_arm.cc", "assembler/disassembler_arm64.cc", - "assembler/disassembler_dbc.cc", "assembler/disassembler_kbc.cc", "assembler/disassembler_kbc.h", "assembler/disassembler_x86.cc", @@ -57,14 +53,12 @@ compiler_sources = [ "backend/flow_graph_compiler.h", "backend/flow_graph_compiler_arm.cc", "backend/flow_graph_compiler_arm64.cc", - "backend/flow_graph_compiler_dbc.cc", "backend/flow_graph_compiler_ia32.cc", "backend/flow_graph_compiler_x64.cc", "backend/il.cc", "backend/il.h", "backend/il_arm.cc", "backend/il_arm64.cc", - "backend/il_dbc.cc", "backend/il_deserializer.cc", "backend/il_deserializer.h", "backend/il_ia32.cc", @@ -151,26 +145,13 @@ compiler_sources = [ "stub_code_compiler.h", "stub_code_compiler_arm.cc", "stub_code_compiler_arm64.cc", - "stub_code_compiler_dbc.cc", "stub_code_compiler_ia32.cc", "stub_code_compiler_x64.cc", ] -# The most common way to include assembly files in C projects is to have -# separate assembly files per architecture and operating system (for example -# boringssl). -# -# Not that this diverges from our convention to build every file on every OS -# but have ifdef guards which make the files empty on some configurations. -if (is_linux || is_mac) { - # MASM on Windows does not support c preproccesor style flags. - compiler_sources += [ "ffi_dbc_trampoline_x64_linux_mac.S" ] -} - compiler_sources_tests = [ "assembler/assembler_arm64_test.cc", "assembler/assembler_arm_test.cc", - "assembler/assembler_dbc_test.cc", "assembler/assembler_ia32_test.cc", "assembler/assembler_test.cc", "assembler/assembler_x64_test.cc", diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc index 596d43c164d..90af59dd934 100644 --- a/runtime/vm/compiler/ffi.cc +++ b/runtime/vm/compiler/ffi.cc @@ -137,28 +137,8 @@ static_assert(offsetof(AbiAlignmentUint64, i) == 8, #error "Unknown platform. Please add alignment requirements for ABI." #endif -#if defined(TARGET_ARCH_DBC) -static Abi HostAbi() { -#if defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64) - return Abi::kWordSize64; -#elif (defined(HOST_ARCH_IA32) && /* NOLINT(whitespace/parens) */ \ - (defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || \ - defined(HOST_OS_ANDROID))) || \ - (defined(HOST_ARCH_ARM) && defined(HOST_OS_IOS)) - return Abi::kWordSize32Align32; -#elif defined(HOST_ARCH_IA32) && defined(HOST_OS_WINDOWS) || \ - defined(HOST_ARCH_ARM) - return Abi::kWordSize32Align64; -#else -#error "Unknown platform. Please add alignment requirements for ABI." -#endif -} -#endif // defined(TARGET_ARCH_DBC) - Abi TargetAbi() { -#if defined(TARGET_ARCH_DBC) - return HostAbi(); -#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64) +#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64) return Abi::kWordSize64; #elif (defined(TARGET_ARCH_IA32) && /* NOLINT(whitespace/parens) */ \ (defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) || \ @@ -260,8 +240,6 @@ Representation ResultRepresentationBase(const Function& signature) { return rep; } -#if !defined(TARGET_ARCH_DBC) - RawFunction* NativeCallbackFunction(const Function& c_signature, const Function& dart_target, const Instance& exceptional_return) { @@ -323,8 +301,6 @@ Representation ResultRepresentation(const Function& signature) { return ResultRepresentationBase(signature); } -#endif // !defined(TARGET_ARCH_DBC) - #if defined(USING_SIMULATOR) ZoneGrowableArray* ArgumentHostRepresentations( @@ -459,7 +435,6 @@ class ArgumentAllocator : public ValueObject { intptr_t stack_height_in_slots = 0; }; -#if !defined(TARGET_ARCH_DBC) ZoneGrowableArray* CallbackArgumentTranslator::TranslateArgumentLocations( const ZoneGrowableArray& arg_locs) { @@ -528,7 +503,6 @@ Location CallbackArgumentTranslator::TranslateArgument(Location arg) { argument_slots_used_ += 8 / target::kWordSize; return result; } -#endif // !defined(TARGET_ARCH_DBC) // Takes a list of argument representations, and converts it to a list of // argument locations based on calling convention. @@ -553,33 +527,11 @@ ZoneGrowableArray* ArgumentLocationsBase( ZoneGrowableArray* ArgumentLocations( const ZoneGrowableArray& arg_reps) { -#if !defined(TARGET_ARCH_DBC) return ArgumentLocationsBase(arg_reps); -#else - intptr_t next_free_register = ffi::kFirstArgumentRegister; - intptr_t num_arguments = arg_reps.length(); - auto result = new ZoneGrowableArray(num_arguments); - for (intptr_t i = 0; i < num_arguments; i++) { - // TODO(dacoharkes): In 32 bits, use pair locations. - result->Add(Location::RegisterLocation(next_free_register)); - next_free_register++; - } - return result; -#endif } -#if defined(TARGET_ARCH_DBC) -ZoneGrowableArray* HostArgumentLocations( - const ZoneGrowableArray& arg_reps) { - return ArgumentLocationsBase( - arg_reps); -} -#endif - Location ResultLocation(Representation result_rep) { -#ifndef TARGET_ARCH_DBC switch (result_rep) { case kUnboxedFloat: case kUnboxedDouble: @@ -604,10 +556,6 @@ Location ResultLocation(Representation result_rep) { default: UNREACHABLE(); } -#else - // TODO(dacoharkes): Support 64 bit result values on 32 bit DBC. - return Location::RegisterLocation(0); -#endif } // TODO(36607): Cache the trampolines. @@ -675,85 +623,6 @@ intptr_t NumStackSlots(const ZoneGrowableArray& locations) { return TemplateNumStackSlots(locations); } -#if defined(TARGET_ARCH_DBC) - -static RawTypedData* typed_data_new_uintptr(intptr_t length) { -#if defined(ARCH_IS_32_BIT) - return TypedData::New(kTypedDataUint32ArrayCid, length); -#else - return TypedData::New(kTypedDataUint64ArrayCid, length); -#endif -} - -static void typed_data_set_uintptr(const TypedData& typed_data, - intptr_t index, - uintptr_t value) { -#if defined(ARCH_IS_32_BIT) - typed_data.SetUint32(target::kWordSize * index, value); -#else - typed_data.SetUint64(target::kWordSize * index, value); -#endif -} - -static uintptr_t typed_data_get_uintptr(const TypedData& typed_data, - intptr_t index) { -#if defined(ARCH_IS_32_BIT) - return typed_data.GetUint32(target::kWordSize * index); -#else - return typed_data.GetUint64(target::kWordSize * index); -#endif -} - -// Number of host stack slots used in 'locations'. -static intptr_t HostNumStackSlots( - const ZoneGrowableArray& locations) { - return TemplateNumStackSlots(locations); -} - -RawTypedData* FfiSignatureDescriptor::New( - const ZoneGrowableArray& arg_host_locations, - const Representation result_representation) { - const uintptr_t num_arguments = arg_host_locations.length(); - const uintptr_t num_stack_slots = HostNumStackSlots(arg_host_locations); - - const TypedData& result = TypedData::Handle( - typed_data_new_uintptr(kOffsetArgumentLocations + num_arguments)); - - typed_data_set_uintptr(result, kOffsetNumArguments, num_arguments); - typed_data_set_uintptr(result, kOffsetNumStackSlots, num_stack_slots); - typed_data_set_uintptr(result, kOffsetResultRepresentation, - result_representation); - - for (uintptr_t i = 0; i < num_arguments; i++) { - typed_data_set_uintptr(result, kOffsetArgumentLocations + i, - arg_host_locations.At(i).write()); - } - - return result.raw(); -} - -intptr_t FfiSignatureDescriptor::length() const { - return typed_data_get_uintptr(typed_data_, kOffsetNumArguments); -} - -intptr_t FfiSignatureDescriptor::num_stack_slots() const { - return typed_data_get_uintptr(typed_data_, kOffsetNumStackSlots); -} - -HostLocation FfiSignatureDescriptor::LocationAt(intptr_t index) const { - return HostLocation::read( - typed_data_get_uintptr(typed_data_, kOffsetArgumentLocations + index)); -} - -Representation FfiSignatureDescriptor::ResultRepresentation() const { - uintptr_t result_int = - typed_data_get_uintptr(typed_data_, kOffsetResultRepresentation); - ASSERT(result_int < kNumRepresentations); - return static_cast(result_int); -} - -#endif // defined(TARGET_ARCH_DBC) - #endif // !defined(DART_PRECOMPILED_RUNTIME) } // namespace ffi diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h index ea352032c30..a1b50b1073d 100644 --- a/runtime/vm/compiler/ffi.h +++ b/runtime/vm/compiler/ffi.h @@ -60,8 +60,6 @@ Location ResultLocation(Representation result_rep); RawFunction* TrampolineFunction(const Function& dart_signature, const Function& c_signature); -#if !defined(TARGET_ARCH_DBC) - RawFunction* NativeCallbackFunction(const Function& c_signature, const Function& dart_target, const Instance& exceptional_return); @@ -73,19 +71,6 @@ ZoneGrowableArray* ArgumentRepresentations( // Unboxed representation of the result of a C signature function. Representation ResultRepresentation(const Function& signature); -#endif // !defined(TARGET_ARCH_DBC) - -#if defined(USING_SIMULATOR) - -// Unboxed host representations of the arguments to a C signature function. -ZoneGrowableArray* ArgumentHostRepresentations( - const Function& signature); - -// Unboxed host representation of the result of a C signature function. -Representation ResultHostRepresentation(const Function& signature); - -#endif // defined(USING_SIMULATOR) - // Location for the arguments of a C signature function. ZoneGrowableArray* ArgumentLocations( const ZoneGrowableArray& arg_reps); @@ -93,44 +78,6 @@ ZoneGrowableArray* ArgumentLocations( // Number of stack slots used in 'locations'. intptr_t NumStackSlots(const ZoneGrowableArray& locations); -#if defined(TARGET_ARCH_DBC) - -// The first argument to a ffi trampoline is the function address, the arguments -// to the call follow the function address. -const intptr_t kFunctionAddressRegister = 0; -const intptr_t kFirstArgumentRegister = 1; - -// Location in host for the arguments of a C signature function. -ZoneGrowableArray* HostArgumentLocations( - const ZoneGrowableArray& arg_reps); - -// A signature descriptor consists of the signature length, argument locations, -// and result representation. -class FfiSignatureDescriptor : public ValueObject { - public: - explicit FfiSignatureDescriptor(const TypedData& typed_data) - : typed_data_(typed_data) {} - - static RawTypedData* New( - const ZoneGrowableArray& arg_host_locations, - const Representation result_representation); - - intptr_t length() const; - intptr_t num_stack_slots() const; - HostLocation LocationAt(intptr_t index) const; - Representation ResultRepresentation() const; - - private: - const TypedData& typed_data_; - - static const intptr_t kOffsetNumArguments = 0; - static const intptr_t kOffsetNumStackSlots = 1; - static const intptr_t kOffsetResultRepresentation = 2; - static const intptr_t kOffsetArgumentLocations = 3; -}; - -#else // defined(TARGET_ARCH_DBC) - // This classes translates the ABI location of arguments into the locations they // will inhabit after entry-frame setup in the invocation of a native callback. // @@ -155,7 +102,6 @@ class CallbackArgumentTranslator : public ValueObject { intptr_t argument_slots_used_ = 0; intptr_t argument_slots_required_ = 0; }; -#endif // defined(TARGET_ARCH_DBC) } // namespace ffi diff --git a/runtime/vm/compiler/ffi_dbc_trampoline.h b/runtime/vm/compiler/ffi_dbc_trampoline.h deleted file mode 100644 index 656d1e1ba65..00000000000 --- a/runtime/vm/compiler/ffi_dbc_trampoline.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_ -#define RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_ - -#include "vm/globals.h" - -namespace dart { - -#if defined(HOST_ARCH_X64) && !defined(HOST_OS_WINDOWS) - -// Generic Trampoline for DBC dart:ffi calls. Argument needs to be layed out as -// a FfiMarshalledArguments. -extern "C" void FfiTrampolineCall(uint64_t* ffi_marshalled_args); - -#else - -void FfiTrampolineCall(uint64_t* ffi_marshalled_args) { - UNREACHABLE(); -} - -#endif // defined(HOST_ARCH_X64) && !defined(HOST_OS_WINDOWS) - -} // namespace dart - -#endif // RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_ diff --git a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S deleted file mode 100644 index 4f422793daa..00000000000 --- a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S +++ /dev/null @@ -1,77 +0,0 @@ -#if defined(_M_X64) || defined(__x86_64__) /* HOST_ARCH_X64 */ - -.intel_syntax noprefix -.text - -#if defined(__linux__) || defined(__FreeBSD__) /* HOST_OS_LINUX */ -.globl FfiTrampolineCall -.type FfiTrampolineCall, @function -FfiTrampolineCall: -#else /* HOST_OS_MACOS */ -.globl _FfiTrampolineCall -_FfiTrampolineCall: -#endif - -/* Save argument in scratch register. */ -push rbx /* Backup caller saved register. */ -mov rbx, rdi /* Save argument in scratch register. */ - -/* Enter frame. */ -push rbp -mov rbp, rsp - -/* Reserve framespace for arguments. */ -mov rax, [rbx+0x80] /* Load number of stack arguments. */ -shl rax, 3 /* Multiply by size (8 bytes). */ -sub rsp, rax /* Reserve num_stack_args stack slots. */ - -/* Stack alignment. */ -and rsp, [rbx+0x78] /* Align stack with stack alignment mask. */ - -/* Copy stack arguments. */ -cmp rax, 0x0 /* Check if number of stack arguments is 0. */ -jz .done /* Skip loop if no stack arguments. */ -add rsp, rax /* Unreserve stack slots so we can push arguments. */ -add rbx, 0x80 /* Offset RBX to point to stack arguments */ -.loop: /* Copy stack arguments loop. */ -push [rbx+rax] /* Push stack argument. */ -sub rax, 0x8 /* Decrement stack argument iterator. */ -cmp rax, 0x0 /* Compare iterator with 0 */ -jnz .loop /* Loop while iterator is not 0 */ -sub rbx, 0x80 /* Restore RBX to original value. */ -.done: /* End stack arguments loop. */ - -/* Copy registers and fpu registers. */ -mov rdi, [rbx+0x8] /* kArg1Reg */ -mov rsi, [rbx+0x10] /* kArg2Reg */ -mov rdx, [rbx+0x18] /* kArg3Reg */ -mov rcx, [rbx+0x20] /* kArg4Reg */ -mov r8, [rbx+0x28] /* kArg5Reg */ -mov r9, [rbx+0x30] /* kArg6Reg */ -movsd xmm0, [rbx+0x38] -movsd xmm1, [rbx+0x40] -movsd xmm2, [rbx+0x48] -movsd xmm3, [rbx+0x50] -movsd xmm4, [rbx+0x58] -movsd xmm5, [rbx+0x60] -movsd xmm6, [rbx+0x68] -movsd xmm7, [rbx+0x70] - -/* Do call. */ -mov rax, [rbx] /* function address */ -call rax /* Call the function. */ - -/* Copy results back. */ -mov [rbx], rax /* Move integer result in kOffsetIntResult */ -movsd [rbx+8], xmm0 /* Move double result in kOffsetDoubleResult */ - -/* leave frame */ -mov rsp, rbp -pop rbp - -/* Restore caller saved register. */ -pop rbx - -ret - -#endif /* HOST_ARCH_X64 */ diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc index 73b417ebb57..b5c17e513b6 100644 --- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc @@ -1935,9 +1935,6 @@ void BytecodeFlowGraphBuilder::BuildFfiAsFunction() { // static tearoff // => [NativeSignatureType] void BytecodeFlowGraphBuilder::BuildFfiNativeCallbackFunction() { -#if defined(TARGET_ARCH_DBC) - UNREACHABLE(); -#else const TypeArguments& type_args = TypeArguments::Cast(B->Peek(/*depth=*/2)->AsConstant()->value()); ASSERT(type_args.IsInstantiated() && type_args.Length() == 1); @@ -1959,7 +1956,6 @@ void BytecodeFlowGraphBuilder::BuildFfiNativeCallbackFunction() { native_sig, target, exceptional_return)); code_ += B->Constant(result); code_ += B->DropTempsPreserveTop(3); -#endif } void BytecodeFlowGraphBuilder::BuildDebugStepCheck() { diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index bb9b886b05a..98900df0375 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -2213,14 +2213,12 @@ Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) { // True if callee can skip argument type checks. bool is_unchecked_call = inferred_type.IsSkipCheck(); -#ifndef TARGET_ARCH_DBC if (call_site_attributes.receiver_type != nullptr && call_site_attributes.receiver_type->HasTypeClass() && !Class::Handle(call_site_attributes.receiver_type->type_class()) .IsGeneric()) { is_unchecked_call = true; } -#endif Fragment instructions(MakeTemp()); LocalVariable* variable = MakeTemporary(); @@ -5154,9 +5152,6 @@ Fragment StreamingFlowGraphBuilder::BuildFfiAsFunctionInternal() { } Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction() { -#if defined(TARGET_ARCH_DBC) - UNREACHABLE(); -#else // The call-site must look like this (guaranteed by the FE which inserts it): // // _nativeCallbackFunction(target, exceptionalReturn) @@ -5209,7 +5204,6 @@ Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction() { native_sig, target, exceptional_return)); code += Constant(result); return code; -#endif } } // namespace kernel diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 6768c3d2b0b..d1c8a02d177 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -676,8 +676,6 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph( const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); switch (kind) { -// On simdbc and the bytecode interpreter we fall back to natives. -#if !defined(TARGET_ARCH_DBC) case MethodRecognizer::kTypedData_ByteDataView_factory: case MethodRecognizer::kTypedData_Int8ArrayView_factory: case MethodRecognizer::kTypedData_Uint8ArrayView_factory: @@ -719,7 +717,6 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph( case MethodRecognizer::kFfiStorePointer: case MethodRecognizer::kFfiFromAddress: case MethodRecognizer::kFfiGetAddress: -#endif // !defined(TARGET_ARCH_DBC) // This list must be kept in sync with BytecodeReaderHelper::NativeEntry in // runtime/vm/compiler/frontend/bytecode_reader.cc and implemented in the // bytecode interpreter in runtime/vm/interpreter.cc. Alternatively, these @@ -780,8 +777,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); switch (kind) { -// On simdbc we fall back to natives. -#if !defined(TARGET_ARCH_DBC) case MethodRecognizer::kTypedData_ByteDataView_factory: body += BuildTypedDataViewFactoryConstructor(function, kByteDataViewCid); break; @@ -841,7 +836,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( body += BuildTypedDataViewFactoryConstructor( function, kTypedDataFloat64x2ArrayViewCid); break; -#endif // !defined(TARGET_ARCH_DBC) case MethodRecognizer::kObjectEquals: ASSERT(function.NumParameters() == 2); body += LoadLocal(parsed_function_->RawParameterVariable(0)); @@ -2638,14 +2632,12 @@ Fragment FlowGraphBuilder::FfiUnboxedExtend(Representation representation, return Fragment(extend); } -#if !defined(TARGET_ARCH_DBC) Fragment FlowGraphBuilder::NativeReturn(Representation result) { auto* instr = new (Z) NativeReturnInstr(TokenPosition::kNoSource, Pop(), result, compiler::ffi::ResultLocation(result), DeoptId::kNone); return Fragment(instr); } -#endif Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) { LocalVariable* address = MakeTemporary(); @@ -2764,13 +2756,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) { body += CheckStackOverflowInPrologue(function.token_pos()); const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature()); -#if !defined(TARGET_ARCH_DBC) const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature); const ZoneGrowableArray* arg_host_locs = nullptr; -#else - const auto& arg_reps = *compiler::ffi::ArgumentHostRepresentations(signature); - const auto* arg_host_locs = compiler::ffi::HostArgumentLocations(arg_reps); -#endif const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps); BuildArgumentTypeChecks(TypeChecksToBuild::kCheckAllTypeParameterBounds, @@ -2796,13 +2783,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) { body += FfiCall(signature, arg_reps, arg_locs, arg_host_locs); ffi_type = signature.result_type(); -#if !defined(TARGET_ARCH_DBC) const Representation from_rep = compiler::ffi::ResultRepresentation(signature); -#else - const Representation from_rep = - compiler::ffi::ResultHostRepresentation(signature); -#endif // !defined(TARGET_ARCH_DBC) body += FfiConvertArgumentToDart(ffi_type, from_rep); body += Return(TokenPosition::kNoSource); @@ -2811,7 +2793,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) { } FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) { -#if !defined(TARGET_ARCH_DBC) const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature()); const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature); const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps); @@ -2893,9 +2874,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) { PrologueInfo prologue_info(-1, -1); return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_, prologue_info); -#else - UNREACHABLE(); -#endif } void FlowGraphBuilder::SetCurrentTryCatchBlock(TryCatchBlock* try_catch_block) { diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc index 728aee51d26..9485474d774 100644 --- a/runtime/vm/compiler/graph_intrinsifier.cc +++ b/runtime/vm/compiler/graph_intrinsifier.cc @@ -3,8 +3,7 @@ // BSD-style license that can be found in the LICENSE file. // Class for intrinsifying functions. -// DBC does not use graph intrinsics. -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) #include "vm/compiler/graph_intrinsifier.h" #include "vm/compiler/backend/block_builder.h" @@ -989,4 +988,4 @@ bool GraphIntrinsifier::Build_DoubleRound(FlowGraph* flow_graph) { } // namespace compiler } // namespace dart -#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#endif // !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/compiler/graph_intrinsifier.h b/runtime/vm/compiler/graph_intrinsifier.h index 6282b5888a6..3e398f15dff 100644 --- a/runtime/vm/compiler/graph_intrinsifier.h +++ b/runtime/vm/compiler/graph_intrinsifier.h @@ -20,8 +20,6 @@ namespace compiler { class Assembler; class Label; -#if !defined(TARGET_ARCH_DBC) - class GraphIntrinsifier : public AllStatic { public: static intptr_t ParameterSlotFromSp(); @@ -36,7 +34,6 @@ class GraphIntrinsifier : public AllStatic { #define DECLARE_FUNCTION(class_name, function_name, enum_name, fp) \ static void enum_name(Assembler* assembler, Label* normal_ir_body); - // On DBC graph intrinsics are handled in the same way as non-graph ones. GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION) #undef DECLARE_FUNCTION @@ -49,18 +46,6 @@ class GraphIntrinsifier : public AllStatic { #undef DECLARE_FUNCTION }; -#else // !defined(TARGET_ARCH_DBC) - -class GraphIntrinsifier : public AllStatic { - public: - static bool GraphIntrinsify(const ParsedFunction& parsed_function, - FlowGraphCompiler* compiler) { - return false; - } -}; - -#endif // !defined(TARGET_ARCH_DBC) - } // namespace compiler } // namespace dart diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc index 68217ef36d4..73daa5becdd 100644 --- a/runtime/vm/compiler/intrinsifier.cc +++ b/runtime/vm/compiler/intrinsifier.cc @@ -198,7 +198,7 @@ bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function, } #endif -#if !defined(PRODUCT) && !defined(TARGET_ARCH_DBC) +#if !defined(PRODUCT) #define EMIT_BREAKPOINT() compiler->assembler()->Breakpoint() #else #define EMIT_BREAKPOINT() @@ -230,16 +230,6 @@ bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function, break; } -// On DBC all graph intrinsics are handled in the same way as non-graph -// intrinsics. -#if defined(TARGET_ARCH_DBC) - switch (function.recognized_kind()) { - GRAPH_INTRINSICS_LIST(EMIT_CASE) - default: - break; - } -#endif - #undef EMIT_BREAKPOINT #undef EMIT_INTRINSIC diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc index 1c3f94f43c9..9608373a34b 100644 --- a/runtime/vm/compiler/jit/compiler.cc +++ b/runtime/vm/compiler/jit/compiler.cc @@ -878,8 +878,7 @@ static RawObject* CompileFunctionHelper(CompilationPipeline* pipeline, } RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) { -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) if (FLAG_precompiled_mode) { return Precompiler::CompileFunction( /* precompiler = */ NULL, thread, thread->zone(), function); diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc index a91342ff5f5..293ff554fba 100644 --- a/runtime/vm/compiler/offsets_extractor.cc +++ b/runtime/vm/compiler/offsets_extractor.cc @@ -24,10 +24,6 @@ #define ARCH_DEF "defined(TARGET_ARCH_IA32)" #elif defined(TARGET_ARCH_ARM64) #define ARCH_DEF "defined(TARGET_ARCH_ARM64)" -#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT) -#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)" -#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT) -#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)" #else #error Unknown architecture #endif diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc index 0f4f567d647..e9f3bf781b9 100644 --- a/runtime/vm/compiler/relocation.cc +++ b/runtime/vm/compiler/relocation.cc @@ -12,8 +12,7 @@ namespace dart { -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) // Only for testing. DEFINE_FLAG(bool, @@ -512,7 +511,6 @@ intptr_t CodeRelocator::FindDestinationInText( offset_into_target; } -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - // !defined(TARGET_ARCH_IA32) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) } // namespace dart diff --git a/runtime/vm/compiler/relocation.h b/runtime/vm/compiler/relocation.h index 91ed48c5bfb..50db3e1d7f3 100644 --- a/runtime/vm/compiler/relocation.h +++ b/runtime/vm/compiler/relocation.h @@ -14,8 +14,7 @@ namespace dart { -#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - !defined(TARGET_ARCH_IA32) +#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) // Represents a pc-relative call which has not been patched up with the final // destination. @@ -208,8 +207,7 @@ class CodeRelocator : public StackResource { Code& destination_; }; -#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \ - // !defined(TARGET_ARCH_IA32) +#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) } // namespace dart diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc index e8db7d02c62..05bb858e9b5 100644 --- a/runtime/vm/compiler/runtime_api.cc +++ b/runtime/vm/compiler/runtime_api.cc @@ -208,7 +208,6 @@ uword SymbolsPredefinedAddress() { } #endif -#if !defined(TARGET_ARCH_DBC) const Code& StubCodeAllocateArray() { return dart::StubCode::AllocateArray(); } @@ -220,7 +219,6 @@ const Code& StubCodeSubtype2TestCache() { const Code& StubCodeSubtype6TestCache() { return dart::StubCode::Subtype6TestCache(); } -#endif // !defined(TARGET_ARCH_DBC) #define DEFINE_ALIAS(name) \ const RuntimeEntry& k##name##RuntimeEntry(dart::k##name##RuntimeEntry); @@ -508,12 +506,10 @@ word Instructions::HeaderSize() { return Utils::RoundUp(Instructions::UnalignedHeaderSize(), target::kWordSize); } -#if !defined(TARGET_ARCH_DBC) word Thread::stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) { return fpu_regs ? stack_overflow_shared_with_fpu_regs_entry_point_offset() : stack_overflow_shared_without_fpu_regs_entry_point_offset(); } -#endif // !defined(TARGET_ARCH_DBC) uword Thread::safepoint_state_unacquired() { return dart::Thread::safepoint_state_unacquired(); diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index 46c677b9f9e..f6f7eaa172b 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -189,11 +189,9 @@ typedef void (*RuntimeEntryCallInternal)(const dart::RuntimeEntry*, Assembler*, intptr_t); -#if !defined(TARGET_ARCH_DBC) const Code& StubCodeAllocateArray(); const Code& StubCodeSubtype2TestCache(); const Code& StubCodeSubtype6TestCache(); -#endif // !defined(TARGET_ARCH_DBC) class RuntimeEntry : public ValueObject { public: @@ -674,7 +672,6 @@ class Thread : public AllStatic { static word callback_code_offset(); static word AllocateArray_entry_point_offset(); -#if !defined(TARGET_ARCH_DBC) static word write_barrier_code_offset(); static word array_write_barrier_code_offset(); static word fix_callers_target_code_offset(); @@ -701,7 +698,6 @@ class Thread : public AllStatic { static word exit_safepoint_stub_offset(); static word call_native_through_safepoint_stub_offset(); static word call_native_through_safepoint_entry_point_offset(); -#endif // !defined(TARGET_ARCH_DBC) static word no_scope_native_wrapper_entry_point_offset(); static word auto_scope_native_wrapper_entry_point_offset(); diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index a24a2981a6b..5bfc88df9d0 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -1456,583 +1456,4 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 8; static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56; #endif // defined(TARGET_ARCH_ARM64) -#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT) -static constexpr dart::compiler::target::word ObjectPool_elements_start_offset = - 16; -static constexpr dart::compiler::target::word ObjectPool_element_size = 8; -static constexpr dart::compiler::target::word Array_kMaxElements = - 576460752303423487; -static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements = - 32765; -static constexpr dart::compiler::target::word - Instructions_kMonomorphicEntryOffsetJIT = 0; -static constexpr dart::compiler::target::word - Instructions_kPolymorphicEntryOffsetJIT = 0; -static constexpr dart::compiler::target::word - Instructions_kMonomorphicEntryOffsetAOT = 0; -static constexpr dart::compiler::target::word - Instructions_kPolymorphicEntryOffsetAOT = 0; -static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 10; -static constexpr dart::compiler::target::word - NativeEntry_kNumCallWrapperArguments = 2; -static constexpr dart::compiler::target::word String_kMaxElements = - 2305843009213693951; -static constexpr dart::compiler::target::word - SubtypeTestCache_kFunctionTypeArguments = 4; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceClassIdOrFunction = 1; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceTypeArguments = 2; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstantiatorTypeArguments = 3; -static constexpr dart::compiler::target::word - SubtypeTestCache_kTestEntryLength = 7; -static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0; -static constexpr dart::compiler::target::word - AbstractType_type_test_stub_entry_point_offset = 8; -static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset = - 32; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_first_named_entry_offset = 48; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_named_entry_size = 16; -static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset = - 0; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_position_offset = 8; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_positional_count_offset = 40; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_type_args_len_offset = 24; -static constexpr dart::compiler::target::word Array_data_offset = 24; -static constexpr dart::compiler::target::word Array_length_offset = 16; -static constexpr dart::compiler::target::word Array_tags_offset = 0; -static constexpr dart::compiler::target::word Array_type_arguments_offset = 8; -static constexpr dart::compiler::target::word Class_declaration_type_offset = - 112; -static constexpr dart::compiler::target::word Class_num_type_arguments_offset = - 190; -static constexpr dart::compiler::target::word Class_super_type_offset = 88; -static constexpr dart::compiler::target::word - Class_type_arguments_field_offset_in_words_offset = 180; -static constexpr dart::compiler::target::word - ClassHeapStats_TraceAllocationMask = 1; -static constexpr dart::compiler::target::word - ClassHeapStats_allocated_since_gc_new_space_offset = 96; -static constexpr dart::compiler::target::word - ClassHeapStats_allocated_size_since_gc_new_space_offset = 104; -static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272; -static constexpr dart::compiler::target::word - ClassTable_shared_class_table_offset = 40; -static constexpr dart::compiler::target::word ClassTable_table_offset = 16; -static constexpr dart::compiler::target::word - SharedClassTable_class_heap_stats_table_offset = 0; -static constexpr dart::compiler::target::word Closure_context_offset = 40; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 24; -static constexpr dart::compiler::target::word Closure_function_offset = 32; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 16; -static constexpr dart::compiler::target::word Closure_hash_offset = 48; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 8; -static constexpr dart::compiler::target::word Code_object_pool_offset = 40; -static constexpr dart::compiler::target::word Code_saved_instructions_offset = - 48; -static constexpr dart::compiler::target::word Code_owner_offset = 56; -static constexpr dart::compiler::target::word Context_num_variables_offset = 8; -static constexpr dart::compiler::target::word Context_parent_offset = 16; -static constexpr dart::compiler::target::word Double_value_offset = 8; -static constexpr dart::compiler::target::word - ExternalOneByteString_external_data_offset = 16; -static constexpr dart::compiler::target::word - ExternalTwoByteString_external_data_offset = 16; -static constexpr dart::compiler::target::word Float32x4_value_offset = 8; -static constexpr dart::compiler::target::word Float64x2_value_offset = 8; -static constexpr dart::compiler::target::word Field_guarded_cid_offset = 88; -static constexpr dart::compiler::target::word - Field_guarded_list_length_in_object_offset_offset = 96; -static constexpr dart::compiler::target::word Field_guarded_list_length_offset = - 56; -static constexpr dart::compiler::target::word Field_is_nullable_offset = 90; -static constexpr dart::compiler::target::word Field_static_value_offset = 32; -static constexpr dart::compiler::target::word Field_kind_bits_offset = 98; -static constexpr dart::compiler::target::word Function_code_offset = 88; -static constexpr dart::compiler::target::word Function_entry_point_offset = 8; -static constexpr dart::compiler::target::word - Function_unchecked_entry_point_offset = 16; -static constexpr dart::compiler::target::word Function_usage_counter_offset = - 132; -static constexpr dart::compiler::target::word GrowableObjectArray_data_offset = - 24; -static constexpr dart::compiler::target::word - GrowableObjectArray_length_offset = 16; -static constexpr dart::compiler::target::word - GrowableObjectArray_type_arguments_offset = 8; -static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40; -static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3; -static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; -static constexpr dart::compiler::target::word - ICData_arguments_descriptor_offset = 24; -static constexpr dart::compiler::target::word ICData_entries_offset = 8; -static constexpr dart::compiler::target::word ICData_owner_offset = 40; -static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; -static constexpr dart::compiler::target::word - ICData_receivers_static_type_offset = 32; -static constexpr dart::compiler::target::word Isolate_class_table_offset = 80; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56; -static constexpr dart::compiler::target::word Isolate_object_store_offset = 72; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 128; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32; -static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32; -static constexpr dart::compiler::target::word - LinkedHashMap_deleted_keys_offset = 48; -static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset = - 24; -static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 16; -static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset = - 40; -static constexpr dart::compiler::target::word - MarkingStackBlock_pointers_offset = 16; -static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8; -static constexpr dart::compiler::target::word - MegamorphicCache_arguments_descriptor_offset = 32; -static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset = - 8; -static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16; -static constexpr dart::compiler::target::word Mint_value_offset = 8; -static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset = - 8; -static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16; -static constexpr dart::compiler::target::word NativeArguments_retval_offset = - 24; -static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0; -static constexpr dart::compiler::target::word ObjectStore_double_type_offset = - 128; -static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 64; -static constexpr dart::compiler::target::word ObjectStore_string_type_offset = - 160; -static constexpr dart::compiler::target::word OneByteString_data_offset = 16; -static constexpr dart::compiler::target::word Pointer_c_memory_address_offset = - 16; -static constexpr dart::compiler::target::word - SingleTargetCache_entry_point_offset = 16; -static constexpr dart::compiler::target::word - SingleTargetCache_lower_limit_offset = 24; -static constexpr dart::compiler::target::word SingleTargetCache_target_offset = - 8; -static constexpr dart::compiler::target::word - SingleTargetCache_upper_limit_offset = 26; -static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = - 16; -static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8; -static constexpr dart::compiler::target::word String_hash_offset = 4; -static constexpr dart::compiler::target::word String_length_offset = 8; -static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8; -static constexpr dart::compiler::target::word - Thread_AllocateArray_entry_point_offset = 304; -static constexpr dart::compiler::target::word Thread_active_exception_offset = - 896; -static constexpr dart::compiler::target::word Thread_active_stacktrace_offset = - 904; -static constexpr dart::compiler::target::word Thread_async_stack_trace_offset = - 176; -static constexpr dart::compiler::target::word - Thread_auto_scope_native_wrapper_entry_point_offset = 224; -static constexpr dart::compiler::target::word Thread_bool_false_offset = 208; -static constexpr dart::compiler::target::word Thread_bool_true_offset = 200; -static constexpr dart::compiler::target::word Thread_dart_stream_offset = 968; -static constexpr dart::compiler::target::word Thread_double_abs_address_offset = - 264; -static constexpr dart::compiler::target::word - Thread_double_negate_address_offset = 256; -static constexpr dart::compiler::target::word Thread_end_offset = 128; -static constexpr dart::compiler::target::word Thread_execution_state_offset = - 936; -static constexpr dart::compiler::target::word - Thread_float_absolute_address_offset = 288; -static constexpr dart::compiler::target::word - Thread_float_negate_address_offset = 280; -static constexpr dart::compiler::target::word Thread_float_not_address_offset = - 272; -static constexpr dart::compiler::target::word - Thread_float_zerow_address_offset = 296; -static constexpr dart::compiler::target::word Thread_global_object_pool_offset = - 912; -static constexpr dart::compiler::target::word Thread_isolate_offset = 104; -static constexpr dart::compiler::target::word - Thread_marking_stack_block_offset = 152; -static constexpr dart::compiler::target::word - Thread_no_scope_native_wrapper_entry_point_offset = 216; -static constexpr dart::compiler::target::word Thread_object_null_offset = 192; -static constexpr dart::compiler::target::word - Thread_predefined_symbols_address_offset = 240; -static constexpr dart::compiler::target::word Thread_resume_pc_offset = 920; -static constexpr dart::compiler::target::word - Thread_saved_shadow_call_stack_offset = 928; -static constexpr dart::compiler::target::word Thread_safepoint_state_offset = - 944; -static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72; -static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset = - 80; -static constexpr dart::compiler::target::word - Thread_stack_overflow_flags_offset = 88; -static constexpr dart::compiler::target::word Thread_store_buffer_block_offset = - 144; -static constexpr dart::compiler::target::word - Thread_top_exit_frame_info_offset = 136; -static constexpr dart::compiler::target::word Thread_top_offset = 120; -static constexpr dart::compiler::target::word Thread_top_resource_offset = 48; -static constexpr dart::compiler::target::word - Thread_unboxed_int64_runtime_arg_offset = 184; -static constexpr dart::compiler::target::word Thread_vm_tag_offset = 168; -static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset = - 96; -static constexpr dart::compiler::target::word Thread_callback_code_offset = 952; -static constexpr dart::compiler::target::word TimelineStream_enabled_offset = - 16; -static constexpr dart::compiler::target::word TwoByteString_data_offset = 16; -static constexpr dart::compiler::target::word Type_arguments_offset = 32; -static constexpr dart::compiler::target::word Type_hash_offset = 40; -static constexpr dart::compiler::target::word Type_signature_offset = 48; -static constexpr dart::compiler::target::word Type_type_class_id_offset = 24; -static constexpr dart::compiler::target::word Type_type_state_offset = 60; -static constexpr dart::compiler::target::word - TypeArguments_instantiations_offset = 8; -static constexpr dart::compiler::target::word TypeRef_type_offset = 24; -static constexpr dart::compiler::target::word TypedDataBase_data_field_offset = - 8; -static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16; -static constexpr dart::compiler::target::word TypedDataView_data_offset = 24; -static constexpr dart::compiler::target::word - TypedDataView_offset_in_bytes_offset = 32; -static constexpr dart::compiler::target::word TypedData_data_offset = 24; -static constexpr dart::compiler::target::word UserTag_tag_offset = 16; -static constexpr dart::compiler::target::word Array_elements_start_offset = 24; -static constexpr dart::compiler::target::word Array_element_size = 8; -static constexpr dart::compiler::target::word - TypeArguments_elements_start_offset = 32; -static constexpr dart::compiler::target::word TypeArguments_element_size = 8; -static constexpr dart::compiler::target::word ClassTable_elements_start_offset = - 0; -static constexpr dart::compiler::target::word ClassTable_element_size = 288; -static constexpr dart::compiler::target::word Code_entry_point_offset[] = { - 8, 24, 16, 32}; -static constexpr dart::compiler::target::word - Code_function_entry_point_offset[] = {8, 16}; -static constexpr dart::compiler::target::word Array_header_size = 24; -static constexpr dart::compiler::target::word Context_header_size = 24; -static constexpr dart::compiler::target::word Double_InstanceSize = 16; -static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24; -static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24; -static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = - 16; -static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; -static constexpr dart::compiler::target::word Mint_InstanceSize = 16; -static constexpr dart::compiler::target::word NativeArguments_StructSize = 32; -static constexpr dart::compiler::target::word String_InstanceSize = 16; -static constexpr dart::compiler::target::word TypedData_InstanceSize = 24; -static constexpr dart::compiler::target::word Object_InstanceSize = 8; -static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24; -static constexpr dart::compiler::target::word Closure_InstanceSize = 56; -static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = - 32; -static constexpr dart::compiler::target::word Instance_InstanceSize = 8; -static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56; -#endif // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT) - -#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT) -static constexpr dart::compiler::target::word ObjectPool_elements_start_offset = - 8; -static constexpr dart::compiler::target::word ObjectPool_element_size = 4; -static constexpr dart::compiler::target::word Array_kMaxElements = 268435455; -static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements = - 65533; -static constexpr dart::compiler::target::word - Instructions_kMonomorphicEntryOffsetJIT = 0; -static constexpr dart::compiler::target::word - Instructions_kPolymorphicEntryOffsetJIT = 0; -static constexpr dart::compiler::target::word - Instructions_kMonomorphicEntryOffsetAOT = 0; -static constexpr dart::compiler::target::word - Instructions_kPolymorphicEntryOffsetAOT = 0; -static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 9; -static constexpr dart::compiler::target::word - NativeEntry_kNumCallWrapperArguments = 2; -static constexpr dart::compiler::target::word String_kMaxElements = 536870911; -static constexpr dart::compiler::target::word - SubtypeTestCache_kFunctionTypeArguments = 4; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceClassIdOrFunction = 1; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstanceTypeArguments = 2; -static constexpr dart::compiler::target::word - SubtypeTestCache_kInstantiatorTypeArguments = 3; -static constexpr dart::compiler::target::word - SubtypeTestCache_kTestEntryLength = 7; -static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0; -static constexpr dart::compiler::target::word - AbstractType_type_test_stub_entry_point_offset = 4; -static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset = - 16; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_first_named_entry_offset = 24; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_named_entry_size = 8; -static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset = - 0; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_position_offset = 4; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_positional_count_offset = 20; -static constexpr dart::compiler::target::word - ArgumentsDescriptor_type_args_len_offset = 12; -static constexpr dart::compiler::target::word Array_data_offset = 12; -static constexpr dart::compiler::target::word Array_length_offset = 8; -static constexpr dart::compiler::target::word Array_tags_offset = 0; -static constexpr dart::compiler::target::word Array_type_arguments_offset = 4; -static constexpr dart::compiler::target::word Class_declaration_type_offset = - 56; -static constexpr dart::compiler::target::word Class_num_type_arguments_offset = - 106; -static constexpr dart::compiler::target::word Class_super_type_offset = 44; -static constexpr dart::compiler::target::word - Class_type_arguments_field_offset_in_words_offset = 96; -static constexpr dart::compiler::target::word - ClassHeapStats_TraceAllocationMask = 1; -static constexpr dart::compiler::target::word - ClassHeapStats_allocated_since_gc_new_space_offset = 48; -static constexpr dart::compiler::target::word - ClassHeapStats_allocated_size_since_gc_new_space_offset = 52; -static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160; -static constexpr dart::compiler::target::word - ClassTable_shared_class_table_offset = 20; -static constexpr dart::compiler::target::word ClassTable_table_offset = 8; -static constexpr dart::compiler::target::word - SharedClassTable_class_heap_stats_table_offset = 0; -static constexpr dart::compiler::target::word Closure_context_offset = 20; -static constexpr dart::compiler::target::word - Closure_delayed_type_arguments_offset = 12; -static constexpr dart::compiler::target::word Closure_function_offset = 16; -static constexpr dart::compiler::target::word - Closure_function_type_arguments_offset = 8; -static constexpr dart::compiler::target::word Closure_hash_offset = 24; -static constexpr dart::compiler::target::word - Closure_instantiator_type_arguments_offset = 4; -static constexpr dart::compiler::target::word Code_object_pool_offset = 20; -static constexpr dart::compiler::target::word Code_saved_instructions_offset = - 24; -static constexpr dart::compiler::target::word Code_owner_offset = 28; -static constexpr dart::compiler::target::word Context_num_variables_offset = 4; -static constexpr dart::compiler::target::word Context_parent_offset = 8; -static constexpr dart::compiler::target::word Double_value_offset = 8; -static constexpr dart::compiler::target::word - ExternalOneByteString_external_data_offset = 12; -static constexpr dart::compiler::target::word - ExternalTwoByteString_external_data_offset = 12; -static constexpr dart::compiler::target::word Float32x4_value_offset = 8; -static constexpr dart::compiler::target::word Float64x2_value_offset = 8; -static constexpr dart::compiler::target::word Field_guarded_cid_offset = 48; -static constexpr dart::compiler::target::word - Field_guarded_list_length_in_object_offset_offset = 56; -static constexpr dart::compiler::target::word Field_guarded_list_length_offset = - 28; -static constexpr dart::compiler::target::word Field_is_nullable_offset = 50; -static constexpr dart::compiler::target::word Field_static_value_offset = 16; -static constexpr dart::compiler::target::word Field_kind_bits_offset = 58; -static constexpr dart::compiler::target::word Function_code_offset = 44; -static constexpr dart::compiler::target::word Function_entry_point_offset = 4; -static constexpr dart::compiler::target::word - Function_unchecked_entry_point_offset = 8; -static constexpr dart::compiler::target::word Function_usage_counter_offset = - 76; -static constexpr dart::compiler::target::word GrowableObjectArray_data_offset = - 12; -static constexpr dart::compiler::target::word - GrowableObjectArray_length_offset = 8; -static constexpr dart::compiler::target::word - GrowableObjectArray_type_arguments_offset = 4; -static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20; -static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3; -static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; -static constexpr dart::compiler::target::word - ICData_arguments_descriptor_offset = 12; -static constexpr dart::compiler::target::word ICData_entries_offset = 4; -static constexpr dart::compiler::target::word ICData_owner_offset = 20; -static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; -static constexpr dart::compiler::target::word - ICData_receivers_static_type_offset = 16; -static constexpr dart::compiler::target::word Isolate_class_table_offset = 40; -static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20; -static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24; -static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28; -static constexpr dart::compiler::target::word Isolate_object_store_offset = 36; -static constexpr dart::compiler::target::word Isolate_single_step_offset = 64; -static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16; -static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16; -static constexpr dart::compiler::target::word - LinkedHashMap_deleted_keys_offset = 24; -static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset = - 12; -static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 8; -static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset = - 20; -static constexpr dart::compiler::target::word - MarkingStackBlock_pointers_offset = 8; -static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4; -static constexpr dart::compiler::target::word - MegamorphicCache_arguments_descriptor_offset = 16; -static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset = - 4; -static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8; -static constexpr dart::compiler::target::word Mint_value_offset = 8; -static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset = - 4; -static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8; -static constexpr dart::compiler::target::word NativeArguments_retval_offset = - 12; -static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0; -static constexpr dart::compiler::target::word ObjectStore_double_type_offset = - 64; -static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 32; -static constexpr dart::compiler::target::word ObjectStore_string_type_offset = - 80; -static constexpr dart::compiler::target::word OneByteString_data_offset = 12; -static constexpr dart::compiler::target::word Pointer_c_memory_address_offset = - 8; -static constexpr dart::compiler::target::word - SingleTargetCache_entry_point_offset = 8; -static constexpr dart::compiler::target::word - SingleTargetCache_lower_limit_offset = 12; -static constexpr dart::compiler::target::word SingleTargetCache_target_offset = - 4; -static constexpr dart::compiler::target::word - SingleTargetCache_upper_limit_offset = 14; -static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset = - 8; -static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4; -static constexpr dart::compiler::target::word String_hash_offset = 8; -static constexpr dart::compiler::target::word String_length_offset = 4; -static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4; -static constexpr dart::compiler::target::word - Thread_AllocateArray_entry_point_offset = 160; -static constexpr dart::compiler::target::word Thread_active_exception_offset = - 456; -static constexpr dart::compiler::target::word Thread_active_stacktrace_offset = - 460; -static constexpr dart::compiler::target::word Thread_async_stack_trace_offset = - 88; -static constexpr dart::compiler::target::word - Thread_auto_scope_native_wrapper_entry_point_offset = 120; -static constexpr dart::compiler::target::word Thread_bool_false_offset = 112; -static constexpr dart::compiler::target::word Thread_bool_true_offset = 108; -static constexpr dart::compiler::target::word Thread_dart_stream_offset = 492; -static constexpr dart::compiler::target::word Thread_double_abs_address_offset = - 140; -static constexpr dart::compiler::target::word - Thread_double_negate_address_offset = 136; -static constexpr dart::compiler::target::word Thread_end_offset = 64; -static constexpr dart::compiler::target::word Thread_execution_state_offset = - 476; -static constexpr dart::compiler::target::word - Thread_float_absolute_address_offset = 152; -static constexpr dart::compiler::target::word - Thread_float_negate_address_offset = 148; -static constexpr dart::compiler::target::word Thread_float_not_address_offset = - 144; -static constexpr dart::compiler::target::word - Thread_float_zerow_address_offset = 156; -static constexpr dart::compiler::target::word Thread_global_object_pool_offset = - 464; -static constexpr dart::compiler::target::word Thread_isolate_offset = 52; -static constexpr dart::compiler::target::word - Thread_marking_stack_block_offset = 76; -static constexpr dart::compiler::target::word - Thread_no_scope_native_wrapper_entry_point_offset = 116; -static constexpr dart::compiler::target::word Thread_object_null_offset = 104; -static constexpr dart::compiler::target::word - Thread_predefined_symbols_address_offset = 128; -static constexpr dart::compiler::target::word Thread_resume_pc_offset = 468; -static constexpr dart::compiler::target::word - Thread_saved_shadow_call_stack_offset = 472; -static constexpr dart::compiler::target::word Thread_safepoint_state_offset = - 480; -static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36; -static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset = - 40; -static constexpr dart::compiler::target::word - Thread_stack_overflow_flags_offset = 44; -static constexpr dart::compiler::target::word Thread_store_buffer_block_offset = - 72; -static constexpr dart::compiler::target::word - Thread_top_exit_frame_info_offset = 68; -static constexpr dart::compiler::target::word Thread_top_offset = 60; -static constexpr dart::compiler::target::word Thread_top_resource_offset = 24; -static constexpr dart::compiler::target::word - Thread_unboxed_int64_runtime_arg_offset = 96; -static constexpr dart::compiler::target::word Thread_vm_tag_offset = 84; -static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset = - 48; -static constexpr dart::compiler::target::word Thread_callback_code_offset = 484; -static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8; -static constexpr dart::compiler::target::word TwoByteString_data_offset = 12; -static constexpr dart::compiler::target::word Type_arguments_offset = 16; -static constexpr dart::compiler::target::word Type_hash_offset = 20; -static constexpr dart::compiler::target::word Type_signature_offset = 24; -static constexpr dart::compiler::target::word Type_type_class_id_offset = 12; -static constexpr dart::compiler::target::word Type_type_state_offset = 32; -static constexpr dart::compiler::target::word - TypeArguments_instantiations_offset = 4; -static constexpr dart::compiler::target::word TypeRef_type_offset = 12; -static constexpr dart::compiler::target::word TypedDataBase_data_field_offset = - 4; -static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8; -static constexpr dart::compiler::target::word TypedDataView_data_offset = 12; -static constexpr dart::compiler::target::word - TypedDataView_offset_in_bytes_offset = 16; -static constexpr dart::compiler::target::word TypedData_data_offset = 12; -static constexpr dart::compiler::target::word UserTag_tag_offset = 8; -static constexpr dart::compiler::target::word Array_elements_start_offset = 12; -static constexpr dart::compiler::target::word Array_element_size = 4; -static constexpr dart::compiler::target::word - TypeArguments_elements_start_offset = 16; -static constexpr dart::compiler::target::word TypeArguments_element_size = 4; -static constexpr dart::compiler::target::word ClassTable_elements_start_offset = - 0; -static constexpr dart::compiler::target::word ClassTable_element_size = 168; -static constexpr dart::compiler::target::word Code_entry_point_offset[] = { - 4, 12, 8, 16}; -static constexpr dart::compiler::target::word - Code_function_entry_point_offset[] = {4, 8}; -static constexpr dart::compiler::target::word Array_header_size = 12; -static constexpr dart::compiler::target::word Context_header_size = 12; -static constexpr dart::compiler::target::word Double_InstanceSize = 16; -static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24; -static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24; -static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize = - 12; -static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24; -static constexpr dart::compiler::target::word Mint_InstanceSize = 16; -static constexpr dart::compiler::target::word NativeArguments_StructSize = 16; -static constexpr dart::compiler::target::word String_InstanceSize = 12; -static constexpr dart::compiler::target::word TypedData_InstanceSize = 12; -static constexpr dart::compiler::target::word Object_InstanceSize = 4; -static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12; -static constexpr dart::compiler::target::word Closure_InstanceSize = 28; -static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize = - 16; -static constexpr dart::compiler::target::word Instance_InstanceSize = 4; -static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28; -#endif // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT) - #endif // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_ diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h index 4d67d2e896c..dc49487a091 100644 --- a/runtime/vm/compiler/runtime_offsets_list.h +++ b/runtime/vm/compiler/runtime_offsets_list.h @@ -149,76 +149,73 @@ FIELD(Thread, AllocateArray_entry_point_offset) \ FIELD(Thread, active_exception_offset) \ FIELD(Thread, active_stacktrace_offset) \ - NOT_IN_DBC(FIELD(Thread, array_write_barrier_code_offset)) \ - NOT_IN_DBC(FIELD(Thread, array_write_barrier_entry_point_offset)) \ + FIELD(Thread, array_write_barrier_code_offset) \ + FIELD(Thread, array_write_barrier_entry_point_offset) \ FIELD(Thread, async_stack_trace_offset) \ FIELD(Thread, auto_scope_native_wrapper_entry_point_offset) \ FIELD(Thread, bool_false_offset) \ FIELD(Thread, bool_true_offset) \ - NOT_IN_DBC(FIELD(Thread, call_to_runtime_entry_point_offset)) \ - NOT_IN_DBC(FIELD(Thread, call_to_runtime_stub_offset)) \ + FIELD(Thread, call_to_runtime_entry_point_offset) \ + FIELD(Thread, call_to_runtime_stub_offset) \ FIELD(Thread, dart_stream_offset) \ - NOT_IN_DBC(FIELD(Thread, optimize_entry_offset)) \ - NOT_IN_DBC(FIELD(Thread, optimize_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, deoptimize_entry_offset)) \ - NOT_IN_DBC(FIELD(Thread, deoptimize_stub_offset)) \ + FIELD(Thread, optimize_entry_offset) \ + FIELD(Thread, optimize_stub_offset) \ + FIELD(Thread, deoptimize_entry_offset) \ + FIELD(Thread, deoptimize_stub_offset) \ FIELD(Thread, double_abs_address_offset) \ FIELD(Thread, double_negate_address_offset) \ FIELD(Thread, end_offset) \ - NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset)) \ + FIELD(Thread, enter_safepoint_stub_offset) \ FIELD(Thread, execution_state_offset) \ - NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, call_native_through_safepoint_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, call_native_through_safepoint_entry_point_offset)) \ - NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset)) \ - NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset)) \ + FIELD(Thread, exit_safepoint_stub_offset) \ + FIELD(Thread, call_native_through_safepoint_stub_offset) \ + FIELD(Thread, call_native_through_safepoint_entry_point_offset) \ + FIELD(Thread, fix_allocation_stub_code_offset) \ + FIELD(Thread, fix_callers_target_code_offset) \ FIELD(Thread, float_absolute_address_offset) \ FIELD(Thread, float_negate_address_offset) \ FIELD(Thread, float_not_address_offset) \ FIELD(Thread, float_zerow_address_offset) \ FIELD(Thread, global_object_pool_offset) \ - NOT_IN_DBC(FIELD(Thread, interpret_call_entry_point_offset)) \ - NOT_IN_DBC(FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, invoke_dart_code_stub_offset)) \ + FIELD(Thread, interpret_call_entry_point_offset) \ + FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset) \ + FIELD(Thread, invoke_dart_code_stub_offset) \ FIELD(Thread, isolate_offset) \ - NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_return_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_throw_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, lazy_specialize_type_test_stub_offset)) \ + FIELD(Thread, lazy_deopt_from_return_stub_offset) \ + FIELD(Thread, lazy_deopt_from_throw_stub_offset) \ + FIELD(Thread, lazy_specialize_type_test_stub_offset) \ FIELD(Thread, marking_stack_block_offset) \ - NOT_IN_DBC(FIELD(Thread, megamorphic_call_checked_entry_offset)) \ - NOT_IN_DBC(FIELD(Thread, monomorphic_miss_entry_offset)) \ - NOT_IN_DBC(FIELD(Thread, monomorphic_miss_stub_offset)) \ + FIELD(Thread, megamorphic_call_checked_entry_offset) \ + FIELD(Thread, monomorphic_miss_entry_offset) \ + FIELD(Thread, monomorphic_miss_stub_offset) \ FIELD(Thread, no_scope_native_wrapper_entry_point_offset) \ - NOT_IN_DBC( \ - FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset)) \ - NOT_IN_DBC(FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset)) \ - NOT_IN_DBC( \ - FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset)) \ - NOT_IN_DBC(FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset)) \ + FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset) \ + FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset) \ + \ + FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset) \ + FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset) \ FIELD(Thread, object_null_offset) \ FIELD(Thread, predefined_symbols_address_offset) \ FIELD(Thread, resume_pc_offset) \ FIELD(Thread, saved_shadow_call_stack_offset) \ FIELD(Thread, safepoint_state_offset) \ - NOT_IN_DBC(FIELD(Thread, slow_type_test_stub_offset)) \ + FIELD(Thread, slow_type_test_stub_offset) \ FIELD(Thread, stack_limit_offset) \ FIELD(Thread, saved_stack_limit_offset) \ FIELD(Thread, stack_overflow_flags_offset) \ - NOT_IN_DBC( \ - FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset)) \ - NOT_IN_DBC(FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset)) \ - NOT_IN_DBC(FIELD(Thread, \ - stack_overflow_shared_without_fpu_regs_entry_point_offset)) \ - NOT_IN_DBC( \ - FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset)) \ + FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset) \ + FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset) \ + FIELD(Thread, stack_overflow_shared_without_fpu_regs_entry_point_offset) \ + \ + FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset) \ FIELD(Thread, store_buffer_block_offset) \ FIELD(Thread, top_exit_frame_info_offset) \ FIELD(Thread, top_offset) \ FIELD(Thread, top_resource_offset) \ FIELD(Thread, unboxed_int64_runtime_arg_offset) \ FIELD(Thread, vm_tag_offset) \ - NOT_IN_DBC(FIELD(Thread, write_barrier_code_offset)) \ - NOT_IN_DBC(FIELD(Thread, write_barrier_entry_point_offset)) \ + FIELD(Thread, write_barrier_code_offset) \ + FIELD(Thread, write_barrier_entry_point_offset) \ FIELD(Thread, write_barrier_mask_offset) \ FIELD(Thread, callback_code_offset) \ FIELD(TimelineStream, enabled_offset) \ diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h index 126d1255294..abb5b97a9f3 100644 --- a/runtime/vm/compiler/stub_code_compiler.h +++ b/runtime/vm/compiler/stub_code_compiler.h @@ -19,7 +19,7 @@ class Assembler; class StubCodeCompiler : public AllStatic { public: -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) static void GenerateBuildMethodExtractorStub( Assembler* assembler, const Object& closure_allocation_stub, @@ -84,10 +84,8 @@ class StubCodeCompiler : public AllStatic { static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2; #endif -#if !defined(TARGET_ARCH_DBC) static void GenerateJITCallbackTrampolines(Assembler* assembler, intptr_t next_callback_id); -#endif #endif // !defined(DART_PRECOMPILED_RUNTIME) }; diff --git a/runtime/vm/compiler/stub_code_compiler_dbc.cc b/runtime/vm/compiler/stub_code_compiler_dbc.cc deleted file mode 100644 index f303ad4cefe..00000000000 --- a/runtime/vm/compiler/stub_code_compiler_dbc.cc +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#include "vm/compiler/assembler/assembler.h" -#include "vm/compiler/backend/flow_graph_compiler.h" -#include "vm/compiler/jit/compiler.h" -#include "vm/cpu.h" -#include "vm/dart_entry.h" -#include "vm/heap/heap.h" -#include "vm/instructions.h" -#include "vm/object_store.h" -#include "vm/runtime_entry.h" -#include "vm/stack_frame.h" -#include "vm/stub_code.h" -#include "vm/tags.h" - -#define __ assembler-> - -namespace dart { - -DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); -DEFINE_FLAG(bool, - use_slow_path, - false, - "Set to true for debugging & verifying the slow paths."); - -namespace compiler { - -void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) { - __ Compile(); -} - -void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub( - Assembler* assembler) { - __ NoSuchMethod(); -} - -// Not executed, but used as a stack marker when calling -// DRT_OptimizeInvokedFunction. -void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) { - __ Trap(); -} - -// Not executed, but used as a sentinel in Simulator::JumpToFrame. -void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) { - __ DeoptRewind(); -} - -// TODO(vegorov) Don't generate this stub. -void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) { - __ Trap(); -} - -// TODO(vegorov) Don't generate these stubs. -void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler, - const Class& cls) { - __ Trap(); -} - -// TODO(vegorov) Don't generate this stub. -void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) { - __ Trap(); -} - -// These deoptimization stubs are only used to populate stack frames -// with something meaningful to make sure GC can scan the stack during -// the last phase of deoptimization which materializes objects. -void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub( - Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub( - Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) { - __ Trap(); -} - -// TODO(kustermann): Don't generate this stub. -void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) { - __ Trap(); -} - -// TODO(kustermann): Don't generate this stub. -void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) { - __ Trap(); -} - -// TODO(kustermann): Don't generate this stub. -void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) { - __ Trap(); -} - -// TODO(kustermann): Don't generate this stub. -void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) { - __ Trap(); -} - -// TODO(kustermann): Don't generate this stub. -void StubCodeCompiler::GenerateLazySpecializeTypeTestStub( - Assembler* assembler) { - __ Trap(); -} - -// TODO(kustermann): Don't generate this stub. -void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub( - Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) { - __ Trap(); -} - -void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub( - Assembler* assembler) { - __ Trap(); -} - -} // namespace compiler - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h index 5e58117c9dd..f0b4045667a 100644 --- a/runtime/vm/constants.h +++ b/runtime/vm/constants.h @@ -13,8 +13,6 @@ #include "vm/constants_arm.h" #elif defined(TARGET_ARCH_ARM64) #include "vm/constants_arm64.h" -#elif defined(TARGET_ARCH_DBC) -#include "vm/constants_dbc.h" #else #error Unknown architecture. #endif @@ -41,8 +39,6 @@ using namespace arch_x64; // NOLINT using namespace arch_arm; // NOLINT #elif defined(TARGET_ARCH_ARM64) using namespace arch_arm64; // NOLINT -#elif defined(TARGET_ARCH_DBC) -// DBC is defined in namespace dart already. #else #error Unknown architecture. #endif @@ -85,8 +81,6 @@ class RegisterNames { #endif // !defined(HOST_ARCH_EQUALS_TARGET_ARCH) }; -#if !defined(TARGET_ARCH_DBC) - static constexpr bool IsArgumentRegister(Register reg) { return ((1 << reg) & CallingConventions::kArgumentRegisters) != 0; } @@ -99,8 +93,6 @@ static constexpr bool IsCalleeSavedRegister(Register reg) { return ((1 << reg) & CallingConventions::kCalleeSaveCpuRegisters) != 0; } -#endif // !defined(TARGET_ARCH_DBC) - } // namespace dart #endif // RUNTIME_VM_CONSTANTS_H_ diff --git a/runtime/vm/constants_dbc.cc b/runtime/vm/constants_dbc.cc deleted file mode 100644 index abad6e509ee..00000000000 --- a/runtime/vm/constants_dbc.cc +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// 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. - -#define RUNTIME_VM_CONSTANTS_H_ // To work around include guard. -#include "vm/constants_dbc.h" - -namespace dart { - -const char* cpu_reg_names[kNumberOfCpuRegisters] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", - "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R18", "R19", "R20", "R21", - "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31", -#if defined(ARCH_IS_64_BIT) - "R32", "R33", "R34", "R35", "R36", "R37", "R38", "R39", "R40", "R41", "R42", - "R43", "R44", "R45", "R46", "R47", "R48", "R49", "R50", "R51", "R52", "R53", - "R54", "R55", "R56", "R57", "R58", "R59", "R60", "R61", "R62", "R63", -#endif -}; - -const char* fpu_reg_names[kNumberOfFpuRegisters] = { - "F0", -}; - -} // namespace dart diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h deleted file mode 100644 index d05a74efa0c..00000000000 --- a/runtime/vm/constants_dbc.h +++ /dev/null @@ -1,1161 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_VM_CONSTANTS_DBC_H_ -#define RUNTIME_VM_CONSTANTS_DBC_H_ - -#include "platform/assert.h" -#include "platform/globals.h" -#include "platform/utils.h" - -namespace dart { - -// clang-format off -// List of Simulator Bytecode instructions. -// -// INTERPRETER STATE -// -// current frame info (see stack_frame_dbc.h for layout) -// v-----^-----v -// ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ -// ~ | ~ ~ | FP[0] | FP[1] | ~ ~ | SP[-1]| SP[0] | -// ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ -// ^ ^ -// FP SP -// -// -// The state of execution is captured in few interpreter registers: -// -// FP - base of the current frame -// SP - top of the stack (TOS) for the current frame -// PP - object pool for the currently execution function -// -// Frame info stored below FP additionally contains pointers to the currently -// executing function and code (see stack_frame_dbc.h for more information). -// -// In the unoptimized code most of bytecodes take operands implicitly from -// stack and store results again on the stack. Constant operands are usually -// taken from the object pool by index. -// -// ENCODING -// -// Each instruction is a 32-bit integer with opcode stored in the least -// significant byte. The following operand encodings are used: -// -// 0........8.......16.......24.......32 -// +--------+--------+--------+--------+ -// | opcode |~~~~~~~~~~~~~~~~~~~~~~~~~~| 0: no operands -// +--------+--------+--------+--------+ -// -// +--------+--------+--------+--------+ -// | opcode | A |~~~~~~~~~~~~~~~~~| A: single unsigned 8-bit operand -// +--------+--------+--------+--------+ -// -// +--------+--------+--------+--------+ -// | opcode | A | D | A_D: unsigned 8-bit operand and -// +--------+--------+--------+--------+ unsigned 16-bit operand -// -// +--------+--------+--------+--------+ -// | opcode | A | X | A_X: unsigned 8-bit operand and -// +--------+--------+--------+--------+ signed 16-bit operand -// -// +--------+--------+--------+--------+ -// | opcode |~~~~~~~~| D | D: unsigned 16-bit operand -// +--------+--------+--------+--------+ -// -// +--------+--------+--------+--------+ -// | opcode |~~~~~~~~| X | X: signed 16-bit operand -// +--------+--------+--------+--------+ -// -// +--------+--------+--------+--------+ -// | opcode | A | B | C | A_B_C: 3 unsigned 8-bit operands -// +--------+--------+--------+--------+ -// -// +--------+--------+--------+--------+ -// | opcode | A | B | Y | A_B_Y: 2 unsigned 8-bit operands -// +--------+--------+--------+--------+ 1 signed 8-bit operand -// -// +--------+--------+--------+--------+ -// | opcode | T | T: signed 24-bit operand -// +--------+--------+--------+--------+ -// -// -// INSTRUCTIONS -// -// - Trap -// -// Unreachable instruction. -// -// - Nop D -// -// This instruction does nothing. It may refer to an object in the constant -// pool that may be decoded by other instructions. -// -// - Compile -// -// Compile current function and start executing newly produced code -// (used to implement LazyCompileStub); -// -// - Intrinsic id -// -// Execute intrinsic with the given id. If intrinsic returns true then -// return from the current function to the caller passing value produced -// by the intrinsic as a result; -// -// - Drop1; DropR n; Drop n -// -// Drop 1 or n values from the stack, if instruction is DropR push the first -// dropped value to the stack; -// -// - Jump target -// -// Jump to the given target. Target is specified as offset from the PC of the -// jump instruction. -// -// - Return R; ReturnTOS -// -// Return to the caller using either a value from the given register or a -// value from the top-of-stack as a result. -// -// Note: return instruction knows how many arguments to remove from the -// stack because it can look at the call instruction at caller's PC and -// take argument count from it. -// -// - Move rA, rX -// -// FP[rA] <- FP[rX] -// Note: rX is signed so it can be used to address parameters which are -// at negative indices with respect to FP. -// -// - Swap rA, rX -// -// FP[rA], FP[rX] <- FP[rX], FP[rA] -// Note: rX is signed so it can be used to address parameters which are -// at negative indices with respect to FP. -// -// - Push rX -// -// Push FP[rX] to the stack. -// -// - LoadConstant rA, D; PushConstant D -// -// Load value at index D from constant pool into FP[rA] or push it onto the -// stack. -// -// - StoreLocal rX; PopLocal rX -// -// Store top of the stack into FP[rX] and pop it if needed. -// -// - StaticCall ArgC, D -// -// Invoke function in SP[0] with arguments SP[-(1+ArgC)], ..., SP[-1] and -// argument descriptor PP[D], which indicates whether the first argument -// is a type argument vector. -// -// - IndirectStaticCall ArgC, D -// -// Invoke the function given by the ICData in SP[0] with arguments -// SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which -// indicates whether the first argument is a type argument vector. -// -// - InstanceCall ArgC, D; InstanceCallOpt ArgC, D -// -// Lookup and invoke method with N checked arguments using ICData in PP[D] -// with arguments SP[-(1+ArgC)], ..., SP[-1]. -// The ICData indicates whether the first argument is a type argument vector. -// -// - NativeCall ArgA, ArgB, ArgC -// -// Invoke native function at pool[ArgB] with argc_tag at pool[ArgC] using -// wrapper at pool[ArgA]. -// -// - FfiCall ArgD -// -// Invoke foreign function with unboxed arguments using the signature -// descriptor PP[D]. -// -// - PushPolymorphicInstanceCall ArgC, D -// -// Skips 2*D + 1 instructions and pushes a function object onto the stack -// if one can be found as follows. Otherwise skips only 2*D instructions. -// The function is looked up in the IC data encoded in the following 2*D -// Nop instructions. The Nop instructions should be arranged in pairs with -// the first being the cid, and the second being the function to push if -// the cid matches the cid in the pair. -// -// - PushPolymorphicInstanceCallByRange ArgC, D -// -// Skips 3*D + 1 instructions and pushes a function object onto the stack -// if one can be found as follows. Otherwise skips only 3*D instructions. -// The function is looked up in the IC data encoded in the following 3*D -// Nop instructions. The Nop instructions should be arranged in triples with -// the first being the start cid, the second being the number of cids, and -// the third being the function to push if the cid is in the range given -// by the first two Nop instructions. -// -// - OneByteStringFromCharCode rA, rX -// -// Load the one-character symbol with the char code given by the Smi -// in FP[rX] into FP[rA]. -// -// - StringToCharCode rA, rX -// -// Load and smi-encode the single char code of the string in FP[rX] into -// FP[rA]. If the string's length is not 1, load smi -1 instead. -// -// - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS; -// GreaterThanTOS; -// -// Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are -// both smis and result of SP[0] SP[-1] is a smi - if this is true -// then pops operands and pushes result on the stack and skips the next -// instruction (which implements a slow path fallback). -// -// - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC -// -// Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC]. -// If these instructions can trigger a deoptimization, the following -// instruction should be Deopt. If no deoptimization should be triggered, -// the immediately following instruction is skipped. These instructions -// expect their operands to be Smis, but don't check that they are. -// -// - SmiTOS -// -// Performs SP[0] SP[-1], pops operands and pushes result on the stack. -// Assumes SP[0] and SP[-1] are both smis and the result is a Smi. -// -// - ShlImm rA, rB, rC -// -// FP[rA] <- FP[rB] << rC. Shifts the Smi in FP[rB] left by rC. rC is -// assumed to be a legal positive number by which left-shifting is possible. -// -// - Min, Max rA, rB, rC -// -// FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are -// Smis. -// -// - Neg rA , rD -// -// FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the -// immediately following instruction is skipped. -// -// - DMin, DMax, DAdd, DSub, DMul, DDiv, DPow, DMod rA, rB, rC -// -// Arithmetic operations on unboxed doubles. FP[rA] <- FP[rB] op FP[rC]. -// -// - DNeg, DCos, DSin, DSqrt rA, rD -// -// FP[rA] <- op(FP[rD]). Assumes FP[rD] is an unboxed double. -// -// - DTruncate, DFloor, DCeil rA, rD -// -// Applies trunc(), floor(), or ceil() to the unboxed double in FP[rD], and -// stores the result in FP[rA]. -// -// - DoubleToFloat, FloatToDouble rA, rD -// -// Convert the unboxed float or double in FP[rD] as indicated, and store the -// result in FP[rA]. -// -// - DoubleIsNaN rA, rD -// -// If the unboxed double in FP[rD] is a NaN, then writes Bool::True().raw() -// into FP[rA], and Bool::False().raw() otherwise. -// -// - DoubleIsInfinite rA, rD -// -// If the unboxed double in FP[rD] is + or - infinity, then -// writes Bool::True().raw() into FP[rA], and Bool::False().raw() otherwise. -// -// - BitOr, BitAnd, BitXor rA, rB, rC -// -// FP[rA] <- FP[rB] op FP[rC]. These instructions expect their operands to be -// Smis, but don't check that they are. -// -// - BitNot rA, rD -// -// FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi. -// -// - WriteIntoDouble rA, rD -// -// Box the double in FP[rD] using the box in FP[rA]. -// -// - UnboxDouble rA, rD -// -// Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double. -// -// - CheckedUnboxDouble rA, rD -// -// Unboxes FP[rD] into FP[rA] and skips the following instruction unless -// FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a -// double. -// -// - UnboxInt32 rA, rB, C -// -// Unboxes the integer in FP[rB] into FP[rA]. If C == 1, the value may be -// truncated. If FP[rA] is successfully unboxed the following instruction is -// skipped. -// -// - BoxInt32 rA, rD -// -// Boxes the unboxed signed 32-bit integer in FP[rD] into FP[rA]. -// -// - BoxUint32 rA, rD -// -// Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA]. -// -// - UnboxInt64 rA, rD -// -// Unboxes the integer in FP[rD] into FP[rA]. -// -// - BoxInt64 rA, rD -// -// Boxes the unboxed signed 64-bit integer in FP[rD] into FP[rA]. If the -// value does not fit into a Smi the following instruction is skipped. (The -// following instruction should be a jump to a label after the slow path -// allocating a Mint box and writing into the Mint box.) -// -// - UnboxedWidthExtender rA rB C -// -// Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed -// integer in FP[rA]. C contains SmallRepresentation which determines how -// the integer is extended. -// -// - WriteIntoMint rA, rD -// -// Box the integer in FP[rD] using the Mint box in FP[rA]. -// -// - SmiToDouble rA, rD -// -// Convert the Smi in FP[rD] to an unboxed double in FP[rA]. -// -// - DoubleToSmi rA, rD -// -// If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then -// this instruction does so, and skips the following instruction. Otherwise, -// the following instruction is not skipped. -// -// - StoreStaticTOS D -// -// Stores TOS into the static field PP[D]. -// -// - PushStatic -// -// Pushes value of the static field PP[D] on to the stack. -// -// - InitStaticTOS -// -// Takes static field from TOS and ensures that it is initialized. -// -// - If(Num)TOS -// If(Num) rA, rD -// -// Cond is either NeStrict or EqStrict -// -// Skips the next instruction unless the given condition holds. 'Num' -// variants perform number check while non-Num variants just compare -// RawObject pointers. -// -// Used to implement conditional jump: -// -// IfNeStrictTOS -// Jump T ;; jump if not equal -// -// - IfNull rA -// IfNullTOS -// -// Cond is Eq or Ne. Skips the next instruction unless the given condition -// holds. -// -// - If rA, rD -// -// Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and -// unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt. -// Skips the next instruction unless FP[rA] FP[rD]. Assumes that -// FP[rA] and FP[rD] are Smis or unboxed doubles as indicated by . -// -// - IfSmiTOS -// -// Cond is Lt, Le, Ge, Gt. -// Skips the next instruction unless SP[-1] SP[-0]. -// It is expected both SP[-1] and SP[-0] are Smis. -// -// - CreateArrayTOS -// -// Allocate array of length SP[0] with type arguments SP[-1]. -// -// - CreateArrayOpt rA, rB, rC -// -// Try to allocate a new array where FP[rB] is the length, and FP[rC] is the -// type. If allocation is successful, the result is stored in FP[rA], and -// the next four instructions, which should be the -// (Push type; Push length; AllocateTOS; PopLocal) slow path are skipped. -// -// - Allocate D -// -// Allocate object of class PP[D] with no type arguments. -// -// - AllocateOpt rA, D -// -// Try allocating an object with tags in PP[D] with no type arguments. -// If allocation is successful, the result is stored in FP[rA], and -// the next two instructions, which should be the (Allocate class; PopLocal) -// slow path are skipped -// -// - AllocateT -// -// Allocate object of class SP[0] with type arguments SP[-1]. -// -// - AllocateTOpt rA, D -// -// Similar to AllocateOpt with the difference that the offset of the -// type arguments in the resulting object is taken from the D field of the -// following Nop instruction, and on success 4 instructions are skipped and -// the object at the top of the stack is popped. -// -// - StoreIndexedTOS -// -// Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done. -// SP[-2] is assumed to be a RawArray, SP[-1] to be a smi. -// -// - StoreIndexed rA, rB, rC -// -// Store FP[rC] into array FP[rA] at index FP[rB]. No typechecking is done. -// FP[rA] is assumed to be a RawArray, FP[rB] to be a smi. -// -// - StoreIndexed{N}{Type} rA, rB, rC -// -// Where Type is Float32, Float64, Uint8, or OneByteString -// Where N is '', '4', or '8'. N may only be '4' for Float32 and '8' for -// Float64. -// -// Store the unboxed double or tagged Smi in FP[rC] into the typed data array -// at FP[rA] at index FP[rB]. If N is not '', the index is assumed to be -// already scaled by N. -// -// - StoreIndexedExternalUint8 rA, rB, rC -// -// Similar to StoreIndexedUint8 but FP[rA] is an external typed data aray. -// -// - NoSuchMethod -// -// Performs noSuchmethod handling code. -// -// - TailCall -// -// Unwinds the current frame, populates the arguments descriptor register -// with SP[-1] and tail calls the code in SP[-0]. -// -// - TailCallOpt rA, rD -// -// Unwinds the current frame, populates the arguments descriptor register -// with rA and tail calls the code in rD. -// -// - LoadArgDescriptor -// -// Load the caller-provoided argument descriptor and pushes it onto the -// stack. -// -// - LoadArgDescriptorOpt rA -// -// Load the caller-provoided argument descriptor into [rA]. -// -// - LoadFpRelativeSlot rD -// -// Loads from FP using the negative index of SP[-0]+rD. -// It is assumed that SP[-0] is a Smi. -// -// - LoadFpRelativeSlotOpt rA, rB, rY -// -// Loads from FP using the negative index of FP[rB]+rY and stores the result -// into rA. -// It is assumed that rY is a Smi. -// -// - StoreFpRelativeSlot rD -// -// Stores SP[-0] by indexing into FP using the negative index of SP[-1]+rD. -// It is assumed that SP[-1] is a Smi. -// -// - StoreFpRelativeSlotOpt rA, rB, rY -// -// Stores rA by indexing into FP using the the negative index of FP[rB]+rY. -// It is assumed that rY is a Smi. -// -// - LoadIndexedTOS -// -// Loads from array SP[-1] at index SP[-0]. -// It is assumed that SP[-0] is a Smi. -// -// - LoadIndexed rA, rB, rC -// -// Loads from array FP[rB] at index FP[rC] into FP[rA]. No typechecking is -// done. FP[rB] is assumed to be a RawArray, and to contain a Smi at FP[rC]. -// -// - LoadIndexed{N}{Type} rA, rB, rC -// -// Where Type is Float32, Float64, OneByteString, TwoByteString, Uint8, -// Int8, and N is '', '4', or '8'. N may only be '4' for Float32, and may -// only be '8' for Float64. -// -// Loads from typed data array FP[rB] at index FP[rC] into an unboxed double, -// or tagged Smi in FP[rA] as indicated by the type in the name. If N is not -// '', the index is assumed to be already scaled by N. -// -// - LoadIndexedExternal{Int8, Uint8} rA, rB, rC -// -// Loads from the external typed data array FP[rB] at index FP[rC] into -// FP[rA]. No typechecking is done. -// -// - StoreField rA, B, rC -// -// Store value FP[rC] into object FP[rA] at offset (in words) B. -// -// - StoreFieldExt rA, rD -// -// Store value FP[rD] into object FP[rA] at offset (in words) -// stored in the following Nop instruction. Used to access fields with -// large offsets. -// -// - StoreUntagged rA, B, rC -// -// Like StoreField, but assumes that FP[rC] is untagged. -// -// - StoreFieldTOS D -// -// Store value SP[0] into object SP[-1] at offset (in words) D. -// -// - LoadField rA, rB, C -// -// Load value at offset (in words) C from object FP[rB] into FP[rA]. -// -// - LoadFieldExt rA, rD -// -// Load value from object FP[rD] at offset (in words) stored in the -// following Nop instruction into FP[rA]. Used to access fields with -// large offsets. -// -// - LoadUntagged rA, rB, C -// -// Like LoadField, but assumes that FP[rB] is untagged. -// -// - LoadFieldTOS D -// -// Push value at offset (in words) D from object SP[0]. -// -// - BooleanNegateTOS -// -// SP[0] = !SP[0] -// -// - BooleanNegate rA, rD -// -// FP[rA] = !FP[rD] -// -// - Throw A -// -// Throw (Rethrow if A != 0) exception. Exception object and stack object -// are taken from TOS. -// -// - Entry rD -// -// Function prologue for the function -// rD - number of local slots to reserve; -// -// - EntryOptimized rD -// -// Function prologue for optimized functions. -// rD - number of local slots to reserve for registers; -// -// Note: reserved slots are not initialized because optimized code -// has stack maps attached to call sites. -// -// - HotCheck A, D -// -// Increment current function's usage counter by A and check if it -// exceeds D. If it does trigger (re)optimization of the current -// function. -// -// - Frame D -// -// Reserve and initialize with null space for D local variables. -// -// - SetFrame A -// -// Reinitialize SP assuming that current frame has size A. -// Used to drop temporaries from the stack in the exception handler. -// -// - AllocateContext D -// -// Allocate Context object assuming for D context variables. -// -// - AllocateUninitializedContext rA, D -// -// Allocates an uninitialized context for D variables, and places the result -// in FP[rA]. On success, skips the next 2 instructions, which should be the -// slow path (AllocateContext D; PopLocal rA). -// -// - CloneContext -// -// Clone context stored in TOS. -// -// - MoveSpecial rA, D -// -// Copy special values from inside interpreter to FP[rA]. Currently only -// used to pass exception object (D = 0) and stack trace object (D = 1) to -// catch handler. -// -// - InstantiateType D -// -// Instantiate type PP[D] with instantiator type arguments SP[-1] and -// function type arguments SP[0]. -// -// - InstantiateTypeArgumentsTOS D -// -// Instantiate type arguments PP[D] with instantiator type arguments SP[-1] -// and function type arguments SP[0]. -// -// - InstanceOf -// -// Test if instance SP[-4] with instantiator type arguments SP[-3] and -// function type arguments SP[-2] is a subtype of type SP[-1] using -// SubtypeTestCache SP[0], with result placed at top of stack. -// -// - AssertAssignable A, D -// -// Assert that instance SP[-4] is assignable to variable named SP[0] of -// type SP[-1] with instantiator type arguments SP[-3] and function type -// arguments SP[-2] using SubtypeTestCache PP[D]. -// If A is 1, then the instance may be a Smi. -// -// Instance remains on stack. Other arguments are consumed. -// -// - AssertSubtype -// -// Assert that one type is a subtype of another. Throws a TypeError -// otherwise. The stack has the following arguments on it: -// -// SP[-4] instantiator type args -// SP[-3] function type args -// SP[-2] sub_type -// SP[-1] super_type -// SP[-0] dst_name -// -// All 5 arguments are consumed from the stack and no results is pushed. -// -// - BadTypeError -// -// If SP[-4] is non-null, throws a BadType error by calling into the runtime. -// Assumes that the stack is arranged the same as for AssertAssignable. -// -// - AssertBoolean A -// -// Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0). -// -// - TestSmi rA, rD -// -// If FP[rA] & FP[rD] != 0, then skip the next instruction. FP[rA] and FP[rD] -// must be Smis. -// -// - TestCids rA, D -// -// The next D instructions must be Nops whose D field encodes a class id. If -// the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's -// A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found, -// jump to PC + N. -// -// - CheckSmi rA -// -// If FP[rA] is a Smi, then skip the next instruction. -// -// - CheckEitherNonSmi rA, rD -// -// If either FP[rA] or FP[rD] is not a Smi, then skip the next instruction. -// -// - CheckClassId rA, D -// -// If the class id in FP[rA] matches the class id D, then skip the -// following instruction. -// -// - CheckClassIdRange rA, D -// -// Next instruction is a Nop with S, the size of the class-id range. -// If the class id in FP[rA] is between the D D + S, then skip the -// following instruction. -// -// - CheckBitTest rA, D -// -// Skips the next 3 instructions if the object at FP[rA] is a valid class for -// a dense switch with low cid encoded in the following Nop instruction, and -// the cid mask encoded in the Nop instruction after that, or if D == 1 and -// FP[rA] is a Smi. Skips 2 instructions otherwise. -// -// - CheckCids rA, rB, rC -// -// Skips rC + 1 instructions if the object at FP[rA] is a Smi and -// rB == 1, or if FP[rA]'s cid is found in the array of cids encoded by the -// following rC Nop instructions. Otherwise skips only rC instructions. -// -// - CheckCidsByRange rA, rB, rC -// -// Skips rC + 1 instructions if the object at FP[rA] is a Smi and rB == -// 1, or if FP[rA]'s cid is found in the array of cid ranges encoded by the -// following rC Nop instructions. The cid ranges from a inclusive to b -// exclusive are coded in pairs of (a, b - a). Otherwise skips only 2 -// instructions. -// -// - CheckStack -// -// Compare SP against isolate stack limit and call StackOverflow handler if -// necessary. -// -// - CheckStackAlwaysExit -// -// Unconditionally call StackOverflow handler. -// -// - CheckFunctionTypeArgs A, D -// -// Check for a passed-in type argument vector of length A and -// store it at FP[D]. -// -// - DebugStep, DebugBreak A -// -// Debugger support. DebugBreak is bytecode that can be patched into the -// instruction stream to trigger in place breakpoint. -// -// When patching instance or static call with DebugBreak we set A to -// match patched call's argument count so that Return instructions continue -// to work. -// -// TODO(vegorov) the way we replace calls with DebugBreak does not work -// with our smi fast paths because DebugBreak is simply skipped. -// -// - LoadClassIdTOS, LoadClassId rA, D -// -// LoadClassIdTOS loads the class id from the object at SP[0] and stores it -// to SP[0]. LoadClassId loads the class id from FP[rA] and stores it to -// FP[D]. -// -// - Deopt ArgC, D -// -// If D != 0 then trigger eager deoptimization with deopt id (D - 1). -// If D == 0 then trigger lazy deoptimization. -// -// The meaning of operand ArgC (encoded as A operand) matches that of an -// ArgC operand in call instructions. This is needed because we could -// potentially patch calls instructions with a lazy deopt and we need to -// ensure that any Return/ReturnTOS instructions -// returning from the patched calls will continue to function, -// e.g. in bytecode sequences like -// -// InstanceCall ... <- lazy deopt inside first call -// InstanceCall ... <- patches second call with Deopt -// -// - NullError -// -// Throws a NullError. -// -// BYTECODE LIST FORMAT -// -// Bytecode list below is specified using the following format: -// -// V(BytecodeName, OperandForm, Op1, Op2, Op3) -// -// - OperandForm specifies operand encoding and should be one of 0, A, T, A_D, -// A_X, X, D (see ENCODING section above). -// -// - Op1, Op2, Op2 specify operand meaning. Possible values: -// -// ___ ignored / non-existent operand -// num immediate operand -// lit constant literal from object pool -// reg register (unsigned FP relative local) -// xeg x-register (signed FP relative local) -// tgt jump target relative to the PC of the current instruction -// -// TODO(vegorov) jump targets should be encoded relative to PC of the next -// instruction because PC is incremented immediately after fetch -// and before decoding. -// -#define BYTECODES_LIST(V) \ - V(Trap, 0, ___, ___, ___) \ - V(Nop, A_D, num, lit, ___) \ - V(Compile, 0, ___, ___, ___) \ - V(HotCheck, A_D, num, num, ___) \ - V(Intrinsic, A, num, ___, ___) \ - V(Drop1, 0, ___, ___, ___) \ - V(DropR, A, num, ___, ___) \ - V(Drop, A, num, ___, ___) \ - V(Jump, T, tgt, ___, ___) \ - V(Return, A, reg, ___, ___) \ - V(ReturnTOS, 0, ___, ___, ___) \ - V(Move, A_X, reg, xeg, ___) \ - V(Swap, A_X, reg, xeg, ___) \ - V(Push, X, xeg, ___, ___) \ - V(LoadConstant, A_D, reg, lit, ___) \ - V(LoadClassId, A_D, reg, reg, ___) \ - V(LoadClassIdTOS, 0, ___, ___, ___) \ - V(PushConstant, D, lit, ___, ___) \ - V(StoreLocal, X, xeg, ___, ___) \ - V(PopLocal, X, xeg, ___, ___) \ - V(IndirectStaticCall, A_D, num, num, ___) \ - V(StaticCall, A_D, num, num, ___) \ - V(InstanceCall1, A_D, num, num, ___) \ - V(InstanceCall2, A_D, num, num, ___) \ - V(InstanceCall1Opt, A_D, num, num, ___) \ - V(InstanceCall2Opt, A_D, num, num, ___) \ - V(PushPolymorphicInstanceCall, A_D, num, num, ___) \ - V(PushPolymorphicInstanceCallByRange, A_D, num, num, ___) \ - V(NativeCall, A_B_C, num, num, num) \ - V(FfiCall, D, lit, ___, ___) \ - V(OneByteStringFromCharCode, A_X, reg, xeg, ___) \ - V(StringToCharCode, A_X, reg, xeg, ___) \ - V(AddTOS, 0, ___, ___, ___) \ - V(SubTOS, 0, ___, ___, ___) \ - V(MulTOS, 0, ___, ___, ___) \ - V(BitOrTOS, 0, ___, ___, ___) \ - V(BitAndTOS, 0, ___, ___, ___) \ - V(EqualTOS, 0, ___, ___, ___) \ - V(LessThanTOS, 0, ___, ___, ___) \ - V(GreaterThanTOS, 0, ___, ___, ___) \ - V(SmiAddTOS, 0, ___, ___, ___) \ - V(SmiSubTOS, 0, ___, ___, ___) \ - V(SmiMulTOS, 0, ___, ___, ___) \ - V(SmiBitAndTOS, 0, ___, ___, ___) \ - V(Add, A_B_C, reg, reg, reg) \ - V(Sub, A_B_C, reg, reg, reg) \ - V(Mul, A_B_C, reg, reg, reg) \ - V(Div, A_B_C, reg, reg, reg) \ - V(Mod, A_B_C, reg, reg, reg) \ - V(Shl, A_B_C, reg, reg, reg) \ - V(Shr, A_B_C, reg, reg, reg) \ - V(ShlImm, A_B_C, reg, reg, num) \ - V(Neg, A_D, reg, reg, ___) \ - V(BitOr, A_B_C, reg, reg, reg) \ - V(BitAnd, A_B_C, reg, reg, reg) \ - V(BitXor, A_B_C, reg, reg, reg) \ - V(BitNot, A_D, reg, reg, ___) \ - V(Min, A_B_C, reg, reg, reg) \ - V(Max, A_B_C, reg, reg, reg) \ - V(WriteIntoDouble, A_D, reg, reg, ___) \ - V(WriteIntoMint, A_D, reg, reg, ___) \ - V(UnboxDouble, A_D, reg, reg, ___) \ - V(CheckedUnboxDouble, A_D, reg, reg, ___) \ - V(UnboxInt32, A_B_C, reg, reg, num) \ - V(BoxInt32, A_D, reg, reg, ___) \ - V(BoxUint32, A_D, reg, reg, ___) \ - V(UnboxInt64, A_D, reg, reg, ___) \ - V(BoxInt64, A_D, reg, reg, ___) \ - V(UnboxedWidthExtender, A_B_C, reg, reg, num) \ - V(SmiToDouble, A_D, reg, reg, ___) \ - V(DoubleToSmi, A_D, reg, reg, ___) \ - V(DAdd, A_B_C, reg, reg, reg) \ - V(DSub, A_B_C, reg, reg, reg) \ - V(DMul, A_B_C, reg, reg, reg) \ - V(DDiv, A_B_C, reg, reg, reg) \ - V(DNeg, A_D, reg, reg, ___) \ - V(DSqrt, A_D, reg, reg, ___) \ - V(DMin, A_B_C, reg, reg, reg) \ - V(DMax, A_B_C, reg, reg, reg) \ - V(DCos, A_D, reg, reg, ___) \ - V(DSin, A_D, reg, reg, ___) \ - V(DPow, A_B_C, reg, reg, reg) \ - V(DMod, A_B_C, reg, reg, reg) \ - V(DTruncate, A_D, reg, reg, ___) \ - V(DFloor, A_D, reg, reg, ___) \ - V(DCeil, A_D, reg, reg, ___) \ - V(DoubleToFloat, A_D, reg, reg, ___) \ - V(FloatToDouble, A_D, reg, reg, ___) \ - V(DoubleIsNaN, A, reg, ___, ___) \ - V(DoubleIsInfinite, A, reg, ___, ___) \ - V(StoreStaticTOS, D, lit, ___, ___) \ - V(PushStatic, D, lit, ___, ___) \ - V(InitStaticTOS, 0, ___, ___, ___) \ - V(IfNeStrictTOS, 0, ___, ___, ___) \ - V(IfEqStrictTOS, 0, ___, ___, ___) \ - V(IfNeStrictNumTOS, 0, ___, ___, ___) \ - V(IfEqStrictNumTOS, 0, ___, ___, ___) \ - V(IfSmiLtTOS, 0, ___, ___, ___) \ - V(IfSmiLeTOS, 0, ___, ___, ___) \ - V(IfSmiGeTOS, 0, ___, ___, ___) \ - V(IfSmiGtTOS, 0, ___, ___, ___) \ - V(IfNeStrict, A_D, reg, reg, ___) \ - V(IfEqStrict, A_D, reg, reg, ___) \ - V(IfLe, A_D, reg, reg, ___) \ - V(IfLt, A_D, reg, reg, ___) \ - V(IfGe, A_D, reg, reg, ___) \ - V(IfGt, A_D, reg, reg, ___) \ - V(IfULe, A_D, reg, reg, ___) \ - V(IfULt, A_D, reg, reg, ___) \ - V(IfUGe, A_D, reg, reg, ___) \ - V(IfUGt, A_D, reg, reg, ___) \ - V(IfDNe, A_D, reg, reg, ___) \ - V(IfDEq, A_D, reg, reg, ___) \ - V(IfDLe, A_D, reg, reg, ___) \ - V(IfDLt, A_D, reg, reg, ___) \ - V(IfDGe, A_D, reg, reg, ___) \ - V(IfDGt, A_D, reg, reg, ___) \ - V(IfNeStrictNum, A_D, reg, reg, ___) \ - V(IfEqStrictNum, A_D, reg, reg, ___) \ - V(IfEqNull, A, reg, ___, ___) \ - V(IfNeNull, A, reg, ___, ___) \ - V(IfEqNullTOS, 0, ___, ___, ___) \ - V(IfNeNullTOS, 0, ___, ___, ___) \ - V(CreateArrayTOS, 0, ___, ___, ___) \ - V(CreateArrayOpt, A_B_C, reg, reg, reg) \ - V(Allocate, D, lit, ___, ___) \ - V(AllocateT, 0, ___, ___, ___) \ - V(AllocateOpt, A_D, reg, lit, ___) \ - V(AllocateTOpt, A_D, reg, lit, ___) \ - V(StoreIndexedTOS, 0, ___, ___, ___) \ - V(StoreIndexed, A_B_C, reg, reg, reg) \ - V(StoreIndexedOneByteString, A_B_C, reg, reg, reg) \ - V(StoreIndexedUint8, A_B_C, reg, reg, reg) \ - V(StoreIndexedUint32, A_B_C, reg, reg, reg) \ - V(StoreIndexedFloat32, A_B_C, reg, reg, reg) \ - V(StoreIndexed4Float32, A_B_C, reg, reg, reg) \ - V(StoreIndexedFloat64, A_B_C, reg, reg, reg) \ - V(StoreIndexed8Float64, A_B_C, reg, reg, reg) \ - V(StoreIndexedUntaggedUint8, A_B_C, reg, reg, reg) \ - V(StoreIndexedUntaggedUint32, A_B_C, reg, reg, reg) \ - V(StoreIndexedUntaggedFloat32, A_B_C, reg, reg, reg) \ - V(StoreIndexedUntaggedFloat64, A_B_C, reg, reg, reg) \ - V(NoSuchMethod, 0, ___, ___, ___) \ - V(TailCall, 0, ___, ___, ___) \ - V(TailCallOpt, A_D, reg, reg, ___) \ - V(LoadArgDescriptor, 0, ___, ___, ___) \ - V(LoadArgDescriptorOpt, A, reg, ___, ___) \ - V(LoadFpRelativeSlot, X, reg, ___, ___) \ - V(LoadFpRelativeSlotOpt, A_B_Y, reg, reg, reg) \ - V(StoreFpRelativeSlot, X, reg, ___, ___) \ - V(StoreFpRelativeSlotOpt, A_B_Y, reg, reg, reg) \ - V(LoadIndexedTOS, 0, ___, ___, ___) \ - V(LoadIndexed, A_B_C, reg, reg, reg) \ - V(LoadIndexedOneByteString, A_B_C, reg, reg, reg) \ - V(LoadIndexedTwoByteString, A_B_C, reg, reg, reg) \ - V(LoadIndexedUint8, A_B_C, reg, reg, reg) \ - V(LoadIndexedInt8, A_B_C, reg, reg, reg) \ - V(LoadIndexedInt32, A_B_C, reg, reg, reg) \ - V(LoadIndexedUint32, A_B_C, reg, reg, reg) \ - V(LoadIndexedFloat32, A_B_C, reg, reg, reg) \ - V(LoadIndexed4Float32, A_B_C, reg, reg, reg) \ - V(LoadIndexedFloat64, A_B_C, reg, reg, reg) \ - V(LoadIndexed8Float64, A_B_C, reg, reg, reg) \ - V(LoadIndexedUntaggedInt8, A_B_C, reg, reg, reg) \ - V(LoadIndexedUntaggedUint8, A_B_C, reg, reg, reg) \ - V(LoadIndexedUntaggedInt32, A_B_C, reg, reg, reg) \ - V(LoadIndexedUntaggedUint32, A_B_C, reg, reg, reg) \ - V(LoadIndexedUntaggedFloat32, A_B_C, reg, reg, reg) \ - V(LoadIndexedUntaggedFloat64, A_B_C, reg, reg, reg) \ - V(StoreField, A_B_C, reg, num, reg) \ - V(StoreFieldExt, A_D, reg, reg, ___) \ - V(StoreUntagged, A_B_C, reg, num, reg) \ - V(StoreFieldTOS, D, num, ___, ___) \ - V(LoadField, A_B_C, reg, reg, num) \ - V(LoadFieldExt, A_D, reg, reg, ___) \ - V(LoadUntagged, A_B_C, reg, reg, num) \ - V(LoadFieldTOS, D, num, ___, ___) \ - V(BooleanNegateTOS, 0, ___, ___, ___) \ - V(BooleanNegate, A_D, reg, reg, ___) \ - V(Throw, A, num, ___, ___) \ - V(Entry, D, num, ___, ___) \ - V(EntryOptimized, A_D, num, num, ___) \ - V(Frame, D, num, ___, ___) \ - V(SetFrame, A, num, ___, ___) \ - V(AllocateContext, D, num, ___, ___) \ - V(AllocateUninitializedContext, A_D, reg, num, ___) \ - V(CloneContext, 0, ___, ___, ___) \ - V(MoveSpecial, A_D, reg, num, ___) \ - V(InstantiateType, D, lit, ___, ___) \ - V(InstantiateTypeArgumentsTOS, A_D, num, lit, ___) \ - V(InstanceOf, 0, ___, ___, ___) \ - V(BadTypeError, 0, ___, ___, ___) \ - V(AssertAssignable, A_D, num, lit, ___) \ - V(AssertSubtype, 0, ___, ___, ___) \ - V(AssertBoolean, A, num, ___, ___) \ - V(TestSmi, A_D, reg, reg, ___) \ - V(TestCids, A_D, reg, num, ___) \ - V(CheckSmi, A, reg, ___, ___) \ - V(CheckEitherNonSmi, A_D, reg, reg, ___) \ - V(CheckClassId, A_D, reg, num, ___) \ - V(CheckClassIdRange, A_D, reg, num, ___) \ - V(CheckBitTest, A_D, reg, num, ___) \ - V(CheckCids, A_B_C, reg, num, num) \ - V(CheckCidsByRange, A_B_C, reg, num, num) \ - V(CheckStack, 0, ___, ___, ___) \ - V(CheckStackAlwaysExit, 0, ___, ___, ___) \ - V(CheckFunctionTypeArgs, A_D, num, num, ___) \ - V(DebugStep, 0, ___, ___, ___) \ - V(DebugBreak, A, num, ___, ___) \ - V(Deopt, A_D, num, num, ___) \ - V(DeoptRewind, 0, ___, ___, ___) \ - V(NullError, 0, ___, ___, ___) - -// clang-format on - -typedef uint32_t Instr; - -class SimulatorBytecode { - public: - enum Opcode { -#define DECLARE_BYTECODE(name, encoding, op1, op2, op3) k##name, - BYTECODES_LIST(DECLARE_BYTECODE) -#undef DECLARE_BYTECODE - }; - - static const char* NameOf(Instr instr) { - const char* names[] = { -#define NAME(name, encoding, op1, op2, op3) #name, - BYTECODES_LIST(NAME) -#undef NAME - }; - return names[DecodeOpcode(instr)]; - } - - static const intptr_t kOpShift = 0; - static const intptr_t kAShift = 8; - static const intptr_t kAMask = 0xFF; - static const intptr_t kBShift = 16; - static const intptr_t kBMask = 0xFF; - static const intptr_t kCShift = 24; - static const intptr_t kCMask = 0xFF; - static const intptr_t kDShift = 16; - static const intptr_t kDMask = 0xFFFF; - static const intptr_t kYShift = 24; - static const intptr_t kYMask = 0xFF; - - static Instr Encode(Opcode op, uintptr_t a, uintptr_t b, uintptr_t c) { - ASSERT((a & kAMask) == a); - ASSERT((b & kBMask) == b); - ASSERT((c & kCMask) == c); - return op | (a << kAShift) | (b << kBShift) | (c << kCShift); - } - - static Instr Encode(Opcode op, uintptr_t a, uintptr_t d) { - ASSERT((a & kAMask) == a); - ASSERT((d & kDMask) == d); - return op | (a << kAShift) | (d << kDShift); - } - - static Instr EncodeSigned(Opcode op, uintptr_t a, intptr_t x) { - ASSERT((a & kAMask) == a); - ASSERT((x << kDShift) >> kDShift == x); - return op | (a << kAShift) | (x << kDShift); - } - - static Instr EncodeSigned(Opcode op, intptr_t x) { - ASSERT((x << kAShift) >> kAShift == x); - return op | (x << kAShift); - } - - static Instr Encode(Opcode op) { return op; } - - DART_FORCE_INLINE static uint8_t DecodeA(Instr bc) { - return (bc >> kAShift) & kAMask; - } - - DART_FORCE_INLINE static uint8_t DecodeB(Instr bc) { - return (bc >> kBShift) & kBMask; - } - - DART_FORCE_INLINE static uint16_t DecodeD(Instr bc) { - return (bc >> kDShift) & kDMask; - } - - DART_FORCE_INLINE static Opcode DecodeOpcode(Instr bc) { - return static_cast(bc & 0xFF); - } - - DART_FORCE_INLINE static bool IsTrap(Instr instr) { - return DecodeOpcode(instr) == SimulatorBytecode::kTrap; - } - - DART_FORCE_INLINE static bool IsCallOpcode(Instr instr) { - switch (DecodeOpcode(instr)) { - case SimulatorBytecode::kStaticCall: - case SimulatorBytecode::kIndirectStaticCall: - case SimulatorBytecode::kInstanceCall1: - case SimulatorBytecode::kInstanceCall2: - case SimulatorBytecode::kInstanceCall1Opt: - case SimulatorBytecode::kInstanceCall2Opt: - case SimulatorBytecode::kDebugBreak: - return true; - - default: - return false; - } - } - - DART_FORCE_INLINE static bool IsFastSmiOpcode(Instr instr) { - switch (DecodeOpcode(instr)) { - case SimulatorBytecode::kAddTOS: - case SimulatorBytecode::kSubTOS: - case SimulatorBytecode::kMulTOS: - case SimulatorBytecode::kBitOrTOS: - case SimulatorBytecode::kBitAndTOS: - case SimulatorBytecode::kEqualTOS: - case SimulatorBytecode::kLessThanTOS: - case SimulatorBytecode::kGreaterThanTOS: - return true; - - default: - return false; - } - } - - DART_FORCE_INLINE static uint8_t DecodeArgc(Instr call) { - ASSERT(IsCallOpcode(call)); - return (call >> 8) & 0xFF; - } - - static Instr At(uword pc) { return *reinterpret_cast(pc); } - - private: - DISALLOW_ALLOCATION(); - DISALLOW_IMPLICIT_CONSTRUCTORS(SimulatorBytecode); -}; - -// Various dummy declarations to make shared code compile. -// TODO(vegorov) we need to prune away as much dead code as possible instead -// of just making it compile. -typedef int16_t Register; - -const int16_t FPREG = 0; -const int16_t SPREG = 1; -#if defined(ARCH_IS_64_BIT) -const intptr_t kNumberOfCpuRegisters = 64; -#else -const intptr_t kNumberOfCpuRegisters = 32; -#endif -const intptr_t kDartAvailableCpuRegs = -1; -const intptr_t kNoRegister = -1; -const intptr_t kReservedCpuRegisters = 0; -const intptr_t ARGS_DESC_REG = 0; -const intptr_t CODE_REG = 0; -const intptr_t kExceptionObjectReg = 0; -const intptr_t kStackTraceObjectReg = 0; - -// The maximum number of fixed registers that are used by some -// DBC instructions. The register allocator must avoid clashing -// with these when assigning registers to catch parameters. -const intptr_t kMaxNumberOfFixedInputRegistersUsedByIL = 3; - -enum FpuRegister { - kNoFpuRegister = -1, - kFakeFpuRegister, - kNumberOfDummyFpuRegisters, -}; -const FpuRegister FpuTMP = kFakeFpuRegister; -const intptr_t kNumberOfFpuRegisters = 1; - -extern const char* cpu_reg_names[kNumberOfCpuRegisters]; -extern const char* fpu_reg_names[kNumberOfFpuRegisters]; - -// After a comparison, the condition NEXT_IS_TRUE means the following -// instruction is executed if the comparison is true and skipped over overwise. -// Condition NEXT_IS_FALSE means the following instruction is executed if the -// comparison is false and skipped over otherwise. -enum Condition { NEXT_IS_TRUE, NEXT_IS_FALSE, INVALID_CONDITION }; - -} // namespace dart - -#endif // RUNTIME_VM_CONSTANTS_DBC_H_ diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h index e0ff37f0936..9bd8b6137fb 100644 --- a/runtime/vm/constants_kbc.h +++ b/runtime/vm/constants_kbc.h @@ -32,7 +32,7 @@ namespace dart { // PP - object pool for the currently execution function // // Frame info stored below FP additionally contains pointers to the currently -// executing function and code (see stack_frame_dbc.h for more information). +// executing function and code. // // In the unoptimized code most of bytecodes take operands implicitly from // stack and store results again on the stack. Constant operands are usually diff --git a/runtime/vm/cpu.h b/runtime/vm/cpu.h index e75e1a168f4..2713cabfd47 100644 --- a/runtime/vm/cpu.h +++ b/runtime/vm/cpu.h @@ -30,8 +30,6 @@ class CPU : public AllStatic { #include "vm/cpu_arm.h" #elif defined(TARGET_ARCH_ARM64) #include "vm/cpu_arm64.h" -#elif defined(TARGET_ARCH_DBC) -#include "vm/cpu_dbc.h" #else #error Unknown architecture. #endif diff --git a/runtime/vm/cpu_dbc.cc b/runtime/vm/cpu_dbc.cc deleted file mode 100644 index c6e9c6a95cd..00000000000 --- a/runtime/vm/cpu_dbc.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#include "vm/cpu.h" -#include "vm/cpu_dbc.h" - -#include "vm/cpuinfo.h" - -namespace dart { - -void CPU::FlushICache(uword start, uword size) { - // Nothing to do. -} - -const char* CPU::Id() { - return "dbc"; -} - -const char* HostCPUFeatures::hardware_ = NULL; -#if defined(DEBUG) -bool HostCPUFeatures::initialized_ = false; -#endif - -void HostCPUFeatures::Init() { - CpuInfo::Init(); - hardware_ = CpuInfo::GetCpuModel(); -#if defined(DEBUG) - initialized_ = true; -#endif -} - -void HostCPUFeatures::Cleanup() { - DEBUG_ASSERT(initialized_); -#if defined(DEBUG) - initialized_ = false; -#endif - ASSERT(hardware_ != NULL); - free(const_cast(hardware_)); - hardware_ = NULL; - CpuInfo::Cleanup(); -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/cpu_dbc.h b/runtime/vm/cpu_dbc.h deleted file mode 100644 index 5e0064bd29d..00000000000 --- a/runtime/vm/cpu_dbc.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_VM_CPU_DBC_H_ -#define RUNTIME_VM_CPU_DBC_H_ - -#if !defined(RUNTIME_VM_CPU_H_) -#error Do not include cpu_dbc.h directly; use cpu.h instead. -#endif - -#include "vm/allocation.h" -#include "vm/simulator.h" - -namespace dart { - -class HostCPUFeatures : public AllStatic { - public: - static void Init(); - static void Cleanup(); - - static const char* hardware() { - DEBUG_ASSERT(initialized_); - return hardware_; - } - - private: - static const char* hardware_; -#if defined(DEBUG) - static bool initialized_; -#endif -}; - -class TargetCPUFeatures : public AllStatic { - public: - static void Init() { HostCPUFeatures::Init(); } - static void Cleanup() { HostCPUFeatures::Cleanup(); } - - static const char* hardware() { return CPU::Id(); } - - static bool double_truncate_round_supported() { return true; } -}; - -} // namespace dart - -#endif // RUNTIME_VM_CPU_DBC_H_ diff --git a/runtime/vm/cpu_test.cc b/runtime/vm/cpu_test.cc index 35c44f4beb0..d9027130241 100644 --- a/runtime/vm/cpu_test.cc +++ b/runtime/vm/cpu_test.cc @@ -26,8 +26,6 @@ VM_UNIT_TEST_CASE(Id) { #else // defined(HOST_ARCH_ARM64) EXPECT_STREQ("simarm64", CPU::Id()); #endif // defined(HOST_ARCH_ARM64) -#elif defined(TARGET_ARCH_DBC) - EXPECT_STREQ("dbc", CPU::Id()); #else #error Architecture was not detected as supported by Dart. #endif diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc index cfd5ff05df3..0aeb9553964 100644 --- a/runtime/vm/dart.cc +++ b/runtime/vm/dart.cc @@ -186,17 +186,6 @@ char* Dart::Init(const uint8_t* vm_isolate_snapshot, } #endif -#if defined(TARGET_ARCH_DBC) - // DBC instructions are never executable. - FLAG_write_protect_code = false; -#endif - - if (FLAG_enable_interpreter) { -#if defined(TARGET_ARCH_DBC) - return strdup("--enable-interpreter is not supported with DBC"); -#endif // defined(TARGET_ARCH_DBC) - } - FrameLayout::Init(); set_thread_exit_callback(thread_exit); @@ -776,7 +765,7 @@ RawError* Dart::InitializeIsolate(const uint8_t* snapshot_data, if (I->object_store()->megamorphic_miss_code() == Code::null()) { MegamorphicCacheTable::InitMissHandler(I); } -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) if (I != Dart::vm_isolate()) { I->object_store()->set_build_method_extractor_code( Code::Handle(StubCode::GetBuildMethodExtractorStub(nullptr))); @@ -896,14 +885,6 @@ const char* Dart::FeaturesString(Isolate* isolate, buffer.AddString(" x64-sysv"); #endif -#elif defined(TARGET_ARCH_DBC) -#if defined(ARCH_IS_32_BIT) - buffer.AddString(" dbc32"); -#elif defined(ARCH_IS_64_BIT) - buffer.AddString(" dbc64"); -#else -#error What word size? -#endif #else #error What architecture? #endif diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 417b620cefd..cf66709e1f1 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -6090,8 +6090,6 @@ DART_EXPORT Dart_Handle Dart_SortClasses() { DART_EXPORT Dart_Handle Dart_Precompile() { #if defined(TARGET_ARCH_IA32) return Api::NewError("AOT compilation is not supported on IA32."); -#elif defined(TARGET_ARCH_DBC) - return Api::NewError("AOT compilation is not supported on DBC."); #elif !defined(DART_PRECOMPILER) return Api::NewError( "This VM was built without support for AOT compilation."); @@ -6116,8 +6114,6 @@ Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, void* callback_data) { #if defined(TARGET_ARCH_IA32) return Api::NewError("AOT compilation is not supported on IA32."); -#elif defined(TARGET_ARCH_DBC) - return Api::NewError("AOT compilation is not supported on DBC."); #elif defined(TARGET_OS_WINDOWS) return Api::NewError("Assembly generation is not implemented for Windows."); #elif !defined(DART_PRECOMPILER) @@ -6154,8 +6150,6 @@ Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, void* callback_data) { #if defined(TARGET_ARCH_IA32) return Api::NewError("AOT compilation is not supported on IA32."); -#elif defined(TARGET_ARCH_DBC) - return Api::NewError("AOT compilation is not supported on DBC."); #elif defined(TARGET_OS_WINDOWS) return Api::NewError("Assembly generation is not implemented for Windows."); #elif !defined(DART_PRECOMPILER) @@ -6184,8 +6178,6 @@ Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback, bool strip) { #if defined(TARGET_ARCH_IA32) return Api::NewError("AOT compilation is not supported on IA32."); -#elif defined(TARGET_ARCH_DBC) - return Api::NewError("AOT compilation is not supported on DBC."); #elif !defined(DART_PRECOMPILER) return Api::NewError( "This VM was built without support for AOT compilation."); @@ -6245,8 +6237,6 @@ Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer, intptr_t* isolate_snapshot_instructions_size) { #if defined(TARGET_ARCH_IA32) return Api::NewError("AOT compilation is not supported on IA32."); -#elif defined(TARGET_ARCH_DBC) - return Api::NewError("AOT compilation is not supported on DBC."); #elif !defined(DART_PRECOMPILER) return Api::NewError( "This VM was built without support for AOT compilation."); diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h index 0b6e42be6cc..496531ece6d 100644 --- a/runtime/vm/dart_api_impl.h +++ b/runtime/vm/dart_api_impl.h @@ -301,10 +301,7 @@ class Api : AllStatic { static bool IsFfiEnabled() { // dart:ffi is not implemented for the following configurations -#if defined(TARGET_ARCH_DBC) && !defined(ARCH_IS_64_BIT) - // TODO(36809): Support SimDBC32. - return false; -#elif defined(TARGET_ARCH_ARM) && \ +#if defined(TARGET_ARCH_ARM) && \ !(defined(TARGET_OS_ANDROID) || defined(TARGET_OS_MACOS_IOS)) // TODO(36309): Support hardfp calling convention. return false; diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc index 389b03e1f4e..49e4b47f804 100644 --- a/runtime/vm/dart_entry.cc +++ b/runtime/vm/dart_entry.cc @@ -159,20 +159,15 @@ RawObject* DartEntry::InvokeFunction(const Function& function, } #endif // !defined(DART_PRECOMPILED_RUNTIME) -// Now Call the invoke stub which will invoke the dart function. -#if !defined(TARGET_ARCH_DBC) + // Now Call the invoke stub which will invoke the dart function. invokestub entrypoint = reinterpret_cast(StubCode::InvokeDartCode().EntryPoint()); -#endif const Code& code = Code::Handle(zone, function.CurrentCode()); ASSERT(!code.IsNull()); ASSERT(thread->no_callback_scope_depth() == 0); SuspendLongJumpScope suspend_long_jump_scope(thread); TransitionToGenerated transition(thread); -#if defined(TARGET_ARCH_DBC) - return Simulator::Current()->Call(code, arguments_descriptor, arguments, - thread); -#elif defined(USING_SIMULATOR) +#if defined(USING_SIMULATOR) return bit_copy(Simulator::Current()->Call( reinterpret_cast(entrypoint), reinterpret_cast(&code), reinterpret_cast(&arguments_descriptor), diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index 3f5212cb077..a8f1db07e1b 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -180,9 +180,7 @@ void Breakpoint::PrintJSON(JSONStream* stream) { void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) { visitor->VisitPointer(reinterpret_cast(&code_)); visitor->VisitPointer(reinterpret_cast(&bytecode_)); -#if !defined(TARGET_ARCH_DBC) visitor->VisitPointer(reinterpret_cast(&saved_value_)); -#endif } ActivationFrame::ActivationFrame(uword pc, @@ -1750,13 +1748,7 @@ CodeBreakpoint::CodeBreakpoint(const Code& code, bpt_location_(NULL), next_(NULL), breakpoint_kind_(kind), -#if !defined(TARGET_ARCH_DBC) - saved_value_(Code::null()) -#else - saved_value_(SimulatorBytecode::kTrap), - saved_value_fastsmi_(SimulatorBytecode::kTrap) -#endif -{ + saved_value_(Code::null()) { ASSERT(!code.IsNull()); ASSERT(token_pos_.IsReal()); ASSERT(pc_ != 0); @@ -1775,13 +1767,7 @@ CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode, bpt_location_(NULL), next_(NULL), breakpoint_kind_(RawPcDescriptors::kAnyKind), -#if !defined(TARGET_ARCH_DBC) - saved_value_(Code::null()) -#else - saved_value_(SimulatorBytecode::kTrap), - saved_value_fastsmi_(SimulatorBytecode::kTrap) -#endif -{ + saved_value_(Code::null()) { ASSERT(!bytecode.IsNull()); ASSERT(FLAG_enable_interpreter); ASSERT(token_pos_.IsReal()); diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h index cff37910b2f..3300813511f 100644 --- a/runtime/vm/debugger.h +++ b/runtime/vm/debugger.h @@ -244,15 +244,7 @@ class CodeBreakpoint { CodeBreakpoint* next_; RawPcDescriptors::Kind breakpoint_kind_; -#if !defined(TARGET_ARCH_DBC) RawCode* saved_value_; -#else - // When running on the DBC interpreter we patch bytecode in place with - // DebugBreak. This is an instruction that was replaced. DebugBreak - // will execute it after the breakpoint. - Instr saved_value_; - Instr saved_value_fastsmi_; -#endif friend class Debugger; DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint); diff --git a/runtime/vm/debugger_dbc.cc b/runtime/vm/debugger_dbc.cc deleted file mode 100644 index 56234ce50af..00000000000 --- a/runtime/vm/debugger_dbc.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#include "vm/code_patcher.h" -#include "vm/cpu.h" -#include "vm/debugger.h" -#include "vm/instructions.h" -#include "vm/stub_code.h" - -namespace dart { - -#ifndef PRODUCT - -RawCode* CodeBreakpoint::OrigStubAddress() const { - return reinterpret_cast(static_cast(saved_value_)); -} - -static Instr* CallInstructionFromReturnAddress(uword pc) { - return reinterpret_cast(pc) - 1; -} - -static Instr* FastSmiInstructionFromReturnAddress(uword pc) { - return reinterpret_cast(pc) - 2; -} - -void CodeBreakpoint::PatchCode() { - ASSERT(!is_enabled_); - auto thread = Thread::Current(); - auto zone = thread->zone(); - const Code& code = Code::Handle(zone, code_); - const Instructions& instrs = Instructions::Handle(zone, code.instructions()); - thread->isolate_group()->RunWithStoppedMutators([&]() { - WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size()); - saved_value_ = *CallInstructionFromReturnAddress(pc_); - switch (breakpoint_kind_) { - case RawPcDescriptors::kIcCall: - case RawPcDescriptors::kUnoptStaticCall: { - // DebugBreak has an A operand matching the call it replaces. - // This ensures that Return instructions continue to work - as they - // look at calls to figure out how many arguments to drop. - *CallInstructionFromReturnAddress(pc_) = SimulatorBytecode::Encode( - SimulatorBytecode::kDebugBreak, - SimulatorBytecode::DecodeArgc(saved_value_), 0, 0); - break; - } - - case RawPcDescriptors::kRuntimeCall: { - *CallInstructionFromReturnAddress(pc_) = SimulatorBytecode::kDebugBreak; - break; - } - - default: - UNREACHABLE(); - } - - // If this call is the fall-through for a fast Smi op, also disable the fast - // Smi op. - if ((SimulatorBytecode::DecodeOpcode(saved_value_) == - SimulatorBytecode::kInstanceCall2) && - SimulatorBytecode::IsFastSmiOpcode( - *FastSmiInstructionFromReturnAddress(pc_))) { - saved_value_fastsmi_ = *FastSmiInstructionFromReturnAddress(pc_); - *FastSmiInstructionFromReturnAddress(pc_) = - SimulatorBytecode::Encode(SimulatorBytecode::kNop, 0, 0, 0); - } else { - saved_value_fastsmi_ = SimulatorBytecode::kTrap; - } - }); - is_enabled_ = true; -} - -void CodeBreakpoint::RestoreCode() { - ASSERT(is_enabled_); - auto thread = Thread::Current(); - auto zone = thread->zone(); - const Code& code = Code::Handle(zone, code_); - const Instructions& instrs = Instructions::Handle(zone, code.instructions()); - thread->isolate_group()->RunWithStoppedMutators([&]() { - WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size()); - switch (breakpoint_kind_) { - case RawPcDescriptors::kIcCall: - case RawPcDescriptors::kUnoptStaticCall: - case RawPcDescriptors::kRuntimeCall: { - *CallInstructionFromReturnAddress(pc_) = saved_value_; - break; - } - default: - UNREACHABLE(); - } - - if (saved_value_fastsmi_ != SimulatorBytecode::kTrap) { - Instr current_instr = *FastSmiInstructionFromReturnAddress(pc_); - ASSERT(SimulatorBytecode::DecodeOpcode(current_instr) == - SimulatorBytecode::kNop); - *FastSmiInstructionFromReturnAddress(pc_) = saved_value_fastsmi_; - } - }); - is_enabled_ = false; -} - -#endif // !PRODUCT - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/deferred_objects.h b/runtime/vm/deferred_objects.h index 39a335e59f5..a46be133724 100644 --- a/runtime/vm/deferred_objects.h +++ b/runtime/vm/deferred_objects.h @@ -219,11 +219,7 @@ class DeferredObject { void Create(); RawObject* GetArg(intptr_t index) const { -#if !defined(TARGET_ARCH_DBC) return args_[index]; -#else - return args_[-index]; -#endif } RawObject* GetClass() const { return GetArg(kClassIndex); } diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc index 4ea755ad842..30579771c52 100644 --- a/runtime/vm/deopt_instructions.cc +++ b/runtime/vm/deopt_instructions.cc @@ -77,14 +77,8 @@ DeoptContext::DeoptContext(const StackFrame* frame, // optimized function contains FP, PP (ARM only), PC-marker and // return-address. This section is copied as well, so that its contained // values can be updated before returning to the deoptimized function. -// Note: on DBC stack grows upwards unlike on all other architectures. -#if defined(TARGET_ARCH_DBC) - ASSERT(frame->sp() >= frame->fp()); - const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize; -#else ASSERT(frame->fp() >= frame->sp()); const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize; -#endif source_frame_size_ = +kDartFrameFixedSize // For saved values below sp. + frame_size // For frame size incl. sp. @@ -201,40 +195,23 @@ void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { intptr_t DeoptContext::DestStackAdjustment() const { return dest_frame_size_ - kDartFrameFixedSize - num_args_ -#if !defined(TARGET_ARCH_DBC) - 1 // For fp. -#endif - kParamEndSlotFromFp; } intptr_t DeoptContext::GetSourceFp() const { -#if !defined(TARGET_ARCH_DBC) return source_frame_[source_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp]; -#else - return source_frame_[num_args_ + kDartFrameFixedSize + - kSavedCallerFpSlotFromFp]; -#endif } intptr_t DeoptContext::GetSourcePp() const { -#if !defined(TARGET_ARCH_DBC) return source_frame_[source_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp + StackFrame::SavedCallerPpSlotFromFp()]; -#else - UNREACHABLE(); - return 0; -#endif } intptr_t DeoptContext::GetSourcePc() const { -#if !defined(TARGET_ARCH_DBC) return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; -#else - return source_frame_[num_args_ + kDartFrameFixedSize + - kSavedCallerPcSlotFromFp]; -#endif } intptr_t DeoptContext::GetCallerFp() const { @@ -351,19 +328,12 @@ const CatchEntryMoves* DeoptContext::ToCatchEntryMoves(intptr_t num_vars) { intptr_t params = function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); for (intptr_t i = 0; i < num_vars; i++) { -#if defined(TARGET_ARCH_DBC) - const intptr_t len = deopt_instructions.length(); - intptr_t slot = i < params ? i : i + kParamEndSlotFromFp; - DeoptInstr* instr = deopt_instructions[len - 1 - slot]; - intptr_t dest_index = kNumberOfCpuRegisters - 1 - i; -#else const intptr_t len = deopt_instructions.length(); intptr_t slot = i < params ? i : i + kParamEndSlotFromFp - runtime_frame_layout.first_local_from_fp; DeoptInstr* instr = deopt_instructions[len - 1 - slot]; intptr_t dest_index = i - params; -#endif moves->At(i) = instr->ToCatchEntryMove(this, dest_index); } @@ -1083,10 +1053,6 @@ FpuRegisterSource DeoptInfoBuilder::ToFpuRegisterSource( Location::Kind stack_slot_kind) { if (loc.IsFpuRegister()) { return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg()); -#if defined(TARGET_ARCH_DBC) - } else if (loc.IsRegister()) { - return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg()); -#endif } else { ASSERT((stack_slot_kind == Location::kQuadStackSlot) || (stack_slot_kind == Location::kDoubleStackSlot)); @@ -1133,12 +1099,7 @@ void DeoptInfoBuilder::AddCopy(Value* value, deopt_instr = new (zone()) DeoptMaterializedObjectRefInstr(index); } else { ASSERT(!source_loc.IsInvalid()); -#if defined(TARGET_ARCH_DBC) - Representation rep = - (value == NULL) ? kTagged : value->definition()->representation(); -#else Representation rep = value->definition()->representation(); -#endif switch (rep) { case kTagged: deopt_instr = diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h index b4404139797..926ea1b1e09 100644 --- a/runtime/vm/deopt_instructions.h +++ b/runtime/vm/deopt_instructions.h @@ -50,23 +50,16 @@ class DeoptContext { intptr_t* GetSourceFrameAddressAt(intptr_t index) const { ASSERT(source_frame_ != NULL); ASSERT((0 <= index) && (index < source_frame_size_)); -#if !defined(TARGET_ARCH_DBC) // Convert FP relative index to SP relative one. index = source_frame_size_ - 1 - index; -#endif // !defined(TARGET_ARCH_DBC) return &source_frame_[index]; } // Returns index in stack slot notation where -1 is the first argument - // For DBC returns index directly relative to FP. intptr_t GetStackSlot(intptr_t index) const { ASSERT((0 <= index) && (index < source_frame_size_)); index -= num_args_; -#if defined(TARGET_ARCH_DBC) - return index < 0 ? index - kDartFrameFixedSize : index; -#else return index < 0 ? index : index - kDartFrameFixedSize; -#endif // defined(TARGET_ARCH_DBC) } intptr_t GetSourceFp() const; @@ -84,28 +77,16 @@ class DeoptContext { intptr_t RegisterValue(Register reg) const { ASSERT(reg >= 0); ASSERT(reg < kNumberOfCpuRegisters); -#if !defined(TARGET_ARCH_DBC) ASSERT(cpu_registers_ != NULL); return cpu_registers_[reg]; -#else - // On DBC registers and stack slots are the same. - const intptr_t stack_index = num_args_ + kDartFrameFixedSize + reg; - return *GetSourceFrameAddressAt(stack_index); -#endif // !defined(TARGET_ARCH_DBC) } double FpuRegisterValue(FpuRegister reg) const { ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles()); -#if !defined(TARGET_ARCH_DBC) ASSERT(fpu_registers_ != NULL); ASSERT(reg >= 0); ASSERT(reg < kNumberOfFpuRegisters); return *reinterpret_cast(&fpu_registers_[reg]); -#else - // On DBC registers and stack slots are the same. - const intptr_t stack_index = num_args_ + kDartFrameFixedSize + reg; - return *reinterpret_cast(GetSourceFrameAddressAt(stack_index)); -#endif } simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { @@ -125,16 +106,10 @@ class DeoptContext { // part of the frame because it contains saved caller PC and FP that // deoptimization will fill in. intptr_t* FrameBase(const StackFrame* frame) { -#if !defined(TARGET_ARCH_DBC) // SP of the deoptimization frame is the lowest slot because // stack is growing downwards. return reinterpret_cast(frame->sp() - (kDartFrameFixedSize * kWordSize)); -#else - // First argument is the lowest slot because stack is growing upwards. - return reinterpret_cast( - frame->fp() - (kDartFrameFixedSize + num_args_) * kWordSize); -#endif // !defined(TARGET_ARCH_DBC) } void set_dest_frame(const StackFrame* frame) { @@ -234,12 +209,6 @@ class DeoptContext { intptr_t* GetDestFrameAddressAt(intptr_t index) const { ASSERT(dest_frame_ != NULL); ASSERT((0 <= index) && (index < dest_frame_size_)); -#if defined(TARGET_ARCH_DBC) - // Stack on DBC is growing upwards but we record deopt commands - // in the same order we record them on other architectures as if - // the stack was growing downwards. - index = dest_frame_size_ - 1 - index; -#endif // defined(TARGET_ARCH_DBC) return &dest_frame_[index]; } @@ -432,11 +401,8 @@ class RegisterSource { } intptr_t StackSlot(DeoptContext* context) const { - if (is_register()) { - return raw_index(); // in DBC stack slots are registers. - } else { - return context->GetStackSlot(raw_index()); - } + ASSERT(!is_register()); + return context->GetStackSlot(raw_index()); } intptr_t source_index() const { return source_index_; } diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc index 80ff999cddc..5be327b88d3 100644 --- a/runtime/vm/elf.cc +++ b/runtime/vm/elf.cc @@ -574,7 +574,6 @@ void Elf::WriteHeader() { #elif defined(TARGET_ARCH_ARM64) WriteHalf(elf::EM_AARCH64); #else - // E.g., DBC. FATAL("Unknown ELF architecture"); #endif diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index 0f54abd6edc..9c153b898b8 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -346,13 +346,9 @@ class ExceptionHandlerFinder : public StackResource { private: template static T* SlotAt(uword fp, int stack_slot) { -#if defined(TARGET_ARCH_DBC) - return reinterpret_cast(fp + stack_slot * kWordSize); -#else const intptr_t frame_slot = runtime_frame_layout.FrameSlotForVariableIndex(-stack_slot); return reinterpret_cast(fp + frame_slot * kWordSize); -#endif } static RawObject** TaggedSlotAt(uword fp, int stack_slot) { @@ -479,7 +475,6 @@ static void FindErrorHandler(uword* handler_pc, static uword RemapExceptionPCForDeopt(Thread* thread, uword program_counter, uword frame_pointer) { -#if !defined(TARGET_ARCH_DBC) MallocGrowableArray* pending_deopts = thread->isolate()->pending_deopts(); if (pending_deopts->length() > 0) { @@ -500,12 +495,10 @@ static uword RemapExceptionPCForDeopt(Thread* thread, } } } -#endif // !DBC return program_counter; } static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { -#if !defined(TARGET_ARCH_DBC) MallocGrowableArray* pending_deopts = thread->isolate()->pending_deopts(); if (pending_deopts->length() > 0) { @@ -548,7 +541,6 @@ static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { ValidateFrames(); #endif } -#endif // !DBC } static void JumpToExceptionHandler(Thread* thread, diff --git a/runtime/vm/ffi_callback_trampolines.cc b/runtime/vm/ffi_callback_trampolines.cc index af987dcc274..6475a3ddd9f 100644 --- a/runtime/vm/ffi_callback_trampolines.cc +++ b/runtime/vm/ffi_callback_trampolines.cc @@ -13,7 +13,7 @@ namespace dart { DECLARE_FLAG(bool, disassemble_stubs); -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) uword NativeCallbackTrampolines::TrampolineForId(int32_t callback_id) { #if defined(DART_PRECOMPILER) ASSERT(!Enabled()); @@ -98,6 +98,6 @@ void NativeCallbackTrampolines::AllocateTrampoline() { next_callback_id_++; #endif // defined(DART_PRECOMPILER) } -#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#endif // !defined(DART_PRECOMPILED_RUNTIME) } // namespace dart diff --git a/runtime/vm/ffi_callback_trampolines.h b/runtime/vm/ffi_callback_trampolines.h index 77822d5a0fe..73288288cc4 100644 --- a/runtime/vm/ffi_callback_trampolines.h +++ b/runtime/vm/ffi_callback_trampolines.h @@ -13,7 +13,7 @@ namespace dart { -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) // In JIT mode, when write-protection is enabled without dual-mapping, we cannot // rely on Instructions generated in the Isolate's heap to be executable while // native code is running in a safepoint. This means that native code cannot @@ -69,7 +69,7 @@ class NativeCallbackTrampolines : public ValueObject { DISALLOW_COPY_AND_ASSIGN(NativeCallbackTrampolines); }; -#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#endif // !defined(DART_PRECOMPILED_RUNTIME) } // namespace dart diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h index be99782de29..4cf3e4a162c 100644 --- a/runtime/vm/flag_list.h +++ b/runtime/vm/flag_list.h @@ -5,13 +5,6 @@ #ifndef RUNTIME_VM_FLAG_LIST_H_ #define RUNTIME_VM_FLAG_LIST_H_ -// Don't use USING_DBC outside of this file. -#if defined(TARGET_ARCH_DBC) -#define USING_DBC true -#else -#define USING_DBC false -#endif - // Don't use USING_PRODUCT outside of this file. #if defined(PRODUCT) #define USING_PRODUCT true @@ -104,7 +97,7 @@ constexpr bool kDartUseBytecode = false; "Consider thread pool isolates for idle tasks after this long.") \ P(idle_duration_micros, int, 500 * kMicrosecondsPerMillisecond, \ "Allow idle tasks to run for this long.") \ - P(interpret_irregexp, bool, USING_DBC, "Use irregexp bytecode interpreter") \ + P(interpret_irregexp, bool, false, "Use irregexp bytecode interpreter") \ P(lazy_dispatchers, bool, true, "Generate dispatchers lazily") \ P(link_natives_lazily, bool, false, "Link native calls lazily") \ R(log_marker_tasks, false, bool, false, \ @@ -194,8 +187,7 @@ constexpr bool kDartUseBytecode = false; P(use_compactor, bool, false, "Compact the heap during old-space GC.") \ P(use_cha_deopt, bool, true, \ "Use class hierarchy analysis even if it can cause deoptimization.") \ - P(use_field_guards, bool, !USING_DBC, \ - "Use field guards and track field types") \ + P(use_field_guards, bool, true, "Use field guards and track field types") \ C(use_osr, false, true, bool, true, "Use OSR") \ P(use_strong_mode_types, bool, true, "Optimize based on strong mode types.") \ R(verbose_gc, false, bool, false, "Enables verbose GC.") \ diff --git a/runtime/vm/gdb_helpers.cc b/runtime/vm/gdb_helpers.cc index b32297c9e69..a8a1a609d48 100644 --- a/runtime/vm/gdb_helpers.cc +++ b/runtime/vm/gdb_helpers.cc @@ -46,7 +46,6 @@ void _printStackTrace() { } } -#if !defined(TARGET_ARCH_DBC) // Like _printDartStackTrace, but works when stopped in generated code. // Must be called with the current fp, sp, and pc. DART_EXPORT @@ -80,7 +79,6 @@ void _printInterpreterStackTrace(RawObject** fp, thread->set_execution_state(Thread::kThreadInGenerated); thread->set_top_exit_frame_info(0); } -#endif // !defined(TARGET_ARCH_DBC) class PrintObjectPointersVisitor : public ObjectPointerVisitor { public: diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h index aa436e1732f..e5ef799e980 100644 --- a/runtime/vm/globals.h +++ b/runtime/vm/globals.h @@ -77,12 +77,6 @@ const intptr_t kDefaultMaxOldGenHeapSize = (kWordSize <= 4) ? 1536 : 15360; #define NOT_IN_PRECOMPILED(code) code #endif // defined(DART_PRECOMPILED_RUNTIME) -#if defined(TARGET_ARCH_DBC) -#define NOT_IN_DBC(code) -#else -#define NOT_IN_DBC(code) code -#endif // defined(TARGET_ARCH_DBC) - #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \ defined(TARGET_ARCH_X64) #define ONLY_IN_ARM_ARM64_X64(code) code diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc index 11fabd6bff4..60a3fd78594 100644 --- a/runtime/vm/heap/pages.cc +++ b/runtime/vm/heap/pages.cc @@ -46,11 +46,7 @@ DEFINE_FLAG(bool, log_growth, false, "Log PageSpace growth policy decisions."); HeapPage* HeapPage::Allocate(intptr_t size_in_words, PageType type, const char* name) { -#if defined(TARGET_ARCH_DBC) - bool executable = false; -#else - bool executable = type == kExecutable; -#endif + const bool executable = type == kExecutable; VirtualMemory* memory = VirtualMemory::AllocateAligned( size_in_words << kWordSizeLog2, kPageSize, executable, name); diff --git a/runtime/vm/instructions.h b/runtime/vm/instructions.h index eb39a5d1cdb..76b929d35a1 100644 --- a/runtime/vm/instructions.h +++ b/runtime/vm/instructions.h @@ -15,8 +15,6 @@ #include "vm/instructions_arm.h" #elif defined(TARGET_ARCH_ARM64) #include "vm/instructions_arm64.h" -#elif defined(TARGET_ARCH_DBC) -#include "vm/instructions_dbc.h" #else #error Unknown architecture. #endif @@ -28,7 +26,7 @@ class Code; bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj); -#if !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC) +#if !defined(TARGET_ARCH_IA32) class TypeTestingStubCallPattern : public ValueObject { public: @@ -40,7 +38,7 @@ class TypeTestingStubCallPattern : public ValueObject { const uword pc_; }; -#endif // !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC) +#endif // !defined(TARGET_ARCH_IA32) } // namespace dart diff --git a/runtime/vm/instructions_dbc.cc b/runtime/vm/instructions_dbc.cc deleted file mode 100644 index 6d5280bbd30..00000000000 --- a/runtime/vm/instructions_dbc.cc +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" // Needed here to get TARGET_ARCH_DBC. -#if defined(TARGET_ARCH_DBC) - -#include "vm/instructions.h" -#include "vm/instructions_dbc.h" - -#include "vm/compiler/assembler/assembler.h" -#include "vm/constants_dbc.h" -#include "vm/cpu.h" -#include "vm/object.h" - -namespace dart { - -static bool HasLoadFromPool(Instr instr) { - switch (SimulatorBytecode::DecodeOpcode(instr)) { - case SimulatorBytecode::kLoadConstant: - case SimulatorBytecode::kPushConstant: - case SimulatorBytecode::kStaticCall: - case SimulatorBytecode::kIndirectStaticCall: - case SimulatorBytecode::kInstanceCall1: - case SimulatorBytecode::kInstanceCall2: - case SimulatorBytecode::kInstanceCall1Opt: - case SimulatorBytecode::kInstanceCall2Opt: - case SimulatorBytecode::kStoreStaticTOS: - case SimulatorBytecode::kPushStatic: - case SimulatorBytecode::kAllocate: - case SimulatorBytecode::kInstantiateType: - case SimulatorBytecode::kInstantiateTypeArgumentsTOS: - case SimulatorBytecode::kAssertAssignable: - return true; - default: - return false; - } -} - -static bool GetLoadedObjectAt(uword pc, - const ObjectPool& object_pool, - Object* obj) { - Instr instr = SimulatorBytecode::At(pc); - if (HasLoadFromPool(instr)) { - uint16_t index = SimulatorBytecode::DecodeD(instr); - if (object_pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) { - *obj = object_pool.ObjectAt(index); - return true; - } - } - return false; -} - -CallPattern::CallPattern(uword pc, const Code& code) - : object_pool_(ObjectPool::Handle(code.GetObjectPool())), - end_(pc), - data_pool_index_(-1), - target_pool_index_(-1) { - ASSERT(code.ContainsInstructionAt(end_)); - const uword call_pc = end_ - sizeof(Instr); - Instr call_instr = SimulatorBytecode::At(call_pc); - ASSERT(SimulatorBytecode::IsCallOpcode(call_instr)); - data_pool_index_ = SimulatorBytecode::DecodeD(call_instr); - target_pool_index_ = SimulatorBytecode::DecodeD(call_instr); -} - -NativeCallPattern::NativeCallPattern(uword pc, const Code& code) - : object_pool_(ObjectPool::Handle(code.GetObjectPool())), - end_(pc), - native_function_pool_index_(-1), - trampoline_pool_index_(-1) { - ASSERT(code.ContainsInstructionAt(end_)); - const uword call_pc = end_ - sizeof(Instr); - Instr call_instr = SimulatorBytecode::At(call_pc); - ASSERT(SimulatorBytecode::DecodeOpcode(call_instr) == - SimulatorBytecode::kNativeCall); - native_function_pool_index_ = SimulatorBytecode::DecodeB(call_instr); - trampoline_pool_index_ = SimulatorBytecode::DecodeA(call_instr); -} - -NativeFunctionWrapper NativeCallPattern::target() const { - return reinterpret_cast( - object_pool_.ObjectAt(trampoline_pool_index_)); -} - -void NativeCallPattern::set_target(NativeFunctionWrapper new_target) const { - object_pool_.SetRawValueAt(trampoline_pool_index_, - reinterpret_cast(new_target)); - // No need to flush the instruction cache, since the code is not modified. -} - -NativeFunction NativeCallPattern::native_function() const { - return reinterpret_cast( - object_pool_.RawValueAt(native_function_pool_index_)); -} - -void NativeCallPattern::set_native_function(NativeFunction func) const { - object_pool_.SetRawValueAt(native_function_pool_index_, - reinterpret_cast(func)); -} - -// Decodes a load sequence ending at 'end' (the last instruction of the load -// sequence is the instruction before the one at end). Returns a pointer to -// the first instruction in the sequence. Returns the register being loaded -// and the loaded object in the output parameters 'reg' and 'obj' -// respectively. -uword InstructionPattern::DecodeLoadObject(uword end, - const ObjectPool& object_pool, - Register* reg, - Object* obj) { - UNIMPLEMENTED(); - return 0; -} - -// Decodes a load sequence ending at 'end' (the last instruction of the load -// sequence is the instruction before the one at end). Returns a pointer to -// the first instruction in the sequence. Returns the register being loaded -// and the loaded immediate value in the output parameters 'reg' and 'value' -// respectively. -uword InstructionPattern::DecodeLoadWordImmediate(uword end, - Register* reg, - intptr_t* value) { - UNIMPLEMENTED(); - return 0; -} - -// Decodes a load sequence ending at 'end' (the last instruction of the load -// sequence is the instruction before the one at end). Returns a pointer to -// the first instruction in the sequence. Returns the register being loaded -// and the index in the pool being read from in the output parameters 'reg' -// and 'index' respectively. -uword InstructionPattern::DecodeLoadWordFromPool(uword end, - Register* reg, - intptr_t* index) { - UNIMPLEMENTED(); - return 0; -} - -bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) { - ASSERT(code.ContainsInstructionAt(pc)); - const ObjectPool& pool = ObjectPool::Handle(code.object_pool()); - return GetLoadedObjectAt(pc, pool, obj); -} - -RawObject* CallPattern::Data() const { - return object_pool_.ObjectAt(data_pool_index_); -} - -void CallPattern::SetData(const Object& data) const { - object_pool_.SetObjectAt(data_pool_index_, data); -} - -RawCode* CallPattern::TargetCode() const { - return reinterpret_cast(object_pool_.ObjectAt(target_pool_index_)); -} - -void CallPattern::SetTargetCode(const Code& target) const { - object_pool_.SetObjectAt(target_pool_index_, target); -} - -void CallPattern::InsertDeoptCallAt(uword pc) { - const uint8_t argc = - SimulatorBytecode::IsCallOpcode(SimulatorBytecode::At(pc)) - ? SimulatorBytecode::DecodeArgc(SimulatorBytecode::At(pc)) - : 0; - *reinterpret_cast(pc) = - SimulatorBytecode::Encode(SimulatorBytecode::kDeopt, argc, 0); -} - -SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) - : object_pool_(ObjectPool::Handle(code.GetObjectPool())), - data_pool_index_(-1), - target_pool_index_(-1) { - UNIMPLEMENTED(); -} - -RawObject* SwitchableCallPattern::data() const { - return object_pool_.ObjectAt(data_pool_index_); -} - -RawCode* SwitchableCallPattern::target() const { - return reinterpret_cast(object_pool_.ObjectAt(target_pool_index_)); -} - -void SwitchableCallPattern::SetData(const Object& data) const { - ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode()); - object_pool_.SetObjectAt(data_pool_index_, data); -} - -void SwitchableCallPattern::SetTarget(const Code& target) const { - ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode()); - object_pool_.SetObjectAt(target_pool_index_, target); -} - -ReturnPattern::ReturnPattern(uword pc) : pc_(pc) { - USE(pc_); -} - -bool ReturnPattern::IsValid() const { - UNIMPLEMENTED(); - return false; -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/instructions_dbc.h b/runtime/vm/instructions_dbc.h deleted file mode 100644 index 3d465fa9935..00000000000 --- a/runtime/vm/instructions_dbc.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. -// Classes that describe assembly patterns as used by inline caches. - -#ifndef RUNTIME_VM_INSTRUCTIONS_DBC_H_ -#define RUNTIME_VM_INSTRUCTIONS_DBC_H_ - -#ifndef RUNTIME_VM_INSTRUCTIONS_H_ -#error Do not include instructions_dbc.h directly; use instructions.h instead. -#endif - -#include "vm/constants_dbc.h" -#include "vm/native_entry.h" -#include "vm/object.h" - -namespace dart { - -class InstructionPattern : public AllStatic { - public: - // Decodes a load sequence ending at 'end' (the last instruction of the - // load sequence is the instruction before the one at end). Returns the - // address of the first instruction in the sequence. Returns the register - // being loaded and the loaded object in the output parameters 'reg' and - // 'obj' respectively. - static uword DecodeLoadObject(uword end, - const ObjectPool& object_pool, - Register* reg, - Object* obj); - - // Decodes a load sequence ending at 'end' (the last instruction of the - // load sequence is the instruction before the one at end). Returns the - // address of the first instruction in the sequence. Returns the register - // being loaded and the loaded immediate value in the output parameters - // 'reg' and 'value' respectively. - static uword DecodeLoadWordImmediate(uword end, - Register* reg, - intptr_t* value); - - // Decodes a load sequence ending at 'end' (the last instruction of the - // load sequence is the instruction before the one at end). Returns the - // address of the first instruction in the sequence. Returns the register - // being loaded and the index in the pool being read from in the output - // parameters 'reg' and 'index' respectively. - static uword DecodeLoadWordFromPool(uword end, - Register* reg, - intptr_t* index); -}; - -class CallPattern : public ValueObject { - public: - CallPattern(uword pc, const Code& caller_code); - - RawObject* Data() const; - void SetData(const Object& data) const; - - RawCode* TargetCode() const; - void SetTargetCode(const Code& code) const; - - static void InsertDeoptCallAt(uword pc); - - private: - const ObjectPool& object_pool_; - - uword end_; - - intptr_t data_pool_index_; - intptr_t target_pool_index_; - - DISALLOW_COPY_AND_ASSIGN(CallPattern); -}; - -class NativeCallPattern : public ValueObject { - public: - NativeCallPattern(uword pc, const Code& code); - - NativeFunctionWrapper target() const; - void set_target(NativeFunctionWrapper target) const; - - NativeFunction native_function() const; - void set_native_function(NativeFunction target) const; - - private: - const ObjectPool& object_pool_; - - uword end_; - intptr_t native_function_pool_index_; - intptr_t trampoline_pool_index_; - - DISALLOW_COPY_AND_ASSIGN(NativeCallPattern); -}; - -// Instance call that can switch between a direct monomorphic call, an IC call, -// and a megamorphic call. -// load guarded cid load ICData load MegamorphicCache -// load monomorphic target <-> load ICLookup stub -> load MMLookup stub -// call target.entry call stub.entry call stub.entry -class SwitchableCallPattern : public ValueObject { - public: - SwitchableCallPattern(uword pc, const Code& code); - - RawObject* data() const; - RawCode* target() const; - void SetData(const Object& data) const; - void SetTarget(const Code& target) const; - - private: - const ObjectPool& object_pool_; - intptr_t data_pool_index_; - intptr_t target_pool_index_; - - DISALLOW_COPY_AND_ASSIGN(SwitchableCallPattern); -}; - -class ReturnPattern : public ValueObject { - public: - explicit ReturnPattern(uword pc); - - static const int kLengthInBytes = 0; - - int pattern_length_in_bytes() const { - UNIMPLEMENTED(); - return kLengthInBytes; - } - - bool IsValid() const; - - private: - const uword pc_; -}; - -} // namespace dart - -#endif // RUNTIME_VM_INSTRUCTIONS_DBC_H_ diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc index eabc1ae514e..7a5deef658f 100644 --- a/runtime/vm/interpreter.cc +++ b/runtime/vm/interpreter.cc @@ -356,10 +356,6 @@ void LookupCache::Insert(intptr_t receiver_cid, Interpreter::Interpreter() : stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL), lookup_cache_() { -#if defined(TARGET_ARCH_DBC) - FATAL("Interpreter is not supported when targeting DBC\n"); -#endif // defined(USING_SIMULATOR) || defined(TARGET_ARCH_DBC) - // Setup interpreter support first. Some of this information is needed to // setup the architecture state. // We allocate the stack here, the size is computed as the sum of @@ -603,10 +599,7 @@ DART_NOINLINE bool Interpreter::InvokeCompiled(Thread* thread, { InterpreterSetjmpBuffer buffer(this); if (!setjmp(buffer.buffer_)) { -#if defined(TARGET_ARCH_DBC) - USE(entrypoint); - UNIMPLEMENTED(); -#elif defined(USING_SIMULATOR) +#if defined(USING_SIMULATOR) // We need to beware that bouncing between the interpreter and the // simulator may exhaust the C stack before exhausting either the // interpreter or simulator stacks. diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index 022deaf77b2..6b42231a58d 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -1164,7 +1164,7 @@ Isolate::Isolate(IsolateGroup* isolate_group, shared_class_table_(new SharedClassTable()), class_table_(shared_class_table_.get()), store_buffer_(new StoreBuffer()), -#if !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME) +#if !defined(DART_PRECOMPILED_RUNTIME) native_callback_trampolines_(), #endif #if !defined(PRODUCT) @@ -2294,11 +2294,6 @@ void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, } #endif // !defined(DART_PRECOMPILED_RUNTIME) -#if defined(TARGET_ARCH_DBC) - if (simulator() != nullptr) { - simulator()->VisitObjectPointers(visitor); - } -#endif // defined(TARGET_ARCH_DBC) VisitStackPointers(visitor, validate_frames); } diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index 9db15458c0f..99a58a06cae 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -455,7 +455,7 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { void set_init_callback_data(void* value) { init_callback_data_ = value; } void* init_callback_data() const { return init_callback_data_; } -#if !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME) +#if !defined(DART_PRECOMPILED_RUNTIME) NativeCallbackTrampolines* native_callback_trampolines() { return &native_callback_trampolines_; } @@ -1083,7 +1083,7 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { Heap* heap_ = nullptr; IsolateGroup* isolate_group_ = nullptr; -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) NativeCallbackTrampolines native_callback_trampolines_; #endif diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc index 45e17dc310f..fa5e4eef375 100644 --- a/runtime/vm/kernel_isolate.cc +++ b/runtime/vm/kernel_isolate.cc @@ -85,7 +85,7 @@ class RunKernelTask : public ThreadPool::Task { Isolate::FlagsInitialize(&api_flags); api_flags.enable_asserts = false; api_flags.unsafe_trust_strong_mode_types = false; -#if !defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILER) api_flags.use_field_guards = true; #endif #if !defined(DART_PRECOMPILER) @@ -650,14 +650,8 @@ class KernelCompilationRequest : public ValueObject { Dart_CObject bytecode; bytecode.type = Dart_CObject_kBool; - // Interpreter is not supported with DBC. -#if !defined(TARGET_ARCH_DBC) bytecode.value.as_bool = FLAG_enable_interpreter || FLAG_use_bytecode_compiler; -#else - bytecode.value.as_bool = - FLAG_use_bytecode_compiler && !FLAG_enable_interpreter; -#endif Dart_CObject package_config_uri; if (package_config != NULL) { diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc index 80dc9d180b6..76b789ba2b9 100644 --- a/runtime/vm/malloc_hooks_test.cc +++ b/runtime/vm/malloc_hooks_test.cc @@ -4,7 +4,7 @@ #include "platform/globals.h" -#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && !defined(TARGET_ARCH_DBC) +#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) #include "platform/assert.h" #include "vm/globals.h" diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h index 8d071431965..5a10bf53a88 100644 --- a/runtime/vm/native_arguments.h +++ b/runtime/vm/native_arguments.h @@ -22,10 +22,7 @@ class Thread; #if defined(TESTING) || defined(DEBUG) -#if defined(TARGET_ARCH_DBC) -// C-stack is always aligned on DBC because we don't have any native code. -#define CHECK_STACK_ALIGNMENT -#elif defined(USING_SIMULATOR) +#if defined(USING_SIMULATOR) #define CHECK_STACK_ALIGNMENT \ { \ uword current_sp = Simulator::Current()->get_register(SPREG); \ diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc index 769fb1bd972..2b36456155d 100644 --- a/runtime/vm/native_entry.cc +++ b/runtime/vm/native_entry.cc @@ -121,8 +121,7 @@ void NativeEntry::BootstrapNativeCallWrapper(Dart_NativeArguments args, uword NativeEntry::NoScopeNativeCallWrapperEntry() { uword entry = reinterpret_cast(NativeEntry::NoScopeNativeCallWrapper); -#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) - // DBC does not use redirections unlike other simulators. +#if defined(USING_SIMULATOR) entry = Simulator::RedirectExternalReference( entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); #endif @@ -158,8 +157,7 @@ void NativeEntry::NoScopeNativeCallWrapperNoStackCheck( uword NativeEntry::AutoScopeNativeCallWrapperEntry() { uword entry = reinterpret_cast(NativeEntry::AutoScopeNativeCallWrapper); -#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) - // DBC does not use redirections unlike other simulators. +#if defined(USING_SIMULATOR) entry = Simulator::RedirectExternalReference( entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); #endif @@ -226,8 +224,7 @@ static NativeFunction ResolveNativeFunction(Zone* zone, uword NativeEntry::LinkNativeCallEntry() { uword entry = reinterpret_cast(NativeEntry::LinkNativeCall); -#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) - // DBC does not use redirections unlike other simulators. +#if defined(USING_SIMULATOR) entry = Simulator::RedirectExternalReference( entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); #endif @@ -275,7 +272,7 @@ void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { &is_bootstrap_native, &is_auto_scope); ASSERT(target_function != NULL); -#if defined(DEBUG) && !defined(TARGET_ARCH_DBC) +#if defined(DEBUG) NativeFunction current_function = NULL; if (caller_frame->is_interpreted()) { #if !defined(DART_PRECOMPILED_RUNTIME) @@ -309,18 +306,6 @@ void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { #endif NativeFunction patch_target_function = target_function; -#if defined(TARGET_ARCH_DBC) - NativeFunctionWrapper trampoline; - if (is_bootstrap_native) { - trampoline = &BootstrapNativeCallWrapper; - } else if (is_auto_scope) { - trampoline = &AutoScopeNativeCallWrapper; - } else { - trampoline = &NoScopeNativeCallWrapper; - } - CodePatcher::PatchNativeCallAt(caller_frame->pc(), code, - patch_target_function, trampoline); -#else if (caller_frame->is_interpreted()) { #if !defined(DART_PRECOMPILED_RUNTIME) ASSERT(FLAG_enable_interpreter); @@ -355,7 +340,6 @@ void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { CodePatcher::PatchNativeCallAt(caller_frame->pc(), code, patch_target_function, trampoline); } -#endif // defined TARGET_ARCH_DBC if (FLAG_trace_natives) { THR_Print(" -> %p (%s)\n", target_function, diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index bbc460a9f6f..e8e01b1f794 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -15194,17 +15194,12 @@ void Code::DisableDartCode() const { } void Code::DisableStubCode() const { -#if !defined(TARGET_ARCH_DBC) ASSERT(Thread::Current()->IsMutatorThread()); ASSERT(IsAllocationStubCode()); ASSERT(instructions() == active_instructions()); const Code& new_code = StubCode::FixAllocationStubTarget(); SetActiveInstructions(Instructions::Handle(new_code.instructions())); StoreNonPointer(&raw_ptr()->unchecked_entry_point_, raw_ptr()->entry_point_); -#else - // DBC does not use allocation stubs. - UNIMPLEMENTED(); -#endif // !defined(TARGET_ARCH_DBC) } void Code::SetActiveInstructions(const Instructions& instructions) const { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 31a78ff63cf..f741aaacf21 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -2729,14 +2729,10 @@ class Function : public Object { if (IsFfiTrampoline()) { return true; } - // On DBC we use native calls instead of IR for the view factories (see - // kernel_to_il.cc) -#if !defined(TARGET_ARCH_DBC) if (IsTypedDataViewFactory() || IsFfiLoad() || IsFfiStore() || IsFfiFromAddress() || IsFfiGetAddress()) { return true; } -#endif return false; } @@ -4792,11 +4788,6 @@ class Instructions : public Object { static const intptr_t kPolymorphicEntryOffsetJIT = 48; static const intptr_t kMonomorphicEntryOffsetAOT = 8; static const intptr_t kPolymorphicEntryOffsetAOT = 28; -#elif defined(TARGET_ARCH_DBC) - static const intptr_t kMonomorphicEntryOffsetJIT = 0; - static const intptr_t kPolymorphicEntryOffsetJIT = 0; - static const intptr_t kMonomorphicEntryOffsetAOT = 0; - static const intptr_t kPolymorphicEntryOffsetAOT = 0; #else #error Missing entry offsets for current architecture #endif diff --git a/runtime/vm/object_dbc_test.cc b/runtime/vm/object_dbc_test.cc deleted file mode 100644 index 8ba27da43bd..00000000000 --- a/runtime/vm/object_dbc_test.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "platform/assert.h" -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#include "vm/compiler/assembler/assembler.h" -#include "vm/object.h" -#include "vm/unit_test.h" - -namespace dart { - -#define __ assembler-> - -// Generate a simple dart code sequence. -// This is used to test Code and Instruction object creation. -// For other architectures, this sequence does do an increment, hence the name. -// On DBC, we don't do an increment because generating an instance call here -// would be too complex. -void GenerateIncrement(compiler::Assembler* assembler) { - __ Frame(1); - __ LoadConstant(0, Smi::Handle(Smi::New(1))); - __ Return(0); -} - -// Generate a dart code sequence that embeds a string object in it. -// This is used to test Embedded String objects in the instructions. -void GenerateEmbedStringInCode(compiler::Assembler* assembler, - const char* str) { - const String& string_object = - String::ZoneHandle(String::New(str, Heap::kOld)); - __ PushConstant(string_object); - __ ReturnTOS(); -} - -// Generate a dart code sequence that embeds a smi object in it. -// This is used to test Embedded Smi objects in the instructions. -void GenerateEmbedSmiInCode(compiler::Assembler* assembler, intptr_t value) { - const Smi& smi_object = Smi::ZoneHandle(Smi::New(value)); - __ PushConstant(smi_object); - __ ReturnTOS(); -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc index 6857b57057a..5767f9e0293 100644 --- a/runtime/vm/object_reload.cc +++ b/runtime/vm/object_reload.cc @@ -93,7 +93,6 @@ void CallSiteResetter::ResetCaches(const Code& code) { #endif } -#if !defined(TARGET_ARCH_DBC) static void FindICData(const Array& ic_data_array, intptr_t deopt_id, ICData* ic_data) { @@ -116,10 +115,8 @@ static void FindICData(const Array& ic_data_array, } FATAL1("Missing deopt id %" Pd "\n", deopt_id); } -#endif // !defined(TARGET_ARCH_DBC) void CallSiteResetter::ResetSwitchableCalls(const Code& code) { -#if !defined(TARGET_ARCH_DBC) if (code.is_optimized()) { return; // No switchable calls in optimized code. } @@ -177,7 +174,6 @@ void CallSiteResetter::ResetSwitchableCalls(const Code& code) { } } } -#endif } void CallSiteResetter::RebindStaticTargets(const Bytecode& bytecode) { diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc index 222ae792f15..7ac97ec4278 100644 --- a/runtime/vm/os_android.cc +++ b/runtime/vm/os_android.cc @@ -181,13 +181,9 @@ int64_t OS::GetCurrentThreadCPUMicros() { // into a architecture specific file e.g: os_ia32_linux.cc intptr_t OS::ActivationFrameAlignment() { #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ - defined(TARGET_ARCH_ARM64) || \ - defined(TARGET_ARCH_DBC) && \ - (defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) || \ - defined(HOST_ARCH_ARM64)) + defined(TARGET_ARCH_ARM64) const int kMinimumAlignment = 16; -#elif defined(TARGET_ARCH_ARM) || \ - defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM) +#elif defined(TARGET_ARCH_ARM) const int kMinimumAlignment = 8; #else #error Unsupported architecture. diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc index a0bfa909ef9..dec2cddd021 100644 --- a/runtime/vm/os_fuchsia.cc +++ b/runtime/vm/os_fuchsia.cc @@ -125,13 +125,9 @@ int64_t OS::GetCurrentThreadCPUMicros() { // into a architecture specific file e.g: os_ia32_fuchsia.cc intptr_t OS::ActivationFrameAlignment() { #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ - defined(TARGET_ARCH_ARM64) || \ - defined(TARGET_ARCH_DBC) && \ - (defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) || \ - defined(HOST_ARCH_ARM64)) + defined(TARGET_ARCH_ARM64) const int kMinimumAlignment = 16; -#elif defined(TARGET_ARCH_ARM) || \ - defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM) +#elif defined(TARGET_ARCH_ARM) const int kMinimumAlignment = 8; #else #error Unsupported architecture. diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc index b1a9231dffc..70341061229 100644 --- a/runtime/vm/os_linux.cc +++ b/runtime/vm/os_linux.cc @@ -496,8 +496,7 @@ int64_t OS::GetCurrentThreadCPUMicros() { // into a architecture specific file e.g: os_ia32_linux.cc intptr_t OS::ActivationFrameAlignment() { #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ - defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC) - // DBC alignment should be at least as much as host architecture. + defined(TARGET_ARCH_ARM64) const int kMinimumAlignment = 16; #elif defined(TARGET_ARCH_ARM) const int kMinimumAlignment = 8; diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc index 9fc4bb0cd3e..c18ca45874f 100644 --- a/runtime/vm/os_macos.cc +++ b/runtime/vm/os_macos.cc @@ -139,8 +139,6 @@ intptr_t OS::ActivationFrameAlignment() { return 16; // iOS simulator #elif TARGET_ARCH_X64 return 16; // iOS simulator -#elif TARGET_ARCH_DBC - return 16; // Should be at least as much as any host architecture. #else #error Unimplemented #endif diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc index 736d9b3b0bb..2ed4d87e04e 100644 --- a/runtime/vm/os_win.cc +++ b/runtime/vm/os_win.cc @@ -175,11 +175,9 @@ int64_t OS::GetCurrentThreadCPUMicros() { } intptr_t OS::ActivationFrameAlignment() { -#if defined(TARGET_ARCH_ARM64) || \ - defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM64) +#if defined(TARGET_ARCH_ARM64) return 16; -#elif defined(TARGET_ARCH_ARM) || \ - defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM) +#elif defined(TARGET_ARCH_ARM) return 8; #elif defined(_WIN64) // Windows 64-bit ABI requires the stack to be 16-byte aligned. diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index 6034052fc90..ca7967c68bf 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc @@ -419,11 +419,6 @@ bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { ASSERT(return_address != NULL); return false; } -#elif defined(TARGET_ARCH_DBC) -bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) { - ASSERT(return_address != NULL); - return false; -} #else #error ReturnAddressLocator implementation missing for this architecture. #endif @@ -1014,13 +1009,8 @@ static bool GetAndValidateThreadStackBounds(OSThread* os_thread, Isolate* isolate = thread->isolate(); ASSERT(isolate != NULL); Simulator* simulator = isolate->simulator(); -#if defined(TARGET_ARCH_DBC) - *stack_lower = simulator->stack_base(); - *stack_upper = simulator->stack_limit(); -#else *stack_lower = simulator->stack_limit(); *stack_upper = simulator->stack_base(); -#endif // defined(TARGET_ARCH_DBC) } #else const bool use_simulator_stack_bounds = false; @@ -1068,7 +1058,7 @@ static Sample* SetupSample(Thread* thread, Sample* sample = sample_buffer->ReserveSample(); sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid); uword vm_tag = thread->vm_tag(); -#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) +#if defined(USING_SIMULATOR) // When running in the simulator, the runtime entry function address // (stored as the vm tag) is the address of a redirect function. // Attempt to find the real runtime entry function address and use that. @@ -1362,12 +1352,7 @@ void Profiler::SampleThread(Thread* thread, if (in_dart_code) { // If we're in Dart code, use the Dart stack pointer. -#if defined(TARGET_ARCH_DBC) - simulator = isolate->simulator(); - sp = simulator->get_sp(); - fp = simulator->get_fp(); - pc = simulator->get_pc(); -#elif defined(USING_SIMULATOR) +#if defined(USING_SIMULATOR) simulator = isolate->simulator(); sp = simulator->get_register(SPREG); fp = simulator->get_register(FPREG); diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc index c7f01a7d961..5edf8e38d4c 100644 --- a/runtime/vm/program_visitor.cc +++ b/runtime/vm/program_visitor.cc @@ -117,7 +117,6 @@ void ProgramVisitor::VisitFunctions(FunctionVisitor* visitor) { #if !defined(DART_PRECOMPILED_RUNTIME) void ProgramVisitor::BindStaticCalls() { -#if !defined(TARGET_ARCH_DBC) if (FLAG_precompiled_mode) { return; } @@ -173,7 +172,6 @@ void ProgramVisitor::BindStaticCalls() { BindJITStaticCallsVisitor visitor(Thread::Current()->zone()); ProgramVisitor::VisitFunctions(&visitor); -#endif // !defined(TARGET_ARCH_DBC) } void ProgramVisitor::ShareMegamorphicBuckets() { diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index 7d3dc189c06..e5b7999ca0a 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -792,7 +792,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { const TypeCheckMode mode = static_cast( Smi::CheckedHandle(zone, arguments.ArgAt(6)).Value()); -#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC) +#if defined(TARGET_ARCH_IA32) ASSERT(mode == kTypeCheckFromInline); #endif @@ -820,7 +820,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { // Note that instantiated dst_type may be malbounded. } if (dst_name.IsNull()) { -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) // Can only come here from type testing stub. ASSERT(mode != kTypeCheckFromInline); @@ -848,8 +848,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { } bool should_update_cache = true; -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) && \ - !defined(DART_PRECOMPILED_RUNTIME) +#if !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME) if (mode == kTypeCheckFromLazySpecializeStub) { if (FLAG_trace_type_checks) { OS::PrintErr(" Specializing type testing stub for %s\n", @@ -886,7 +885,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) { if (should_update_cache) { if (cache.IsNull()) { -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) ASSERT(mode == kTypeCheckFromSlowStub); // We lazily create [SubtypeTestCache] for those call sites which actually // need one and will patch the pool entry. @@ -1024,7 +1023,7 @@ DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { UNREACHABLE(); return; } -#elif !defined(TARGET_ARCH_DBC) +#else // Gets called from debug stub when code reaches a breakpoint // set on a runtime stub call. DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { @@ -1041,13 +1040,7 @@ DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { ThrowIfError(error); arguments.SetReturn(orig_stub); } -#else -// Gets called from the simulator when the breakpoint is reached. -DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { - const Error& error = Error::Handle(isolate->debugger()->PauseBreakpoint()); - ThrowIfError(error); -} -#endif // !defined(TARGET_ARCH_DBC) +#endif DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { #if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME) @@ -1130,7 +1123,7 @@ RawFunction* InlineCacheMissHelper(const Class& receiver_class, static void TrySwitchInstanceCall(const ICData& ic_data, const Function& target_function) { -#if !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME) +#if !defined(DART_PRECOMPILED_RUNTIME) // Monomorphic/megamorphic calls only check the receiver CID. if (ic_data.NumArgsTested() != 1) return; @@ -1221,7 +1214,7 @@ static void TrySwitchInstanceCall(const ICData& ic_data, return; // Success. } -#endif // !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME) +#endif // !defined(DART_PRECOMPILED_RUNTIME) } // Perform the subtype and return constant function based on the result. @@ -1417,7 +1410,6 @@ DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { arguments.SetReturn(target); } -#if !defined(TARGET_ARCH_DBC) static bool IsSingleTarget(Isolate* isolate, Zone* zone, intptr_t lower_cid, @@ -1440,17 +1432,12 @@ static bool IsSingleTarget(Isolate* isolate, } return true; } -#endif // Handle a miss of a single target cache. // Arg1: Receiver. // Arg0: Stub out. // Returns: the ICData used to continue with a polymorphic call. DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 2) { -#if defined(TARGET_ARCH_DBC) - // DBC does not use switchable calls. - UNREACHABLE(); -#else const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1)); DartFrameIterator iterator(thread, @@ -1531,7 +1518,6 @@ DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 2) { // IC call stub. arguments.SetArgAt(0, stub); arguments.SetReturn(ic_data); -#endif } #if defined(DART_PRECOMPILED_RUNTIME) @@ -1604,10 +1590,6 @@ const bool kInstructionsCanBeDeduped = false; // Arg0: Stub out. // Returns: the ICData used to continue with a polymorphic call. DEFINE_RUNTIME_ENTRY(UnlinkedCall, 3) { -#if defined(TARGET_ARCH_DBC) - // DBC does not use switchable calls. - UNREACHABLE(); -#else const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1)); const UnlinkedCall& unlinked = UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(2)); @@ -1709,10 +1691,9 @@ DEFINE_RUNTIME_ENTRY(UnlinkedCall, 3) { // stub. arguments.SetArgAt(0, stub); arguments.SetReturn(ic_data); -#endif // !DBC } -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) static RawICData* FindICDataForInstanceCall(Zone* zone, const Code& code, uword pc) { @@ -1730,17 +1711,14 @@ static RawICData* FindICDataForInstanceCall(Zone* zone, ASSERT(deopt_id != -1); return Function::Handle(zone, code.function()).FindICData(deopt_id); } -#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#endif // !defined(DART_PRECOMPILED_RUNTIME) // Handle a miss of a megamorphic cache. // Arg1: Receiver. // Arg0: continuation Code (out parameter). // Returns: the ICData used to continue with a polymorphic call. DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 2) { -#if defined(TARGET_ARCH_DBC) - // DBC does not use switchable calls. - UNREACHABLE(); -#elif defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILED_RUNTIME) const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1)); DartFrameIterator iterator(thread, @@ -1896,7 +1874,7 @@ DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 2) { } arguments.SetArgAt(0, stub); arguments.SetReturn(ic_data); -#endif // !defined(TARGET_ARCH_DBC) +#endif // defined(DART_PRECOMPILED_RUNTIME) } // Handle a miss of a megamorphic cache. @@ -1905,10 +1883,6 @@ DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 2) { // Arg2: Arguments descriptor array. // Returns: target function to call. DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { -#if defined(TARGET_ARCH_DBC) - // DBC does not use megamorphic calls right now. - UNREACHABLE(); -#else const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1)); const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2)); @@ -1995,7 +1969,6 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { cache.Insert(class_id, target_function); } arguments.SetReturn(target_function); -#endif // !defined(TARGET_ARCH_DBC) } // Handles interpreted interface call cache miss. @@ -2448,7 +2421,6 @@ DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { // If an interrupt happens at the same time as a stack overflow, we // process the stack overflow now and leave the interrupt for next // time. - // TODO(regis): Warning: IsCalleeFrameOf is overridden in stack_frame_dbc.h. if (interpreter_stack_overflow || !thread->os_thread()->HasStackHeadroom() || IsCalleeFrameOf(thread->saved_stack_limit(), stack_pos)) { if (FLAG_verbose_stack_overflow) { @@ -2787,30 +2759,6 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { function.SwitchToUnoptimizedCode(); } -#if defined(TARGET_ARCH_DBC) - const Instructions& instrs = - Instructions::Handle(zone, optimized_code.instructions()); - { - WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size()); - CodePatcher::InsertDeoptimizationCallAt(frame->pc()); - if (FLAG_trace_patching) { - const String& name = String::Handle(function.name()); - OS::PrintErr("InsertDeoptimizationCallAt: 0x%" Px " for %s\n", - frame->pc(), name.ToCString()); - } - const ExceptionHandlers& handlers = - ExceptionHandlers::Handle(zone, optimized_code.exception_handlers()); - ExceptionHandlerInfo info; - for (intptr_t i = 0; i < handlers.num_entries(); ++i) { - handlers.GetHandlerInfo(i, &info); - const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset; - CodePatcher::InsertDeoptimizationCallAt(patch_pc); - if (FLAG_trace_patching) { - OS::PrintErr(" at handler 0x%" Px "\n", patch_pc); - } - } - } -#else // !DBC if (frame->IsMarkedForLazyDeopt()) { // Deopt already scheduled. if (FLAG_trace_deoptimization) { @@ -2835,7 +2783,6 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { frame->fp(), deopt_pc); } } -#endif // !DBC // Mark code as dead (do not GC its embedded objects). optimized_code.set_is_alive(false); @@ -2861,13 +2808,8 @@ void DeoptimizeFunctionsOnStack() { } #if !defined(DART_PRECOMPILED_RUNTIME) -#if !defined(TARGET_ARCH_DBC) static const intptr_t kNumberOfSavedCpuRegisters = kNumberOfCpuRegisters; static const intptr_t kNumberOfSavedFpuRegisters = kNumberOfFpuRegisters; -#else -static const intptr_t kNumberOfSavedCpuRegisters = 0; -static const intptr_t kNumberOfSavedFpuRegisters = 0; -#endif static void CopySavedRegisters(uword saved_registers_address, fpu_register_t** fpu_registers, @@ -2936,7 +2878,6 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, (is_lazy_deopt != 0u) ? "lazy-deopt" : ""); } -#if !defined(TARGET_ARCH_DBC) if (is_lazy_deopt != 0u) { uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp()); if (FLAG_trace_deoptimization) { @@ -2956,7 +2897,6 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, caller_frame->pc()); } } -#endif // !DBC // Copy the saved registers from the stack. fpu_register_t* fpu_registers; @@ -3183,8 +3123,7 @@ DEFINE_RAW_LEAF_RUNTIME_ENTRY( uword RuntimeEntry::InterpretCallEntry() { uword entry = reinterpret_cast(RuntimeEntry::InterpretCall); -#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) - // DBC does not use redirections unlike other simulators. +#if defined(USING_SIMULATOR) entry = Simulator::RedirectExternalReference(entry, Simulator::kLeafRuntimeCall, 5); #endif diff --git a/runtime/vm/runtime_entry_dbc.cc b/runtime/vm/runtime_entry_dbc.cc deleted file mode 100644 index c8636a26990..00000000000 --- a/runtime/vm/runtime_entry_dbc.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#include "vm/runtime_entry.h" - -#include "vm/compiler/assembler/assembler.h" -#include "vm/simulator.h" -#include "vm/stub_code.h" - -namespace dart { - -uword RuntimeEntry::GetEntryPoint() const { - return reinterpret_cast(function()); -} - -#if !defined(DART_PRECOMPILED_RUNTIME) -void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry, - compiler::Assembler* assembler, - intptr_t argument_count) { - UNIMPLEMENTED(); -} -#endif // !defined(DART_PRECOMPILED_RUNTIME) - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/simulator.h b/runtime/vm/simulator.h index c746d45c526..3194aa918fd 100644 --- a/runtime/vm/simulator.h +++ b/runtime/vm/simulator.h @@ -15,8 +15,6 @@ #include "vm/simulator_arm.h" #elif defined(TARGET_ARCH_ARM64) #include "vm/simulator_arm64.h" -#elif defined(TARGET_ARCH_DBC) -#include "vm/simulator_dbc.h" #else #error Unknown architecture. #endif // defined(TARGET_ARCH_...) diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc deleted file mode 100644 index a0993b7821d..00000000000 --- a/runtime/vm/simulator_dbc.cc +++ /dev/null @@ -1,4249 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#include // NOLINT -#include - -#include "vm/globals.h" -#if defined(TARGET_ARCH_DBC) - -#if !defined(USING_SIMULATOR) -#error "DBC is a simulated architecture" -#endif - -#include "vm/simulator.h" - -#include "lib/ffi.h" -#include "platform/assert.h" -#include "vm/compiler/assembler/assembler.h" -#include "vm/compiler/assembler/disassembler.h" -#include "vm/compiler/backend/il.h" -#include "vm/compiler/backend/locations.h" -#include "vm/compiler/ffi.h" -#include "vm/compiler/ffi_dbc_trampoline.h" -#include "vm/compiler/jit/compiler.h" -#include "vm/constants_dbc.h" -#include "vm/cpu.h" -#include "vm/dart_entry.h" -#include "vm/debugger.h" -#include "vm/heap/safepoint.h" -#include "vm/lockers.h" -#include "vm/native_arguments.h" -#include "vm/native_entry.h" -#include "vm/object.h" -#include "vm/object_store.h" -#include "vm/os_thread.h" -#include "vm/stack_frame.h" -#include "vm/symbols.h" - -namespace dart { - -DEFINE_FLAG(uint64_t, - trace_sim_after, - ULLONG_MAX, - "Trace simulator execution after instruction count reached."); -DEFINE_FLAG(uint64_t, - stop_sim_at, - ULLONG_MAX, - "Instruction address or instruction count to stop simulator at."); - -// SimulatorSetjmpBuffer are linked together, and the last created one -// is referenced by the Simulator. When an exception is thrown, the exception -// runtime looks at where to jump and finds the corresponding -// SimulatorSetjmpBuffer based on the stack pointer of the exception handler. -// The runtime then does a Longjmp on that buffer to return to the simulator. -class SimulatorSetjmpBuffer { - public: - void Longjmp() { - // "This" is now the last setjmp buffer. - simulator_->set_last_setjmp_buffer(this); - longjmp(buffer_, 1); - } - - explicit SimulatorSetjmpBuffer(Simulator* sim) { - simulator_ = sim; - link_ = sim->last_setjmp_buffer(); - sim->set_last_setjmp_buffer(this); - fp_ = sim->fp_; - } - - ~SimulatorSetjmpBuffer() { - ASSERT(simulator_->last_setjmp_buffer() == this); - simulator_->set_last_setjmp_buffer(link_); - } - - SimulatorSetjmpBuffer* link() const { return link_; } - - uword fp() const { return reinterpret_cast(fp_); } - - jmp_buf buffer_; - - private: - RawObject** fp_; - Simulator* simulator_; - SimulatorSetjmpBuffer* link_; - - friend class Simulator; - - DISALLOW_ALLOCATION(); - DISALLOW_COPY_AND_ASSIGN(SimulatorSetjmpBuffer); -}; - -DART_FORCE_INLINE static RawObject** SavedCallerFP(RawObject** FP) { - return reinterpret_cast(FP[kSavedCallerFpSlotFromFp]); -} - -DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP, - intptr_t argc) { - return FP - (kDartFrameFixedSize + argc); -} - -#define RAW_CAST(Type, val) (SimulatorHelpers::CastTo##Type(val)) - -class SimulatorHelpers { - public: -#define DEFINE_CASTS(Type) \ - DART_FORCE_INLINE static Raw##Type* CastTo##Type(RawObject* obj) { \ - ASSERT((k##Type##Cid == kSmiCid) ? !obj->IsHeapObject() \ - : obj->Is##Type()); \ - return reinterpret_cast(obj); \ - } - CLASS_LIST(DEFINE_CASTS) -#undef DEFINE_CASTS - - DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) { - return Smi::New(obj->IsHeapObject() ? obj->GetClassId() - : static_cast(kSmiCid)); - } - - DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) { - return obj->IsHeapObject() ? obj->GetClassId() - : static_cast(kSmiCid); - } - - DART_FORCE_INLINE static void IncrementUsageCounter(RawFunction* f) { - f->ptr()->usage_counter_++; - } - - DART_FORCE_INLINE static void IncrementICUsageCount(RawObject** entries, - intptr_t offset, - intptr_t args_tested) { - const intptr_t count_offset = ICData::CountIndexFor(args_tested); - const intptr_t raw_smi_old = - reinterpret_cast(entries[offset + count_offset]); - const intptr_t raw_smi_new = raw_smi_old + Smi::RawValue(1); - *reinterpret_cast(&entries[offset + count_offset]) = raw_smi_new; - } - - DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs, - RawObject* rhs) { - if (lhs == rhs) { - return true; - } - - if (lhs->IsHeapObject() && rhs->IsHeapObject()) { - const intptr_t lhs_cid = lhs->GetClassId(); - const intptr_t rhs_cid = rhs->GetClassId(); - if (lhs_cid == rhs_cid) { - switch (lhs_cid) { - case kDoubleCid: - return (bit_cast( - static_cast(lhs)->ptr()->value_) == - bit_cast( - static_cast(rhs)->ptr()->value_)); - - case kMintCid: - return (static_cast(lhs)->ptr()->value_ == - static_cast(rhs)->ptr()->value_); - } - } - } - - return false; - } - - template - DART_FORCE_INLINE static T* Untag(T* tagged) { - return tagged->ptr(); - } - - DART_FORCE_INLINE static bool CheckIndex(RawSmi* index, RawSmi* length) { - return !index->IsHeapObject() && (reinterpret_cast(index) >= 0) && - (reinterpret_cast(index) < - reinterpret_cast(length)); - } - - DART_FORCE_INLINE static intptr_t ArgDescTypeArgsLen(RawArray* argdesc) { - return Smi::Value(*reinterpret_cast( - reinterpret_cast(argdesc->ptr()) + - Array::element_offset(ArgumentsDescriptor::kTypeArgsLenIndex))); - } - - DART_FORCE_INLINE static intptr_t ArgDescArgCount(RawArray* argdesc) { - return Smi::Value(*reinterpret_cast( - reinterpret_cast(argdesc->ptr()) + - Array::element_offset(ArgumentsDescriptor::kCountIndex))); - } - - DART_FORCE_INLINE static intptr_t ArgDescPosCount(RawArray* argdesc) { - return Smi::Value(*reinterpret_cast( - reinterpret_cast(argdesc->ptr()) + - Array::element_offset(ArgumentsDescriptor::kPositionalCountIndex))); - } - - static bool ObjectArraySetIndexed(Thread* thread, - RawObject** FP, - RawObject** result) { - return ObjectArraySetIndexedUnchecked(thread, FP, result); - } - - static bool ObjectArraySetIndexedUnchecked(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 3); - RawSmi* index = static_cast(args[1]); - RawArray* array = static_cast(args[0]); - if (CheckIndex(index, array->ptr()->length_)) { - array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), - args[2], thread); - return true; - } - return false; - } - - static bool ObjectArrayGetIndexed(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 2); - RawSmi* index = static_cast(args[1]); - RawArray* array = static_cast(args[0]); - if (CheckIndex(index, array->ptr()->length_)) { - *result = array->ptr()->data()[Smi::Value(index)]; - return true; - } - return false; - } - - static bool GrowableArraySetIndexed(Thread* thread, - RawObject** FP, - RawObject** result) { - return GrowableArraySetIndexedUnchecked(thread, FP, result); - } - - static bool GrowableArraySetIndexedUnchecked(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 3); - RawSmi* index = static_cast(args[1]); - RawGrowableObjectArray* array = - static_cast(args[0]); - if (CheckIndex(index, array->ptr()->length_)) { - RawArray* data = array->ptr()->data_; - data->StoreArrayPointer(data->ptr()->data() + Smi::Value(index), args[2], - thread); - return true; - } - return false; - } - - static bool GrowableArrayGetIndexed(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 2); - RawSmi* index = static_cast(args[1]); - RawGrowableObjectArray* array = - static_cast(args[0]); - if (CheckIndex(index, array->ptr()->length_)) { - *result = array->ptr()->data_->ptr()->data()[Smi::Value(index)]; - return true; - } - return false; - } - - static bool Double_getIsNan(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 1); - RawDouble* d = static_cast(args[0]); - *result = - isnan(d->ptr()->value_) ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool Double_getIsInfinite(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 1); - RawDouble* d = static_cast(args[0]); - *result = - isinf(d->ptr()->value_) ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool ObjectEquals(Thread* thread, RawObject** FP, RawObject** result) { - RawObject** args = FrameArguments(FP, 2); - *result = args[0] == args[1] ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool ObjectRuntimeType(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 1); - const intptr_t cid = GetClassId(args[0]); - if (cid == kClosureCid) { - return false; - } - if (cid < kNumPredefinedCids) { - if (cid == kDoubleCid) { - *result = thread->isolate()->object_store()->double_type(); - return true; - } else if (RawObject::IsStringClassId(cid)) { - *result = thread->isolate()->object_store()->string_type(); - return true; - } else if (RawObject::IsIntegerClassId(cid)) { - *result = thread->isolate()->object_store()->int_type(); - return true; - } - } - RawClass* cls = thread->isolate()->class_table()->At(cid); - if (cls->ptr()->num_type_arguments_ != 0) { - return false; - } - RawType* typ = cls->ptr()->declaration_type_; - if (typ == Object::null()) { - return false; - } - *result = static_cast(typ); - return true; - } - - static bool GetDoubleOperands(RawObject** args, double* d1, double* d2) { - RawObject* obj2 = args[1]; - if (!obj2->IsHeapObject()) { - *d2 = - static_cast(reinterpret_cast(obj2) >> kSmiTagSize); - } else if (obj2->GetClassId() == kDoubleCid) { - RawDouble* obj2d = static_cast(obj2); - *d2 = obj2d->ptr()->value_; - } else { - return false; - } - RawDouble* obj1 = static_cast(args[0]); - *d1 = obj1->ptr()->value_; - return true; - } - - static RawObject* AllocateDouble(Thread* thread, double value) { - const intptr_t instance_size = Double::InstanceSize(); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - uword tags = 0; - tags = RawObject::ClassIdTag::update(kDoubleCid, tags); - tags = RawObject::SizeTag::update(instance_size, tags); - tags = RawObject::NewBit::update(true, tags); - // Also writes zero in the hash_ field. - *reinterpret_cast(start + Double::tags_offset()) = tags; - *reinterpret_cast(start + Double::value_offset()) = value; - return reinterpret_cast(start + kHeapObjectTag); - } - return NULL; - } - - static bool Double_add(Thread* thread, RawObject** FP, RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - RawObject* new_double = AllocateDouble(thread, d1 + d2); - if (new_double != NULL) { - *result = new_double; - return true; - } - return false; - } - - static bool Double_mul(Thread* thread, RawObject** FP, RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - RawObject* new_double = AllocateDouble(thread, d1 * d2); - if (new_double != NULL) { - *result = new_double; - return true; - } - return false; - } - - static bool Double_sub(Thread* thread, RawObject** FP, RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - RawObject* new_double = AllocateDouble(thread, d1 - d2); - if (new_double != NULL) { - *result = new_double; - return true; - } - return false; - } - - static bool Double_div(Thread* thread, RawObject** FP, RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - RawObject* new_double = AllocateDouble(thread, d1 / d2); - if (new_double != NULL) { - *result = new_double; - return true; - } - return false; - } - - static bool Double_greaterThan(Thread* thread, - RawObject** FP, - RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - *result = d1 > d2 ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool Double_greaterEqualThan(Thread* thread, - RawObject** FP, - RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - *result = d1 >= d2 ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool Double_lessThan(Thread* thread, - RawObject** FP, - RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - *result = d1 < d2 ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool Double_equal(Thread* thread, RawObject** FP, RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - *result = d1 == d2 ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool Double_lessEqualThan(Thread* thread, - RawObject** FP, - RawObject** result) { - double d1, d2; - if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) { - return false; - } - *result = d1 <= d2 ? Bool::True().raw() : Bool::False().raw(); - return true; - } - - static bool ClearAsyncThreadStack(Thread* thread, - RawObject** FP, - RawObject** result) { - thread->clear_async_stack_trace(); - *result = Object::null(); - return true; - } - - static bool SetAsyncThreadStackTrace(Thread* thread, - RawObject** FP, - RawObject** result) { - RawObject** args = FrameArguments(FP, 1); - thread->set_raw_async_stack_trace( - reinterpret_cast(args[0])); - *result = Object::null(); - return true; - } - - DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) { - ASSERT(GetClassId(FP[kPcMarkerSlotFromFp]) == kCodeCid); - return static_cast(FP[kPcMarkerSlotFromFp]); - } - - DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) { - ASSERT(GetClassId(code) == kCodeCid); - FP[kPcMarkerSlotFromFp] = code; - } - - DART_FORCE_INLINE static uint8_t* GetTypedData(RawObject* obj, - RawObject* index) { - ASSERT(RawObject::IsTypedDataClassId(obj->GetClassId())); - RawTypedData* array = reinterpret_cast(obj); - const intptr_t byte_offset = Smi::Value(RAW_CAST(Smi, index)); - ASSERT(byte_offset >= 0); - return array->ptr()->data() + byte_offset; - } -}; - -DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) { - return reinterpret_cast(FP[kSavedCallerPcSlotFromFp]); -} - -DART_FORCE_INLINE static RawFunction* FrameFunction(RawObject** FP) { - RawFunction* function = static_cast(FP[kFunctionSlotFromFp]); - ASSERT(SimulatorHelpers::GetClassId(function) == kFunctionCid || - SimulatorHelpers::GetClassId(function) == kNullCid); - return function; -} - -IntrinsicHandler Simulator::intrinsics_[Simulator::kIntrinsicCount]; - -// Synchronization primitives support. -void Simulator::Init() { - for (intptr_t i = 0; i < kIntrinsicCount; i++) { - intrinsics_[i] = 0; - } - - intrinsics_[kObjectArraySetIndexedIntrinsic] = - SimulatorHelpers::ObjectArraySetIndexed; - intrinsics_[kObjectArraySetIndexedUncheckedIntrinsic] = - SimulatorHelpers::ObjectArraySetIndexedUnchecked; - intrinsics_[kObjectArrayGetIndexedIntrinsic] = - SimulatorHelpers::ObjectArrayGetIndexed; - intrinsics_[kGrowableArraySetIndexedIntrinsic] = - SimulatorHelpers::GrowableArraySetIndexed; - intrinsics_[kGrowableArraySetIndexedUncheckedIntrinsic] = - SimulatorHelpers::GrowableArraySetIndexedUnchecked; - intrinsics_[kGrowableArrayGetIndexedIntrinsic] = - SimulatorHelpers::GrowableArrayGetIndexed; - intrinsics_[kObjectEqualsIntrinsic] = SimulatorHelpers::ObjectEquals; - intrinsics_[kObjectRuntimeTypeIntrinsic] = - SimulatorHelpers::ObjectRuntimeType; - - intrinsics_[kDouble_getIsNaNIntrinsic] = SimulatorHelpers::Double_getIsNan; - intrinsics_[kDouble_getIsInfiniteIntrinsic] = - SimulatorHelpers::Double_getIsInfinite; - intrinsics_[kDouble_addIntrinsic] = SimulatorHelpers::Double_add; - intrinsics_[kDouble_mulIntrinsic] = SimulatorHelpers::Double_mul; - intrinsics_[kDouble_subIntrinsic] = SimulatorHelpers::Double_sub; - intrinsics_[kDouble_divIntrinsic] = SimulatorHelpers::Double_div; - intrinsics_[kDouble_greaterThanIntrinsic] = - SimulatorHelpers::Double_greaterThan; - intrinsics_[kDouble_greaterEqualThanIntrinsic] = - SimulatorHelpers::Double_greaterEqualThan; - intrinsics_[kDouble_lessThanIntrinsic] = SimulatorHelpers::Double_lessThan; - intrinsics_[kDouble_equalIntrinsic] = SimulatorHelpers::Double_equal; - intrinsics_[kDouble_lessEqualThanIntrinsic] = - SimulatorHelpers::Double_lessEqualThan; - intrinsics_[kClearAsyncThreadStackTraceIntrinsic] = - SimulatorHelpers::ClearAsyncThreadStack; - intrinsics_[kSetAsyncThreadStackTraceIntrinsic] = - SimulatorHelpers::SetAsyncThreadStackTrace; -} - -Simulator::Simulator() : stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL) { - // Setup simulator support first. Some of this information is needed to - // setup the architecture state. - // We allocate the stack here, the size is computed as the sum of - // the size specified by the user and the buffer space needed for - // handling stack overflow exceptions. To be safe in potential - // stack underflows we also add some underflow buffer space. - stack_ = new uintptr_t[(OSThread::GetSpecifiedStackSize() + - OSThread::kStackSizeBufferMax + - kSimulatorStackUnderflowSize) / - sizeof(uintptr_t)]; - // Low address. - stack_base_ = reinterpret_cast(stack_) + kSimulatorStackUnderflowSize; - // Limit for StackOverflowError. - overflow_stack_limit_ = stack_base_ + OSThread::GetSpecifiedStackSize(); - // High address. - stack_limit_ = overflow_stack_limit_ + OSThread::kStackSizeBufferMax; - - last_setjmp_buffer_ = NULL; - - DEBUG_ONLY(icount_ = 0); -} - -Simulator::~Simulator() { - delete[] stack_; - Isolate* isolate = Isolate::Current(); - if (isolate != NULL) { - isolate->set_simulator(NULL); - } -} - -// Get the active Simulator for the current isolate. -Simulator* Simulator::Current() { - Isolate* isolate = Isolate::Current(); - Simulator* simulator = isolate->simulator(); - if (simulator == NULL) { - NoSafepointScope no_safepoint; - simulator = new Simulator(); - isolate->set_simulator(simulator); - } - return simulator; -} - -#if defined(DEBUG) -// Returns true if tracing of executed instructions is enabled. -DART_FORCE_INLINE bool Simulator::IsTracingExecution() const { - return icount_ > FLAG_trace_sim_after; -} - -// Prints bytecode instruction at given pc for instruction tracing. -DART_NOINLINE void Simulator::TraceInstruction(uint32_t* pc) const { - THR_Print("%" Pu64 " ", icount_); - if (FLAG_support_disassembler) { - Disassembler::Disassemble(reinterpret_cast(pc), - reinterpret_cast(pc + 1)); - } else { - THR_Print("Disassembler not supported in this mode.\n"); - } -} -#endif // defined(DEBUG) - -// Calls into the Dart runtime are based on this interface. -typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); - -// Calls to leaf Dart runtime functions are based on this interface. -typedef intptr_t (*SimulatorLeafRuntimeCall)(intptr_t r0, - intptr_t r1, - intptr_t r2, - intptr_t r3); - -// Calls to leaf float Dart runtime functions are based on this interface. -typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); - -// Set up an exit frame for the garbage collector. -void Simulator::Exit(Thread* thread, - RawObject** base, - RawObject** frame, - uint32_t* pc) { - frame[0] = Function::null(); - frame[1] = Code::null(); - frame[2] = reinterpret_cast(pc); - frame[3] = reinterpret_cast(base); - fp_ = frame + kDartFrameFixedSize; - thread->set_top_exit_frame_info(reinterpret_cast(fp_)); -} - -// TODO(vegorov): Investigate advantages of using -// __builtin_s{add,sub,mul}_overflow() intrinsics here and below. -// Note that they may clobber the output location even when there is overflow: -// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html -DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs, - intptr_t rhs, - intptr_t* out) { - intptr_t res = 1; -#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) - asm volatile( - "add %2, %1\n" - "jo 1f;\n" - "xor %0, %0\n" - "mov %1, 0(%3)\n" - "1: " - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) - asm volatile( - "adds %1, %1, %2;\n" - "bvs 1f;\n" - "mov %0, #0;\n" - "str %1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#else -#error "Unsupported platform" -#endif - return (res != 0); -} - -DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs, - intptr_t rhs, - intptr_t* out) { - intptr_t res = 1; -#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) - asm volatile( - "sub %2, %1\n" - "jo 1f;\n" - "xor %0, %0\n" - "mov %1, 0(%3)\n" - "1: " - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64) - asm volatile( - "subs %1, %1, %2;\n" - "bvs 1f;\n" - "mov %0, #0;\n" - "str %1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#else -#error "Unsupported platform" -#endif - return (res != 0); -} - -DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs, - intptr_t rhs, - intptr_t* out) { - const intptr_t kMaxBits = (sizeof(intptr_t) * 8) - 2; - if ((Utils::HighestBit(lhs) + Utils::HighestBit(rhs)) < kMaxBits) { - *out = lhs * rhs; - return false; - } - return true; -} - -DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) { - return ((a | b) & kHeapObjectTag) == 0; -} - -#define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres) -#define SMI_COND(cond, lhs, rhs, pres) \ - ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false) -#define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres) -#define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres) -#define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres) -#define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false) -#define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false) -#define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false) - -void Simulator::CallRuntime(Thread* thread, - RawObject** base, - RawObject** exit_frame, - uint32_t* pc, - intptr_t argc_tag, - RawObject** args, - RawObject** result, - uword target) { - Exit(thread, base, exit_frame, pc); - NativeArguments native_args(thread, argc_tag, args, result); - reinterpret_cast(target)(native_args); -} - -DART_FORCE_INLINE static void EnterSyntheticFrame(RawObject*** FP, - RawObject*** SP, - uint32_t* pc) { - RawObject** fp = *SP + kDartFrameFixedSize; - fp[kPcMarkerSlotFromFp] = 0; - fp[kSavedCallerPcSlotFromFp] = reinterpret_cast(pc); - fp[kSavedCallerFpSlotFromFp] = reinterpret_cast(*FP); - *FP = fp; - *SP = fp - 1; -} - -DART_FORCE_INLINE static void LeaveSyntheticFrame(RawObject*** FP, - RawObject*** SP) { - RawObject** fp = *FP; - *FP = reinterpret_cast(fp[kSavedCallerFpSlotFromFp]); - *SP = fp - kDartFrameFixedSize; -} - -DART_FORCE_INLINE void Simulator::Invoke(Thread* thread, - RawObject** call_base, - RawObject** call_top, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP) { - RawObject** callee_fp = call_top + kDartFrameFixedSize; - - RawFunction* function = FrameFunction(callee_fp); - RawCode* code = function->ptr()->code_; - callee_fp[kPcMarkerSlotFromFp] = code; - callee_fp[kSavedCallerPcSlotFromFp] = reinterpret_cast(*pc); - callee_fp[kSavedCallerFpSlotFromFp] = reinterpret_cast(*FP); - pp_ = code->ptr()->object_pool_; - *pc = reinterpret_cast(code->ptr()->entry_point_); - pc_ = reinterpret_cast(*pc); // For the profiler. - *FP = callee_fp; - *SP = *FP - 1; -} - -void Simulator::InlineCacheMiss(int checked_args, - Thread* thread, - RawICData* icdata, - RawObject** args, - RawObject** top, - uint32_t* pc, - RawObject** FP, - RawObject** SP) { - RawObject** result = top; - top[0] = 0; // Clean up result slot. - - // Save arguments descriptor as it may be clobbered by running Dart code - // during the call to miss handler (class finalization). - top[1] = argdesc_; - - RawObject** miss_handler_args = top + 2; - for (intptr_t i = 0; i < checked_args; i++) { - miss_handler_args[i] = args[i]; - } - miss_handler_args[checked_args] = icdata; - RuntimeFunction handler = NULL; - switch (checked_args) { - case 1: - handler = DRT_InlineCacheMissHandlerOneArg; - break; - case 2: - handler = DRT_InlineCacheMissHandlerTwoArgs; - break; - default: - UNREACHABLE(); - break; - } - - // Handler arguments: arguments to check and an ICData object. - const intptr_t miss_handler_argc = checked_args + 1; - RawObject** exit_frame = miss_handler_args + miss_handler_argc; - CallRuntime(thread, FP, exit_frame, pc, miss_handler_argc, miss_handler_args, - result, reinterpret_cast(handler)); - - argdesc_ = Array::RawCast(top[1]); -} - -DART_FORCE_INLINE void Simulator::InstanceCall1(Thread* thread, - RawICData* icdata, - RawObject** call_base, - RawObject** top, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP, - bool optimized) { - ASSERT(icdata->GetClassId() == kICDataCid); - - const intptr_t kCheckedArgs = 1; - RawObject** args = call_base; - RawArray* cache = icdata->ptr()->entries_->ptr(); - - const intptr_t type_args_len = - SimulatorHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_); - const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0; - RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[receiver_idx]); - - bool found = false; - const intptr_t length = Smi::Value(cache->length_); - intptr_t i; - for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { - if (cache->data()[i + 0] == receiver_cid) { - top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)]; - found = true; - break; - } - } - - argdesc_ = icdata->ptr()->args_descriptor_; - - if (found) { - if (!optimized) { - SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs); - } - } else { - InlineCacheMiss(kCheckedArgs, thread, icdata, call_base + receiver_idx, top, - *pc, *FP, *SP); - } - - Invoke(thread, call_base, top, pc, FP, SP); -} - -DART_FORCE_INLINE void Simulator::InstanceCall2(Thread* thread, - RawICData* icdata, - RawObject** call_base, - RawObject** top, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP, - bool optimized) { - ASSERT(icdata->GetClassId() == kICDataCid); - - const intptr_t kCheckedArgs = 2; - RawObject** args = call_base; - RawArray* cache = icdata->ptr()->entries_->ptr(); - - const intptr_t type_args_len = - SimulatorHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_); - const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0; - RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[receiver_idx]); - RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[receiver_idx + 1]); - - bool found = false; - const intptr_t length = Smi::Value(cache->length_); - intptr_t i; - for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) { - if ((cache->data()[i + 0] == receiver_cid) && - (cache->data()[i + 1] == arg0_cid)) { - top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)]; - found = true; - break; - } - } - - argdesc_ = icdata->ptr()->args_descriptor_; - - if (found) { - if (!optimized) { - SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs); - } - } else { - InlineCacheMiss(kCheckedArgs, thread, icdata, call_base + receiver_idx, top, - *pc, *FP, *SP); - } - - Invoke(thread, call_base, top, pc, FP, SP); -} - -DART_FORCE_INLINE void Simulator::PrepareForTailCall( - RawCode* code, - RawImmutableArray* args_desc, - RawObject** FP, - RawObject*** SP, - uint32_t** pc) { - // Drop all stack locals. - *SP = FP - 1; - - // Replace the callee with the new [code]. - FP[kFunctionSlotFromFp] = Object::null(); - FP[kPcMarkerSlotFromFp] = code; - *pc = reinterpret_cast(code->ptr()->entry_point_); - pc_ = reinterpret_cast(pc); // For the profiler. - pp_ = code->ptr()->object_pool_; - argdesc_ = args_desc; -} - -// Note: functions below are marked DART_NOINLINE to recover performance where -// inlining these functions into the interpreter loop seemed to cause some code -// quality issues. Functions with the "returns_twice" attribute, such as setjmp, -// prevent reusing spill slots and large frame sizes. -DART_NOINLINE static bool InvokeRuntime(Thread* thread, - Simulator* sim, - RuntimeFunction drt, - const NativeArguments& args) { - SimulatorSetjmpBuffer buffer(sim); - if (!setjmp(buffer.buffer_)) { - thread->set_vm_tag(reinterpret_cast(drt)); - drt(args); - thread->set_vm_tag(VMTag::kDartCompiledTagId); - thread->set_top_exit_frame_info(0); - return true; - } else { - return false; - } -} - -DART_NOINLINE static bool InvokeNative(Thread* thread, - Simulator* sim, - NativeFunctionWrapper wrapper, - Dart_NativeFunction function, - Dart_NativeArguments args) { - SimulatorSetjmpBuffer buffer(sim); - if (!setjmp(buffer.buffer_)) { - thread->set_vm_tag(reinterpret_cast(function)); - wrapper(args, function); - thread->set_vm_tag(VMTag::kDartCompiledTagId); - thread->set_top_exit_frame_info(0); - return true; - } else { - return false; - } -} - -// Note: all macro helpers are intended to be used only inside Simulator::Call. - -// Counts and prints executed bytecode instructions (in DEBUG mode). -#if defined(DEBUG) -#define TRACE_INSTRUCTION \ - icount_++; \ - if (IsTracingExecution()) { \ - TraceInstruction(pc - 1); \ - } -#else -#define TRACE_INSTRUCTION -#endif // defined(DEBUG) - -// Decode opcode and A part of the given value and dispatch to the -// corresponding bytecode handler. -#ifdef DART_HAS_COMPUTED_GOTO -#define DISPATCH_OP(val) \ - do { \ - op = (val); \ - rA = ((op >> 8) & 0xFF); \ - TRACE_INSTRUCTION \ - goto* dispatch[op & 0xFF]; \ - } while (0) -#else -#define DISPATCH_OP(val) \ - do { \ - op = (val); \ - rA = ((op >> 8) & 0xFF); \ - TRACE_INSTRUCTION \ - goto SwitchDispatch; \ - } while (0) -#endif - -// Fetch next operation from PC, increment program counter and dispatch. -#define DISPATCH() DISPATCH_OP(*pc++) - -// Define entry point that handles bytecode Name with the given operand format. -#define BYTECODE(Name, Operands) \ - BYTECODE_HEADER(Name, DECLARE_##Operands, DECODE_##Operands) - -#define BYTECODE_HEADER(Name, Declare, Decode) \ - Declare; \ - bc##Name : Decode - -// Helpers to decode common instruction formats. Used in conjunction with -// BYTECODE() macro. -#define DECLARE_A_B_C \ - uint16_t rB, rC; \ - USE(rB); \ - USE(rC) -#define DECODE_A_B_C \ - rB = ((op >> SimulatorBytecode::kBShift) & SimulatorBytecode::kBMask); \ - rC = ((op >> SimulatorBytecode::kCShift) & SimulatorBytecode::kCMask); - -#define DECLARE_A_B_Y \ - uint16_t rB; \ - int8_t rY; \ - USE(rB); \ - USE(rY) -#define DECODE_A_B_Y \ - rB = ((op >> SimulatorBytecode::kBShift) & SimulatorBytecode::kBMask); \ - rY = ((op >> SimulatorBytecode::kYShift) & SimulatorBytecode::kYMask); - -#define DECLARE_0 -#define DECODE_0 - -#define DECLARE_A -#define DECODE_A - -#define DECLARE___D \ - uint32_t rD; \ - USE(rD) -#define DECODE___D rD = (op >> SimulatorBytecode::kDShift); - -#define DECLARE_A_D DECLARE___D -#define DECODE_A_D DECODE___D - -#define DECLARE_A_X \ - int32_t rD; \ - USE(rD) -#define DECODE_A_X \ - rD = (static_cast(op) >> SimulatorBytecode::kDShift); - -#define SMI_FASTPATH_ICDATA_INC \ - do { \ - ASSERT(SimulatorBytecode::IsCallOpcode(*pc)); \ - const uint16_t kidx = SimulatorBytecode::DecodeD(*pc); \ - const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); \ - RawObject** entries = icdata->ptr()->entries_->ptr()->data(); \ - SimulatorHelpers::IncrementICUsageCount(entries, 0, 2); \ - } while (0); - -// Declare bytecode handler for a smi operation (e.g. AddTOS) with the -// given result type and the given behavior specified as a function -// that takes left and right operands and result slot and returns -// true if fast-path succeeds. -#define SMI_FASTPATH_TOS(ResultT, Func) \ - { \ - const intptr_t lhs = reinterpret_cast(SP[-1]); \ - const intptr_t rhs = reinterpret_cast(SP[-0]); \ - ResultT* slot = reinterpret_cast(SP - 1); \ - if (NOT_IN_PRODUCT(LIKELY(!thread->isolate()->single_step()) &&) \ - LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) { \ - SMI_FASTPATH_ICDATA_INC; \ - /* Fast path succeeded. Skip the generic call that follows. */ \ - pc++; \ - /* We dropped 2 arguments and push result */ \ - SP--; \ - } \ - } - -// Skip the next instruction if there is no overflow. -#define SMI_OP_CHECK(ResultT, Func) \ - { \ - const intptr_t lhs = reinterpret_cast(FP[rB]); \ - const intptr_t rhs = reinterpret_cast(FP[rC]); \ - ResultT* slot = reinterpret_cast(&FP[rA]); \ - if (LIKELY(!Func(lhs, rhs, slot))) { \ - /* Success. Skip the instruction that follows. */ \ - pc++; \ - } \ - } - -// Do not check for overflow. -#define SMI_OP_NOCHECK(ResultT, Func) \ - { \ - const intptr_t lhs = reinterpret_cast(FP[rB]); \ - const intptr_t rhs = reinterpret_cast(FP[rC]); \ - ResultT* slot = reinterpret_cast(&FP[rA]); \ - Func(lhs, rhs, slot); \ - } - -// Exception handling helper. Gets handler FP and PC from the Simulator where -// they were stored by Simulator::Longjmp and proceeds to execute the handler. -// Corner case: handler PC can be a fake marker that marks entry frame, which -// means exception was not handled in the Dart code. In this case we return -// caught exception from Simulator::Call. -#define HANDLE_EXCEPTION \ - do { \ - FP = reinterpret_cast(fp_); \ - pc = reinterpret_cast(pc_); \ - if ((reinterpret_cast(pc) & 2) != 0) { /* Entry frame? */ \ - fp_ = reinterpret_cast(fp_[0]); \ - thread->set_top_exit_frame_info(reinterpret_cast(fp_)); \ - thread->set_top_resource(top_resource); \ - thread->set_vm_tag(vm_tag); \ - return special_[kExceptionSpecialIndex]; \ - } \ - pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_; \ - goto DispatchAfterException; \ - } while (0) - -#define HANDLE_RETURN \ - do { \ - pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_; \ - } while (0) - -// Runtime call helpers: handle invocation and potential exception after return. -#define INVOKE_RUNTIME(Func, Args) \ - if (!InvokeRuntime(thread, this, Func, Args)) { \ - HANDLE_EXCEPTION; \ - } else { \ - HANDLE_RETURN; \ - } - -#define INVOKE_NATIVE(Wrapper, Func, Args) \ - if (!InvokeNative(thread, this, Wrapper, Func, Args)) { \ - HANDLE_EXCEPTION; \ - } else { \ - HANDLE_RETURN; \ - } - -#define LOAD_CONSTANT(index) (pp_->ptr()->data()[(index)].raw_obj_) - -// Returns true if deoptimization succeeds. -DART_FORCE_INLINE bool Simulator::Deoptimize(Thread* thread, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP, - bool is_lazy) { - // Note: frame translation will take care of preserving result at the - // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo. - - // Make sure we preserve SP[0] when entering synthetic frame below. - (*SP)++; - - // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. - // The code in this frame may not cause GC. - // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls. - EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); - const intptr_t frame_size_in_bytes = - DLRT_DeoptimizeCopyFrame(reinterpret_cast(*FP), is_lazy ? 1 : 0); - LeaveSyntheticFrame(FP, SP); - - *SP = *FP + (frame_size_in_bytes / kWordSize); - EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); - DLRT_DeoptimizeFillFrame(reinterpret_cast(*FP)); - - // We are now inside a valid frame. - { - *++(*SP) = 0; // Space for the result: number of materialization args. - Exit(thread, *FP, *SP + 1, /*pc=*/0); - NativeArguments native_args(thread, 0, *SP, *SP); - if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) { - return false; - } - } - const intptr_t materialization_arg_count = - Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize; - - // Restore caller PC. - *pc = SavedCallerPC(*FP); - pc_ = reinterpret_cast(*pc); // For the profiler. - - // Check if it is a fake PC marking the entry frame. - ASSERT((reinterpret_cast(*pc) & 2) == 0); - - // Restore SP, FP and PP. - // Unoptimized frame SP is one below FrameArguments(...) because - // FrameArguments(...) returns a pointer to the first argument. - *SP = FrameArguments(*FP, materialization_arg_count) - 1; - *FP = SavedCallerFP(*FP); - - // Restore pp. - pp_ = SimulatorHelpers::FrameCode(*FP)->ptr()->object_pool_; - - return true; -} - -RawObject* Simulator::Call(const Code& code, - const Array& arguments_descriptor, - const Array& arguments, - Thread* thread) { - // Interpreter state (see constants_dbc.h for high-level overview). - uint32_t* pc; // Program Counter: points to the next op to execute. - RawObject** FP; // Frame Pointer. - RawObject** SP; // Stack Pointer. - - uint32_t op; // Currently executing op. - uint16_t rA; // A component of the currently executing op. - - if (fp_ == NULL) { - fp_ = reinterpret_cast(stack_base_); - } - - // Save current VM tag and mark thread as executing Dart code. - const uword vm_tag = thread->vm_tag(); - thread->set_vm_tag(VMTag::kDartCompiledTagId); - - // Save current top stack resource and reset the list. - StackResource* top_resource = thread->top_resource(); - thread->set_top_resource(NULL); - - // Setup entry frame: - // - // ^ - // | previous Dart frames - // ~~~~~~~~~~~~~~~ | - // | ........... | -+ - // fp_ > | | saved top_exit_frame_info - // | arg 0 | -+ - // ~~~~~~~~~~~~~~~ | - // > incoming arguments - // ~~~~~~~~~~~~~~~ | - // | arg 1 | -+ - // | function | -+ - // | code | | - // | caller PC | ---> special fake PC marking an entry frame - // SP > | fp_ | | - // FP > | ........... | > normal Dart frame (see stack_frame_dbc.h) - // | - // v - // - FP = fp_ + 1 + arguments.Length() + kDartFrameFixedSize; - SP = FP - 1; - - // Save outer top_exit_frame_info. - fp_[0] = reinterpret_cast(thread->top_exit_frame_info()); - thread->set_top_exit_frame_info(0); - - // Copy arguments and setup the Dart frame. - const intptr_t argc = arguments.Length(); - for (intptr_t i = 0; i < argc; i++) { - fp_[1 + i] = arguments.At(i); - } - - FP[kFunctionSlotFromFp] = code.function(); - FP[kPcMarkerSlotFromFp] = code.raw(); - FP[kSavedCallerPcSlotFromFp] = reinterpret_cast((argc << 2) | 2); - FP[kSavedCallerFpSlotFromFp] = reinterpret_cast(fp_); - - // Load argument descriptor. - argdesc_ = arguments_descriptor.raw(); - - // Ready to start executing bytecode. Load entry point and corresponding - // object pool. - pc = reinterpret_cast(code.raw()->ptr()->entry_point_); - pc_ = reinterpret_cast(pc); // For the profiler. - pp_ = code.object_pool(); - - // Cache some frequently used values in the frame. - RawBool* true_value = Bool::True().raw(); - RawBool* false_value = Bool::False().raw(); - RawObject* null_value = Object::null(); - -#if defined(DEBUG) - Function& function_h = Function::Handle(); -#endif - -#ifdef DART_HAS_COMPUTED_GOTO - static const void* dispatch[] = { -#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, - BYTECODES_LIST(TARGET) -#undef TARGET - }; - DISPATCH(); // Enter the dispatch loop. -#else - DISPATCH(); // Enter the dispatch loop. -SwitchDispatch: - switch (op & 0xFF) { -#define TARGET(name, fmt, fmta, fmtb, fmtc) \ - case SimulatorBytecode::k##name: \ - goto bc##name; - BYTECODES_LIST(TARGET) -#undef TARGET - default: - FATAL1("Undefined opcode: %d\n", op); - } -#endif - - // Bytecode handlers (see constants_dbc.h for bytecode descriptions). - { - BYTECODE(Entry, A_D); - const uint16_t num_locals = rD; - - // Initialize locals with null & set SP. - for (intptr_t i = 0; i < num_locals; i++) { - FP[i] = null_value; - } - SP = FP + num_locals - 1; - - DISPATCH(); - } - - { - BYTECODE(EntryOptimized, A_D); - const uint16_t num_registers = rD; - - // Reserve space for registers used by the optimized code. - SP = FP + num_registers - 1; - - DISPATCH(); - } - - { - BYTECODE(Frame, A_D); - // Initialize locals with null and increment SP. - const uint16_t num_locals = rD; - for (intptr_t i = 1; i <= num_locals; i++) { - SP[i] = null_value; - } - SP += num_locals; - - DISPATCH(); - } - - { - BYTECODE(SetFrame, A); - SP = FP + rA - 1; - DISPATCH(); - } - - { - BYTECODE(Compile, 0); - FP[0] = argdesc_; - FP[1] = FrameFunction(FP); - FP[2] = 0; - Exit(thread, FP, FP + 3, pc); - NativeArguments args(thread, 1, FP + 1, FP + 2); - INVOKE_RUNTIME(DRT_CompileFunction, args); - { - // Function should be compiled now, dispatch to its entry point. - RawCode* code = FrameFunction(FP)->ptr()->code_; - SimulatorHelpers::SetFrameCode(FP, code); - pp_ = code->ptr()->object_pool_; - pc = reinterpret_cast(code->ptr()->entry_point_); - pc_ = reinterpret_cast(pc); // For the profiler. - argdesc_ = static_cast(FP[0]); - } - DISPATCH(); - } - - { - BYTECODE(HotCheck, A_D); - const uint8_t increment = rA; - const uint16_t threshold = rD; - RawFunction* f = FrameFunction(FP); - int32_t counter = f->ptr()->usage_counter_; - // Note: we don't increment usage counter in the prologue of optimized - // functions. - if (increment) { - counter += increment; - f->ptr()->usage_counter_ = counter; - } - if (UNLIKELY(counter >= threshold)) { - FP[0] = f; - FP[1] = 0; - - // Save the args desriptor which came in. - FP[2] = argdesc_; - - // Make the DRT_OptimizeInvokedFunction see a stub as its caller for - // consistency with the other architectures, and to avoid needing to - // generate a stackmap for the HotCheck pc. - const Code& stub = StubCode::OptimizeFunction(); - FP[kPcMarkerSlotFromFp] = stub.raw(); - pc = reinterpret_cast(stub.EntryPoint()); - - Exit(thread, FP, FP + 3, pc); - NativeArguments args(thread, 1, /*argv=*/FP, /*retval=*/FP + 1); - INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, args); - { - // DRT_OptimizeInvokedFunction returns the code object to execute. - ASSERT(FP[1]->GetClassId() == kFunctionCid); - RawFunction* function = static_cast(FP[1]); - RawCode* code = function->ptr()->code_; - SimulatorHelpers::SetFrameCode(FP, code); - - // Restore args descriptor which came in. - argdesc_ = Array::RawCast(FP[2]); - - pp_ = code->ptr()->object_pool_; - pc = reinterpret_cast(function->ptr()->entry_point_); - pc_ = reinterpret_cast(pc); // For the profiler. - } - } - DISPATCH(); - } - - { - BYTECODE(CheckStack, A); - { - if (reinterpret_cast(SP) >= thread->stack_limit()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_StackOverflow, args); - } - } - DISPATCH(); - } - - { - BYTECODE(CheckStackAlwaysExit, A); - { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_StackOverflow, args); - } - DISPATCH(); - } - - { - BYTECODE(CheckFunctionTypeArgs, A_D); - const uint16_t declared_type_args_len = rA; - const uint16_t first_stack_local_index = rD; - - // Decode arguments descriptor's type args len. - const intptr_t type_args_len = - SimulatorHelpers::ArgDescTypeArgsLen(argdesc_); - if ((type_args_len != declared_type_args_len) && (type_args_len != 0)) { - goto ClosureNoSuchMethod; - } - if (type_args_len > 0) { - // Decode arguments descriptor's argument count (excluding type args). - const intptr_t arg_count = SimulatorHelpers::ArgDescArgCount(argdesc_); - // Copy passed-in type args to first local slot. - FP[first_stack_local_index] = *FrameArguments(FP, arg_count + 1); - } else if (declared_type_args_len > 0) { - FP[first_stack_local_index] = Object::null(); - } - DISPATCH(); - } - - { - BYTECODE(DebugStep, A); -#ifdef PRODUCT - FATAL("No debugging in PRODUCT mode"); -#else - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } -#endif // !PRODUCT - DISPATCH(); - } - - { - BYTECODE(DebugBreak, A); -#ifdef PRODUCT - FATAL("No debugging in PRODUCT mode"); -#else - { - const uint32_t original_bc = - static_cast(reinterpret_cast( - thread->isolate()->debugger()->GetPatchedStubAddress( - reinterpret_cast(pc)))); - - SP[1] = null_value; - Exit(thread, FP, SP + 2, pc); - NativeArguments args(thread, 0, NULL, SP + 1); - INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args) - DISPATCH_OP(original_bc); - } -#endif - DISPATCH(); - } - - { - BYTECODE(InstantiateType, A_D); - // Stack: instantiator type args, function type args - RawObject* type = LOAD_CONSTANT(rD); - SP[1] = type; - SP[2] = SP[-1]; - SP[3] = SP[0]; - Exit(thread, FP, SP + 4, pc); - { - NativeArguments args(thread, 3, SP + 1, SP - 1); - INVOKE_RUNTIME(DRT_InstantiateType, args); - } - SP -= 1; - DISPATCH(); - } - - { - BYTECODE(InstantiateTypeArgumentsTOS, A_D); - // Stack: instantiator type args, function type args - RawTypeArguments* type_arguments = - static_cast(LOAD_CONSTANT(rD)); - - RawObject* instantiator_type_args = SP[-1]; - RawObject* function_type_args = SP[0]; - // If both instantiators are null and if the type argument vector - // instantiated from null becomes a vector of dynamic, then use null as - // the type arguments. - if ((rA == 0) || (null_value != instantiator_type_args) || - (null_value != function_type_args)) { - // First lookup in the cache. - RawArray* instantiations = type_arguments->ptr()->instantiations_; - for (intptr_t i = 0; - instantiations->ptr()->data()[i] != NULL; // kNoInstantiator - i += 3) { // kInstantiationSizeInWords - if ((instantiations->ptr()->data()[i] == instantiator_type_args) && - (instantiations->ptr()->data()[i + 1] == function_type_args)) { - // Found in the cache. - SP[-1] = instantiations->ptr()->data()[i + 2]; - goto InstantiateTypeArgumentsTOSDone; - } - } - - // Cache lookup failed, call runtime. - SP[1] = type_arguments; - SP[2] = instantiator_type_args; - SP[3] = function_type_args; - - Exit(thread, FP, SP + 4, pc); - NativeArguments args(thread, 3, SP + 1, SP - 1); - INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args); - } - - InstantiateTypeArgumentsTOSDone: - SP -= 1; - DISPATCH(); - } - - { - BYTECODE(Throw, A); - { - SP[1] = 0; // Space for result. - Exit(thread, FP, SP + 2, pc); - if (rA == 0) { // Throw - NativeArguments args(thread, 1, SP, SP + 1); - INVOKE_RUNTIME(DRT_Throw, args); - } else { // ReThrow - NativeArguments args(thread, 2, SP - 1, SP + 1); - INVOKE_RUNTIME(DRT_ReThrow, args); - } - } - DISPATCH(); - } - - { - BYTECODE(Drop1, 0); - SP--; - DISPATCH(); - } - - { - BYTECODE(Drop, 0); - SP -= rA; - DISPATCH(); - } - - { - BYTECODE(DropR, 0); - RawObject* result = SP[0]; - SP -= rA; - SP[0] = result; - DISPATCH(); - } - - { - BYTECODE(LoadConstant, A_D); - FP[rA] = LOAD_CONSTANT(rD); - DISPATCH(); - } - - { - BYTECODE(PushConstant, __D); - *++SP = LOAD_CONSTANT(rD); - DISPATCH(); - } - - { - BYTECODE(Push, A_X); - *++SP = FP[rD]; - DISPATCH(); - } - - { - BYTECODE(Move, A_X); - FP[rA] = FP[rD]; - DISPATCH(); - } - - { - BYTECODE(Swap, A_X); - RawObject* tmp = FP[rD]; - FP[rD] = FP[rA]; - FP[rA] = tmp; - DISPATCH(); - } - - { - BYTECODE(StoreLocal, A_X); - FP[rD] = *SP; - DISPATCH(); - } - - { - BYTECODE(PopLocal, A_X); - FP[rD] = *SP--; - DISPATCH(); - } - - { - BYTECODE(MoveSpecial, A_D); - FP[rA] = special_[rD]; - DISPATCH(); - } - - { - BYTECODE(BooleanNegateTOS, 0); - SP[0] = (SP[0] == true_value) ? false_value : true_value; - DISPATCH(); - } - - { - BYTECODE(BooleanNegate, A_D); - FP[rA] = (FP[rD] == true_value) ? false_value : true_value; - DISPATCH(); - } - - { - BYTECODE(IndirectStaticCall, A_D); - -#ifndef PRODUCT - // Check if single stepping. - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } -#endif // !PRODUCT - - // Invoke target function. - { - const uint16_t argc = rA; - // Look up the function in the ICData. - RawObject* ic_data_obj = SP[0]; - RawICData* ic_data = RAW_CAST(ICData, ic_data_obj); - RawObject** data = ic_data->ptr()->entries_->ptr()->data(); - SimulatorHelpers::IncrementICUsageCount(data, 0, 0); - SP[0] = data[ICData::TargetIndexFor(ic_data->ptr()->state_bits_ & 0x3)]; - RawObject** call_base = SP - argc; - RawObject** call_top = SP; // *SP contains function - argdesc_ = static_cast(LOAD_CONSTANT(rD)); - Invoke(thread, call_base, call_top, &pc, &FP, &SP); - } - - DISPATCH(); - } - - { - BYTECODE(StaticCall, A_D); - const uint16_t argc = rA; - RawObject** call_base = SP - argc; - RawObject** call_top = SP; // *SP contains function - argdesc_ = static_cast(LOAD_CONSTANT(rD)); - Invoke(thread, call_base, call_top, &pc, &FP, &SP); - DISPATCH(); - } - - { - BYTECODE(InstanceCall1, A_D); - -#ifndef PRODUCT - // Check if single stepping. - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } -#endif // !PRODUCT - - { - const uint16_t argc = rA; - const uint16_t kidx = rD; - - RawObject** call_base = SP - argc + 1; - RawObject** call_top = SP + 1; - - RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); - SimulatorHelpers::IncrementUsageCounter( - RAW_CAST(Function, icdata->ptr()->owner_)); - InstanceCall1(thread, icdata, call_base, call_top, &pc, &FP, &SP, - false /* optimized */); - } - - DISPATCH(); - } - - { - BYTECODE(InstanceCall2, A_D); - -#ifndef PRODUCT - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } -#endif // !PRODUCT - - { - const uint16_t argc = rA; - const uint16_t kidx = rD; - - RawObject** call_base = SP - argc + 1; - RawObject** call_top = SP + 1; - - RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); - SimulatorHelpers::IncrementUsageCounter( - RAW_CAST(Function, icdata->ptr()->owner_)); - InstanceCall2(thread, icdata, call_base, call_top, &pc, &FP, &SP, - false /* optimized */); - } - - DISPATCH(); - } - - { - BYTECODE(InstanceCall1Opt, A_D); - - { - const uint16_t argc = rA; - const uint16_t kidx = rD; - - RawObject** call_base = SP - argc + 1; - RawObject** call_top = SP + 1; - - RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); - SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP)); - InstanceCall1(thread, icdata, call_base, call_top, &pc, &FP, &SP, - true /* optimized */); - } - - DISPATCH(); - } - - { - BYTECODE(InstanceCall2Opt, A_D); - - { - const uint16_t argc = rA; - const uint16_t kidx = rD; - - RawObject** call_base = SP - argc + 1; - RawObject** call_top = SP + 1; - - RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); - SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP)); - InstanceCall2(thread, icdata, call_base, call_top, &pc, &FP, &SP, - true /* optimized */); - } - - DISPATCH(); - } - - { - BYTECODE(PushPolymorphicInstanceCall, A_D); - const uint8_t argc = rA; - const intptr_t cids_length = rD; - RawObject** args = SP - argc + 1; - const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]); - for (intptr_t i = 0; i < 2 * cids_length; i += 2) { - const intptr_t icdata_cid = SimulatorBytecode::DecodeD(*(pc + i)); - if (receiver_cid == icdata_cid) { - RawFunction* target = RAW_CAST( - Function, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + i + 1)))); - *++SP = target; - pc++; - break; - } - } - pc += 2 * cids_length; - DISPATCH(); - } - - { - BYTECODE(PushPolymorphicInstanceCallByRange, A_D); - const uint8_t argc = rA; - const intptr_t cids_length = rD; - RawObject** args = SP - argc + 1; - const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]); - for (intptr_t i = 0; i < 3 * cids_length; i += 3) { - // Note unsigned types to get an unsigned range compare. - const uintptr_t cid_start = SimulatorBytecode::DecodeD(*(pc + i)); - const uintptr_t cids = SimulatorBytecode::DecodeD(*(pc + i + 1)); - if (receiver_cid - cid_start < cids) { - RawFunction* target = RAW_CAST( - Function, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + i + 2)))); - *++SP = target; - pc++; - break; - } - } - pc += 3 * cids_length; - DISPATCH(); - } - - { - BYTECODE(NativeCall, A_B_C); - NativeFunctionWrapper trampoline = - reinterpret_cast(LOAD_CONSTANT(rA)); - Dart_NativeFunction function = - reinterpret_cast(LOAD_CONSTANT(rB)); - intptr_t argc_tag = reinterpret_cast(LOAD_CONSTANT(rC)); - const intptr_t num_arguments = NativeArguments::ArgcBits::decode(argc_tag); - - *++SP = null_value; // Result slot. - - RawObject** incoming_args = SP - num_arguments; - RawObject** return_slot = SP; - Exit(thread, FP, SP, pc); - NativeArguments args(thread, argc_tag, incoming_args, return_slot); - INVOKE_NATIVE(trampoline, function, - reinterpret_cast(&args)); - - *(SP - num_arguments) = *return_slot; - SP -= num_arguments; - DISPATCH(); - } - - { - BYTECODE(FfiCall, __D); - { - const auto& sig_desc = compiler::ffi::FfiSignatureDescriptor( - TypedData::Cast(Object::Handle(LOAD_CONSTANT(rD)))); - - // The arguments to this ffi call are on the stack at FP. - // kFirstLocalSlotFromFp is 0 in DBC, but the const is -1. - uint64_t* arg_values = reinterpret_cast(FP); - - uint64_t* marshalled_args_data = - FfiMarshalledArguments::New(sig_desc, arg_values); - const auto& marshalled_args = - FfiMarshalledArguments(marshalled_args_data); - - Exit(thread, FP, SP, pc); - { - thread->set_execution_state(Thread::kThreadInNative); - thread->EnterSafepoint(); - - FfiTrampolineCall(marshalled_args_data); - - // We set the execution state to kThreadInVM before waiting for the - // safepoint to end for the benefit of tests like ffi/function_gc_test. - thread->set_execution_state(Thread::kThreadInVM); - thread->ExitSafepoint(); - thread->set_execution_state(Thread::kThreadInGenerated); - } - - const Representation result_rep = sig_desc.ResultRepresentation(); - intptr_t result; - if (result_rep == kUnboxedDouble || result_rep == kUnboxedFloat) { - result = marshalled_args.DoubleResult(); - } else { - result = marshalled_args.IntResult(); - } - FP[0] = reinterpret_cast(result); - } - DISPATCH(); - } - - { - BYTECODE(OneByteStringFromCharCode, A_X); - const intptr_t char_code = Smi::Value(RAW_CAST(Smi, FP[rD])); - ASSERT(char_code >= 0); - ASSERT(char_code <= 255); - RawString** strings = Symbols::PredefinedAddress(); - const intptr_t index = char_code + Symbols::kNullCharCodeSymbolOffset; - FP[rA] = strings[index]; - DISPATCH(); - } - - { - BYTECODE(StringToCharCode, A_X); - RawOneByteString* str = RAW_CAST(OneByteString, FP[rD]); - if (str->ptr()->length_ == Smi::New(1)) { - FP[rA] = Smi::New(str->ptr()->data()[0]); - } else { - FP[rA] = Smi::New(-1); - } - DISPATCH(); - } - - { - BYTECODE(AddTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SignedAddWithOverflow); - DISPATCH(); - } - { - BYTECODE(SubTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SignedSubWithOverflow); - DISPATCH(); - } - { - BYTECODE(MulTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SMI_MUL); - DISPATCH(); - } - { - BYTECODE(BitOrTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SMI_BITOR); - DISPATCH(); - } - { - BYTECODE(BitAndTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SMI_BITAND); - DISPATCH(); - } - { - BYTECODE(EqualTOS, A_B_C); - SMI_FASTPATH_TOS(RawObject*, SMI_EQ); - DISPATCH(); - } - { - BYTECODE(LessThanTOS, A_B_C); - SMI_FASTPATH_TOS(RawObject*, SMI_LT); - DISPATCH(); - } - { - BYTECODE(GreaterThanTOS, A_B_C); - SMI_FASTPATH_TOS(RawObject*, SMI_GT); - DISPATCH(); - } - { - BYTECODE(SmiAddTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) + Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(SmiSubTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) - Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(SmiMulTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) * Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(SmiBitAndTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) & Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(Add, A_B_C); - SMI_OP_CHECK(intptr_t, SignedAddWithOverflow); - DISPATCH(); - } - { - BYTECODE(Sub, A_B_C); - SMI_OP_CHECK(intptr_t, SignedSubWithOverflow); - DISPATCH(); - } - { - BYTECODE(Mul, A_B_C); - SMI_OP_CHECK(intptr_t, SMI_MUL); - DISPATCH(); - } - { - BYTECODE(Neg, A_D); - const intptr_t value = reinterpret_cast(FP[rD]); - intptr_t* out = reinterpret_cast(&FP[rA]); - if (LIKELY(!SignedSubWithOverflow(0, value, out))) { - pc++; - } - DISPATCH(); - } - { - BYTECODE(BitOr, A_B_C); - SMI_OP_NOCHECK(intptr_t, SMI_BITOR); - DISPATCH(); - } - { - BYTECODE(BitAnd, A_B_C); - SMI_OP_NOCHECK(intptr_t, SMI_BITAND); - DISPATCH(); - } - { - BYTECODE(BitXor, A_B_C); - SMI_OP_NOCHECK(intptr_t, SMI_BITXOR); - DISPATCH(); - } - { - BYTECODE(BitNot, A_D); - const intptr_t value = reinterpret_cast(FP[rD]); - *reinterpret_cast(&FP[rA]) = ~value & (~kSmiTagMask); - DISPATCH(); - } - - { - BYTECODE(Div, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]); - if (rhs != 0) { - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize); -#if defined(ARCH_IS_64_BIT) - const intptr_t untaggable = 0x4000000000000000LL; -#else - const intptr_t untaggable = 0x40000000L; -#endif // defined(ARCH_IS_64_BIT) - if (res != untaggable) { - *reinterpret_cast(&FP[rA]) = res << kSmiTagSize; - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(Mod, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]); - if (rhs != 0) { - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t res = ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) - << kSmiTagSize; - *reinterpret_cast(&FP[rA]) = - (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res; - pc++; - } - DISPATCH(); - } - - { - BYTECODE(Shl, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]) >> kSmiTagSize; - if (static_cast(rhs) < kBitsPerWord) { - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t res = lhs << rhs; - if (lhs == (res >> rhs)) { - *reinterpret_cast(&FP[rA]) = res; - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(Shr, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]) >> kSmiTagSize; - if (rhs >= 0) { - const intptr_t shift_amount = - (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs; - const intptr_t lhs = reinterpret_cast(FP[rB]) >> kSmiTagSize; - *reinterpret_cast(&FP[rA]) = (lhs >> shift_amount) - << kSmiTagSize; - pc++; - } - DISPATCH(); - } - - { - BYTECODE(ShlImm, A_B_C); - const uint8_t shift = rC; - const intptr_t lhs = reinterpret_cast(FP[rB]); - FP[rA] = reinterpret_cast(lhs << shift); - DISPATCH(); - } - - { - BYTECODE(Min, A_B_C); - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t rhs = reinterpret_cast(FP[rC]); - FP[rA] = reinterpret_cast((lhs < rhs) ? lhs : rhs); - DISPATCH(); - } - - { - BYTECODE(Max, A_B_C); - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t rhs = reinterpret_cast(FP[rC]); - FP[rA] = reinterpret_cast((lhs > rhs) ? lhs : rhs); - DISPATCH(); - } - - { - BYTECODE(UnboxInt32, A_B_C); - const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rB]); - const bool may_truncate = rC == 1; - if (box_cid == kSmiCid) { - const intptr_t value = reinterpret_cast(FP[rB]) >> kSmiTagSize; - const int32_t value32 = static_cast(value); - if (may_truncate || (value == static_cast(value32))) { - FP[rA] = reinterpret_cast(value); - pc++; - } - } else if (box_cid == kMintCid) { - RawMint* mint = RAW_CAST(Mint, FP[rB]); - const int64_t value = mint->ptr()->value_; - const int32_t value32 = static_cast(value); - if (may_truncate || (value == static_cast(value32))) { - FP[rA] = reinterpret_cast(value); - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(UnboxedWidthExtender, A_B_C); - auto rep = static_cast(rC); - const intptr_t value_32_or_64_bit = reinterpret_cast(FP[rB]); - int32_t value = value_32_or_64_bit & kMaxUint32; // Prevent overflow. - switch (rep) { - case kSmallUnboxedInt8: - // Sign extend the top 24 bits from the sign bit. - value <<= 24; - value >>= 24; - break; - case kSmallUnboxedUint8: - value &= 0x000000FF; // Throw away upper bits. - break; - case kSmallUnboxedInt16: - // Sign extend the top 16 bits from the sign bit. - value <<= 16; - value >>= 16; - break; - case kSmallUnboxedUint16: - value &= 0x0000FFFF; // Throw away upper bits. - break; - default: - UNREACHABLE(); - } - FP[rA] = reinterpret_cast(value); - DISPATCH(); - } - -#if defined(ARCH_IS_64_BIT) - { - BYTECODE(WriteIntoDouble, A_D); - const double value = bit_cast(FP[rD]); - RawDouble* box = RAW_CAST(Double, FP[rA]); - box->ptr()->value_ = value; - DISPATCH(); - } - - { - BYTECODE(UnboxDouble, A_D); - const RawDouble* box = RAW_CAST(Double, FP[rD]); - FP[rA] = bit_cast(box->ptr()->value_); - DISPATCH(); - } - - { - BYTECODE(CheckedUnboxDouble, A_D); - const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rD]); - if (box_cid == kSmiCid) { - const intptr_t value = reinterpret_cast(FP[rD]) >> kSmiTagSize; - const double result = static_cast(value); - FP[rA] = bit_cast(result); - pc++; - } else if (box_cid == kDoubleCid) { - const RawDouble* box = RAW_CAST(Double, FP[rD]); - FP[rA] = bit_cast(box->ptr()->value_); - pc++; - } - DISPATCH(); - } - - { - BYTECODE(DoubleToSmi, A_D); - const double value = bit_cast(FP[rD]); - if (!isnan(value)) { - const intptr_t result = static_cast(value); - if ((result <= Smi::kMaxValue) && (result >= Smi::kMinValue)) { - FP[rA] = reinterpret_cast(result << kSmiTagSize); - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(SmiToDouble, A_D); - const intptr_t value = reinterpret_cast(FP[rD]) >> kSmiTagSize; - const double result = static_cast(value); - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DAdd, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(lhs + rhs); - DISPATCH(); - } - - { - BYTECODE(DSub, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(lhs - rhs); - DISPATCH(); - } - - { - BYTECODE(DMul, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(lhs * rhs); - DISPATCH(); - } - - { - BYTECODE(DDiv, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - const double result = lhs / rhs; - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DNeg, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(-value); - DISPATCH(); - } - - { - BYTECODE(DSqrt, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(sqrt(value)); - DISPATCH(); - } - - { - BYTECODE(DSin, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(sin(value)); - DISPATCH(); - } - - { - BYTECODE(DCos, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(cos(value)); - DISPATCH(); - } - - { - BYTECODE(DPow, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - const double result = pow(lhs, rhs); - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DMod, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - const double result = DartModulo(lhs, rhs); - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DMin, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(fmin(lhs, rhs)); - DISPATCH(); - } - - { - BYTECODE(DMax, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(fmax(lhs, rhs)); - DISPATCH(); - } - - { - BYTECODE(DTruncate, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(trunc(value)); - DISPATCH(); - } - - { - BYTECODE(DFloor, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(floor(value)); - DISPATCH(); - } - - { - BYTECODE(DCeil, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(ceil(value)); - DISPATCH(); - } - - { - BYTECODE(DoubleToFloat, A_D); - const double value = bit_cast(FP[rD]); - const float valuef = static_cast(value); - *reinterpret_cast(&FP[rA]) = valuef; - DISPATCH(); - } - - { - BYTECODE(FloatToDouble, A_D); - const float valuef = *reinterpret_cast(&FP[rD]); - const double value = static_cast(valuef); - FP[rA] = bit_cast(value); - DISPATCH(); - } - - { - BYTECODE(DoubleIsNaN, A); - const double v = bit_cast(FP[rA]); - if (!isnan(v)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(DoubleIsInfinite, A); - const double v = bit_cast(FP[rA]); - if (!isinf(v)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat32, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]); - const uint32_t value = *reinterpret_cast(data); - const uint64_t value64 = value; - FP[rA] = reinterpret_cast(value64); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed4Float32, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - const uint32_t value = - reinterpret_cast(array->ptr()->data())[Smi::Value(index)]; - const uint64_t value64 = value; // sign extend to clear high bits. - FP[rA] = reinterpret_cast(value64); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat64, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]); - *reinterpret_cast(&FP[rA]) = *reinterpret_cast(data); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed8Float64, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - const int64_t value = - reinterpret_cast(array->ptr()->data())[Smi::Value(index)]; - FP[rA] = reinterpret_cast(value); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat32, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]); - const float value = *reinterpret_cast(&FP[rC]); - *reinterpret_cast(data) = value; - DISPATCH(); - } - - { - BYTECODE(StoreIndexed4Float32, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - const float value = *reinterpret_cast(&FP[rC]); - reinterpret_cast(array->ptr()->data())[Smi::Value(index)] = value; - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat64, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]); - *reinterpret_cast(data) = reinterpret_cast(FP[rC]); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed8Float64, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - const int64_t value = reinterpret_cast(FP[rC]); - reinterpret_cast(array->ptr()->data())[Smi::Value(index)] = value; - DISPATCH(); - } - - { - BYTECODE(BoxInt32, A_D); - // Casts sign-extend high 32 bits from low 32 bits. - const intptr_t value = reinterpret_cast(FP[rD]); - const int32_t value32 = static_cast(value); - FP[rA] = Smi::New(static_cast(value32)); - DISPATCH(); - } - - { - BYTECODE(BoxUint32, A_D); - // Casts to zero out high 32 bits. - const uintptr_t value = reinterpret_cast(FP[rD]); - const uint32_t value32 = static_cast(value); - FP[rA] = Smi::New(static_cast(value32)); - DISPATCH(); - } - - { - BYTECODE(UnboxInt64, A_D); - const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rD]); - if (box_cid == kSmiCid) { - const int64_t value = Smi::Value(RAW_CAST(Smi, FP[rD])); - FP[rA] = reinterpret_cast(value); - } else if (box_cid == kMintCid) { - RawMint* mint = RAW_CAST(Mint, FP[rD]); - const int64_t value = mint->ptr()->value_; - FP[rA] = reinterpret_cast(value); - } - DISPATCH(); - } - - { - BYTECODE(BoxInt64, A_D); - const int64_t value = reinterpret_cast(FP[rD]); - if (Smi::IsValid(value)) { - FP[rA] = Smi::New(static_cast(value)); - } else { - // If the value does not fit into a Smi the following instruction is - // skipped. (The following instruction should be a jump to a label after - // the slow path allocating a Mint box and writing into the Mint box.) - pc++; - } - DISPATCH(); - } - - { - BYTECODE(WriteIntoMint, A_D); - const int64_t value = bit_cast(FP[rD]); - RawMint* box = RAW_CAST(Mint, FP[rA]); - box->ptr()->value_ = value; - DISPATCH(); - } - -#else // defined(ARCH_IS_64_BIT) - { - BYTECODE(WriteIntoDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(UnboxDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(CheckedUnboxDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DoubleToSmi, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(SmiToDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DAdd, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DSub, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DMul, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DDiv, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DNeg, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DSqrt, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DSin, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DCos, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DPow, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DMod, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DMin, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DMax, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DTruncate, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DFloor, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DCeil, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DoubleToFloat, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(FloatToDouble, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DoubleIsNaN, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DoubleIsInfinite, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed4Float32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed8Float64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed4Float32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed8Float64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(BoxInt32, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(BoxUint32, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(UnboxInt64, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(BoxInt64, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(WriteIntoMint, A_D); - UNREACHABLE(); - DISPATCH(); - } -#endif // defined(ARCH_IS_64_BIT) - - // Return and return like instructions (Instrinsic). - { - RawObject* result; // result to return to the caller. - - BYTECODE(Intrinsic, A); - // Try invoking intrinsic handler. If it succeeds (returns true) - // then just return the value it returned to the caller. - result = null_value; - if (!intrinsics_[rA](thread, FP, &result)) { - DISPATCH(); - } - goto ReturnImpl; - - BYTECODE(Return, A); - result = FP[rA]; - goto ReturnImpl; - - BYTECODE(ReturnTOS, 0); - result = *SP; - // Fall through to the ReturnImpl. - - ReturnImpl: - // Restore caller PC. - pc = SavedCallerPC(FP); - pc_ = reinterpret_cast(pc); // For the profiler. - - // Check if it is a fake PC marking the entry frame. - if ((reinterpret_cast(pc) & 2) != 0) { - const intptr_t argc = reinterpret_cast(pc) >> 2; - fp_ = reinterpret_cast(FrameArguments(FP, argc + 1)[0]); - thread->set_top_exit_frame_info(reinterpret_cast(fp_)); - thread->set_top_resource(top_resource); - thread->set_vm_tag(vm_tag); - return result; - } - - // Look at the caller to determine how many arguments to pop. - const uint8_t argc = SimulatorBytecode::DecodeArgc(pc[-1]); - - // Restore SP, FP and PP. Push result and dispatch. - SP = FrameArguments(FP, argc); - FP = SavedCallerFP(FP); - pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_; - *SP = result; - DISPATCH(); - } - - { - BYTECODE(StoreStaticTOS, A_D); - RawField* field = reinterpret_cast(LOAD_CONSTANT(rD)); - RawInstance* value = static_cast(*SP--); - field->StorePointer(&field->ptr()->value_.static_value_, value, thread); - DISPATCH(); - } - - { - BYTECODE(PushStatic, A_D); - RawField* field = reinterpret_cast(LOAD_CONSTANT(rD)); - // Note: field is also on the stack, hence no increment. - *SP = field->ptr()->value_.static_value_; - DISPATCH(); - } - - { - BYTECODE(StoreField, A_B_C); - const uint16_t offset_in_words = rB; - const uint16_t value_reg = rC; - - RawInstance* instance = reinterpret_cast(FP[rA]); - RawObject* value = FP[value_reg]; - - instance->StorePointer( - reinterpret_cast(instance->ptr()) + offset_in_words, value, - thread); - DISPATCH(); - } - - { - BYTECODE(StoreFieldExt, A_D); - // The offset is stored in the following nop-instruction which is skipped. - const uint16_t offset_in_words = SimulatorBytecode::DecodeD(*pc++); - RawInstance* instance = reinterpret_cast(FP[rA]); - RawObject* value = FP[rD]; - - instance->StorePointer( - reinterpret_cast(instance->ptr()) + offset_in_words, value, - thread); - DISPATCH(); - } - - { - BYTECODE(StoreUntagged, A_B_C); - const uint16_t offset_in_words = rB; - const uint16_t value_reg = rC; - - RawInstance* instance = reinterpret_cast(FP[rA]); - word value = reinterpret_cast(FP[value_reg]); - reinterpret_cast(instance->ptr())[offset_in_words] = value; - DISPATCH(); - } - - { - BYTECODE(StoreFieldTOS, __D); - const uint16_t offset_in_words = rD; - RawInstance* instance = reinterpret_cast(SP[-1]); - RawObject* value = reinterpret_cast(SP[0]); - SP -= 2; // Drop instance and value. - instance->StorePointer( - reinterpret_cast(instance->ptr()) + offset_in_words, value, - thread); - - DISPATCH(); - } - - { - BYTECODE(LoadField, A_B_C); - const uint16_t instance_reg = rB; - const uint16_t offset_in_words = rC; - RawInstance* instance = reinterpret_cast(FP[instance_reg]); - FP[rA] = reinterpret_cast(instance->ptr())[offset_in_words]; - DISPATCH(); - } - - { - BYTECODE(LoadFieldExt, A_D); - // The offset is stored in the following nop-instruction which is skipped. - const uint16_t offset_in_words = SimulatorBytecode::DecodeD(*pc++); - const uint16_t instance_reg = rD; - RawInstance* instance = reinterpret_cast(FP[instance_reg]); - FP[rA] = reinterpret_cast(instance->ptr())[offset_in_words]; - DISPATCH(); - } - - { - BYTECODE(LoadUntagged, A_B_C); - const uint16_t instance_reg = rB; - const uint16_t offset_in_words = rC; - RawInstance* instance = reinterpret_cast(FP[instance_reg]); - FP[rA] = reinterpret_cast(instance)[offset_in_words]; - DISPATCH(); - } - - { - BYTECODE(LoadFieldTOS, __D); - const uint16_t offset_in_words = rD; - RawInstance* instance = static_cast(SP[0]); - SP[0] = reinterpret_cast(instance->ptr())[offset_in_words]; - DISPATCH(); - } - - { - BYTECODE(InitStaticTOS, 0); - RawField* field = static_cast(*SP--); - RawObject* value = field->ptr()->value_.static_value_; - if ((value == Object::sentinel().raw()) || - (value == Object::transition_sentinel().raw())) { - // Note: SP[1] already contains the field object. - SP[2] = 0; - Exit(thread, FP, SP + 3, pc); - NativeArguments args(thread, 1, SP + 1, SP + 2); - INVOKE_RUNTIME(DRT_InitStaticField, args); - } - DISPATCH(); - } - - // TODO(vegorov) allocation bytecodes can benefit from the new-space - // allocation fast-path that does not transition into the runtime system. - { - BYTECODE(AllocateUninitializedContext, A_D); - const uint16_t num_context_variables = rD; - const intptr_t instance_size = Context::InstanceSize(num_context_variables); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - uint32_t tags = 0; - tags = RawObject::ClassIdTag::update(kContextCid, tags); - tags = RawObject::SizeTag::update(instance_size, tags); - tags = RawObject::NewBit::update(true, tags); - // Also writes 0 in the hash_ field of the header. - *reinterpret_cast(start + Array::tags_offset()) = tags; - *reinterpret_cast(start + Context::num_variables_offset()) = - num_context_variables; - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - pc += 2; - } - DISPATCH(); - } - - { - BYTECODE(AllocateContext, A_D); - const uint16_t num_context_variables = rD; - { - *++SP = 0; - SP[1] = Smi::New(num_context_variables); - Exit(thread, FP, SP + 2, pc); - NativeArguments args(thread, 1, SP + 1, SP); - INVOKE_RUNTIME(DRT_AllocateContext, args); - } - DISPATCH(); - } - - { - BYTECODE(CloneContext, A); - { - SP[1] = SP[0]; // Context to clone. - Exit(thread, FP, SP + 2, pc); - NativeArguments args(thread, 1, SP + 1, SP); - INVOKE_RUNTIME(DRT_CloneContext, args); - } - DISPATCH(); - } - - { - BYTECODE(AllocateOpt, A_D); - uint32_t tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))); - const intptr_t instance_size = RawObject::SizeTag::decode(tags); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - // Writes both the tags and the initial identity hash on 64 bit platforms. - tags = RawObject::NewBit::update(true, tags); - *reinterpret_cast(start + Instance::tags_offset()) = tags; - for (intptr_t current_offset = sizeof(RawInstance); - current_offset < instance_size; current_offset += kWordSize) { - *reinterpret_cast(start + current_offset) = null_value; - } - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - pc += 2; - } - DISPATCH(); - } - - { - BYTECODE(Allocate, A_D); - SP[1] = 0; // Space for the result. - SP[2] = LOAD_CONSTANT(rD); // Class object. - SP[3] = null_value; // Type arguments. - Exit(thread, FP, SP + 4, pc); - NativeArguments args(thread, 2, SP + 2, SP + 1); - INVOKE_RUNTIME(DRT_AllocateObject, args); - SP++; // Result is in SP[1]. - DISPATCH(); - } - - { - BYTECODE(AllocateTOpt, A_D); - uint32_t tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))); - const intptr_t instance_size = RawObject::SizeTag::decode(tags); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - RawObject* type_args = SP[0]; - const intptr_t type_args_offset = SimulatorBytecode::DecodeD(*pc); - // Writes both the tags and the initial identity hash on 64 bit platforms. - tags = RawObject::NewBit::update(true, tags); - *reinterpret_cast(start + Instance::tags_offset()) = tags; - for (intptr_t current_offset = sizeof(RawInstance); - current_offset < instance_size; current_offset += kWordSize) { - *reinterpret_cast(start + current_offset) = null_value; - } - *reinterpret_cast(start + type_args_offset) = type_args; - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - SP -= 1; // Consume the type arguments on the stack. - pc += 4; - } - DISPATCH(); - } - - { - BYTECODE(AllocateT, 0); - SP[1] = SP[-0]; // Class object. - SP[2] = SP[-1]; // Type arguments - Exit(thread, FP, SP + 3, pc); - NativeArguments args(thread, 2, SP + 1, SP - 1); - INVOKE_RUNTIME(DRT_AllocateObject, args); - SP -= 1; // Result is in SP - 1. - DISPATCH(); - } - - { - BYTECODE(CreateArrayOpt, A_B_C); - if (LIKELY(!FP[rB]->IsHeapObject())) { - const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB])); - if (LIKELY(static_cast(length) <= Array::kMaxElements)) { - const intptr_t fixed_size_plus_alignment_padding = - sizeof(RawArray) + kObjectAlignment - 1; - const intptr_t instance_size = - (fixed_size_plus_alignment_padding + length * kWordSize) & - ~(kObjectAlignment - 1); - const uword start = thread->heap()->new_space()->TryAllocateInTLAB( - thread, instance_size); - if (LIKELY(start != 0)) { - const intptr_t cid = kArrayCid; - uword tags = 0; - if (LIKELY(instance_size <= RawObject::SizeTag::kMaxSizeTag)) { - tags = RawObject::SizeTag::update(instance_size, tags); - } - tags = RawObject::ClassIdTag::update(cid, tags); - tags = RawObject::NewBit::update(true, tags); - // Writes both the tags and the initial identity hash on 64 bit - // platforms. - *reinterpret_cast(start + Instance::tags_offset()) = tags; - *reinterpret_cast(start + Array::length_offset()) = - FP[rB]; - *reinterpret_cast( - start + Array::type_arguments_offset()) = FP[rC]; - RawObject** data = - reinterpret_cast(start + Array::data_offset()); - for (intptr_t i = 0; i < length; i++) { - data[i] = null_value; - } - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - pc += 4; - } - } - } - DISPATCH(); - } - - { - BYTECODE(CreateArrayTOS, 0); - SP[1] = SP[-0]; // Length. - SP[2] = SP[-1]; // Type. - Exit(thread, FP, SP + 3, pc); - NativeArguments args(thread, 2, SP + 1, SP - 1); - INVOKE_RUNTIME(DRT_AllocateArray, args); - SP -= 1; - DISPATCH(); - } - - { - BYTECODE(InstanceOf, 0); - // Stack: instance, instantiator type args, function type args, type, cache - RawInstance* instance = static_cast(SP[-4]); - RawTypeArguments* instantiator_type_arguments = - static_cast(SP[-3]); - RawTypeArguments* function_type_arguments = - static_cast(SP[-2]); - RawAbstractType* type = static_cast(SP[-1]); - RawSubtypeTestCache* cache = static_cast(SP[0]); - - if (cache != null_value) { - const intptr_t cid = SimulatorHelpers::GetClassId(instance); - - RawTypeArguments* instance_type_arguments = - static_cast(null_value); - RawObject* instance_cid_or_function; - RawTypeArguments* parent_function_type_arguments; - RawTypeArguments* delayed_function_type_arguments; - if (cid == kClosureCid) { - RawClosure* closure = static_cast(instance); - instance_type_arguments = closure->ptr()->instantiator_type_arguments_; - parent_function_type_arguments = - closure->ptr()->function_type_arguments_; - delayed_function_type_arguments = - closure->ptr()->delayed_type_arguments_; - instance_cid_or_function = closure->ptr()->function_; - } else { - instance_cid_or_function = Smi::New(cid); - - RawClass* instance_class = thread->isolate()->class_table()->At(cid); - if (instance_class->ptr()->num_type_arguments_ < 0) { - goto InstanceOfCallRuntime; - } else if (instance_class->ptr()->num_type_arguments_ > 0) { - instance_type_arguments = reinterpret_cast( - instance->ptr())[instance_class->ptr() - ->type_arguments_field_offset_in_words_]; - } - parent_function_type_arguments = - static_cast(null_value); - delayed_function_type_arguments = - static_cast(null_value); - } - - for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); - entries[0] != null_value; - entries += SubtypeTestCache::kTestEntryLength) { - if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == - instance_cid_or_function) && - (entries[SubtypeTestCache::kInstanceTypeArguments] == - instance_type_arguments) && - (entries[SubtypeTestCache::kInstantiatorTypeArguments] == - instantiator_type_arguments) && - (entries[SubtypeTestCache::kFunctionTypeArguments] == - function_type_arguments) && - (entries[SubtypeTestCache::kInstanceParentFunctionTypeArguments] == - parent_function_type_arguments) && - (entries[SubtypeTestCache::kInstanceDelayedFunctionTypeArguments] == - delayed_function_type_arguments)) { - SP[-4] = entries[SubtypeTestCache::kTestResult]; - goto InstanceOfOk; - } - } - } - - // clang-format off - InstanceOfCallRuntime: - { - SP[1] = instance; - SP[2] = type; - SP[3] = instantiator_type_arguments; - SP[4] = function_type_arguments; - SP[5] = cache; - Exit(thread, FP, SP + 6, pc); - NativeArguments native_args(thread, 5, SP + 1, SP - 4); - INVOKE_RUNTIME(DRT_Instanceof, native_args); - } - // clang-format on - - InstanceOfOk: - SP -= 4; - DISPATCH(); - } - - { - BYTECODE(NullError, 0); - Exit(thread, FP, SP, pc); - NativeArguments native_args(thread, 0, SP, SP); - INVOKE_RUNTIME(DRT_NullError, native_args); - UNREACHABLE(); - } - - { - BYTECODE(BadTypeError, 0); - // Stack: instance, instantiator type args, function type args, type, name - RawObject** args = SP - 4; - if (args[0] != null_value) { - SP[1] = args[0]; // instance. - SP[2] = args[4]; // name. - SP[3] = args[3]; // type. - Exit(thread, FP, SP + 4, pc); - NativeArguments native_args(thread, 3, SP + 1, SP - 4); - INVOKE_RUNTIME(DRT_BadTypeError, native_args); - UNREACHABLE(); - } - SP -= 4; - DISPATCH(); - } - - { - BYTECODE(AssertAssignable, A_D); - // Stack: instance, instantiator type args, function type args, type, name - RawObject** args = SP - 4; - const bool may_be_smi = (rA == 1); - const bool is_smi = - ((reinterpret_cast(args[0]) & kSmiTagMask) == kSmiTag); - const bool smi_ok = is_smi && may_be_smi; - if (!smi_ok && (args[0] != null_value)) { - RawSubtypeTestCache* cache = - static_cast(LOAD_CONSTANT(rD)); - if (cache != null_value) { - RawInstance* instance = static_cast(args[0]); - RawTypeArguments* instantiator_type_arguments = - static_cast(args[1]); - RawTypeArguments* function_type_arguments = - static_cast(args[2]); - - const intptr_t cid = SimulatorHelpers::GetClassId(instance); - - RawTypeArguments* instance_type_arguments = - static_cast(null_value); - RawObject* instance_cid_or_function; - - RawTypeArguments* parent_function_type_arguments; - RawTypeArguments* delayed_function_type_arguments; - if (cid == kClosureCid) { - RawClosure* closure = static_cast(instance); - instance_type_arguments = - closure->ptr()->instantiator_type_arguments_; - parent_function_type_arguments = - closure->ptr()->function_type_arguments_; - delayed_function_type_arguments = - closure->ptr()->delayed_type_arguments_; - instance_cid_or_function = closure->ptr()->function_; - } else { - instance_cid_or_function = Smi::New(cid); - - RawClass* instance_class = thread->isolate()->class_table()->At(cid); - if (instance_class->ptr()->num_type_arguments_ < 0) { - goto AssertAssignableCallRuntime; - } else if (instance_class->ptr()->num_type_arguments_ > 0) { - instance_type_arguments = reinterpret_cast( - instance->ptr())[instance_class->ptr() - ->type_arguments_field_offset_in_words_]; - } - parent_function_type_arguments = - static_cast(null_value); - delayed_function_type_arguments = - static_cast(null_value); - } - - for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); - entries[0] != null_value; - entries += SubtypeTestCache::kTestEntryLength) { - if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == - instance_cid_or_function) && - (entries[SubtypeTestCache::kInstanceTypeArguments] == - instance_type_arguments) && - (entries[SubtypeTestCache::kInstantiatorTypeArguments] == - instantiator_type_arguments) && - (entries[SubtypeTestCache::kFunctionTypeArguments] == - function_type_arguments) && - (entries - [SubtypeTestCache::kInstanceParentFunctionTypeArguments] == - parent_function_type_arguments) && - (entries - [SubtypeTestCache::kInstanceDelayedFunctionTypeArguments] == - delayed_function_type_arguments)) { - if (true_value == entries[SubtypeTestCache::kTestResult]) { - goto AssertAssignableOk; - } else { - break; - } - } - } - } - - AssertAssignableCallRuntime: - SP[1] = args[0]; // instance - SP[2] = args[3]; // type - SP[3] = args[1]; // instantiator type args - SP[4] = args[2]; // function type args - SP[5] = args[4]; // name - SP[6] = cache; - SP[7] = Smi::New(kTypeCheckFromInline); - Exit(thread, FP, SP + 8, pc); - NativeArguments native_args(thread, 7, SP + 1, SP - 4); - INVOKE_RUNTIME(DRT_TypeCheck, native_args); - } - - AssertAssignableOk: - SP -= 4; - DISPATCH(); - } - - { - BYTECODE(AssertSubtype, A); - RawObject** args = SP - 4; - - // TODO(kustermann): Implement fast case for common arguments. - - // The arguments on the stack look like: - // args[0] instantiator type args - // args[1] function type args - // args[2] sub_type - // args[3] super_type - // args[4] name - - // This is unused, since the negative case throws an exception. - SP++; - RawObject** result_slot = SP; - - Exit(thread, FP, SP + 1, pc); - NativeArguments native_args(thread, 5, args, result_slot); - INVOKE_RUNTIME(DRT_SubtypeCheck, native_args); - - // Result slot not used anymore. - SP--; - - // Drop all arguments. - SP -= 5; - - DISPATCH(); - } - - { - BYTECODE(AssertBoolean, A); - RawObject* value = SP[0]; - if (rA) { // Should we perform type check? - if ((value == true_value) || (value == false_value)) { - goto AssertBooleanOk; - } - } else if (value != null_value) { - goto AssertBooleanOk; - } - - // Assertion failed. - { - SP[1] = SP[0]; // instance - Exit(thread, FP, SP + 2, pc); - NativeArguments args(thread, 1, SP + 1, SP); - INVOKE_RUNTIME(DRT_NonBoolTypeError, args); - } - - AssertBooleanOk: - DISPATCH(); - } - - { - BYTECODE(TestSmi, A_D); - intptr_t left = reinterpret_cast(RAW_CAST(Smi, FP[rA])); - intptr_t right = reinterpret_cast(RAW_CAST(Smi, FP[rD])); - if ((left & right) != 0) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(TestCids, A_D); - const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]); - const intptr_t num_cases = rD; - for (intptr_t i = 0; i < num_cases; i++) { - ASSERT(SimulatorBytecode::DecodeOpcode(pc[i]) == SimulatorBytecode::kNop); - intptr_t test_target = SimulatorBytecode::DecodeA(pc[i]); - intptr_t test_cid = SimulatorBytecode::DecodeD(pc[i]); - if (cid == test_cid) { - if (test_target != 0) { - pc += 1; // Match true. - } else { - pc += 2; // Match false. - } - break; - } - } - pc += num_cases; - DISPATCH(); - } - - { - BYTECODE(CheckSmi, 0); - intptr_t obj = reinterpret_cast(FP[rA]); - if ((obj & kSmiTagMask) == kSmiTag) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(CheckEitherNonSmi, A_D); - const intptr_t obj1 = reinterpret_cast(FP[rA]); - const intptr_t obj2 = reinterpret_cast(FP[rD]); - const intptr_t tag = (obj1 | obj2) & kSmiTagMask; - if (tag != kSmiTag) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(CheckClassId, A_D); - const intptr_t actual_cid = - reinterpret_cast(FP[rA]) >> kSmiTagSize; - const intptr_t desired_cid = rD; - pc += (actual_cid == desired_cid) ? 1 : 0; - DISPATCH(); - } - - { - BYTECODE(CheckClassIdRange, A_D); - const intptr_t actual_cid = - reinterpret_cast(FP[rA]) >> kSmiTagSize; - const uintptr_t cid_start = rD; - const uintptr_t cid_range = SimulatorBytecode::DecodeD(*pc); - // Unsigned comparison. Skip either just the nop or both the nop and the - // following instruction. - pc += (actual_cid - cid_start <= cid_range) ? 2 : 1; - DISPATCH(); - } - - { - BYTECODE(CheckBitTest, A_D); - const intptr_t raw_value = reinterpret_cast(FP[rA]); - const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag); - const intptr_t cid_min = SimulatorBytecode::DecodeD(*pc); - const intptr_t cid_mask = Smi::Value( - RAW_CAST(Smi, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + 1))))); - if (LIKELY(!is_smi)) { - const intptr_t cid_max = Utils::HighestBit(cid_mask) + cid_min; - const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]); - // The cid is in-bounds, and the bit is set in the mask. - if ((cid >= cid_min) && (cid <= cid_max) && - ((cid_mask & (1 << (cid - cid_min))) != 0)) { - pc += 3; - } else { - pc += 2; - } - } else { - const bool may_be_smi = (rD == 1); - pc += (may_be_smi ? 3 : 2); - } - DISPATCH(); - } - - { - BYTECODE(CheckCids, A_B_C); - const intptr_t raw_value = reinterpret_cast(FP[rA]); - const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag); - const bool may_be_smi = (rB == 1); - const intptr_t cids_length = rC; - if (LIKELY(!is_smi)) { - const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]); - for (intptr_t i = 0; i < cids_length; i++) { - const intptr_t desired_cid = SimulatorBytecode::DecodeD(*(pc + i)); - if (cid == desired_cid) { - pc++; - break; - } - } - pc += cids_length; - } else { - pc += cids_length; - pc += (may_be_smi ? 1 : 0); - } - DISPATCH(); - } - - { - BYTECODE(CheckCidsByRange, A_B_C); - const intptr_t raw_value = reinterpret_cast(FP[rA]); - const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag); - const bool may_be_smi = (rB == 1); - const intptr_t cids_length = rC; - if (LIKELY(!is_smi)) { - const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]); - for (intptr_t i = 0; i < cids_length; i += 2) { - // Note unsigned type to get unsigned range check below. - const uintptr_t cid_start = SimulatorBytecode::DecodeD(*(pc + i)); - const uintptr_t cids = SimulatorBytecode::DecodeD(*(pc + i + 1)); - if (cid - cid_start < cids) { - pc++; - break; - } - } - pc += cids_length; - } else { - pc += cids_length; - pc += (may_be_smi ? 1 : 0); - } - DISPATCH(); - } - - { - BYTECODE(IfEqStrictTOS, 0); - SP -= 2; - if (SP[1] != SP[2]) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrictTOS, 0); - SP -= 2; - if (SP[1] == SP[2]) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfEqStrictNumTOS, 0); - -#ifndef PRODUCT - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } -#endif // !PRODUCT - - SP -= 2; - if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrictNumTOS, 0); - -#ifndef PRODUCT - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } -#endif // !PRODUCT - - SP -= 2; - if (SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfSmiLtTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) < Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfSmiLeTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) <= Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfSmiGeTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) >= Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfSmiGtTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) > Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfEqStrict, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (lhs != rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrict, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (lhs == rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfLe, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs > rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfLt, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs >= rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfGe, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs < rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfGt, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs <= rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfULe, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs > rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfULt, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs >= rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfUGe, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs < rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfUGt, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs <= rhs) { - pc++; - } - DISPATCH(); - } - -#if defined(ARCH_IS_64_BIT) - { - BYTECODE(IfDEq, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs == rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDNe, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs != rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDLe, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs <= rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDLt, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs < rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDGe, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs >= rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDGt, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs > rhs) ? 0 : 1; - DISPATCH(); - } -#else // defined(ARCH_IS_64_BIT) - { - BYTECODE(IfDEq, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDNe, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDLe, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDLt, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDGe, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDGt, A_D); - UNREACHABLE(); - DISPATCH(); - } -#endif // defined(ARCH_IS_64_BIT) - - { - BYTECODE(IfEqStrictNum, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(lhs, rhs)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrictNum, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (SimulatorHelpers::IsStrictEqualWithNumberCheck(lhs, rhs)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfEqNull, A); - if (FP[rA] != null_value) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeNull, A_D); - if (FP[rA] == null_value) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfEqNullTOS, 0); - if (SP[0] != null_value) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeNullTOS, 0); - if (SP[0] == null_value) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(Jump, 0); - const int32_t target = static_cast(op) >> 8; - pc += (target - 1); - DISPATCH(); - } - - { - BYTECODE(LoadClassId, A_D); - const uint16_t object_reg = rD; - RawObject* obj = static_cast(FP[object_reg]); - FP[rA] = SimulatorHelpers::GetClassIdAsSmi(obj); - DISPATCH(); - } - - { - BYTECODE(LoadClassIdTOS, 0); - RawObject* obj = static_cast(SP[0]); - SP[0] = SimulatorHelpers::GetClassIdAsSmi(obj); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedTOS, 0); - SP -= 3; - RawArray* array = RAW_CAST(Array, SP[1]); - RawSmi* index = RAW_CAST(Smi, SP[2]); - RawObject* value = SP[3]; - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), value, - thread); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed, A_B_C); - RawArray* array = RAW_CAST(Array, FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - RawObject* value = FP[rC]; - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), value, - thread); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUint8, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]); - *data = static_cast(reinterpret_cast(FP[rC])); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUntaggedUint8, A_B_C); - uint8_t* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - array[Smi::Value(index)] = - static_cast(reinterpret_cast(FP[rC])); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUntaggedUint32, A_B_C); - uint8_t* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const uint32_t value = *reinterpret_cast(&FP[rC]); - *reinterpret_cast(array + Smi::Value(index)) = value; - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUntaggedFloat32, A_B_C); - uint8_t* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const float value = *reinterpret_cast(&FP[rC]); - *reinterpret_cast(array + Smi::Value(index)) = value; - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUntaggedFloat64, A_B_C); - uint8_t* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const double value = *reinterpret_cast(&FP[rC]); - *reinterpret_cast(array + Smi::Value(index)) = value; - DISPATCH(); - } - - { - BYTECODE(StoreIndexedOneByteString, A_B_C); - RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - array->ptr()->data()[Smi::Value(index)] = - static_cast(reinterpret_cast(FP[rC])); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUint32, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]); - const uintptr_t value = reinterpret_cast(FP[rC]); - *reinterpret_cast(data) = static_cast(value); - DISPATCH(); - } - - { - BYTECODE(TailCall, 0); - RawCode* code = RAW_CAST(Code, SP[-0]); - RawImmutableArray* args_desc = RAW_CAST(ImmutableArray, SP[-1]); - PrepareForTailCall(code, args_desc, FP, &SP, &pc); - DISPATCH(); - } - - { - BYTECODE(TailCallOpt, A_D); - RawImmutableArray* args_desc = RAW_CAST(ImmutableArray, FP[rA]); - RawCode* code = RAW_CAST(Code, FP[rD]); - PrepareForTailCall(code, args_desc, FP, &SP, &pc); - DISPATCH(); - } - - { - BYTECODE(LoadArgDescriptor, 0); - SP++; - SP[0] = argdesc_; - DISPATCH(); - } - - { - BYTECODE(LoadArgDescriptorOpt, A); - FP[rA] = argdesc_; - DISPATCH(); - } - - { - BYTECODE(NoSuchMethod, 0); - goto ClosureNoSuchMethod; - } - - { - BYTECODE(LoadFpRelativeSlot, A_X); - RawSmi* index = RAW_CAST(Smi, SP[-0]); - const int16_t offset = rD; - SP[-0] = FP[-(Smi::Value(index) + offset)]; - DISPATCH(); - } - - { - BYTECODE(LoadFpRelativeSlotOpt, A_B_Y); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const int8_t offset = rY; - FP[rA] = FP[-(Smi::Value(index) + offset)]; - DISPATCH(); - } - - { - BYTECODE(StoreFpRelativeSlot, A_X); - RawSmi* index = RAW_CAST(Smi, SP[-1]); - const int16_t offset = rD; - FP[-(Smi::Value(index) + offset) - 0] = SP[-0]; - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(StoreFpRelativeSlotOpt, A_B_Y); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const int8_t offset = rY; - FP[-(Smi::Value(index) + offset) - 0] = FP[rA]; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedTOS, 0); - // Currently this instruction is only emitted if it's safe to do. - ASSERT(!SP[0]->IsHeapObject()); - ASSERT(SP[-1]->IsArray() || SP[-1]->IsImmutableArray()); - - const intptr_t index_scale = rA; - RawSmi* index = RAW_CAST(Smi, SP[-0]); - RawArray* array = Array::RawCast(SP[-1]); - - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - SP[-1] = array->ptr()->data()[Smi::Value(index) << index_scale]; - SP--; - DISPATCH(); - } - - { - BYTECODE(LoadIndexed, A_B_C); - RawObject* obj = FP[rB]; - ASSERT(obj->IsArray() || obj->IsImmutableArray()); - RawArray* array = reinterpret_cast(obj); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - FP[rA] = array->ptr()->data()[Smi::Value(index)]; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUint8, A_B_C); - uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]); - FP[rA] = reinterpret_cast(static_cast(*data)); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedInt8, A_B_C); - int8_t* data = reinterpret_cast( - SimulatorHelpers::GetTypedData(FP[rB], FP[rC])); - FP[rA] = reinterpret_cast(static_cast(*data)); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUint32, A_B_C); - const uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]); - const uint32_t value = *reinterpret_cast(data); - *reinterpret_cast(&FP[rA]) = value; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedInt32, A_B_C); - const uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]); - const int32_t value = *reinterpret_cast(data); - *reinterpret_cast(&FP[rA]) = value; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUntaggedInt8, A_B_C); - int8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - FP[rA] = reinterpret_cast( - static_cast(data[Smi::Value(index)])); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUntaggedUint8, A_B_C); - uint8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - FP[rA] = reinterpret_cast( - static_cast(data[Smi::Value(index)])); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUntaggedInt32, A_B_C); - uint8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - const int32_t value = *reinterpret_cast(data + Smi::Value(index)); - *reinterpret_cast(&FP[rA]) = value; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUntaggedUint32, A_B_C); - uint8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - const uint32_t value = - *reinterpret_cast(data + Smi::Value(index)); - *reinterpret_cast(&FP[rA]) = value; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUntaggedFloat32, A_B_C); - uint8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - const float value = *reinterpret_cast(data + Smi::Value(index)); - *reinterpret_cast(&FP[rA]) = value; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUntaggedFloat64, A_B_C); - uint8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - const double value = *reinterpret_cast(data + Smi::Value(index)); - *reinterpret_cast(&FP[rA]) = value; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedOneByteString, A_B_C); - RawOneByteString* array = RAW_CAST(OneByteString, FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - FP[rA] = reinterpret_cast( - static_cast(array->ptr()->data()[Smi::Value(index)])); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedTwoByteString, A_B_C); - RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); - FP[rA] = reinterpret_cast( - static_cast(array->ptr()->data()[Smi::Value(index)])); - DISPATCH(); - } - - { - BYTECODE(Deopt, A_D); - const bool is_lazy = rD == 0; - if (!Deoptimize(thread, &pc, &FP, &SP, is_lazy)) { - HANDLE_EXCEPTION; - } - DISPATCH(); - } - - { - BYTECODE(DeoptRewind, 0); - pc = reinterpret_cast(thread->resume_pc()); - if (!Deoptimize(thread, &pc, &FP, &SP, false /* eager */)) { - HANDLE_EXCEPTION; - } - { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_RewindPostDeopt, args); - } - UNREACHABLE(); // DRT_RewindPostDeopt does not exit normally. - DISPATCH(); - } - - { - BYTECODE(Nop, 0); - DISPATCH(); - } - - { - BYTECODE(Trap, 0); - UNIMPLEMENTED(); - DISPATCH(); - } - - // Helper used to handle noSuchMethod on closures. - { - ClosureNoSuchMethod: -#if defined(DEBUG) - function_h ^= FrameFunction(FP); - ASSERT(function_h.IsNull() || function_h.IsClosureFunction()); -#endif - - // Restore caller context as we are going to throw NoSuchMethod. - pc = SavedCallerPC(FP); - - const bool has_dart_caller = (reinterpret_cast(pc) & 2) == 0; - const intptr_t argc = has_dart_caller - ? SimulatorBytecode::DecodeArgc(pc[-1]) - : (reinterpret_cast(pc) >> 2); - const bool has_function_type_args = - has_dart_caller && SimulatorHelpers::ArgDescTypeArgsLen(argdesc_) > 0; - - SP = FrameArguments(FP, 0); - RawObject** args = SP - argc; - FP = SavedCallerFP(FP); - if (has_dart_caller) { - pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_; - } - - RawClosure* closure = - Closure::RawCast(args[has_function_type_args ? 1 : 0]); - *++SP = null_value; - *++SP = closure; - *++SP = closure->ptr()->function_; - *++SP = argdesc_; - *++SP = null_value; // Array of arguments (will be filled). - - // Allocate array of arguments. - { - SP[1] = Smi::New(argc); // length - SP[2] = null_value; // type - Exit(thread, FP, SP + 3, pc); - NativeArguments native_args(thread, 2, SP + 1, SP); - if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) { - HANDLE_EXCEPTION; - } else if (has_dart_caller) { - HANDLE_RETURN; - } - - // Copy arguments into the newly allocated array. - RawArray* array = static_cast(SP[0]); - ASSERT(array->GetClassId() == kArrayCid); - for (intptr_t i = 0; i < argc; i++) { - array->ptr()->data()[i] = args[i]; - } - } - - // Invoke noSuchMethod passing down closure, argument descriptor and - // array of arguments. - { - Exit(thread, FP, SP + 1, pc); - NativeArguments native_args(thread, 4, SP - 3, SP - 4); - INVOKE_RUNTIME(DRT_NoSuchMethodFromPrologue, native_args); - UNREACHABLE(); - } - - DISPATCH(); - } - - // Single dispatch point used by exception handling macros. - { - DispatchAfterException: - DISPATCH(); - } - - UNREACHABLE(); - return 0; -} - -void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { - // Walk over all setjmp buffers (simulated --> C++ transitions) - // and try to find the setjmp associated with the simulated frame pointer. - SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); - while ((buf->link() != NULL) && (buf->link()->fp() > fp)) { - buf = buf->link(); - } - ASSERT(buf != NULL); - ASSERT(last_setjmp_buffer() == buf); - - // The C++ caller has not cleaned up the stack memory of C++ frames. - // Prepare for unwinding frames by destroying all the stack resources - // in the previous C++ frames. - StackResource::Unwind(thread); - - fp_ = reinterpret_cast(fp); - - if (pc == StubCode::RunExceptionHandler().EntryPoint()) { - // The RunExceptionHandler stub is a placeholder. We implement - // its behavior here. - RawObject* raw_exception = thread->active_exception(); - RawObject* raw_stacktrace = thread->active_stacktrace(); - ASSERT(raw_exception != Object::null()); - thread->set_active_exception(Object::null_object()); - thread->set_active_stacktrace(Object::null_object()); - special_[kExceptionSpecialIndex] = raw_exception; - special_[kStackTraceSpecialIndex] = raw_stacktrace; - pc_ = thread->resume_pc(); - } else { - pc_ = pc; - } - - // Set the tag. - thread->set_vm_tag(VMTag::kDartCompiledTagId); - // Clear top exit frame. - thread->set_top_exit_frame_info(0); - - buf->Longjmp(); - UNREACHABLE(); -} - -void Simulator::VisitObjectPointers(ObjectPointerVisitor* visitor) { - visitor->VisitPointer(reinterpret_cast(&pp_)); - visitor->VisitPointer(reinterpret_cast(&argdesc_)); -} - -} // namespace dart - -#endif // defined TARGET_ARCH_DBC diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h deleted file mode 100644 index 7ed6fce7576..00000000000 --- a/runtime/vm/simulator_dbc.h +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_VM_SIMULATOR_DBC_H_ -#define RUNTIME_VM_SIMULATOR_DBC_H_ - -#ifndef RUNTIME_VM_SIMULATOR_H_ -#error Do not include simulator_dbc.h directly; use simulator.h. -#endif - -#include "vm/compiler/method_recognizer.h" -#include "vm/constants_dbc.h" - -namespace dart { - -class Array; -class Code; -class Isolate; -class ObjectPointerVisitor; -class RawArray; -class RawCode; -class RawFunction; -class RawICData; -class RawImmutableArray; -class RawObject; -class RawObjectPool; -class SimulatorSetjmpBuffer; -class Thread; - -// Simulator intrinsic handler. It is invoked on entry to the intrinsified -// function via Intrinsic bytecode before the frame is setup. -// If the handler returns true then Intrinsic bytecode works as a return -// instruction returning the value in result. Otherwise interpreter proceeds to -// execute the body of the function. -typedef bool (*IntrinsicHandler)(Thread* thread, - RawObject** FP, - RawObject** result); - -class Simulator { - public: - static const uword kSimulatorStackUnderflowSize = 0x80; - - Simulator(); - ~Simulator(); - - // The currently executing Simulator instance, which is associated to the - // current isolate - static Simulator* Current(); - - // Low address (DBC stack grows up). - uword stack_base() const { return stack_base_; } - // Limit for StackOverflowError. - uword overflow_stack_limit() const { return overflow_stack_limit_; } - // High address (DBC stack grows up). - uword stack_limit() const { return stack_limit_; } - - // Call on program start. - static void Init(); - - RawObject* Call(const Code& code, - const Array& arguments_descriptor, - const Array& arguments, - Thread* thread); - - void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread); - - uword get_sp() const { return reinterpret_cast(fp_); } - uword get_fp() const { return reinterpret_cast(fp_); } - uword get_pc() const { return reinterpret_cast(pc_); } - - enum IntrinsicId { -#define V(test_class_name, test_function_name, enum_name, fp) \ - k##enum_name##Intrinsic, - ALL_INTRINSICS_LIST(V) GRAPH_INTRINSICS_LIST(V) -#undef V - kIntrinsicCount, - }; - - static bool IsSupportedIntrinsic(IntrinsicId id) { - return intrinsics_[id] != NULL; - } - - enum SpecialIndex { - kExceptionSpecialIndex, - kStackTraceSpecialIndex, - kSpecialIndexCount - }; - - void VisitObjectPointers(ObjectPointerVisitor* visitor); - - private: - uintptr_t* stack_; - uword stack_base_; - uword overflow_stack_limit_; - uword stack_limit_; - - RawObject** fp_; - uword pc_; - DEBUG_ONLY(uint64_t icount_;) - - SimulatorSetjmpBuffer* last_setjmp_buffer_; - - RawObjectPool* pp_; // Pool Pointer. - RawArray* argdesc_; // Arguments Descriptor: used to pass information between - // call instruction and the function entry. - RawObject* special_[kSpecialIndexCount]; - - static IntrinsicHandler intrinsics_[kIntrinsicCount]; - - // Set up an exit frame for the garbage collector. - void Exit(Thread* thread, - RawObject** base, - RawObject** exit_frame, - uint32_t* pc); - - void CallRuntime(Thread* thread, - RawObject** base, - RawObject** exit_frame, - uint32_t* pc, - intptr_t argc_tag, - RawObject** args, - RawObject** result, - uword target); - - void Invoke(Thread* thread, - RawObject** call_base, - RawObject** call_top, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP); - - bool Deoptimize(Thread* thread, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP, - bool is_lazy); - - void InlineCacheMiss(int checked_args, - Thread* thread, - RawICData* icdata, - RawObject** call_base, - RawObject** top, - uint32_t* pc, - RawObject** FP, - RawObject** SP); - - void InstanceCall1(Thread* thread, - RawICData* icdata, - RawObject** call_base, - RawObject** call_top, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP, - bool optimized); - - void InstanceCall2(Thread* thread, - RawICData* icdata, - RawObject** call_base, - RawObject** call_top, - uint32_t** pc, - RawObject*** FP, - RawObject*** SP, - bool optimized); - - void PrepareForTailCall(RawCode* code, - RawImmutableArray* args_desc, - RawObject** FP, - RawObject*** SP, - uint32_t** pc); - -#if !defined(PRODUCT) - // Returns true if tracing of executed instructions is enabled. - bool IsTracingExecution() const; - - // Prints bytecode instruction at given pc for instruction tracing. - void TraceInstruction(uint32_t* pc) const; -#endif // !defined(PRODUCT) - - // Longjmp support for exceptions. - SimulatorSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; } - void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) { - last_setjmp_buffer_ = buffer; - } - - friend class SimulatorSetjmpBuffer; - DISALLOW_COPY_AND_ASSIGN(Simulator); -}; - -} // namespace dart - -#endif // RUNTIME_VM_SIMULATOR_DBC_H_ diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc index 5e161d9e478..2b07d464a55 100644 --- a/runtime/vm/source_report.cc +++ b/runtime/vm/source_report.cc @@ -218,14 +218,7 @@ void SourceReport::PrintCallSitesData(JSONObject* jsobj, RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); while (iter.MoveNext()) { HANDLESCOPE(thread()); -// TODO(zra): Remove this bailout once DBC has reliable ICData. -#if defined(TARGET_ARCH_DBC) - if (iter.DeoptId() >= ic_data_array->length()) { - continue; - } -#else ASSERT(iter.DeoptId() < ic_data_array->length()); -#endif const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; if (ic_data != NULL) { const TokenPosition token_pos = iter.TokenPos(); @@ -276,14 +269,7 @@ void SourceReport::PrintCoverageData(JSONObject* jsobj, RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall); while (iter.MoveNext()) { HANDLESCOPE(thread()); -// TODO(zra): Remove this bailout once DBC has reliable ICData. -#if defined(TARGET_ARCH_DBC) - if (iter.DeoptId() >= ic_data_array->length()) { - continue; - } -#else ASSERT(iter.DeoptId() < ic_data_array->length()); -#endif const ICData* ic_data = (*ic_data_array)[iter.DeoptId()]; if (ic_data != NULL) { const TokenPosition token_pos = iter.TokenPos(); diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index defc700da55..260e99fe42e 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -220,23 +220,17 @@ void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { reinterpret_cast(fp()) + (is_interpreted() ? kKBCFirstObjectSlotFromFp : runtime_frame_layout.last_fixed_object_from_fp); -#if !defined(TARGET_ARCH_DBC) if (first_fixed <= last_fixed) { visitor->VisitPointers(first_fixed, last_fixed); } else { ASSERT(runtime_frame_layout.first_object_from_fp == runtime_frame_layout.first_local_from_fp); } -#else - ASSERT(last_fixed <= first_fixed); - visitor->VisitPointers(last_fixed, first_fixed); -#endif } void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { ASSERT(visitor != NULL); // Visit objects between SP and (FP - callee_save_area). -#if !defined(TARGET_ARCH_DBC) RawObject** first = is_interpreted() ? reinterpret_cast(fp()) + kKBCSavedArgDescSlotFromEntryFp : reinterpret_cast(sp()); @@ -245,13 +239,6 @@ void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { kExitLinkSlotFromEntryFp - 1; // There may not be any pointer to visit; in this case, first > last. visitor->VisitPointers(first, last); -#else - // On DBC stack is growing upwards which implies fp() <= sp(). - RawObject** first = reinterpret_cast(fp()); - RawObject** last = reinterpret_cast(sp()); - ASSERT(first <= last); - visitor->VisitPointers(first, last); -#endif } void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { @@ -293,7 +280,6 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { const uword start = Instructions::PayloadStart(code.instructions()); const uint32_t pc_offset = pc() - start; if (it.Find(pc_offset)) { -#if !defined(TARGET_ARCH_DBC) if (is_interpreted()) { UNIMPLEMENTED(); } @@ -341,42 +327,6 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { last = reinterpret_cast( fp() + (runtime_frame_layout.first_object_from_fp * kWordSize)); visitor->VisitPointers(first, last); -#else - RawObject** first = reinterpret_cast(fp()); - RawObject** last = reinterpret_cast(sp()); - - // Visit fixed prefix of the frame. - RawObject** first_fixed = - first + runtime_frame_layout.first_object_from_fp; - RawObject** last_fixed = - first + (runtime_frame_layout.first_object_from_fp + 1); - ASSERT(first_fixed <= last_fixed); - visitor->VisitPointers(first_fixed, last_fixed); - - // A stack map is present in the code object, use the stack map to - // visit frame slots which are marked as having objects. - // - // The layout of the frame is (lower addresses to the left): - // | registers | outgoing arguments | - // |XXXXXXXXXXX|--------------------| - // - // The DBC registers are described in the stack map. - // The outgoing arguments are assumed to be tagged; the number - // of outgoing arguments is not explicitly tracked. - - // Visit DBC registers that contain tagged values. - intptr_t length = it.length(); - for (intptr_t bit = 0; bit < length; ++bit) { - if (it.IsObject(bit)) { - visitor->VisitPointer(first + bit); - } - } - - // Visit outgoing arguments. - if ((first + length) <= last) { - visitor->VisitPointers(first + length, last); - } -#endif // !defined(TARGET_ARCH_DBC) return; } @@ -388,7 +338,6 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { (pc_offset == code.EntryPoint() - code.PayloadStart())); } -#if !defined(TARGET_ARCH_DBC) // For normal unoptimized Dart frames and Stub frames each slot // between the first and last included are tagged objects. if (is_interpreted()) { @@ -406,12 +355,6 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { is_interpreted() ? sp() : fp() + (runtime_frame_layout.first_object_from_fp * kWordSize)); -#else - // On DBC stack grows upwards: fp() <= sp(). - RawObject** first = reinterpret_cast( - fp() + (runtime_frame_layout.first_object_from_fp * kWordSize)); - RawObject** last = reinterpret_cast(sp()); -#endif // !defined(TARGET_ARCH_DBC) visitor->VisitPointers(first, last); } @@ -655,7 +598,6 @@ StackFrameIterator::StackFrameIterator(uword last_fp, } } -#if !defined(TARGET_ARCH_DBC) StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc, @@ -677,7 +619,6 @@ StackFrameIterator::StackFrameIterator(uword fp, frames_.CheckIfInterpreted(fp); } } -#endif StackFrame* StackFrameIterator::NextFrame() { // When we are at the start of iteration after having created an @@ -697,7 +638,6 @@ StackFrame* StackFrameIterator::NextFrame() { return NULL; } UnpoisonStack(frames_.fp_); -#if !defined(TARGET_ARCH_DBC) if (frames_.pc_ == 0) { // Iteration starts from an exit frame given by its fp. current_frame_ = NextExitFrame(); @@ -712,12 +652,6 @@ StackFrame* StackFrameIterator::NextFrame() { // Iteration starts from a Dart or stub frame given by its fp, sp, and pc. current_frame_ = frames_.NextFrame(validate_); } -#else - // Iteration starts from an exit frame given by its fp. This is the only - // mode supported on DBC. - ASSERT(frames_.pc_ == 0); - current_frame_ = NextExitFrame(); -#endif // !defined(TARGET_ARCH_DBC) return current_frame_; } ASSERT(!validate_ || current_frame_->IsValid()); @@ -865,14 +799,7 @@ intptr_t InlinedFunctionsIterator::GetDeoptFpOffset() const { for (intptr_t index = index_; index < deopt_instructions_.length(); index++) { DeoptInstr* deopt_instr = deopt_instructions_[index]; if (deopt_instr->kind() == DeoptInstr::kCallerFp) { - intptr_t fp_offset = (index - num_materializations_); -#if defined(TARGET_ARCH_DBC) - // Stack on DBC is growing upwards but we record deopt commands - // in the same order we record them on other architectures as if - // the stack was growing downwards. - fp_offset = dest_frame_size_ - fp_offset; -#endif - return fp_offset; + return index - num_materializations_; } } UNREACHABLE(); diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h index b36721d41a9..69368fe3e5f 100644 --- a/runtime/vm/stack_frame.h +++ b/runtime/vm/stack_frame.h @@ -20,8 +20,6 @@ #include "vm/stack_frame_arm.h" #elif defined(TARGET_ARCH_ARM64) #include "vm/stack_frame_arm64.h" -#elif defined(TARGET_ARCH_DBC) -#include "vm/stack_frame_dbc.h" #else #error Unknown architecture. #endif @@ -258,7 +256,6 @@ class StackFrameIterator : public ValueObject { Thread* thread, CrossThreadPolicy cross_thread_policy); -#if !defined(TARGET_ARCH_DBC) // Iterator for iterating over all frames from the current frame (given by its // fp, sp, and pc) to the first EntryFrame. StackFrameIterator(uword fp, @@ -267,7 +264,6 @@ class StackFrameIterator : public ValueObject { ValidationPolicy validation_policy, Thread* thread, CrossThreadPolicy cross_thread_policy); -#endif // Checks if a next frame exists. bool HasNextFrame() const { return frames_.fp_ != 0; } @@ -371,7 +367,6 @@ class DartFrameIterator : public ValueObject { thread, cross_thread_policy) {} -#if !defined(TARGET_ARCH_DBC) DartFrameIterator(uword fp, uword sp, uword pc, @@ -383,7 +378,6 @@ class DartFrameIterator : public ValueObject { ValidationPolicy::kDontValidateFrames, thread, cross_thread_policy) {} -#endif // Get next dart frame. StackFrame* NextFrame() { @@ -446,7 +440,6 @@ class InlinedFunctionsIterator : public ValueObject { void ValidateFrames(); #endif -#if !defined(TARGET_ARCH_DBC) DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset, intptr_t var_index) { return fp_offset + var_index; @@ -457,7 +450,6 @@ DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) { } // Both fp and other_fp are compiled code frame pointers. -// See stack_frame_dbc.h for the DBC version. DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) { return other_fp < fp; } @@ -469,10 +461,7 @@ DART_FORCE_INLINE static bool IsBytecodeCalleeFrameOf(uword fp, } // Value for stack limit that is used to cause an interrupt. -// Note that on DBC stack is growing upwards so interrupt limit is 0 unlike -// on all other architectures. static const uword kInterruptStackLimit = ~static_cast(0); -#endif DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) { return fp + LocalVarIndex(0, index) * kWordSize; diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h deleted file mode 100644 index 616b01283bc..00000000000 --- a/runtime/vm/stack_frame_dbc.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -#ifndef RUNTIME_VM_STACK_FRAME_DBC_H_ -#define RUNTIME_VM_STACK_FRAME_DBC_H_ - -#if !defined(RUNTIME_VM_STACK_FRAME_H_) -#error Do not include stack_frame_dbc.h directly; use stack_frame.h instead. -#endif - -namespace dart { - -/* DBC Frame Layout - -IMPORTANT: On DBC stack is growing upwards which is different from all other -architectures. This enables efficient addressing for locals via unsigned index. - - | | <- TOS -Callee frame | ... | - | saved FP | (FP of current frame) - | saved PC | (PC of current frame) - | code object | - | function object | - +--------------------+ -Current frame | ... T| <- SP of current frame - | ... T| - | first local T| <- FP of current frame - | caller's FP *| - | caller's PC *| - | code object T| (current frame's code object) - | function object T| (current frame's function object) - +--------------------+ -Caller frame | last parameter | <- SP of caller frame - | ... | - - T against a slot indicates it needs to be traversed during GC. - * against a slot indicates that it can be traversed during GC - because it will look like a smi to the visitor. -*/ - -static const int kDartFrameFixedSize = 4; // Function, Code, PC, FP -static const int kSavedPcSlotFromSp = 3; - -static const int kFirstObjectSlotFromFp = -4; // Used by GC to traverse stack. -static const int kLastFixedObjectSlotFromFp = -3; - -static const int kSavedCallerFpSlotFromFp = -1; -static const int kSavedCallerPpSlotFromFp = kSavedCallerFpSlotFromFp; -static const int kSavedCallerPcSlotFromFp = -2; -static const int kCallerSpSlotFromFp = -kDartFrameFixedSize - 1; -static const int kPcMarkerSlotFromFp = -3; -static const int kFunctionSlotFromFp = -4; - -// Note: These constants don't match actual DBC behavior. This is done because -// setting kFirstLocalSlotFromFp to 0 breaks assumptions spread across the code. -// Instead for the purposes of local variable allocation we pretend that DBC -// behaves as other architectures (stack growing downwards) and later fix -// these indices during code generation in the backend. -static const int kParamEndSlotFromFp = 4; // One slot past last parameter. -static const int kFirstLocalSlotFromFp = -1; -static const int kLastParamSlotFromEntrySp = 0; // Should not be used on DBC. - -DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset, - intptr_t var_index) { - if (var_index > 0) { - return fp_offset - var_index; - } else { - return fp_offset - (var_index + 1); - } -} - -DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) { - return fp - (kDartFrameFixedSize + reverse_index) * kWordSize; -} - -DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) { - return other_fp > fp; -} - -DART_FORCE_INLINE static bool IsBytecodeCalleeFrameOf(uword fp, - uword other_fp) { - UNREACHABLE(); - return false; -} - -static const int kExitLinkSlotFromEntryFp = 0; - -// Value for stack limit that is used to cause an interrupt. -// Note that on DBC stack is growing upwards so interrupt limit is 0 unlike -// on all other architectures. -static const uword kInterruptStackLimit = 0; - -// TODO(37140): For FFI native -> Dart callbacks, the number of stack slots -// between arguments passed on stack and arguments saved in callback prologue. -constexpr intptr_t kCallbackSlotsBeforeSavedArguments = -1; - -} // namespace dart - -#endif // RUNTIME_VM_STACK_FRAME_DBC_H_ diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc index 097510ec173..739e4fdeec3 100644 --- a/runtime/vm/stub_code.cc +++ b/runtime/vm/stub_code.cc @@ -103,7 +103,6 @@ bool StubCode::HasBeenInitialized() { } bool StubCode::InInvocationStub(uword pc, bool is_interpreted_frame) { -#if !defined(TARGET_ARCH_DBC) ASSERT(HasBeenInitialized()); #if !defined(DART_PRECOMPILED_RUNTIME) if (FLAG_enable_interpreter) { @@ -124,33 +123,16 @@ bool StubCode::InInvocationStub(uword pc, bool is_interpreted_frame) { uword entry = StubCode::InvokeDartCode().EntryPoint(); uword size = StubCode::InvokeDartCodeSize(); return (pc >= entry) && (pc < (entry + size)); -#else - if (FLAG_enable_interpreter) { - FATAL( - "Simultaneous usage of DBC simulator " - "and interpreter not yet supported."); - } - // On DBC we use a special marker PC to signify entry frame because there is - // no such thing as invocation stub. - return (pc & 2) != 0; -#endif } bool StubCode::InJumpToFrameStub(uword pc) { -#if !defined(TARGET_ARCH_DBC) ASSERT(HasBeenInitialized()); uword entry = StubCode::JumpToFrame().EntryPoint(); uword size = StubCode::JumpToFrameSize(); return (pc >= entry) && (pc < (entry + size)); -#else - // This stub does not exist on DBC. - return false; -#endif } RawCode* StubCode::GetAllocationStubForClass(const Class& cls) { -// These stubs are not used by DBC. -#if !defined(TARGET_ARCH_DBC) Thread* thread = Thread::Current(); Zone* zone = thread->zone(); const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread)); @@ -231,12 +213,9 @@ RawCode* StubCode::GetAllocationStubForClass(const Class& cls) { } #endif // !defined(DART_PRECOMPILED_RUNTIME) return stub.raw(); -#endif // !DBC - UNIMPLEMENTED(); - return Code::null(); } -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) RawCode* StubCode::GetBuildMethodExtractorStub( compiler::ObjectPoolBuilder* pool) { #if !defined(DART_PRECOMPILED_RUNTIME) @@ -283,11 +262,9 @@ RawCode* StubCode::GetBuildMethodExtractorStub( return nullptr; #endif // !defined(DART_PRECOMPILED_RUNTIME) } -#endif // !defined(TARGET_ARCH_DBC) +#endif // !defined(TARGET_ARCH_IA32) const Code& StubCode::UnoptimizedStaticCallEntry(intptr_t num_args_tested) { -// These stubs are not used by DBC. -#if !defined(TARGET_ARCH_DBC) switch (num_args_tested) { case 0: return ZeroArgsUnoptimizedStaticCall(); @@ -299,9 +276,6 @@ const Code& StubCode::UnoptimizedStaticCallEntry(intptr_t num_args_tested) { UNIMPLEMENTED(); return Code::Handle(); } -#else - return Code::Handle(); -#endif } const char* StubCode::NameOfStub(uword entry_point) { diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h index 6de3ae45905..cf832cb7d16 100644 --- a/runtime/vm/stub_code.h +++ b/runtime/vm/stub_code.h @@ -59,7 +59,7 @@ class StubCode : public AllStatic { static RawCode* GetAllocationStubForClass(const Class& cls); -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) static RawCode* GetBuildMethodExtractorStub( compiler::ObjectPoolBuilder* pool); #endif diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h index 0ca76d29a63..ba767d0e355 100644 --- a/runtime/vm/stub_code_list.h +++ b/runtime/vm/stub_code_list.h @@ -9,7 +9,6 @@ namespace dart { // List of stubs created in the VM isolate, these stubs are shared by different // isolates running in this dart process. -#if !defined(TARGET_ARCH_DBC) #define VM_STUB_CODE_LIST(V) \ V(GetCStackPointer) \ V(JumpToFrame) \ @@ -80,30 +79,6 @@ namespace dart { V(ExitSafepoint) \ V(CallNativeThroughSafepoint) -#else -#define VM_STUB_CODE_LIST(V) \ - V(LazyCompile) \ - V(OptimizeFunction) \ - V(CallClosureNoSuchMethod) \ - V(RunExceptionHandler) \ - V(DeoptForRewind) \ - V(FixCallersTarget) \ - V(Deoptimize) \ - V(DeoptimizeLazyFromReturn) \ - V(DeoptimizeLazyFromThrow) \ - V(DefaultTypeTest) \ - V(TopTypeTypeTest) \ - V(TypeRefTypeTest) \ - V(UnreachableTypeTest) \ - V(SlowTypeTest) \ - V(LazySpecializeTypeTest) \ - V(FrameAwaitingMaterialization) \ - V(AsynchronousGapMarker) \ - V(InvokeDartCodeFromBytecode) \ - V(InterpretCall) - -#endif // !defined(TARGET_ARCH_DBC) - } // namespace dart #endif // RUNTIME_VM_STUB_CODE_LIST_H_ diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index 6e25f4f5103..c79be7b86d5 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc @@ -951,7 +951,7 @@ int32_t Thread::AllocateFfiCallbackId() { const int32_t id = array.Length() - 1; // Allocate a native callback trampoline if necessary. -#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC) +#if !defined(DART_PRECOMPILED_RUNTIME) if (NativeCallbackTrampolines::Enabled()) { auto* const tramps = isolate()->native_callback_trampolines(); ASSERT(tramps->next_callback_id() == id); diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h index e9f2fa5929a..2469d3081c3 100644 --- a/runtime/vm/thread.h +++ b/runtime/vm/thread.h @@ -95,9 +95,6 @@ class Thread; V(TypeArguments) \ V(TypeParameter) -#if defined(TARGET_ARCH_DBC) -#define CACHED_VM_STUBS_LIST(V) -#else #define CACHED_VM_STUBS_LIST(V) \ V(RawCode*, write_barrier_code_, StubCode::WriteBarrier().raw(), NULL) \ V(RawCode*, array_write_barrier_code_, StubCode::ArrayWriteBarrier().raw(), \ @@ -133,8 +130,6 @@ class Thread; V(RawCode*, call_native_through_safepoint_stub_, \ StubCode::CallNativeThroughSafepoint().raw(), NULL) -#endif - #define CACHED_NON_VM_STUB_LIST(V) \ V(RawObject*, object_null_, Object::null(), NULL) \ V(RawBool*, bool_true_, Object::bool_true().raw(), NULL) \ @@ -152,9 +147,6 @@ class Thread; ASSERT((Thread::bool_true_offset() + kWordSize) == \ Thread::bool_false_offset()); -#if defined(TARGET_ARCH_DBC) -#define CACHED_VM_STUBS_ADDRESSES_LIST(V) -#else #define CACHED_VM_STUBS_ADDRESSES_LIST(V) \ V(uword, write_barrier_entry_point_, StubCode::WriteBarrier().EntryPoint(), \ 0) \ @@ -178,7 +170,6 @@ class Thread; V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0) \ V(uword, call_native_through_safepoint_entry_point_, \ StubCode::CallNativeThroughSafepoint().EntryPoint(), 0) -#endif #define CACHED_ADDRESSES_LIST(V) \ CACHED_VM_STUBS_ADDRESSES_LIST(V) \ @@ -295,11 +286,6 @@ class Thread : public ThreadState { return OFFSET_OF(Thread, saved_shadow_call_stack_); } -#if defined(TARGET_ARCH_DBC) - // Access to the current stack limit for DBC interpreter. - uword stack_limit() const { return stack_limit_; } -#endif - // Stack overflow flags enum { kOsrRequest = 0x1, // Current stack overflow caused by OSR request. @@ -318,13 +304,11 @@ class Thread : public ThreadState { return ++stack_overflow_count_; } -#if !defined(TARGET_ARCH_DBC) static uword stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) { return fpu_regs ? stack_overflow_shared_with_fpu_regs_entry_point_offset() : stack_overflow_shared_without_fpu_regs_entry_point_offset(); } -#endif static intptr_t safepoint_state_offset() { return OFFSET_OF(Thread, safepoint_state_); diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc index d4195bd73a1..79db5498be5 100644 --- a/runtime/vm/type_testing_stubs.cc +++ b/runtime/vm/type_testing_stubs.cc @@ -138,7 +138,7 @@ TypeTestingStubGenerator::TypeTestingStubGenerator() RawCode* TypeTestingStubGenerator::OptimizedCodeForType( const AbstractType& type) { -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) ASSERT(StubCode::HasBeenInitialized()); if (type.IsTypeRef()) { @@ -168,11 +168,11 @@ RawCode* TypeTestingStubGenerator::OptimizedCodeForType( #endif // !defined(DART_PRECOMPILED_RUNTIME) } } -#endif // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#endif // !defined(TARGET_ARCH_IA32) return TypeTestingStubGenerator::DefaultCodeForType(type, false); } -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) #if !defined(DART_PRECOMPILED_RUNTIME) RawCode* TypeTestingStubGenerator::BuildCodeForType(const Type& type) { @@ -546,7 +546,7 @@ void RegisterTypeArgumentsUse(const Function& function, #endif // !defined(DART_PRECOMPILED_RUNTIME) -#else // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#else // !defined(TARGET_ARCH_IA32) void RegisterTypeArgumentsUse(const Function& function, TypeUsageInfo* type_usage_info, @@ -556,7 +556,7 @@ void RegisterTypeArgumentsUse(const Function& function, UNREACHABLE(); } -#endif // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#endif // !defined(TARGET_ARCH_IA32) #undef __ diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h index b0a772db61e..65c9bd22a30 100644 --- a/runtime/vm/type_testing_stubs.h +++ b/runtime/vm/type_testing_stubs.h @@ -51,7 +51,7 @@ class TypeTestingStubGenerator { RawCode* OptimizedCodeForType(const AbstractType& type); private: -#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#if !defined(TARGET_ARCH_IA32) #if !defined(DART_PRECOMPILED_RUNTIME) RawCode* BuildCodeForType(const Type& type); static void BuildOptimizedTypeTestStub(compiler::Assembler* assembler, @@ -116,7 +116,7 @@ class TypeTestingStubGenerator { compiler::Label* check_failed); #endif // !defined(DART_PRECOMPILED_RUNTIME) -#endif // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) +#endif // !defined(TARGET_ARCH_IA32) TypeTestingStubNamer namer_; ObjectStore* object_store_; diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc index 1fa611e79c5..67aa62db646 100644 --- a/runtime/vm/unit_test.cc +++ b/runtime/vm/unit_test.cc @@ -696,7 +696,7 @@ void AssemblerTest::Assemble() { String::ZoneHandle(Symbols::New(Thread::Current(), name_)); // We make a dummy script so that exception objects can be composed for - // assembler instructions that do runtime calls, in particular on DBC. + // assembler instructions that do runtime calls. const char* kDummyScript = "assembler_test_dummy_function() {}"; const Script& script = Script::Handle( Script::New(function_name, String::Handle(String::New(kDummyScript)), diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h index af1e38e6f54..947cd1536c5 100644 --- a/runtime/vm/unit_test.h +++ b/runtime/vm/unit_test.h @@ -481,7 +481,7 @@ class AssemblerTest { // using the ABI calling convention. // ResultType is the return type of the assembler test function. // ArgNType is the type of the Nth argument. -#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) +#if defined(USING_SIMULATOR) #if defined(ARCH_IS_64_BIT) // TODO(fschneider): Make InvokeWithCodeAndThread<> more general and work on @@ -532,29 +532,6 @@ class AssemblerTest { reinterpret_cast(arg2), reinterpret_cast(arg3), 0, fp_return, fp_args); } -#elif defined(USING_SIMULATOR) && defined(TARGET_ARCH_DBC) - template - ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) { - // TODO(fschneider): Support double arguments for simulator calls. - COMPILE_ASSERT(is_void::value); - COMPILE_ASSERT(!is_double::value); - COMPILE_ASSERT(!is_double::value); - COMPILE_ASSERT(!is_double::value); - const Object& arg1obj = Object::Handle(reinterpret_cast(arg1)); - const Object& arg2obj = Object::Handle(reinterpret_cast(arg2)); - const intptr_t kTypeArgsLen = 0; - const intptr_t kNumArgs = 2; - const Array& argdesc = - Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)); - const Array& arguments = Array::Handle(Array::New(2)); - arguments.SetAt(0, arg1obj); - arguments.SetAt(1, arg2obj); - Simulator::Current()->Call(code(), argdesc, arguments, - reinterpret_cast(arg3)); - } #else template ResultType InvokeWithCodeAndThread() { @@ -580,7 +557,7 @@ class AssemblerTest { typedef ResultType (*FunctionType)(Arg1Type, Arg2Type, Arg3Type); return reinterpret_cast(entry())(arg1, arg2, arg3); } -#endif // defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) +#endif // defined(USING_SIMULATOR) // Assemble test and set code_. void Assemble(); diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc index bf4fed7b040..22a6b4d152e 100644 --- a/runtime/vm/virtual_memory_posix.cc +++ b/runtime/vm/virtual_memory_posix.cc @@ -169,10 +169,6 @@ VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size, intptr_t alignment, bool is_executable, const char* name) { -#if defined(TARGET_ARCH_DBC) - RELEASE_ASSERT(!is_executable); -#endif - // When FLAG_write_protect_code is active, code memory (indicated by // is_executable = true) is allocated as non-executable and later // changed to executable via VirtualMemory::Protect. @@ -265,9 +261,6 @@ void VirtualMemory::FreeSubSegment(void* address, } void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) { -#if defined(TARGET_ARCH_DBC) - RELEASE_ASSERT((mode != kReadExecute) && (mode != kReadWriteExecute)); -#endif #if defined(DEBUG) Thread* thread = Thread::Current(); ASSERT((thread == nullptr) || thread->IsMutatorThread() || diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni index b692ab45763..1a6c0de1719 100644 --- a/runtime/vm/vm_sources.gni +++ b/runtime/vm/vm_sources.gni @@ -39,7 +39,6 @@ vm_sources = [ "code_patcher.h", "code_patcher_arm.cc", "code_patcher_arm64.cc", - "code_patcher_dbc.cc", "code_patcher_ia32.cc", "code_patcher_kbc.cc", "code_patcher_x64.cc", @@ -49,8 +48,6 @@ vm_sources = [ "constants_arm.h", "constants_arm64.cc", "constants_arm64.h", - "constants_dbc.cc", - "constants_dbc.h", "constants_ia32.cc", "constants_ia32.h", "constants_kbc.cc", @@ -60,7 +57,6 @@ vm_sources = [ "cpu.h", "cpu_arm.cc", "cpu_arm64.cc", - "cpu_dbc.cc", "cpu_ia32.cc", "cpu_x64.cc", "cpuid.cc", @@ -86,7 +82,6 @@ vm_sources = [ "debugger.h", "debugger_arm.cc", "debugger_arm64.cc", - "debugger_dbc.cc", "debugger_ia32.cc", "debugger_kbc.cc", "debugger_x64.cc", @@ -127,8 +122,6 @@ vm_sources = [ "instructions_arm.h", "instructions_arm64.cc", "instructions_arm64.h", - "instructions_dbc.cc", - "instructions_dbc.h", "instructions_ia32.cc", "instructions_ia32.h", "instructions_kbc.cc", @@ -265,7 +258,6 @@ vm_sources = [ "runtime_entry.h", "runtime_entry_arm.cc", "runtime_entry_arm64.cc", - "runtime_entry_dbc.cc", "runtime_entry_ia32.cc", "runtime_entry_list.h", "runtime_entry_x64.cc", @@ -289,8 +281,6 @@ vm_sources = [ "simulator_arm.h", "simulator_arm64.cc", "simulator_arm64.h", - "simulator_dbc.cc", - "simulator_dbc.h", "snapshot.cc", "snapshot.h", "snapshot_ids.h", @@ -300,7 +290,6 @@ vm_sources = [ "stack_frame.h", "stack_frame_arm.h", "stack_frame_arm64.h", - "stack_frame_dbc.h", "stack_frame_ia32.h", "stack_frame_kbc.h", "stack_frame_x64.h", @@ -425,7 +414,6 @@ vm_sources_tests = [ "native_entry_test.h", "object_arm64_test.cc", "object_arm_test.cc", - "object_dbc_test.cc", "object_graph_test.cc", "object_ia32_test.cc", "object_id_ring_test.cc", diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status index e6024bc8312..25112126204 100644 --- a/tests/co19_2/co19_2-kernel.status +++ b/tests/co19_2/co19_2-kernel.status @@ -178,17 +178,6 @@ LanguageFeatures/Set-literals/disambiguating_A02_t03: Crash LanguageFeatures/regression/34803_t01: Crash LanguageFeatures/regression/34803_t02: Crash -[ $arch == simdbc64 && $compiler == dartk ] -LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Issue http://dartbug.com/35242 -LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Issue http://dartbug.com/35242 -LibTest/core/List/List_class_A01_t02: Crash # Issue http://dartbug.com/35242 - -[ $arch == simdbc64 && $system == macos && ($compiler == dartk || $compiler == dartkb) ] -LanguageFeatures/Subtyping/static/generated/function_type_function_arguments_binding_A04_t02: Crash - -[ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ] -LibTest/isolate/Isolate/removeErrorListener_A02_t01: Crash - [ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ] LibTest/isolate/Isolate/spawn_A06_t03: Crash @@ -212,5 +201,5 @@ LibTest/isolate/SendPort/send_A01_t03: Crash # as that would involve running CFE (the front end) in simulator mode # to compile the URI file specified in spawnURI code. # These Isolate tests that use spawnURI are hence skipped on purpose. -[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ] +[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ] LibTest/isolate/Isolate/spawnUri*: Skip diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status index ed4ecb1513d..834728b8c8b 100644 --- a/tests/corelib_2/corelib_2.status +++ b/tests/corelib_2/corelib_2.status @@ -34,10 +34,7 @@ regexp/pcre_test: Slow # Issue 21593 int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support. typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support. -[ ($arch == simdbc || $arch == simdbc64) && ($hot_reload || $hot_reload_rollback) ] -uri_parse_test: SkipSlow - -[ $arch == simarm || $arch == simarm64 || $arch == simdbc64 ] +[ $arch == simarm || $arch == simarm64 ] bigint_parse_radix_test: Skip # Issue 31659 bigint_test: Skip # Issue 31659 diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status index 9f280660fc4..4e5b3d110cc 100644 --- a/tests/ffi/ffi.status +++ b/tests/ffi/ffi.status @@ -2,9 +2,6 @@ # 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. -[ $arch == simdbc || $arch == simdbc64 ] -*: Skip # SIMDBC will be deleted soon. - [ $builder_tag == asan ] data_not_asan_test: SkipByDesign # This test tries to allocate too much memory on purpose. diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status index 6d06af785d7..a592e6a2890 100644 --- a/tests/lib_2/lib_2.status +++ b/tests/lib_2/lib_2.status @@ -70,7 +70,7 @@ isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be # as that would involve running CFE (the front end) in simulator mode # to compile the URI file specified in spawnURI code. # These Isolate tests that use spawnURI are hence skipped on purpose. -[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ] +[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ] isolate/count_test: Skip # Isolate.spawnUri isolate/cross_isolate_message_test: Skip # Isolate.spawnUri isolate/deferred_in_isolate2_test: Skip # Isolate.spawnUri diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status index 2aeba0caaa6..8698a2c5642 100644 --- a/tests/lib_2/lib_2_kernel.status +++ b/tests/lib_2/lib_2_kernel.status @@ -14,9 +14,6 @@ isolate/isolate_complex_messages_test: Crash # runtime/vm/object.cc: 17395: erro html/*: Skip # TODO(ahe): Make dart:html available. js/*: Skip # TODO(ahe): Make dart:js available. -[ $arch == simdbc64 && $hot_reload_rollback ] -convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Uses --verify_before_gc --verify_after_gc --old_gen_growth_rate=1 flags - [ $arch == x64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ] mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439. diff --git a/tests/standalone_2/io/test_extension_test.dart b/tests/standalone_2/io/test_extension_test.dart index aa6a1c9307e..e69ae28e102 100644 --- a/tests/standalone_2/io/test_extension_test.dart +++ b/tests/standalone_2/io/test_extension_test.dart @@ -46,8 +46,6 @@ String getExtensionPath(String buildDirectory, String filename) { String getArchFromBuildDir(String buildDirectory) { if (buildDirectory.endsWith('SIMARM')) return ''; if (buildDirectory.endsWith('SIMARM64')) return ''; - if (buildDirectory.endsWith('SIMDBC')) return ''; - if (buildDirectory.endsWith('SIMDBC64')) return ''; if (buildDirectory.endsWith('ARM')) return '-arm'; if (buildDirectory.endsWith('ARM64')) return '-arm64'; if (buildDirectory.endsWith('IA32')) return '-ia32'; diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status index 93f0fdaabfe..6ec98049684 100644 --- a/tests/standalone_2/standalone_2_kernel.status +++ b/tests/standalone_2/standalone_2_kernel.status @@ -85,10 +85,10 @@ io/http_outgoing_size_test: Crash io/directory_chdir_test: Skip # Timeout io/echo_server_stream_test: Slow -# Enabling of dartk for sim{arm,arm64,dbc64} revealed these test failures, which +# Enabling of dartk for sim{arm,arm64} revealed these test failures, which # are to be triaged. Isolate tests are skipped on purpose due to the usage of # batch mode. -[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ] +[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ] io/file_blocking_lock_test: Crash # Please triage. io/file_lock_test: Slow map_insert_remove_oom_test: Skip # Heap limit too low. diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status index 59190893f9c..93e314f7b19 100644 --- a/tests/standalone_2/standalone_2_vm.status +++ b/tests/standalone_2/standalone_2_vm.status @@ -47,18 +47,15 @@ verbose_gc_to_bmu_test: Skip [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ] io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426 -[ $arch == simdbc64 && $mode == debug && $checked ] -io/web_socket_test: Pass, RuntimeError # Issue 26814. - [ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ] io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192 +[ $arch == x64 && $mode == release && $runtime == vm && $system == linux ] +io/http_bind_test: Pass, Timeout # Issue 35192 + [ $compiler != dart2analyzer && $system == windows ] io/platform_resolved_executable_test/06: RuntimeError # Issue 23641 -[ $mode == release && $runtime == vm && $system == linux && ($arch == simdbc64 || $arch == x64) ] -io/http_bind_test: Pass, Timeout # Issue 35192 - [ $mode == release && $runtime == vm && $system == macos ] io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout. io/named_pipe_script_test: Pass, RuntimeError # Issue 28737 @@ -80,8 +77,3 @@ io/process_sync_test: Timeout, Pass io/dart_std_io_pipe_test: Timeout, Pass io/http_client_stays_alive_test: Skip # Spawns process in Dart2 mode. io/process_sync_test: Timeout, Pass - -[ $arch == simdbc || $arch == simdbc64 ] -full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet. -link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives. -no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index 0dbe6a69bb7..a5d3038a498 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -199,7 +199,6 @@ "out/DebugSIMARM/", "out/DebugSIMARM64/", "out/DebugSIMARM_X64/", - "out/DebugSIMDBC64/", "out/DebugAndroidARM/", "out/DebugAndroidARM_X64/", "out/DebugAndroidARM64/", @@ -208,7 +207,6 @@ "out/ReleaseSIMARM/", "out/ReleaseSIMARM64/", "out/ReleaseSIMARM_X64/", - "out/ReleaseSIMDBC64/", "out/ReleaseAndroidARM/", "out/ReleaseAndroidARM_X64/", "out/ReleaseAndroidARM64/", @@ -218,21 +216,18 @@ "out/ProductSIMARM/", "out/ProductSIMARM64/", "out/ProductSIMARM_X64/", - "out/ProductSIMDBC64/", "out/ProductAndroidARM/", "out/ProductAndroidARM64/", "xcodebuild/DebugIA32/", "xcodebuild/DebugSIMARM/", "xcodebuild/DebugSIMARM64/", "xcodebuild/DebugSIMARM_X64/", - "xcodebuild/DebugSIMDBC64/", "xcodebuild/DebugX64/", "xcodebuild/ProductX64/", "xcodebuild/ReleaseIA32/", "xcodebuild/ReleaseSIMARM/", "xcodebuild/ReleaseSIMARM64/", "xcodebuild/ReleaseSIMARM_X64/", - "xcodebuild/ReleaseSIMDBC64/", "xcodebuild/ReleaseX64/", "samples/", "samples-dev/", @@ -471,7 +466,7 @@ "options": { "enable-asserts": true }}, - "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64|simdbc64)": { }, + "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64)": { }, "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { "options": { "builder-tag": "optimization_counter_threshold", @@ -481,10 +476,6 @@ "options": { "hot-reload": true }}, - "dartk-reload-mac-(debug|product|release)-simdbc64": { - "options": { - "hot-reload": true - }}, "dartk-reload-rollback-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { "options": { "hot-reload-rollback": true @@ -1181,15 +1172,11 @@ { "builders": [ "vm-kernel-linux-product-x64", - "vm-kernel-linux-release-simdbc64", "vm-kernel-linux-release-x64", "vm-kernel-linux-debug-ia32", - "vm-kernel-linux-debug-simdbc64", "vm-kernel-linux-debug-x64", "vm-kernel-mac-product-x64", - "vm-kernel-mac-release-simdbc64", "vm-kernel-mac-release-x64", - "vm-kernel-mac-debug-simdbc64", "vm-kernel-mac-debug-x64" ], "meta": { @@ -1591,9 +1578,7 @@ { "builders": [ "vm-kernel-reload-linux-debug-x64", - "vm-kernel-reload-linux-release-x64", - "vm-kernel-reload-mac-debug-simdbc64", - "vm-kernel-reload-mac-release-simdbc64" + "vm-kernel-reload-linux-release-x64" ], "meta": { "description": "This is the configuration for the kernel hot reload builders." @@ -2484,11 +2469,6 @@ "gen_snapshot", "dart_precompiled_runtime"] }, - { - "name": "build linux-x64 simdbc for benchmarking", - "script": "tools/build.py", - "arguments": ["--mode=release", "--arch=simdbc64", "runtime"] - }, { "name": "archive linux-x64 for benchmarking", "script": "tools/bots/try_benchmarks.sh", diff --git a/tools/build.py b/tools/build.py index b862d5dd03e..ecff331b0da 100755 --- a/tools/build.py +++ b/tools/build.py @@ -18,7 +18,7 @@ SCRIPT_DIR = os.path.dirname(sys.argv[0]) DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) AVAILABLE_ARCHS = [ 'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6', 'simarm64', - 'arm64', 'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64', 'simarm_x64' + 'arm64', 'simarm_x64' ] usage = """\ @@ -86,7 +86,7 @@ def ProcessOsOption(os_name): def ProcessOptions(options, args): if options.arch == 'all': - options.arch = 'ia32,x64,simarm,simarm64,simdbc64' + options.arch = 'ia32,x64,simarm,simarm64' if options.mode == 'all': options.mode = 'debug,release,product' if options.os == 'all': @@ -116,8 +116,7 @@ def ProcessOptions(options, args): % (os_name, HOST_OS)) return False if not arch in [ - 'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64', 'simdbc', - 'simdbc64' + 'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64' ]: print( "Cross-compilation to %s is not supported for architecture %s." diff --git a/tools/diff_results.dart b/tools/diff_results.dart index c0107d3aa4b..0e5ee510819 100644 --- a/tools/diff_results.dart +++ b/tools/diff_results.dart @@ -388,7 +388,6 @@ List extractBuilderPattern(List builders) { 'simarm64', 'arm', 'arm64', - 'simdbc64' ]); } } diff --git a/tools/gardening/lib/src/buildbot_data.dart b/tools/gardening/lib/src/buildbot_data.dart index ebca746c153..ffd29e391ab 100644 --- a/tools/gardening/lib/src/buildbot_data.dart +++ b/tools/gardening/lib/src/buildbot_data.dart @@ -11,18 +11,6 @@ const List buildGroups = const [ const BuildGroup( groupName: 'vm', subgroups: const [ - const BuildSubgroup(shardNames: const [ - 'vm-mac-debug-simdbc64-be', - ], testSteps: const [ - 'vm tests', - 'checked vm tests', - ]), - const BuildSubgroup(shardNames: const [ - 'vm-mac-release-simdbc64-be', - ], testSteps: const [ - 'vm tests', - 'checked vm tests', - ]), const BuildSubgroup(shardNames: const [ 'vm-linux-debug-x64-be', ], testSteps: const [ @@ -286,12 +274,6 @@ const List buildGroups = const [ 'vm tests', 'checked vm tests', ]), - const BuildSubgroup(shardNames: const [ - 'vm-mac-debug-simdbc64-reload-be', - ], testSteps: const [ - 'vm tests', - 'checked vm tests', - ]), const BuildSubgroup(shardNames: const [ 'vm-linux-release-x64-reload-be', ], testSteps: const [ @@ -304,12 +286,6 @@ const List buildGroups = const [ 'vm tests', 'checked vm tests', ]), - const BuildSubgroup(shardNames: const [ - 'vm-mac-release-simdbc64-reload-be', - ], testSteps: const [ - 'vm tests', - 'checked vm tests', - ]), ], ), const BuildGroup( diff --git a/tools/gardening/lib/src/results/configurations.dart b/tools/gardening/lib/src/results/configurations.dart index 999273f89f9..7d20657200c 100644 --- a/tools/gardening/lib/src/results/configurations.dart +++ b/tools/gardening/lib/src/results/configurations.dart @@ -19,8 +19,6 @@ class Architecture { static const simarm = const Architecture._('simarm'); static const simarmv6 = const Architecture._('simarmv6'); static const simarm64 = const Architecture._('simarm64'); - static const simdbc = const Architecture._('simdbc'); - static const simdbc64 = const Architecture._('simdbc64'); static final List names = _all.keys.toList(); @@ -33,8 +31,6 @@ class Architecture { simarm, simarmv6, simarm64, - simdbc, - simdbc64 ], key: (architecture) => (architecture as Architecture).name); static Architecture find(String name) { diff --git a/tools/gardening/lib/src/shard_data.dart b/tools/gardening/lib/src/shard_data.dart index ad781d88354..dcb012fcd01 100644 --- a/tools/gardening/lib/src/shard_data.dart +++ b/tools/gardening/lib/src/shard_data.dart @@ -8,8 +8,6 @@ library gardening.shard_data; const Map> shardGroups = const { 'vm': const [ - 'vm-mac-debug-simdbc64-be', - 'vm-mac-release-simdbc64-be', 'vm-linux-debug-x64-be', 'vm-linux-release-x64-be', 'vm-linux-debug-ia32-be', @@ -80,10 +78,8 @@ const Map> shardGroups = const { 'vm-reload': const [ 'vm-linux-debug-x64-reload-be', 'vm-linux-debug-x64-reload-rollback-be', - 'vm-mac-debug-simdbc64-reload-be', 'vm-linux-release-x64-reload-be', 'vm-linux-release-x64-reload-rollback-be', - 'vm-mac-release-simdbc64-reload-be', ], 'dart2js-d8-hostchecked': const [ 'dart2js-linux-d8-hostchecked-unittest-1-5-be', @@ -168,8 +164,6 @@ const Map> shardGroups = const { 'app-linux-product-x64-dev', ], 'vm-dev': const [ - 'vm-mac-debug-simdbc64-dev', - 'vm-mac-release-simdbc64-dev', 'vm-linux-debug-x64-dev', 'vm-linux-release-x64-dev', 'vm-linux-debug-ia32-dev', @@ -235,10 +229,8 @@ const Map> shardGroups = const { 'vm-reload-dev': const [ 'vm-linux-debug-x64-reload-dev', 'vm-linux-debug-x64-reload-rollback-dev', - 'vm-mac-debug-simdbc64-reload-dev', 'vm-linux-release-x64-reload-dev', 'vm-linux-release-x64-reload-rollback-dev', - 'vm-mac-release-simdbc64-reload-dev', ], 'dart2js-d8-hostchecked-dev': const [ 'dart2js-linux-d8-hostchecked-unittest-1-5-dev', @@ -371,14 +363,10 @@ const Map> shardGroups = const { 'vm-reload-stable': const [ 'vm-linux-debug-x64-reload-stable', 'vm-linux-debug-x64-reload-rollback-stable', - 'vm-mac-debug-simdbc64-reload-stable', 'vm-linux-release-x64-reload-stable', 'vm-linux-release-x64-reload-rollback-stable', - 'vm-mac-release-simdbc64-reload-stable', ], 'vm-stable': const [ - 'vm-mac-debug-simdbc64-stable', - 'vm-mac-release-simdbc64-stable', 'vm-linux-debug-x64-stable', 'vm-linux-release-x64-stable', 'vm-linux-debug-ia32-stable', diff --git a/tools/generate_buildfiles.py b/tools/generate_buildfiles.py index 0bca73dcd04..1de693632a9 100755 --- a/tools/generate_buildfiles.py +++ b/tools/generate_buildfiles.py @@ -53,7 +53,7 @@ def RunCrossGn(options): '-m', 'all', '-a', - 'arm,armsimdbc,arm64,armsimdbc64', + 'arm,arm64', ] if options.verbose: gn_command.append('-v') diff --git a/tools/gn.py b/tools/gn.py index e245561ce22..c98246a3339 100755 --- a/tools/gn.py +++ b/tools/gn.py @@ -95,13 +95,10 @@ def ToCommandLine(gn_args): def HostCpuForArch(arch): if arch in [ - 'ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simdbc', 'armsimdbc', - 'simarm_x64' + 'ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simarm_x64' ]: return 'x86' - if arch in [ - 'x64', 'arm64', 'simarm64', 'simdbc64', 'armsimdbc64', 'arm_x64' - ]: + if arch in ['x64', 'arm64', 'simarm64', 'arm_x64']: return 'x64' @@ -111,16 +108,8 @@ def TargetCpuForArch(arch, target_os): return 'x86' if arch in ['x64', 'simarm64', 'simarm_x64']: return 'x64' - if arch == 'simdbc': - return 'arm' if target_os == 'android' else 'x86' - if arch in ['simdbc64']: - return 'arm64' if target_os == 'android' else 'x64' if arch == 'arm_x64': return 'arm' - if arch == 'armsimdbc': - return 'arm' - if arch == 'armsimdbc64': - return 'arm64' return arch @@ -136,8 +125,6 @@ def DartTargetCpuForArch(arch): return 'armv6' if arch in ['arm64', 'simarm64']: return 'arm64' - if arch in ['simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']: - return 'dbc' return arch @@ -311,7 +298,7 @@ def ProcessOsOption(os_name): def ProcessOptions(args): if args.arch == 'all': - args.arch = 'ia32,x64,simarm,simarm64,simdbc64' + args.arch = 'ia32,x64,simarm,simarm64' if args.mode == 'all': args.mode = 'debug,release,product' if args.os == 'all': @@ -326,8 +313,7 @@ def ProcessOptions(args): for arch in args.arch: archs = [ 'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6', - 'simarm64', 'arm64', 'simdbc', 'simdbc64', 'armsimdbc', - 'armsimdbc64', 'simarm_x64' + 'simarm64', 'arm64', 'simarm_x64' ] if not arch in archs: print("Unknown arch %s" % arch) @@ -346,8 +332,7 @@ def ProcessOptions(args): % (os_name, HOST_OS)) return False if not arch in [ - 'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64', 'simdbc', - 'simdbc64' + 'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64' ]: print( "Cross-compilation to %s is not supported for architecture %s." @@ -386,7 +371,7 @@ def parse_args(args): type=str, help='Target architectures (comma-separated).', metavar='[all,ia32,x64,simarm,arm,arm_x64,simarmv6,armv6,' - 'simarm64,arm64,simdbc,armsimdbc,simarm_x64]', + 'simarm64,arm64,simarm_x64]', default='x64') common_group.add_argument( '--mode', diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh index 4e1a5ad2b92..e7bf651fc60 100755 --- a/tools/run_offsets_extractor.sh +++ b/tools/run_offsets_extractor.sh @@ -31,8 +31,6 @@ run simarm ReleaseSIMARM run x64 ReleaseX64 run ia32 ReleaseIA32 run simarm64 ReleaseSIMARM64 -run simdbc64 ReleaseSIMDBC64 -run simdbc ReleaseSIMDBC # Cleanup. echo "" >>"$TEMP" diff --git a/tools/test.dart b/tools/test.dart index 4c181a0e247..1e1b405ce7a 100755 --- a/tools/test.dart +++ b/tools/test.dart @@ -99,13 +99,9 @@ String archOfBuilder(String builder) { (component) => [ "arm", "arm64", - "armsimdbc", - "armsimdbc64", "ia32", "simarm", "simarm64", - "simdbc", - "simdbc64", "x64", ].contains(component), orElse: () => null); diff --git a/tools/utils.py b/tools/utils.py index 9cda434768b..1002e37ec83 100644 --- a/tools/utils.py +++ b/tools/utils.py @@ -270,10 +270,6 @@ ARCH_FAMILY = { 'simarm': 'ia32', 'simarmv6': 'ia32', 'simarm64': 'ia32', - 'simdbc': 'ia32', - 'simdbc64': 'ia32', - 'armsimdbc': 'arm', - 'armsimdbc64': 'arm', 'simarm_x64': 'ia32', }