Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: runtime/vm/dart_api_impl.cc

Issue 15772005: - Add different types for persistent and weak persistent handles (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "include/dart_api.h" 5 #include "include/dart_api.h"
6 6
7 #include "platform/assert.h" 7 #include "platform/assert.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 18 matching lines...) Expand all
29 #include "vm/timer.h" 29 #include "vm/timer.h"
30 #include "vm/unicode.h" 30 #include "vm/unicode.h"
31 #include "vm/verifier.h" 31 #include "vm/verifier.h"
32 #include "vm/version.h" 32 #include "vm/version.h"
33 33
34 namespace dart { 34 namespace dart {
35 35
36 DECLARE_FLAG(bool, print_class_table); 36 DECLARE_FLAG(bool, print_class_table);
37 37
38 ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey; 38 ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey;
39 Dart_Handle Api::true_handle_ = NULL;
40 Dart_Handle Api::false_handle_ = NULL;
41 Dart_Handle Api::null_handle_ = NULL;
39 42
40 43
41 const char* CanonicalFunction(const char* func) { 44 const char* CanonicalFunction(const char* func) {
42 if (strncmp(func, "dart::", 6) == 0) { 45 if (strncmp(func, "dart::", 6) == 0) {
43 return func + 6; 46 return func + 6;
44 } else { 47 } else {
45 return func; 48 return func;
46 } 49 }
47 } 50 }
48 51
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 ref->set_raw(raw); 90 ref->set_raw(raw);
88 return reinterpret_cast<Dart_Handle>(ref); 91 return reinterpret_cast<Dart_Handle>(ref);
89 } 92 }
90 93
91 RawObject* Api::UnwrapHandle(Dart_Handle object) { 94 RawObject* Api::UnwrapHandle(Dart_Handle object) {
92 #if defined(DEBUG) 95 #if defined(DEBUG)
93 Isolate* isolate = Isolate::Current(); 96 Isolate* isolate = Isolate::Current();
94 ASSERT(isolate != NULL); 97 ASSERT(isolate != NULL);
95 ApiState* state = isolate->api_state(); 98 ApiState* state = isolate->api_state();
96 ASSERT(state != NULL); 99 ASSERT(state != NULL);
97 ASSERT(state->IsValidLocalHandle(object) || 100 ASSERT(state->IsValidLocalHandle(object));
98 state->IsValidPersistentHandle(object) ||
99 state->IsValidWeakPersistentHandle(object) ||
100 state->IsValidPrologueWeakPersistentHandle(object));
101 ASSERT(FinalizablePersistentHandle::raw_offset() == 0 && 101 ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
102 PersistentHandle::raw_offset() == 0 && 102 PersistentHandle::raw_offset() == 0 &&
103 LocalHandle::raw_offset() == 0); 103 LocalHandle::raw_offset() == 0);
104 #endif 104 #endif
105 return (reinterpret_cast<LocalHandle*>(object))->raw(); 105 return (reinterpret_cast<LocalHandle*>(object))->raw();
106 } 106 }
107 107
108 #define DEFINE_UNWRAP(type) \ 108 #define DEFINE_UNWRAP(type) \
109 const type& Api::Unwrap##type##Handle(Isolate* iso, \ 109 const type& Api::Unwrap##type##Handle(Isolate* iso, \
110 Dart_Handle dart_handle) { \ 110 Dart_Handle dart_handle) { \
111 const Object& obj = Object::Handle(iso, Api::UnwrapHandle(dart_handle)); \ 111 const Object& obj = Object::Handle(iso, Api::UnwrapHandle(dart_handle)); \
112 if (obj.Is##type()) { \ 112 if (obj.Is##type()) { \
113 return type::Cast(obj); \ 113 return type::Cast(obj); \
114 } \ 114 } \
115 return type::Handle(iso); \ 115 return type::Handle(iso); \
116 } 116 }
117 CLASS_LIST_FOR_HANDLES(DEFINE_UNWRAP) 117 CLASS_LIST_FOR_HANDLES(DEFINE_UNWRAP)
118 #undef DEFINE_UNWRAP 118 #undef DEFINE_UNWRAP
119 119
120 120
121 LocalHandle* Api::UnwrapAsLocalHandle(const ApiState& state, 121 LocalHandle* Api::UnwrapAsLocalHandle(const ApiState& state,
122 Dart_Handle object) { 122 Dart_Handle object) {
123 ASSERT(state.IsValidLocalHandle(object)); 123 ASSERT(state.IsValidLocalHandle(object));
124 return reinterpret_cast<LocalHandle*>(object); 124 return reinterpret_cast<LocalHandle*>(object);
125 } 125 }
126 126
127 127
128 PersistentHandle* Api::UnwrapAsPersistentHandle(const ApiState& state, 128 PersistentHandle* Api::UnwrapAsPersistentHandle(const ApiState& state,
129 Dart_Handle object) { 129 Dart_PersistentHandle object) {
130 ASSERT(state.IsValidPersistentHandle(object)); 130 ASSERT(state.IsValidPersistentHandle(object));
131 return reinterpret_cast<PersistentHandle*>(object); 131 return reinterpret_cast<PersistentHandle*>(object);
132 } 132 }
133 133
134 134
135 FinalizablePersistentHandle* Api::UnwrapAsWeakPersistentHandle( 135 FinalizablePersistentHandle* Api::UnwrapAsWeakPersistentHandle(
136 const ApiState& state, 136 const ApiState& state,
137 Dart_Handle object) { 137 Dart_WeakPersistentHandle object) {
138 ASSERT(state.IsValidWeakPersistentHandle(object)); 138 ASSERT(state.IsValidWeakPersistentHandle(object));
139 return reinterpret_cast<FinalizablePersistentHandle*>(object); 139 return reinterpret_cast<FinalizablePersistentHandle*>(object);
140 } 140 }
141 141
142 142
143 FinalizablePersistentHandle* Api::UnwrapAsPrologueWeakPersistentHandle( 143 FinalizablePersistentHandle* Api::UnwrapAsPrologueWeakPersistentHandle(
144 const ApiState& state, 144 const ApiState& state,
145 Dart_Handle object) { 145 Dart_WeakPersistentHandle object) {
146 ASSERT(state.IsValidPrologueWeakPersistentHandle(object)); 146 ASSERT(state.IsValidPrologueWeakPersistentHandle(object));
147 return reinterpret_cast<FinalizablePersistentHandle*>(object); 147 return reinterpret_cast<FinalizablePersistentHandle*>(object);
148 } 148 }
149 149
150 150
151 Dart_Handle Api::CheckIsolateState(Isolate* isolate) { 151 Dart_Handle Api::CheckIsolateState(Isolate* isolate) {
152 if (ClassFinalizer::FinalizePendingClasses() && 152 if (ClassFinalizer::FinalizePendingClasses() &&
153 isolate->object_store()->PreallocateObjects()) { 153 isolate->object_store()->PreallocateObjects()) {
154 return Api::Success(isolate); 154 return Api::Success(isolate);
155 } 155 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 Dart_Handle Api::AcquiredError(Isolate* isolate) { 204 Dart_Handle Api::AcquiredError(Isolate* isolate) {
205 ASSERT(isolate != NULL); 205 ASSERT(isolate != NULL);
206 ApiState* state = isolate->api_state(); 206 ApiState* state = isolate->api_state();
207 ASSERT(state != NULL); 207 ASSERT(state != NULL);
208 PersistentHandle* acquired_error_handle = state->AcquiredError(); 208 PersistentHandle* acquired_error_handle = state->AcquiredError();
209 return reinterpret_cast<Dart_Handle>(acquired_error_handle); 209 return reinterpret_cast<Dart_Handle>(acquired_error_handle);
210 } 210 }
211 211
212 212
213 Dart_Handle Api::Null(Isolate* isolate) { 213 Dart_Handle Api::Null(Isolate* isolate) {
214 ASSERT(isolate != NULL); 214 return Api::NewHandle(isolate, Object::null());
215 ApiState* state = isolate->api_state();
216 ASSERT(state != NULL);
217 PersistentHandle* null_handle = state->Null();
218 return reinterpret_cast<Dart_Handle>(null_handle);
219 } 215 }
220 216
221 217
222 Dart_Handle Api::True(Isolate* isolate) { 218 Dart_Handle Api::True(Isolate* isolate) {
223 ASSERT(isolate != NULL); 219 return Api::NewHandle(isolate, Bool::True().raw());
224 ApiState* state = isolate->api_state();
225 ASSERT(state != NULL);
226 PersistentHandle* true_handle = state->True();
227 return reinterpret_cast<Dart_Handle>(true_handle);
228 } 220 }
229 221
230 222
231 Dart_Handle Api::False(Isolate* isolate) { 223 Dart_Handle Api::False(Isolate* isolate) {
232 ASSERT(isolate != NULL); 224 return Api::NewHandle(isolate, Bool::False().raw());
233 ApiState* state = isolate->api_state();
234 ASSERT(state != NULL);
235 PersistentHandle* false_handle = state->False();
236 return reinterpret_cast<Dart_Handle>(false_handle);
237 } 225 }
238 226
239 227
240 ApiLocalScope* Api::TopScope(Isolate* isolate) { 228 ApiLocalScope* Api::TopScope(Isolate* isolate) {
241 ASSERT(isolate != NULL); 229 ASSERT(isolate != NULL);
242 ApiState* state = isolate->api_state(); 230 ApiState* state = isolate->api_state();
243 ASSERT(state != NULL); 231 ASSERT(state != NULL);
244 ApiLocalScope* scope = state->top_scope(); 232 ApiLocalScope* scope = state->top_scope();
245 ASSERT(scope != NULL); 233 ASSERT(scope != NULL);
246 return scope; 234 return scope;
247 } 235 }
248 236
249 237
250 void Api::InitOnce() { 238 void Api::InitOnce() {
251 ASSERT(api_native_key_ == Thread::kUnsetThreadLocalKey); 239 ASSERT(api_native_key_ == Thread::kUnsetThreadLocalKey);
252 api_native_key_ = Thread::CreateThreadLocal(); 240 api_native_key_ = Thread::CreateThreadLocal();
253 ASSERT(api_native_key_ != Thread::kUnsetThreadLocalKey); 241 ASSERT(api_native_key_ != Thread::kUnsetThreadLocalKey);
254 } 242 }
255 243
256 244
245 void Api::InitHandles() {
246 Isolate* isolate = Isolate::Current();
247 ASSERT(isolate != NULL);
248 ASSERT(isolate == Dart::vm_isolate());
249 ApiState* state = isolate->api_state();
250 ASSERT(state != NULL);
251 ASSERT(true_handle_ == NULL);
252 true_handle_ = Api::NewHandle(isolate, Bool::True().raw());
253
254 ASSERT(false_handle_ == NULL);
255 false_handle_ = Api::NewHandle(isolate, Bool::False().raw());
256
257 ASSERT(null_handle_ == NULL);
258 null_handle_ = Api::NewHandle(isolate, Object::null());
259 }
260
261
257 bool Api::ExternalStringGetPeerHelper(Dart_Handle object, void** peer) { 262 bool Api::ExternalStringGetPeerHelper(Dart_Handle object, void** peer) {
258 NoGCScope no_gc_scope; 263 NoGCScope no_gc_scope;
259 RawObject* raw_obj = Api::UnwrapHandle(object); 264 RawObject* raw_obj = Api::UnwrapHandle(object);
260 switch (Api::ClassId(object)) { 265 switch (Api::ClassId(object)) {
261 case kExternalOneByteStringCid: { 266 case kExternalOneByteStringCid: {
262 RawExternalOneByteString* raw_string = 267 RawExternalOneByteString* raw_string =
263 reinterpret_cast<RawExternalOneByteString*>(raw_obj)->ptr(); 268 reinterpret_cast<RawExternalOneByteString*>(raw_obj)->ptr();
264 ExternalStringData<uint8_t>* data = raw_string->external_data_; 269 ExternalStringData<uint8_t>* data = raw_string->external_data_;
265 *peer = data->peer(); 270 *peer = data->peer();
266 return true; 271 return true;
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 522
518 523
519 DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) { 524 DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) {
520 Isolate* isolate = Isolate::Current(); 525 Isolate* isolate = Isolate::Current();
521 CHECK_ISOLATE(isolate); 526 CHECK_ISOLATE(isolate);
522 NoGCScope ngc; 527 NoGCScope ngc;
523 return Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2); 528 return Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2);
524 } 529 }
525 530
526 531
527 DART_EXPORT Dart_Handle Dart_NewPersistentHandle(Dart_Handle object) { 532 DART_EXPORT Dart_Handle Dart_NewHandleFromPersistent(Dart_PersistentHandle objec t) {
533 Isolate* isolate = Isolate::Current();
534 DARTSCOPE(isolate);
535 ApiState* state = isolate->api_state();
536 ASSERT(state != NULL);
537 ASSERT(state->IsValidPersistentHandle(object));
538 return Api::NewHandle(isolate, reinterpret_cast<PersistentHandle*>(object)->ra w());
539 }
540
541
542 DART_EXPORT Dart_Handle Dart_NewHandleFromWeakPersistent(Dart_WeakPersistentHand le object) {
543 Isolate* isolate = Isolate::Current();
544 DARTSCOPE(isolate);
545 ApiState* state = isolate->api_state();
546 ASSERT(state != NULL);
547 ASSERT(state->IsValidWeakPersistentHandle(object));
548 return Api::NewHandle(isolate, reinterpret_cast<FinalizablePersistentHandle*>( object)->raw());
549 }
550
551
552 DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
528 Isolate* isolate = Isolate::Current(); 553 Isolate* isolate = Isolate::Current();
529 DARTSCOPE(isolate); 554 DARTSCOPE(isolate);
530 ApiState* state = isolate->api_state(); 555 ApiState* state = isolate->api_state();
531 ASSERT(state != NULL); 556 ASSERT(state != NULL);
532 const Object& old_ref = Object::Handle(isolate, Api::UnwrapHandle(object)); 557 const Object& old_ref = Object::Handle(isolate, Api::UnwrapHandle(object));
533 PersistentHandle* new_ref = state->persistent_handles().AllocateHandle(); 558 PersistentHandle* new_ref = state->persistent_handles().AllocateHandle();
534 new_ref->set_raw(old_ref); 559 new_ref->set_raw(old_ref);
535 return reinterpret_cast<Dart_Handle>(new_ref); 560 return reinterpret_cast<Dart_PersistentHandle>(new_ref);
536 } 561 }
537 562
538 static Dart_Handle AllocateFinalizableHandle( 563 static Dart_WeakPersistentHandle AllocateFinalizableHandle(
539 Isolate* isolate, 564 Isolate* isolate,
540 FinalizablePersistentHandles* handles, 565 FinalizablePersistentHandles* handles,
541 Dart_Handle object, 566 Dart_Handle object,
542 void* peer, 567 void* peer,
543 Dart_WeakPersistentHandleFinalizer callback) { 568 Dart_WeakPersistentHandleFinalizer callback) {
544 const Object& ref = Object::Handle(isolate, Api::UnwrapHandle(object)); 569 const Object& ref = Object::Handle(isolate, Api::UnwrapHandle(object));
545 FinalizablePersistentHandle* finalizable_ref = handles->AllocateHandle(); 570 FinalizablePersistentHandle* finalizable_ref = handles->AllocateHandle();
546 finalizable_ref->set_raw(ref); 571 finalizable_ref->set_raw(ref);
547 finalizable_ref->set_peer(peer); 572 finalizable_ref->set_peer(peer);
548 finalizable_ref->set_callback(callback); 573 finalizable_ref->set_callback(callback);
549 return reinterpret_cast<Dart_Handle>(finalizable_ref); 574 return reinterpret_cast<Dart_WeakPersistentHandle>(finalizable_ref);
550 } 575 }
551 576
552 577
553 DART_EXPORT Dart_Handle Dart_NewWeakPersistentHandle( 578 DART_EXPORT Dart_WeakPersistentHandle Dart_NewWeakPersistentHandle(
554 Dart_Handle object, 579 Dart_Handle object,
555 void* peer, 580 void* peer,
556 Dart_WeakPersistentHandleFinalizer callback) { 581 Dart_WeakPersistentHandleFinalizer callback) {
557 Isolate* isolate = Isolate::Current(); 582 Isolate* isolate = Isolate::Current();
558 DARTSCOPE(isolate); 583 DARTSCOPE(isolate);
559 ApiState* state = isolate->api_state(); 584 ApiState* state = isolate->api_state();
560 ASSERT(state != NULL); 585 ASSERT(state != NULL);
561 return AllocateFinalizableHandle(isolate, 586 return AllocateFinalizableHandle(isolate,
562 &state->weak_persistent_handles(), 587 &state->weak_persistent_handles(),
563 object, 588 object,
564 peer, 589 peer,
565 callback); 590 callback);
566 } 591 }
567 592
568 593
569 DART_EXPORT Dart_Handle Dart_NewPrologueWeakPersistentHandle( 594 DART_EXPORT Dart_WeakPersistentHandle Dart_NewPrologueWeakPersistentHandle(
570 Dart_Handle object, 595 Dart_Handle object,
571 void* peer, 596 void* peer,
572 Dart_WeakPersistentHandleFinalizer callback) { 597 Dart_WeakPersistentHandleFinalizer callback) {
573 Isolate* isolate = Isolate::Current(); 598 Isolate* isolate = Isolate::Current();
574 DARTSCOPE(isolate); 599 DARTSCOPE(isolate);
575 ApiState* state = isolate->api_state(); 600 ApiState* state = isolate->api_state();
576 ASSERT(state != NULL); 601 ASSERT(state != NULL);
577 return AllocateFinalizableHandle(isolate, 602 return AllocateFinalizableHandle(isolate,
578 &state->prologue_weak_persistent_handles(), 603 &state->prologue_weak_persistent_handles(),
579 object, 604 object,
580 peer, 605 peer,
581 callback); 606 callback);
582 } 607 }
583 608
584 609
585 DART_EXPORT void Dart_DeletePersistentHandle(Dart_Handle object) { 610 DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object) {
611 Isolate* isolate = Isolate::Current();
612 CHECK_ISOLATE(isolate);
613 ApiState* state = isolate->api_state();
614 ASSERT(state != NULL);
615 PersistentHandle* ref = Api::UnwrapAsPersistentHandle(*state, object);
616 ASSERT(!state->IsProtectedHandle(ref));
617 if (!state->IsProtectedHandle(ref)) {
618 state->persistent_handles().FreeHandle(ref);
619 }
620 }
621
622
623 DART_EXPORT void Dart_DeleteWeakPersistentHandle(Dart_WeakPersistentHandle objec t) {
586 Isolate* isolate = Isolate::Current(); 624 Isolate* isolate = Isolate::Current();
587 CHECK_ISOLATE(isolate); 625 CHECK_ISOLATE(isolate);
588 ApiState* state = isolate->api_state(); 626 ApiState* state = isolate->api_state();
589 ASSERT(state != NULL); 627 ASSERT(state != NULL);
590 if (state->IsValidPrologueWeakPersistentHandle(object)) { 628 if (state->IsValidPrologueWeakPersistentHandle(object)) {
591 FinalizablePersistentHandle* prologue_weak_ref = 629 FinalizablePersistentHandle* prologue_weak_ref =
592 Api::UnwrapAsPrologueWeakPersistentHandle(*state, object); 630 Api::UnwrapAsPrologueWeakPersistentHandle(*state, object);
593 state->prologue_weak_persistent_handles().FreeHandle(prologue_weak_ref); 631 state->prologue_weak_persistent_handles().FreeHandle(prologue_weak_ref);
594 return; 632 return;
595 } 633 }
596 if (state->IsValidWeakPersistentHandle(object)) { 634 FinalizablePersistentHandle* weak_ref =
597 FinalizablePersistentHandle* weak_ref = 635 Api::UnwrapAsWeakPersistentHandle(*state, object);
598 Api::UnwrapAsWeakPersistentHandle(*state, object); 636 state->weak_persistent_handles().FreeHandle(weak_ref);
599 state->weak_persistent_handles().FreeHandle(weak_ref); 637 return;
600 return;
601 }
602 PersistentHandle* ref = Api::UnwrapAsPersistentHandle(*state, object);
603 ASSERT(!state->IsProtectedHandle(ref));
604 if (!state->IsProtectedHandle(ref)) {
605 state->persistent_handles().FreeHandle(ref);
606 }
607 } 638 }
608 639
609 640
610 DART_EXPORT bool Dart_IsWeakPersistentHandle(Dart_Handle object) { 641 DART_EXPORT bool Dart_IsWeakPersistentHandle(Dart_WeakPersistentHandle object) {
611 Isolate* isolate = Isolate::Current(); 642 Isolate* isolate = Isolate::Current();
612 CHECK_ISOLATE(isolate); 643 CHECK_ISOLATE(isolate);
613 ApiState* state = isolate->api_state(); 644 ApiState* state = isolate->api_state();
614 ASSERT(state != NULL); 645 ASSERT(state != NULL);
615 return state->IsValidWeakPersistentHandle(object); 646 return state->IsValidWeakPersistentHandle(object);
616 } 647 }
617 648
618 649
619 DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(Dart_Handle object) { 650 DART_EXPORT bool Dart_IsPrologueWeakPersistentHandle(Dart_WeakPersistentHandle o bject) {
620 Isolate* isolate = Isolate::Current(); 651 Isolate* isolate = Isolate::Current();
621 CHECK_ISOLATE(isolate); 652 CHECK_ISOLATE(isolate);
622 ApiState* state = isolate->api_state(); 653 ApiState* state = isolate->api_state();
623 ASSERT(state != NULL); 654 ASSERT(state != NULL);
624 return state->IsValidPrologueWeakPersistentHandle(object); 655 return state->IsValidPrologueWeakPersistentHandle(object);
625 } 656 }
626 657
627 658
628 DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(Dart_Handle* keys, 659 DART_EXPORT Dart_Handle Dart_NewWeakReferenceSet(Dart_Handle* keys,
629 intptr_t num_keys, 660 intptr_t num_keys,
(...skipping 4242 matching lines...) Expand 10 before | Expand all | Expand 10 after
4872 } 4903 }
4873 { 4904 {
4874 NoGCScope no_gc; 4905 NoGCScope no_gc;
4875 RawObject* raw_obj = obj.raw(); 4906 RawObject* raw_obj = obj.raw();
4876 isolate->heap()->SetPeer(raw_obj, peer); 4907 isolate->heap()->SetPeer(raw_obj, peer);
4877 } 4908 }
4878 return Api::Success(isolate); 4909 return Api::Success(isolate);
4879 } 4910 }
4880 4911
4881 } // namespace dart 4912 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698