Version 2.12.0-118.0.dev
Merge commit '16f163157aa2b3d6f39a8dae4ce96d9c663e8f0c' into 'dev'
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 49dcb3d..30a2a3dd 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -759,30 +759,26 @@
);
try {
- List<Assist> assists;
- try {
- var processor = AssistProcessor(context);
- assists = await processor.compute();
- } on InconsistentAnalysisException {
- assists = [];
- } catch (exception, stackTrace) {
- var parametersFile = '''
-offset: $offset
-length: $length
- ''';
- throw CaughtExceptionWithFiles(exception, stackTrace, {
- file: result.content,
- 'parameters': parametersFile,
- });
- }
-
+ var processor = AssistProcessor(context);
+ var assists = await processor.compute();
assists.sort(Assist.SORT_BY_RELEVANCE);
for (var assist in assists) {
changes.add(assist.change);
}
+ } on InconsistentAnalysisException {
+ // ignore
+ } catch (exception, stackTrace) {
+ var parametersFile = '''
+offset: $offset
+length: $length
+ ''';
+ throw CaughtExceptionWithFiles(exception, stackTrace, {
+ file: result.content,
+ 'parameters': parametersFile,
+ });
+ }
- server.requestStatistics?.addItemTimeNow(request, 'computedAssists');
- } catch (_) {}
+ server.requestStatistics?.addItemTimeNow(request, 'computedAssists');
}
return changes;
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index 7a966f5..98bc900 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -100,14 +100,18 @@
bool compare_exchange_weak(
T& expected, // NOLINT
T desired,
- std::memory_order order = std::memory_order_acq_rel) {
- return value_.compare_exchange_weak(expected, desired, order, order);
+ std::memory_order success_order = std::memory_order_acq_rel,
+ std::memory_order failure_order = std::memory_order_seq_cst) {
+ return value_.compare_exchange_weak(expected, desired, success_order,
+ failure_order);
}
bool compare_exchange_strong(
T& expected, // NOLINT
T desired,
- std::memory_order order = std::memory_order_acq_rel) {
- return value_.compare_exchange_strong(expected, desired, order, order);
+ std::memory_order success_order = std::memory_order_acq_rel,
+ std::memory_order failure_order = std::memory_order_seq_cst) {
+ return value_.compare_exchange_strong(expected, desired, success_order,
+ failure_order);
}
// Require explicit loads and stores.
diff --git a/runtime/vm/compiler/backend/type_propagator_test.cc b/runtime/vm/compiler/backend/type_propagator_test.cc
index 2920aca..852a885 100644
--- a/runtime/vm/compiler/backend/type_propagator_test.cc
+++ b/runtime/vm/compiler/backend/type_propagator_test.cc
@@ -187,7 +187,11 @@
/*is_reflectable=*/true,
/*is_late=*/false, object_class, Object::dynamic_type(),
TokenPosition::kNoSource, TokenPosition::kNoSource));
- thread->isolate_group()->RegisterStaticField(field, Instance::Handle());
+ {
+ SafepointWriteRwLocker locker(thread,
+ thread->isolate_group()->program_lock());
+ thread->isolate_group()->RegisterStaticField(field, Instance::Handle());
+ }
FlowGraphBuilderHelper H;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 9dd6654..9f63a72 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -697,8 +697,7 @@
}
I->isolate_object_store()->Init();
I->isolate_object_store()->PreallocateObjects();
- I->set_field_table(T, source_isolate_group->initial_field_table()->Clone(
- /*is_isolate_field_table=*/true));
+ I->set_field_table(T, source_isolate_group->initial_field_table()->Clone(I));
return true;
}
@@ -743,8 +742,7 @@
return error.raw();
}
- I->set_field_table(T, I->group()->initial_field_table()->Clone(
- /*is_isolate_field_table=*/true));
+ I->set_field_table(T, I->group()->initial_field_table()->Clone(I));
#if defined(SUPPORT_TIMELINE)
if (tbes.enabled()) {
diff --git a/runtime/vm/field_table.cc b/runtime/vm/field_table.cc
index 8185067..a6358a1 100644
--- a/runtime/vm/field_table.cc
+++ b/runtime/vm/field_table.cc
@@ -98,13 +98,13 @@
// via store to table_.
std::atomic_thread_fence(std::memory_order_release);
table_ = new_table;
- if (is_isolate_field_table_) {
- Thread::Current()->field_table_values_ = table_;
+ if (isolate_ != nullptr) {
+ isolate_->mutator_thread()->field_table_values_ = table_;
}
}
-FieldTable* FieldTable::Clone(bool is_isolate_field_table) {
- FieldTable* clone = new FieldTable(is_isolate_field_table);
+FieldTable* FieldTable::Clone(Isolate* for_isolate) {
+ FieldTable* clone = new FieldTable(for_isolate);
auto new_table = static_cast<InstancePtr*>(
malloc(capacity_ * sizeof(InstancePtr))); // NOLINT
memmove(new_table, table_, capacity_ * sizeof(InstancePtr));
diff --git a/runtime/vm/field_table.h b/runtime/vm/field_table.h
index dde4200..4fc1ca8 100644
--- a/runtime/vm/field_table.h
+++ b/runtime/vm/field_table.h
@@ -16,17 +16,18 @@
namespace dart {
+class Isolate;
class Field;
class FieldTable {
public:
- explicit FieldTable(bool is_isolate_field_table)
+ explicit FieldTable(Isolate* isolate)
: top_(0),
capacity_(0),
free_head_(-1),
table_(nullptr),
old_tables_(new MallocGrowableArray<InstancePtr*>()),
- is_isolate_field_table_(is_isolate_field_table) {}
+ isolate_(isolate) {}
~FieldTable();
@@ -56,7 +57,7 @@
}
void SetAt(intptr_t index, InstancePtr raw_instance);
- FieldTable* Clone(bool is_isolate_field_table);
+ FieldTable* Clone(Isolate* for_isolate);
void VisitObjectPointers(ObjectPointerVisitor* visitor);
@@ -83,10 +84,10 @@
// so it will get freed when its are no longer in use.
MallocGrowableArray<InstancePtr*>* old_tables_;
- // Whether this table is used as a isolate-specific table of it's global field
- // values and therefore needs to keep the cached field table in the `Thread`
- // object up-to-date.
- bool is_isolate_field_table_;
+ // If non-NULL, it will specify the isolate this field table belongs to.
+ // Growing the field table will keep the cached field table on the isolate's
+ // mutator thread up-to-date.
+ Isolate* isolate_;
DISALLOW_COPY_AND_ASSIGN(FieldTable);
};
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 52ce79c..96e7750 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -353,7 +353,7 @@
store_buffer_(new StoreBuffer()),
heap_(nullptr),
saved_unlinked_calls_(Array::null()),
- initial_field_table_(new FieldTable(/*is_isolate_field_table=*/false)),
+ initial_field_table_(new FieldTable(/*isolate=*/nullptr)),
symbols_lock_(new SafepointRwLock()),
type_canonicalization_mutex_(
NOT_IN_PRODUCT("IsolateGroup::type_canonicalization_mutex_")),
@@ -907,6 +907,8 @@
void IsolateGroup::RegisterStaticField(const Field& field,
const Instance& initial_value) {
+ ASSERT(program_lock()->IsCurrentThreadWriter());
+
ASSERT(field.is_static());
initial_field_table()->Register(field);
initial_field_table()->SetAt(field.field_id(), initial_value.raw());
@@ -1631,7 +1633,7 @@
default_tag_(UserTag::null()),
ic_miss_code_(Code::null()),
shared_class_table_(isolate_group->shared_class_table()),
- field_table_(new FieldTable(/*is_isolate_field_table=*/true)),
+ field_table_(new FieldTable(/*isolate=*/this)),
isolate_group_(isolate_group),
isolate_object_store_(
new IsolateObjectStore(isolate_group->object_store())),
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ccd43d8..cc5e5c1 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3065,7 +3065,11 @@
const Field& field = Field::Handle(Field::New(
field_name, true, false, false, true, false, cls, Object::dynamic_type(),
TokenPosition::kMinSource, TokenPosition::kMinSource));
- thread->isolate_group()->RegisterStaticField(field, Instance::sentinel());
+ {
+ SafepointWriteRwLocker locker(thread,
+ thread->isolate_group()->program_lock());
+ thread->isolate_group()->RegisterStaticField(field, Instance::sentinel());
+ }
return field.raw();
}
diff --git a/sdk/lib/_internal/vm/lib/growable_array.dart b/sdk/lib/_internal/vm/lib/growable_array.dart
index 537fb34..865b874 100644
--- a/sdk/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk/lib/_internal/vm/lib/growable_array.dart
@@ -261,7 +261,7 @@
void add(T value) {
var len = length;
if (len == _capacity) {
- _grow(_nextCapacity(len));
+ _growToNextCapacity();
}
_setLength(len + 1);
this[len] = value;
@@ -310,7 +310,7 @@
if (this.length != newLen) throw new ConcurrentModificationError(this);
len = newLen;
}
- _grow(_nextCapacity(_capacity));
+ _growToNextCapacity();
} while (true);
}
@@ -370,6 +370,14 @@
_setData(newData);
}
+ // This method is marked as never-inline to conserve code size.
+ // It is called in rare cases, but used in the add() which is
+ // used very often and always inlined.
+ @pragma("vm:never-inline")
+ void _growToNextCapacity() {
+ _grow(_nextCapacity(_capacity));
+ }
+
void _shrink(int new_capacity, int new_length) {
var newData = _allocateData(new_capacity);
// This is a work-around for dartbug.com/30090. See the comment in _grow.
diff --git a/sdk/lib/ffi/struct.dart b/sdk/lib/ffi/struct.dart
index 0faf7ca..da034ef 100644
--- a/sdk/lib/ffi/struct.dart
+++ b/sdk/lib/ffi/struct.dart
@@ -4,19 +4,48 @@
part of dart.ffi;
-/// This class is extended to define structs.
+/// The supertype of all FFI struct types.
///
-/// Fields in a struct, annotated with a subtype of [NativeType], are
-/// automatically transformed into wrappers to access the fields of the struct
-/// in native memory.
+/// FFI struct types should extend this class and declare fields corresponding
+/// to the underlying native structure.
///
-/// All fields in a struct must either have a type which extends [NativeType] or
-/// else have an annotation indicating the corresponding native type (e.g.
-/// "@Int32()" for "int").
+/// Field declarations in a [Struct] subclass declaration are automatically
+/// given a setter and getter implementation which accesses the native struct's
+/// field in memory.
+///
+/// All field declarations in a [Struct] subclass declaration must either have
+/// type [int] or [float] and be annotated with a [NativeType] representing the
+/// native type, or must be of type [Pointer]. For example:
+///
+/// ```
+/// typedef struct {
+/// int a;
+/// float b;
+/// void* c;
+/// } my_struct;
+/// ```
+///
+/// ```
+/// class MyStruct extends Struct {
+/// @Int32
+/// external int a;
+///
+/// @Float
+/// external double b;
+///
+/// external Pointer<Void> c;
+/// }
+/// ```
+///
+/// All field declarations in a [Struct] subclass declaration must be marked
+/// `external`. You cannot create instances of the class, only have it point to
+/// existing native memory, so there is no memory in which to store non-native
+/// fields. External fields also cannot be initialized by constructors since no
+/// Dart object is being created.
///
/// Instances of a subclass of [Struct] have reference semantics and are backed
/// by native memory. The may allocated via allocation or loaded from a
-/// [Pointer], but not by a generative constructor.
+/// [Pointer], but cannot be created by a generative constructor.
abstract class Struct extends NativeType {
final Object _addressOf;
diff --git a/tests/language/async/return_throw_test.dart b/tests/language/async/return_throw_test.dart
new file mode 100644
index 0000000..43c9271
--- /dev/null
+++ b/tests/language/async/return_throw_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, 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.
+
+import "package:expect/expect.dart";
+
+Future<String> f() async {
+ throw 'f';
+}
+
+Future<String> g() async {
+ try {
+ // Should obtain the `Future<String>`, await it, then throw.
+ return f();
+ } catch (e) {
+ // Having caught the exception, we return a value.
+ return 'g';
+ }
+}
+
+void main() async {
+ Expect.equals('g', await g());
+}
diff --git a/tests/language_2/async/return_throw_test.dart b/tests/language_2/async/return_throw_test.dart
new file mode 100644
index 0000000..43c9271
--- /dev/null
+++ b/tests/language_2/async/return_throw_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, 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.
+
+import "package:expect/expect.dart";
+
+Future<String> f() async {
+ throw 'f';
+}
+
+Future<String> g() async {
+ try {
+ // Should obtain the `Future<String>`, await it, then throw.
+ return f();
+ } catch (e) {
+ // Having caught the exception, we return a value.
+ return 'g';
+ }
+}
+
+void main() async {
+ Expect.equals('g', await g());
+}
diff --git a/tools/VERSION b/tools/VERSION
index c7c1689..4f60b94 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 117
+PRERELEASE 118
PRERELEASE_PATCH 0
\ No newline at end of file