From d52d3a444849f2e7809c62f644b18903ae76da87 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Fri, 6 May 2016 15:37:59 -0700 Subject: [PATCH] Wire up the interpreter on iOS devices. (#2648) --- DEPS | 2 +- sky/build/PackagerInvoke | 2 +- sky/build/SnapshotterInvoke | 52 +++++++++--- sky/build/sdk_xcode_harness/Flutter.xcconfig | 4 + .../project.pbxproj | 9 +- .../xcschemes/Application.xcscheme | 12 --- .../InstructionsSnapshotSource.S | 5 +- .../kDartIsolateSnapshotBufferSource.c | 2 +- .../kDartVmIsolateSnapshotBufferSource.c | 2 +- .../sdk_xcode_harness/Interpreter.xcconfig | 5 ++ sky/build/sky_precompilation_sdk.gni | 40 ++------- sky/engine/core/script/dart_init.cc | 48 ++++++----- .../framework/Headers/FlutterDartProject.h | 3 + .../framework/Source/FlutterAppDelegate.mm | 28 +++--- .../framework/Source/FlutterDartProject.mm | 85 +++++++++++++------ .../ios/framework/Source/FlutterDartSource.h | 4 + .../ios/framework/Source/FlutterDartSource.mm | 47 ++++++++-- .../framework/Source/FlutterViewController.mm | 14 ++- sky/tools/gn | 8 ++ sky/tools/sky_snapshot/vm.cc | 5 ++ 20 files changed, 240 insertions(+), 137 deletions(-) create mode 100644 sky/build/sdk_xcode_harness/Interpreter.xcconfig diff --git a/DEPS b/DEPS index 75852acb5..afaab6d41 100644 --- a/DEPS +++ b/DEPS @@ -25,7 +25,7 @@ vars = { # Note: When updating the Dart revision, ensure that all entries that are # dependencies of dart are also updated - 'dart_revision': '14ec00f86bbc893f1c731ea36afb1b98d8cd77cc', + 'dart_revision': 'e4db01fdd43f019988a901eb51c72790652760a4', 'dart_boringssl_revision': 'daeafc22c66ad48f6b32fc8d3362eb9ba31b774e', 'dart_observatory_packages_revision': 'cf90eb9077177d3d6b3fd5e8289477c2385c026a', 'dart_root_certificates_revision': 'aed07942ce98507d2be28cbd29e879525410c7fc', diff --git a/sky/build/PackagerInvoke b/sky/build/PackagerInvoke index 8ba63de63..6c36f2ac2 100755 --- a/sky/build/PackagerInvoke +++ b/sky/build/PackagerInvoke @@ -51,7 +51,7 @@ PackageProject() { AssertExists $src_dir local precompilation_flag="" - if [ $CURRENT_ARCH != "x86_64" ]; then + if [[ $CURRENT_ARCH != "x86_64" ]] && [[ "$DART_EXPERIMENTAL_INTERPRETER" != "1" ]]; then precompilation_flag="--precompiled" fi diff --git a/sky/build/SnapshotterInvoke b/sky/build/SnapshotterInvoke index 4789273fb..5c68002bc 100755 --- a/sky/build/SnapshotterInvoke +++ b/sky/build/SnapshotterInvoke @@ -99,6 +99,13 @@ SnapshotProject() { fi AssertExists $ui_path + # For dart:jni + local jni_path="$(readlink ${packages}/sky_engine)/../sdk_ext/dart_jni/jni.dart" + if [[ "${jni_path:0:1}" != "/" ]]; then + jni_path="${packages}/${jni_path}" + fi + AssertExists $jni_path + # For dart:vmservice_sky local vm_service_path="$(readlink ${packages}/sky_engine)/../sdk_ext/dart/runtime/bin/vmservice/vmservice_io.dart" if [[ "${vm_service_path:0:1}" != "/" ]]; then @@ -123,20 +130,39 @@ SnapshotProject() { RunCommand rm -f ${derived_dir}/kDartIsolateSnapshotBuffer.c RunCommand rm -f ${derived_dir}/InstructionsSnapshot.S - # Finally! Generate the snapshot. The instructions buffer is already in an - # assembly file which can be directly used by the linker. For the VM isolate - # snapshot buffer and isolate snapshot buffer, we name the file to match - # the name of the symbol the VM expects at runtime. On these binary files, - # we invoke xxd. - # - # Note about "checked mode": Precompilation snapshots are never in checked - # mode. The flag is also ignored by the standalone VM. So there is no sense - # in generating the larger snapshot. For development purposes, a - # non-precompilation-enabled VM is used. - RunCommand ${FLUTTER_ARCH_TOOLS_PATH}/Snapshotter \ + if [[ $DART_EXPERIMENTAL_INTERPRETER == "1" ]]; then + # In case the experimental interpreter is enabled, we need a generic + # script snapshot instead of a precompilation snapshot. + RunCommand ${FLUTTER_ARCH_TOOLS_PATH}/Snapshotter \ --vm_isolate_snapshot=${derived_dir}/kDartVmIsolateSnapshotBuffer \ --isolate_snapshot=${derived_dir}/kDartIsolateSnapshotBuffer \ - --assembly=${derived_dir}/InstructionsSnapshot.S \ + --package_root=${packages} \ + --url_mapping=dart:mojo.internal,${mojo_internal_path} \ + --url_mapping=dart:ui,${ui_path} \ + --url_mapping=dart:jni,${jni_path} \ + --url_mapping=dart:vmservice_sky,$vm_service_path \ + --conditional_directives \ + ${src_dir}/snapshot.dart + + local dummy_snapshot=${derived_dir}/InstructionsSnapshot.S + RunCommand rm -f ${dummy_snapshot} + RunCommand touch ${dummy_snapshot} + + else + # Generate the precompilation snapshot. The instructions buffer is in an + # assembly file which can be directly used by the linker. For the VM isolate + # snapshot buffer and isolate snapshot buffer, we name the file to match + # the name of the symbol the VM expects at runtime. On these binary files, + # we invoke xxd. + # + # Note about "checked mode": Precompilation snapshots are never in checked + # mode. The flag is also ignored by the standalone VM. So there is no sense + # in generating the larger snapshot. For development purposes, a + # non-precompilation-enabled VM is used. + RunCommand ${FLUTTER_ARCH_TOOLS_PATH}/Snapshotter \ + --vm_isolate_snapshot=${derived_dir}/kDartVmIsolateSnapshotBuffer \ + --isolate_snapshot=${derived_dir}/kDartIsolateSnapshotBuffer \ + --assembly=${derived_dir}/InstructionsSnapshot.S \ --embedder_entry_points_manifest=${src_dir}/EmbedderEntryPoints \ --package_root=${packages} \ --url_mapping=dart:mojo.internal,${mojo_internal_path} \ @@ -145,6 +171,8 @@ SnapshotProject() { --conditional_directives \ $main_path + fi + if [[ $? -ne 0 ]]; then EchoError "Snapshotter failed for $1 ..." exit -1 diff --git a/sky/build/sdk_xcode_harness/Flutter.xcconfig b/sky/build/sdk_xcode_harness/Flutter.xcconfig index 7d9a7153a..0f2934cd5 100644 --- a/sky/build/sdk_xcode_harness/Flutter.xcconfig +++ b/sky/build/sdk_xcode_harness/Flutter.xcconfig @@ -4,4 +4,8 @@ #include "Local.xcconfig" +// This file only exists in case the embedder VM supports the interpreter on the +// device. If this file is not present, it is not an error. +#include "Interpreter.xcconfig" + FLUTTER_ARCH_TOOLS_PATH=${SOURCE_ROOT}/Tools/${PLATFORM_NAME} diff --git a/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/project.pbxproj b/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/project.pbxproj index b7cb2c821..7bbde943c 100644 --- a/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/project.pbxproj +++ b/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 9E0FB06D1C1A3F5600DDAEFA /* InstructionsSnapshotSource.S in Sources */ = {isa = PBXBuildFile; fileRef = 9E0FB0691C1A3F5600DDAEFA /* InstructionsSnapshotSource.S */; }; 9E0FB06E1C1A3F5600DDAEFA /* kDartIsolateSnapshotBufferSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 9E0FB06A1C1A3F5600DDAEFA /* kDartIsolateSnapshotBufferSource.c */; }; 9E0FB06F1C1A3F5600DDAEFA /* kDartVmIsolateSnapshotBufferSource.c in Sources */ = {isa = PBXBuildFile; fileRef = 9E0FB06B1C1A3F5600DDAEFA /* kDartVmIsolateSnapshotBufferSource.c */; }; - 9E40465D1C1B6E9200A4B87C /* icudtl.dat in Resources */ = {isa = PBXBuildFile; fileRef = 9E4046541C1B6A3600A4B87C /* icudtl.dat */; }; 9E627AD91C582ABB000D800D /* app.flx in Resources */ = {isa = PBXBuildFile; fileRef = 9E627AD81C582ABB000D800D /* app.flx */; }; 9EA2FB801C6D2D6B00670B03 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9EA2FB7F1C6D2D6B00670B03 /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ @@ -49,7 +48,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 97F908AF1CDC02C500D4520F /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = ../iphonesimulator/Flutter.framework; sourceTree = ""; }; + 97F908AF1CDC02C500D4520F /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = ../common/Flutter.framework; sourceTree = ""; }; 9E07CF861BE7F4D200BCD8DE /* FlutterApplication.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FlutterApplication.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9E07CF891BE7F4D200BCD8DE /* FlutterApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlutterApplication.h; sourceTree = ""; }; 9E07CF8B1BE7F4D200BCD8DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -65,10 +64,10 @@ 9E4046501C1B6A3600A4B87C /* EmbedderEntryPoints */ = {isa = PBXFileReference; lastKnownFileType = text; path = EmbedderEntryPoints; sourceTree = ""; }; 9E4046511C1B6A3600A4B87C /* PackagerInvoke */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = PackagerInvoke; sourceTree = ""; }; 9E4046531C1B6A3600A4B87C /* SnapshotterInvoke */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = SnapshotterInvoke; sourceTree = ""; }; - 9E4046541C1B6A3600A4B87C /* icudtl.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = icudtl.dat; sourceTree = ""; }; 9E4046571C1B6A3600A4B87C /* Snapshotter */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = Snapshotter; sourceTree = ""; }; 9E40465A1C1B6A3600A4B87C /* Snapshotter */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = Snapshotter; sourceTree = ""; }; 9E40465E1C1B6F7900A4B87C /* Local.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Local.xcconfig; sourceTree = ""; }; + 9E5CD2D81CD97EFF00D93CCC /* snapshot.dart */ = {isa = PBXFileReference; lastKnownFileType = text; path = snapshot.dart; sourceTree = ""; }; 9E627AD81C582ABB000D800D /* app.flx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = app.flx; path = Generated/app.flx; sourceTree = ""; }; 9EA2FB7F1C6D2D6B00670B03 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = ../LaunchScreen.storyboard; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -160,10 +159,10 @@ 9E40464F1C1B6A3600A4B87C /* common */ = { isa = PBXGroup; children = ( + 9E5CD2D81CD97EFF00D93CCC /* snapshot.dart */, 9E4046501C1B6A3600A4B87C /* EmbedderEntryPoints */, 9E4046511C1B6A3600A4B87C /* PackagerInvoke */, 9E4046531C1B6A3600A4B87C /* SnapshotterInvoke */, - 9E4046541C1B6A3600A4B87C /* icudtl.dat */, 97F908AF1CDC02C500D4520F /* Flutter.framework */, ); path = common; @@ -298,7 +297,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9E40465D1C1B6E9200A4B87C /* icudtl.dat in Resources */, 9EA2FB801C6D2D6B00670B03 /* LaunchScreen.storyboard in Resources */, 9E07CFA91BE8280A00BCD8DE /* Assets.xcassets in Resources */, ); @@ -492,6 +490,7 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/xcshareddata/xcschemes/Application.xcscheme b/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/xcshareddata/xcschemes/Application.xcscheme index 6c8867882..aafbcc4a2 100644 --- a/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/xcshareddata/xcschemes/Application.xcscheme +++ b/sky/build/sdk_xcode_harness/FlutterApplication.xcodeproj/xcshareddata/xcschemes/Application.xcscheme @@ -62,18 +62,6 @@ - - - - - - diff --git a/sky/build/sdk_xcode_harness/FlutterApplication/InstructionsSnapshotSource.S b/sky/build/sdk_xcode_harness/FlutterApplication/InstructionsSnapshotSource.S index 3490b95eb..d15f76253 100644 --- a/sky/build/sdk_xcode_harness/FlutterApplication/InstructionsSnapshotSource.S +++ b/sky/build/sdk_xcode_harness/FlutterApplication/InstructionsSnapshotSource.S @@ -1,4 +1,7 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#if __arm__ || __aarch64__ +#if (__arm__ || __aarch64__) #include "Generated/InstructionsSnapshot.S" #endif diff --git a/sky/build/sdk_xcode_harness/FlutterApplication/kDartIsolateSnapshotBufferSource.c b/sky/build/sdk_xcode_harness/FlutterApplication/kDartIsolateSnapshotBufferSource.c index 168cae5b2..6d6cf1591 100644 --- a/sky/build/sdk_xcode_harness/FlutterApplication/kDartIsolateSnapshotBufferSource.c +++ b/sky/build/sdk_xcode_harness/FlutterApplication/kDartIsolateSnapshotBufferSource.c @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if __arm__ || __aarch64__ +#if (__arm__ || __aarch64__) #include "Generated/kDartIsolateSnapshotBuffer.c" #endif diff --git a/sky/build/sdk_xcode_harness/FlutterApplication/kDartVmIsolateSnapshotBufferSource.c b/sky/build/sdk_xcode_harness/FlutterApplication/kDartVmIsolateSnapshotBufferSource.c index e2c75c5cc..b2fe8ac66 100644 --- a/sky/build/sdk_xcode_harness/FlutterApplication/kDartVmIsolateSnapshotBufferSource.c +++ b/sky/build/sdk_xcode_harness/FlutterApplication/kDartVmIsolateSnapshotBufferSource.c @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if __arm__ || __aarch64__ +#if (__arm__ || __aarch64__) #include "Generated/kDartVmIsolateSnapshotBuffer.c" #endif diff --git a/sky/build/sdk_xcode_harness/Interpreter.xcconfig b/sky/build/sdk_xcode_harness/Interpreter.xcconfig new file mode 100644 index 000000000..5c19927fc --- /dev/null +++ b/sky/build/sdk_xcode_harness/Interpreter.xcconfig @@ -0,0 +1,5 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +DART_EXPERIMENTAL_INTERPRETER=1 diff --git a/sky/build/sky_precompilation_sdk.gni b/sky/build/sky_precompilation_sdk.gni index 9216ef429..7ea3a6c23 100644 --- a/sky/build/sky_precompilation_sdk.gni +++ b/sky/build/sky_precompilation_sdk.gni @@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//sky/engine/bindings/bindings.gni") import("//build/config/templates/templates.gni") +import("//sky/engine/bindings/bindings.gni") template("sky_precompilation_sdk") { assert(is_ios, "The precompilation SDK is only supported for iOS targets") @@ -61,6 +61,7 @@ template("sky_precompilation_sdk") { sources = [ "//sky/build/SnapshotterInvoke", "//sky/build/PackagerInvoke", + "//sky/engine/bindings/snapshot.dart", ] outputs = [ "$sdk_dir/$tools_dir/{{source_file_part}}" ] } @@ -73,6 +74,13 @@ template("sky_precompilation_sdk") { "//sky/build/sdk_xcode_harness/Local.xcconfig", "//sky/build/sdk_xcode_harness/Runner", ] + + if (dart_experimental_interpreter) { + sources += [ + "//sky/build/sdk_xcode_harness/Interpreter.xcconfig", + ] + } + outputs = [ "$sdk_dir/{{source_file_part}}" ] } @@ -87,41 +95,11 @@ template("sky_precompilation_sdk") { outputs = [ "$root_out_dir/{{source_file_part}}" ] } - executable_gen_target_name = target_name + "_runner" - executable(executable_gen_target_name) { - libs = [ - "AudioToolbox.framework", - "AVFoundation.framework", - "OpenGLES.framework", - "QuartzCore.framework", - "UIKit.framework", - ] - deps = [ "//sky/shell:ios_scaffolding" ] - } - - copy_runner_gen_target_name = target_name + "_copy_runner" - copy(copy_runner_gen_target_name) { - sources = [ "$root_out_dir/$executable_gen_target_name" ] - outputs = [ "$sdk_dir/$arch_tools_dir/FlutterRunner" ] - - deps = [ ":$executable_gen_target_name" ] - } - - copy_data_gen_target_name = target_name + "_copy_data" - copy(copy_data_gen_target_name) { - set_sources_assignment_filter([]) - sources = [ "//third_party/icu/android/icudtl.dat" ] - outputs = [ "$sdk_dir/$tools_dir/{{source_file_part}}" ] - set_sources_assignment_filter(sources_assignment_filter) - } - group(target_name) { deps = [ ":copy_snapshotter", ":copy_flutter_framework", ":embedder_entry_points", - ":$copy_runner_gen_target_name", - ":$copy_data_gen_target_name", ":precompilation_xcode_scripts", ":copy_sdk_xcode_harness", ":copy_user_editable_files", diff --git a/sky/engine/core/script/dart_init.cc b/sky/engine/core/script/dart_init.cc index 11712dcce..0299e86f0 100644 --- a/sky/engine/core/script/dart_init.cc +++ b/sky/engine/core/script/dart_init.cc @@ -457,6 +457,20 @@ void SetServiceIsolateHook(ServiceIsolateHook hook) { g_service_isolate_hook = hook; } +static bool ShouldEnableCheckedMode() { + if (IsRunningPrecompiledCode()) { + // Checked mode is never enabled during precompilation. Even snapshot + // generation disables checked mode arguments. + return false; + } + +#if ENABLE(DART_STRICT) + return true; +#else + return SkySettings::Get().enable_dart_checked_mode; +#endif +} + void InitDartVM() { TRACE_EVENT0("flutter", __func__); @@ -468,30 +482,23 @@ void InitDartVM() { DartMojoInternal::SetHandleWatcherProducerHandle( mojo::dart::HandleWatcher::Start()); - bool enable_checked_mode = SkySettings::Get().enable_dart_checked_mode; -#if ENABLE(DART_STRICT) - enable_checked_mode = true; -#endif + Vector args; - if (IsRunningPrecompiledCode()) { - enable_checked_mode = false; - } + // Instruct the VM to ignore unrecognized flags. + // There is a lot of diversity in a lot of combinations when it + // comes to the arguments the VM supports. And, if the VM comes across a flag + // it does not recognize, it exits immediately. + args.append("--ignore-unrecognized-flags"); - Vector args; args.append(kDartProfilingArgs, arraysize(kDartProfilingArgs)); + args.append(kDartMirrorsArgs, arraysize(kDartMirrorsArgs)); + args.append(kDartBackgroundCompilationArgs, + arraysize(kDartBackgroundCompilationArgs)); - if (!IsRunningPrecompiledCode()) { - // The version of the VM setup to run precompiled code does not recognize - // the mirrors or the background compilation flags. They are never enabled. - // Make sure we dont pass in unrecognized flags. - args.append(kDartMirrorsArgs, arraysize(kDartMirrorsArgs)); - args.append(kDartBackgroundCompilationArgs, - arraysize(kDartBackgroundCompilationArgs)); - } else { + if (IsRunningPrecompiledCode()) args.append(kDartPrecompilationArgs, arraysize(kDartPrecompilationArgs)); - } - if (enable_checked_mode) + if (ShouldEnableCheckedMode()) args.append(kDartCheckedModeArgs, arraysize(kDartCheckedModeArgs)); if (SkySettings::Get().start_paused) @@ -502,12 +509,9 @@ void InitDartVM() { Vector dart_flags; if (base::CommandLine::ForCurrentProcess()->HasSwitch(kDartFlags)) { - // Instruct the VM to ignore unrecognized flags. - args.append("--ignore-unrecognized-flags"); // Split up dart flags by spaces. base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - std::stringstream ss( - command_line.GetSwitchValueNative(kDartFlags)); + std::stringstream ss(command_line.GetSwitchValueNative(kDartFlags)); std::istream_iterator it(ss); std::istream_iterator end; while (it != end) { diff --git a/sky/shell/platform/ios/framework/Headers/FlutterDartProject.h b/sky/shell/platform/ios/framework/Headers/FlutterDartProject.h index 36da0b9d8..2e1d6eba1 100644 --- a/sky/shell/platform/ios/framework/Headers/FlutterDartProject.h +++ b/sky/shell/platform/ios/framework/Headers/FlutterDartProject.h @@ -20,6 +20,9 @@ FLUTTER_EXPORT packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL + NS_DESIGNATED_INITIALIZER; + - (instancetype)initFromDefaultSourceForConfiguration; @end diff --git a/sky/shell/platform/ios/framework/Source/FlutterAppDelegate.mm b/sky/shell/platform/ios/framework/Source/FlutterAppDelegate.mm index 64df3506b..0966841a6 100644 --- a/sky/shell/platform/ios/framework/Source/FlutterAppDelegate.mm +++ b/sky/shell/platform/ios/framework/Source/FlutterAppDelegate.mm @@ -9,7 +9,6 @@ - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { - FlutterDartProject* project = [[FlutterDartProject alloc] initFromDefaultSourceForConfiguration]; @@ -19,6 +18,7 @@ [[FlutterViewController alloc] initWithProject:project nibName:nil bundle:nil]; + [project release]; window.rootViewController = viewController; [viewController release]; self.window = window; @@ -31,22 +31,28 @@ // Use the NSNotificationCenter to notify services when we're opened with URLs. // TODO(jackson): Revisit this API once we have more services using URLs to make // it more typed and less brittle -- (BOOL)application:(UIApplication *)app - openURL:(NSURL *)url - sourceApplication:(NSString *)sourceApplication - annotation:(id)annotation -{ - NSDictionary *dict = [@{ - @"handled": [NSMutableDictionary dictionary], - @"url": url, - @"sourceApplication": sourceApplication, +- (BOOL)application:(UIApplication*)app + openURL:(NSURL*)url + sourceApplication:(NSString*)sourceApplication + annotation:(id)annotation { + + NSDictionary* dict = [@{ + @"handled" : [NSMutableDictionary dictionary], + @"url" : url, + @"sourceApplication" : sourceApplication, } mutableCopy]; + if (annotation != nil) [dict setValue:annotation forKey:@"annotation"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"openURL" object:self userInfo:dict]; - return ((NSNumber *)dict[@"handled"][@"value"]).boolValue; + + BOOL handled = ((NSNumber*)dict[@"handled"][@"value"]).boolValue; + [dict release]; + + return handled; } @end diff --git a/sky/shell/platform/ios/framework/Source/FlutterDartProject.mm b/sky/shell/platform/ios/framework/Source/FlutterDartProject.mm index 97ff728c4..2d17ac7cb 100644 --- a/sky/shell/platform/ios/framework/Source/FlutterDartProject.mm +++ b/sky/shell/platform/ios/framework/Source/FlutterDartProject.mm @@ -5,14 +5,11 @@ #include "sky/shell/platform/ios/framework/Source/FlutterDartProject_Internal.h" #include "base/command_line.h" +#include "dart/runtime/include/dart_api.h" #include "sky/shell/platform/ios/framework/Source/FlutterDartSource.h" #include "sky/shell/switches.h" -namespace { - -#if TARGET_IPHONE_SIMULATOR - -NSURL* URLForSwitch(const char* name) { +static NSURL* URLForSwitch(const char* name) { auto cmd = *base::CommandLine::ForCurrentProcess(); NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; @@ -26,10 +23,6 @@ NSURL* URLForSwitch(const char* name) { return [defaults URLForKey:@(name)]; } -#endif // TARGET_IPHONE_SIMULATOR - -} // namespace - @implementation FlutterDartProject { NSBundle* _precompiledDartBundle; FlutterDartSource* _dartSource; @@ -73,22 +66,60 @@ NSURL* URLForSwitch(const char* name) { return self; } +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL { + self = [super init]; + + if (self) { + _dartSource = [[FlutterDartSource alloc] + initWithFLXArchiveWithScriptSnapshot:archiveURL]; + + [self checkReadiness]; + } + + return self; +} + #pragma mark - Convenience initializers - (instancetype)initFromDefaultSourceForConfiguration { - #if TARGET_IPHONE_SIMULATOR - return [self - initWithFLXArchive:URLForSwitch(sky::shell::switches::kFLX) - dartMain:URLForSwitch(sky::shell::switches::kMainDartFile) - packages:URLForSwitch(sky::shell::switches::kPackages)]; - #else - NSString* bundlePath = - [[NSBundle mainBundle] pathForResource:@"FlutterApplication" - ofType:@"framework" - inDirectory:@"Frameworks"]; - NSBundle* bundle = [NSBundle bundleWithPath:bundlePath]; + NSString* bundlePath = + [[NSBundle mainBundle] pathForResource:@"FlutterApplication" + ofType:@"framework" + inDirectory:@"Frameworks"]; + NSBundle* bundle = [NSBundle bundleWithPath:bundlePath]; + + // In both precompilation and non-precompilation cases, we need to bundle + // loaded since at least the FLX archive is present in it. + [bundle load]; + + if (Dart_IsPrecompiledRuntime()) { + // Load from an AOTC snapshot. return [self initWithPrecompiledDartBundle:bundle]; - #endif + } else { + // Load directly from sources if the appropriate command line flags are + // specified. If not, try loading from a script snapshot in the framework + // bundle. + NSURL* flxURL = URLForSwitch(sky::shell::switches::kFLX); + + if (flxURL == nil) { + // If the URL was not specified on the command line, look inside the + // FlutterApplication bundle. + flxURL = + [NSURL fileURLWithPath:[bundle pathForResource:@"app" ofType:@"flx"] + isDirectory:NO]; + } + + NSURL* dartMainURL = URLForSwitch(sky::shell::switches::kMainDartFile); + NSURL* dartPackagesURL = URLForSwitch(sky::shell::switches::kPackages); + + return [self initWithFLXArchive:flxURL + dartMain:dartMainURL + packages:dartPackagesURL]; + } + + NSAssert(NO, @"Unreachable"); + [self release]; + return nil; } #pragma mark - Common initialization tasks @@ -202,9 +233,15 @@ static NSString* NSStringFromVMType(VMType type) { return result(NO, message); } - engine->RunFromFile(_dartSource.dartMain.absoluteURL.path.UTF8String, - _dartSource.packages.absoluteURL.path.UTF8String, - _dartSource.flxArchive.absoluteURL.path.UTF8String); + if (_dartSource.archiveContainsScriptSnapshot) { + engine->RunFromBundle("file://script_snapshot", + _dartSource.flxArchive.absoluteURL.path.UTF8String); + } else { + engine->RunFromFile(_dartSource.dartMain.absoluteURL.path.UTF8String, + _dartSource.packages.absoluteURL.path.UTF8String, + _dartSource.flxArchive.absoluteURL.path.UTF8String); + } + result(YES, @"Success"); }]; } diff --git a/sky/shell/platform/ios/framework/Source/FlutterDartSource.h b/sky/shell/platform/ios/framework/Source/FlutterDartSource.h index 436c6a305..399ee5740 100644 --- a/sky/shell/platform/ios/framework/Source/FlutterDartSource.h +++ b/sky/shell/platform/ios/framework/Source/FlutterDartSource.h @@ -14,11 +14,15 @@ typedef void (^ValidationResult)(BOOL result, NSString* message); @property(nonatomic, readonly) NSURL* dartMain; @property(nonatomic, readonly) NSURL* packages; @property(nonatomic, readonly) NSURL* flxArchive; +@property(nonatomic, readonly) BOOL archiveContainsScriptSnapshot; - (instancetype)initWithDartMain:(NSURL*)dartMain packages:(NSURL*)packages flxArchive:(NSURL*)flxArchive NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flxArchive + NS_DESIGNATED_INITIALIZER; + - (void)validate:(ValidationResult)result; @end diff --git a/sky/shell/platform/ios/framework/Source/FlutterDartSource.mm b/sky/shell/platform/ios/framework/Source/FlutterDartSource.mm index 3681fece6..4187c41df 100644 --- a/sky/shell/platform/ios/framework/Source/FlutterDartSource.mm +++ b/sky/shell/platform/ios/framework/Source/FlutterDartSource.mm @@ -4,16 +4,22 @@ #include "sky/shell/platform/ios/framework/Source/FlutterDartSource.h" -@implementation FlutterDartSource { - NSURL* _dartMain; - NSURL* _packages; - NSURL* _flxArchive; -} +@implementation FlutterDartSource + +@synthesize dartMain=_dartMain; +@synthesize packages=_packages; +@synthesize flxArchive=_flxArchive; +@synthesize archiveContainsScriptSnapshot=_archiveContainsScriptSnapshot; + +#pragma mark - Convenience Initializers - (instancetype)init { return [self initWithDartMain:nil packages:nil flxArchive:nil]; } + +#pragma mark - Designated Initializers + - (instancetype)initWithDartMain:(NSURL*)dartMain packages:(NSURL*)packages flxArchive:(NSURL*)flxArchive { @@ -23,6 +29,30 @@ _dartMain = [dartMain copy]; _packages = [packages copy]; _flxArchive = [flxArchive copy]; + + NSFileManager* fileManager = [NSFileManager defaultManager]; + + const BOOL dartMainExists = + [fileManager fileExistsAtPath:dartMain.absoluteURL.path]; + const BOOL packagesExists = + [fileManager fileExistsAtPath:packages.absoluteURL.path]; + + if (!dartMainExists || !packagesExists) { + // We cannot actually verify this without opening up the archive. This is + // just an assumption. + _archiveContainsScriptSnapshot = YES; + } + } + + return self; +} + +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flxArchive { + self = [super init]; + + if (self) { + _flxArchive = [flxArchive copy]; + _archiveContainsScriptSnapshot = YES; } return self; @@ -56,8 +86,11 @@ static BOOL CheckDartProjectURL(NSMutableString* log, BOOL isValid = YES; isValid &= CheckDartProjectURL(log, _flxArchive, @"FLX archive"); - isValid &= CheckDartProjectURL(log, _dartMain, @"Dart main"); - isValid &= CheckDartProjectURL(log, _packages, @"Dart packages"); + + if (!_archiveContainsScriptSnapshot) { + isValid &= CheckDartProjectURL(log, _dartMain, @"Dart main"); + isValid &= CheckDartProjectURL(log, _packages, @"Dart packages"); + } result(isValid, log); } diff --git a/sky/shell/platform/ios/framework/Source/FlutterViewController.mm b/sky/shell/platform/ios/framework/Source/FlutterViewController.mm index 6c42bd0a9..5f3894eb0 100644 --- a/sky/shell/platform/ios/framework/Source/FlutterViewController.mm +++ b/sky/shell/platform/ios/framework/Source/FlutterViewController.mm @@ -10,6 +10,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/trace_event/trace_event.h" +#include "dart/runtime/include/dart_api.h" #include "mojo/public/cpp/application/connect.h" #include "mojo/public/interfaces/application/service_provider.mojom.h" #include "sky/engine/wtf/MakeUnique.h" @@ -23,8 +24,8 @@ #include "sky/shell/platform/ios/framework/Source/FlutterDynamicServiceLoader.h" #include "sky/shell/platform/ios/framework/Source/FlutterView.h" #include "sky/shell/platform/mac/platform_mac.h" -#include "sky/shell/platform/mac/platform_view_mac.h" #include "sky/shell/platform/mac/platform_service_provider.h" +#include "sky/shell/platform/mac/platform_view_mac.h" #include "sky/shell/platform/mac/view_service_provider.h" #include "sky/shell/platform_view.h" #include "sky/shell/shell.h" @@ -147,13 +148,10 @@ void FlutterInit(int argc, const char* argv[]) { [self setupPlatformServiceProvider]; - enum VMType type = VMTypeInvalid; - -#if TARGET_IPHONE_SIMULATOR - type = VMTypeInterpreter; -#else - type = VMTypePrecompilation; -#endif + // We ask the VM to check what it supports. + const enum VMType type = Dart_IsPrecompiledRuntime() + ? VMTypePrecompilation + : VMTypeInterpreter; [_dartProject launchInEngine:_engine embedderVMType:type diff --git a/sky/tools/gn b/sky/tools/gn index d81ff2c59..9589a62b2 100755 --- a/sky/tools/gn +++ b/sky/tools/gn @@ -50,6 +50,11 @@ def to_gn_args(args): gn_args['is_debug'] = args.debug gn_args['is_clang'] = args.clang and args.target_os not in ['android'] + + ios_target_cpu = 'arm64' + if args.ios_force_armv7: + ios_target_cpu = 'arm' + if args.target_os == 'android': gn_args['target_os'] = 'android' aot = not args.develop @@ -88,6 +93,8 @@ def to_gn_args(args): else: gn_args['dart_runtime_mode'] = 'develop' + gn_args['dart_experimental_interpreter'] = args.experimental_interpreter + gn_args['flutter_product_mode'] = (gn_args['dart_runtime_mode'] == 'release') if args.target_sysroot: @@ -126,6 +133,7 @@ def parse_args(args): # Adding it now unblocks bot/tool work. parser.add_argument('--develop', default=True, action='store_true') parser.add_argument('--deploy', default=False, dest='develop', action='store_false') + parser.add_argument('--experimental-interpreter', default=False, dest='experimental_interpreter', action='store_true') parser.add_argument('--target-os', type=str, choices=['android', 'ios']) parser.add_argument('--android', dest='target_os', action='store_const', const='android') diff --git a/sky/tools/sky_snapshot/vm.cc b/sky/tools/sky_snapshot/vm.cc index f7cb9f9f8..973343427 100644 --- a/sky/tools/sky_snapshot/vm.cc +++ b/sky/tools/sky_snapshot/vm.cc @@ -17,6 +17,11 @@ static const char* kDartArgs[] = { "--enable_mirrors=false", "--load_deferred_eagerly=true", "--conditional_directives", + // TODO(chinmaygarde): The experimental interpreter for iOS device targets + // does not support all these flags. The build process uses its own version + // of this snapshotter. Till support for all these flags is added, make + // sure the snapshotter does not error out on unrecognized flags. + "--ignore-unrecognized-flags", }; void InitDartVM() { -- GitLab