Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
class_finalizer.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include <memory>
6#include <utility>
7
9
10#include "vm/canonical_tables.h"
13#include "vm/flags.h"
14#include "vm/hash_table.h"
15#include "vm/heap/heap.h"
16#include "vm/isolate.h"
17#include "vm/kernel_loader.h"
18#include "vm/log.h"
19#include "vm/longjump.h"
20#include "vm/object_store.h"
21#include "vm/program_visitor.h"
22#include "vm/runtime_entry.h"
23#include "vm/symbols.h"
24#include "vm/timeline.h"
26
27namespace dart {
28
29DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
30DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
31DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
32
35 const GrowableObjectArray& classes =
36 GrowableObjectArray::Handle(object_store->pending_classes());
37 return classes.Length() == 0;
38}
39
40#if defined(DART_PRECOMPILED_RUNTIME)
41
44 return true;
45}
46
47#else
48
49// Removes optimized code once we load more classes, since CHA based
50// optimizations may have become invalid.
51// Only methods which owner classes where subclasses can be invalid.
52// TODO(srdjan): Be even more precise by recording the exact CHA optimization.
54 const Class& subclass,
55 const GrowableArray<intptr_t>& added_subclass_to_cids) {
56 ASSERT(FLAG_use_cha_deopt);
57 if (added_subclass_to_cids.is_empty()) {
58 return;
59 }
60 // Switch all functions' code to unoptimized.
61 const ClassTable& class_table = *IsolateGroup::Current()->class_table();
62 Class& cls = Class::Handle();
63 for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {
64 intptr_t cid = added_subclass_to_cids[i];
65 cls = class_table.At(cid);
66 ASSERT(!cls.IsNull());
67 cls.DisableCHAOptimizedCode(subclass);
68 }
69}
70
71static void AddSuperType(const AbstractType& type,
72 GrowableArray<intptr_t>* finalized_super_classes) {
73 ASSERT(type.HasTypeClass());
74 ASSERT(!type.IsDynamicType());
75 if (type.IsObjectType()) {
76 return;
77 }
78 const Class& cls = Class::Handle(type.type_class());
79 ASSERT(cls.is_finalized());
80 const intptr_t cid = cls.id();
81 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) {
82 if ((*finalized_super_classes)[i] == cid) {
83 // Already added.
84 return;
85 }
86 }
87 finalized_super_classes->Add(cid);
88 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
89 AddSuperType(super_type, finalized_super_classes);
90}
91
92// Use array instead of set since we expect very few subclassed classes
93// to occur.
95 const Class& cls_,
96 GrowableArray<intptr_t>* finalized_super_classes) {
97 Class& cls = Class::Handle(cls_.ptr());
98 AbstractType& super_type = Type::Handle();
99 super_type = cls.super_type();
100 if (!super_type.IsNull()) {
101 if (super_type.HasTypeClass()) {
102 cls = super_type.type_class();
103 if (cls.is_finalized()) {
104 AddSuperType(super_type, finalized_super_classes);
105 }
106 }
107 }
108}
109
111 public:
113 ClassTable* class_table,
115 : class_table_(class_table),
116 array_handles_(zone),
117 class_handles_(zone),
118 type_handles_(zone),
119 cids_(cids) {}
120
121 void FindAllInterfaces(const Class& klass) {
122 // The class is implementing its own interface.
123 cids_->Add(klass.id());
124
125 ScopedHandle<Array> array(&array_handles_);
126 ScopedHandle<Class> interface_class(&class_handles_);
127 ScopedHandle<Class> current_class(&class_handles_);
128 ScopedHandle<AbstractType> type(&type_handles_);
129
130 *current_class = klass.ptr();
131 while (true) {
132 // We don't care about top types.
133 const intptr_t cid = current_class->id();
134 if (cid == kObjectCid || cid == kDynamicCid || cid == kVoidCid) {
135 break;
136 }
137
138 // The class is implementing its directly declared implemented interfaces.
139 *array = klass.interfaces();
140 if (!array->IsNull()) {
141 for (intptr_t i = 0; i < array->Length(); ++i) {
142 *type ^= array->At(i);
143 *interface_class = class_table_->At(type->type_class_id());
144 FindAllInterfaces(*interface_class);
145 }
146 }
147
148 // The class is implementing its super type's interfaces.
149 *type = current_class->super_type();
150 if (type->IsNull()) break;
151 *current_class = class_table_->At(type->type_class_id());
152 }
153 }
154
155 private:
156 ClassTable* class_table_;
157 ReusableHandleStack<Array> array_handles_;
158 ReusableHandleStack<Class> class_handles_;
161};
162
165 const Array& interfaces = Array::Handle(cls.interfaces());
166 Class& ifc = Class::Handle();
168 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
169 type ^= interfaces.At(i);
170 if (!type.HasTypeClass()) continue;
171 ifc = type.type_class();
172 for (intptr_t j = 0; j < cids->length(); ++j) {
173 if ((*cids)[j] == ifc.id()) {
174 // Already added.
175 return;
176 }
177 }
178 cids->Add(ifc.id());
179 }
180}
181
182// Processing ObjectStore::pending_classes_ occurs:
183// a) when bootstrap process completes (VerifyBootstrapClasses).
184// b) after the user classes are loaded (dart_api).
186 Thread* thread = Thread::Current();
187 TIMELINE_DURATION(thread, Isolate, "ProcessPendingClasses");
188 auto isolate_group = thread->isolate_group();
189 ASSERT(isolate_group != nullptr);
190 HANDLESCOPE(thread);
191 ObjectStore* object_store = isolate_group->object_store();
192 const Error& error = Error::Handle(thread->zone(), thread->sticky_error());
193 if (!error.IsNull()) {
194 return false;
195 }
196 if (AllClassesFinalized()) {
197 return true;
198 }
199
200 LongJumpScope jump;
201 if (setjmp(*jump.Set()) == 0) {
203 class_array = object_store->pending_classes();
204 ASSERT(!class_array.IsNull());
205 Class& cls = Class::Handle();
206
207#if defined(DEBUG)
208 for (intptr_t i = 0; i < class_array.Length(); i++) {
209 cls ^= class_array.At(i);
210 // Recognized a new class, but forgot to add @pragma('vm:entrypoint')?
212 }
213#endif
214
215 // Finalize types in all classes.
216 for (intptr_t i = 0; i < class_array.Length(); i++) {
217 cls ^= class_array.At(i);
219#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
221#endif
222 }
223
224 // Clear pending classes array.
225 class_array = GrowableObjectArray::New();
226 object_store->set_pending_classes(class_array);
227 VerifyImplicitFieldOffsets(); // Verification after an error may fail.
228
229 return true;
230 } else {
231 return false;
232 }
233 UNREACHABLE();
234 return true;
235}
236
238 if (FLAG_trace_class_finalization) {
239 OS::PrintErr("VerifyBootstrapClasses START.\n");
240 }
242
243 Class& cls = Class::Handle();
244#if defined(DEBUG)
245 // Basic checking.
246 cls = object_store->object_class();
248 cls = object_store->integer_implementation_class();
250 cls = object_store->smi_class();
252 cls = object_store->mint_class();
254 cls = object_store->one_byte_string_class();
256 cls = object_store->two_byte_string_class();
258 cls = object_store->double_class();
260 cls = object_store->bool_class();
262 cls = object_store->array_class();
264 cls = object_store->immutable_array_class();
266 cls = object_store->weak_property_class();
268 cls = object_store->weak_reference_class();
270 cls = object_store->finalizer_class();
272 cls = object_store->finalizer_entry_class();
274 cls = object_store->map_impl_class();
276 cls = object_store->const_map_impl_class();
278 cls = object_store->set_impl_class();
280 cls = object_store->const_set_impl_class();
282#endif // defined(DEBUG)
283
284 // Remember the currently pending classes.
285 const GrowableObjectArray& class_array =
286 GrowableObjectArray::Handle(object_store->pending_classes());
287 for (intptr_t i = 0; i < class_array.Length(); i++) {
288 // TODO(iposva): Add real checks.
289 cls ^= class_array.At(i);
290 if (cls.is_finalized() || cls.is_prefinalized()) {
291 // Pre-finalized bootstrap classes must not define any fields.
293 }
294 }
295
296 // Finalize type hierarchy for types that aren't pre-finalized
297 // by Object::Init().
298 if (!ProcessPendingClasses()) {
299 // TODO(srdjan): Exit like a real VM instead.
300 const Error& err = Error::Handle(Thread::Current()->sticky_error());
301 OS::PrintErr("Could not verify bootstrap classes : %s\n",
302 err.ToErrorCString());
303 OS::Exit(255);
304 }
305
306 if (FLAG_trace_class_finalization) {
307 OS::PrintErr("VerifyBootstrapClasses END.\n");
308 }
309 IsolateGroup::Current()->heap()->Verify("VerifyBootstrapClasses END");
310}
311#endif // defined(DART_PRECOMPILED_RUNTIME)
312
313void ClassFinalizer::FinalizeTypeParameters(Zone* zone,
314 const TypeParameters& type_params,
315 FinalizationKind finalization) {
316 if (!type_params.IsNull()) {
317 TypeArguments& type_args = TypeArguments::Handle(zone);
318
319 type_args = type_params.bounds();
320 type_args = FinalizeTypeArguments(zone, type_args, finalization);
321 type_params.set_bounds(type_args);
322
323 type_args = type_params.defaults();
324 type_args = FinalizeTypeArguments(zone, type_args, finalization);
325 type_params.set_defaults(type_args);
326
327 type_params.OptimizeFlags();
328 }
329}
330
331TypeArgumentsPtr ClassFinalizer::FinalizeTypeArguments(
332 Zone* zone,
333 const TypeArguments& type_args,
334 FinalizationKind finalization) {
335 if (type_args.IsNull()) {
336 return TypeArguments::null();
337 }
338 ASSERT(type_args.ptr() != Object::empty_type_arguments().ptr());
339 AbstractType& type = AbstractType::Handle(zone);
340 for (intptr_t i = 0, n = type_args.Length(); i < n; ++i) {
341 type = type_args.TypeAt(i);
343 }
344 if (finalization >= kCanonicalize) {
345 return type_args.Canonicalize(Thread::Current());
346 }
347 return type_args.ptr();
348}
349
351 FinalizationKind finalization) {
352 if (type.IsFinalized()) {
353 if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
354 return type.Canonicalize(Thread::Current());
355 }
356 return type.ptr();
357 }
358
359 Thread* thread = Thread::Current();
360 Zone* zone = thread->zone();
361
362 if (FLAG_trace_type_finalization) {
363 THR_Print("Finalizing type '%s'\n", type.ToCString());
364 }
365
366 if (type.IsType()) {
367 const auto& t = Type::Cast(type);
368 const auto& type_args = TypeArguments::Handle(zone, t.arguments());
369 ASSERT(type_args.IsNull() ||
370 type_args.Length() ==
371 Class::Handle(zone, t.type_class()).NumTypeParameters(thread));
372 FinalizeTypeArguments(zone, type_args, kFinalize);
373
374 } else if (type.IsTypeParameter()) {
375 const TypeParameter& type_parameter = TypeParameter::Cast(type);
376 // The base and index of a function type parameter are eagerly calculated
377 // upon loading and do not require adjustment here.
378 if (type_parameter.IsClassTypeParameter()) {
379 const Class& parameterized_class = Class::Cast(
380 Object::Handle(zone, type_parameter.parameterized_class()));
381 ASSERT(!parameterized_class.IsNull());
382 // The index must reflect the position of this type parameter in the type
383 // arguments vector of its parameterized class. The offset to add is the
384 // number of type arguments in the super type, which is equal to the
385 // difference in number of type arguments and type parameters of the
386 // parameterized class.
387 const intptr_t offset = parameterized_class.NumTypeArguments() -
388 parameterized_class.NumTypeParameters();
389 const intptr_t index = type_parameter.index() + offset;
390 if (!Utils::IsUint(16, index)) {
391 FATAL("Too many type parameters in %s",
392 parameterized_class.UserVisibleNameCString());
393 }
394 type_parameter.set_base(offset); // Informative, but not needed.
395 type_parameter.set_index(index);
396
397 if (AbstractType::Handle(zone, type_parameter.bound())
398 .IsNullableObjectType()) {
399 // Remove the reference to the parameterized class to
400 // canonicalize common class type parameters
401 // with 'Object?' bound and same indices to the same
402 // instances.
404 }
405 }
406 } else if (type.IsFunctionType()) {
407 const auto& signature = FunctionType::Cast(type);
408 FinalizeTypeParameters(
409 zone, TypeParameters::Handle(zone, signature.type_parameters()),
410 kFinalize);
411
413 type = signature.result_type();
415
416 for (intptr_t i = 0, n = signature.NumParameters(); i < n; ++i) {
417 type = signature.ParameterTypeAt(i);
419 }
420
421 } else if (type.IsRecordType()) {
422 const auto& record = RecordType::Cast(type);
424 for (intptr_t i = 0, n = record.NumFields(); i < n; ++i) {
425 type = record.FieldTypeAt(i);
427 }
428 }
429
430 type.SetIsFinalized();
431
432 if (finalization >= kCanonicalize) {
433 return type.Canonicalize(thread);
434 } else {
435 return type.ptr();
436 }
437}
438
439#if !defined(DART_PRECOMPILED_RUNTIME)
440
441#if defined(TARGET_ARCH_X64)
442static bool IsPotentialExactGeneric(const AbstractType& type) {
443 // TODO(dartbug.com/34170) Investigate supporting this for fields with types
444 // that depend on type parameters of the enclosing class.
445 if (type.IsType() && !type.IsDartFunctionType() && type.IsInstantiated() &&
446 !type.IsFutureOrType()) {
447 const Class& cls = Class::Handle(type.type_class());
448 return cls.IsGeneric();
449 }
450
451 return false;
452}
453#else
454// TODO(dartbug.com/34170) Support other architectures.
456 return false;
457}
458#endif
459
460void ClassFinalizer::FinalizeMemberTypes(const Class& cls) {
461 // Note that getters and setters are explicitly listed as such in the list of
462 // functions of a class, so we do not need to consider fields as implicitly
463 // generating getters and setters.
464 // Most overriding conflicts are only static warnings, i.e. they are not
465 // reported as compile-time errors by the vm.
466 // Static warning examples are:
467 // - a static getter 'v' conflicting with an inherited instance setter 'v='.
468 // - a static setter 'v=' conflicting with an inherited instance member 'v'.
469 // - an instance member 'v' conflicting with an accessible static member 'v'
470 // or 'v=' of a super class (except that an instance method 'v' does not
471 // conflict with an accessible static setter 'v=' of a super class).
472 // The compile-time errors we report are:
473 // - a static member 'v' conflicting with an inherited instance member 'v'.
474 // - a static setter 'v=' conflicting with an inherited instance setter 'v='.
475 // - an instance method conflicting with an inherited instance field or
476 // instance getter.
477 // - an instance field or instance getter conflicting with an inherited
478 // instance method.
479
480 // Finalize type of fields and check for conflicts in super classes.
481 auto isolate_group = IsolateGroup::Current();
482 Zone* zone = Thread::Current()->zone();
483 Array& array = Array::Handle(zone, cls.fields());
484 Field& field = Field::Handle(zone);
485 AbstractType& type = AbstractType::Handle(zone);
486 Function& function = Function::Handle(zone);
487 FunctionType& signature = FunctionType::Handle(zone);
488 const intptr_t num_fields = array.Length();
489 const bool track_exactness = isolate_group->use_field_guards();
490 for (intptr_t i = 0; i < num_fields; i++) {
491 field ^= array.At(i);
492 type = field.type();
494 field.SetFieldType(type);
495 ASSERT(!field.static_type_exactness_state().IsTracking());
496 if (track_exactness && (field.guarded_cid() != kDynamicCid) &&
498 field.set_static_type_exactness_state(
500 }
501 function = field.InitializerFunction();
502 if (!function.IsNull()) {
503 // TODO(regis): It looks like the initializer is never set at this point.
504 // Remove this finalization code?
505 signature = function.signature();
506 signature ^= FinalizeType(signature);
507 function.SetSignature(signature);
508 }
509 }
510 // Finalize function signatures and check for conflicts in super classes and
511 // interfaces.
512 array = cls.current_functions();
513 const intptr_t num_functions = array.Length();
514 for (intptr_t i = 0; i < num_functions; i++) {
515 function ^= array.At(i);
516 signature = function.signature();
517 signature ^= FinalizeType(signature);
518 function.SetSignature(signature);
519 if (function.IsSetterFunction() || function.IsImplicitSetterFunction()) {
520 continue;
521 }
522 }
523}
524
525// For a class used as an interface marks this class and all its superclasses
526// implemented.
527//
528// Does not mark its interfaces implemented because those would already be
529// marked as such.
530static void MarkImplemented(Zone* zone, const Class& iface) {
531 if (iface.is_implemented()) {
532 return;
533 }
534
535 Class& cls = Class::Handle(zone, iface.ptr());
537
538 while (!cls.is_implemented()) {
539 cls.set_is_implemented();
540
541 type = cls.super_type();
542 if (type.IsNull() || type.IsObjectType()) {
543 break;
544 }
545 cls = type.type_class();
546 }
547}
548#endif // !defined(DART_PRECOMPILED_RUNTIME)
549
551 Thread* thread = Thread::Current();
552 HANDLESCOPE(thread);
554 if (cls.is_type_finalized()) {
555 return;
556 }
557
558#if defined(DART_PRECOMPILED_RUNTIME)
559 UNREACHABLE();
560#else
561 Zone* zone = thread->zone();
562 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
563 if (cls.is_type_finalized()) {
564 return;
565 }
566
567 if (FLAG_trace_class_finalization) {
568 THR_Print("Finalize types in %s\n", cls.ToCString());
569 }
570
571 bool has_isolate_unsendable_pragma =
573 bool is_future_subtype = cls.IsFutureClass();
574
575 // Finalize super class.
576 Class& super_class = Class::Handle(zone, cls.SuperClass());
577 if (!super_class.IsNull()) {
578 FinalizeTypesInClass(super_class);
579 }
580 // Finalize type parameters before finalizing the super type.
581 FinalizeTypeParameters(
583 ASSERT(super_class.ptr() == cls.SuperClass()); // Not modified.
584 ASSERT(super_class.IsNull() || super_class.is_type_finalized());
585 // Finalize super type.
586 Type& super_type = Type::Handle(zone, cls.super_type());
587 if (!super_type.IsNull()) {
588 super_type ^= FinalizeType(super_type);
589 cls.set_super_type(super_type);
590 has_isolate_unsendable_pragma |=
592 is_future_subtype |= super_class.is_future_subtype();
593 }
594 // Finalize interface types (but not necessarily interface classes).
595 const auto& interface_types = Array::Handle(zone, cls.interfaces());
596 auto& interface_type = AbstractType::Handle(zone);
597 auto& interface_class = Class::Handle(zone);
598 for (intptr_t i = 0; i < interface_types.Length(); i++) {
599 interface_type ^= interface_types.At(i);
600 interface_type = FinalizeType(interface_type);
601 interface_class = interface_type.type_class();
602 ASSERT(!interface_class.IsNull());
603 FinalizeTypesInClass(interface_class);
604 interface_types.SetAt(i, interface_type);
605 has_isolate_unsendable_pragma |=
606 interface_class.is_isolate_unsendable_due_to_pragma();
607 is_future_subtype |= interface_class.is_future_subtype();
608 }
610 cls.set_is_isolate_unsendable_due_to_pragma(has_isolate_unsendable_pragma);
611 cls.set_is_future_subtype(is_future_subtype);
612 if (is_future_subtype && !cls.is_abstract()) {
613 MarkClassCanBeFuture(zone, cls);
614 }
615
616 RegisterClassInHierarchy(zone, cls);
617#endif // defined(DART_PRECOMPILED_RUNTIME)
618}
619
620#if !defined(DART_PRECOMPILED_RUNTIME)
622 auto& type = AbstractType::Handle(zone, cls.super_type());
623 auto& other_cls = Class::Handle(zone);
624 // Add this class to the direct subclasses of the superclass, unless the
625 // superclass is Object.
626 if (!type.IsNull() && !type.IsObjectType()) {
627 other_cls = cls.SuperClass();
628 ASSERT(!other_cls.IsNull());
629 other_cls.AddDirectSubclass(cls);
630 }
631
632 // Add this class as an implementor to the implemented interface's type
633 // classes.
634 auto& interfaces = Array::Handle(zone, cls.interfaces());
635 const intptr_t mixin_index =
636 cls.is_transformed_mixin_application() ? interfaces.Length() - 1 : -1;
637 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
638 type ^= interfaces.At(i);
639 other_cls = type.type_class();
640 MarkImplemented(zone, other_cls);
641 other_cls.AddDirectImplementor(cls, /* is_mixin = */ i == mixin_index);
642 }
643
644 // Propagate known concrete implementors to interfaces.
645 if (!cls.is_abstract()) {
647 worklist.Add(&cls);
648 while (!worklist.is_empty()) {
649 const Class& implemented = *worklist.RemoveLast();
650 if (!implemented.NoteImplementor(cls)) continue;
651 type = implemented.super_type();
652 if (!type.IsNull()) {
653 worklist.Add(&Class::Handle(zone, implemented.SuperClass()));
654 }
655 interfaces = implemented.interfaces();
656 for (intptr_t i = 0; i < interfaces.Length(); i++) {
657 type ^= interfaces.At(i);
658 worklist.Add(&Class::Handle(zone, type.type_class()));
659 }
660 }
661 }
662}
663
665 if (cls.can_be_future()) return;
666
667 cls.set_can_be_future(true);
668
669 Class& base = Class::Handle(zone, cls.SuperClass());
670 if (!base.IsNull()) {
672 }
673 auto& interfaces = Array::Handle(zone, cls.interfaces());
674 auto& type = AbstractType::Handle(zone);
675 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
676 type ^= interfaces.At(i);
677 base = type.type_class();
679 }
680}
681#endif // defined(DART_PRECOMPILED_RUNTIME)
682
685 if (cls.is_finalized()) {
686 return;
687 }
688
689#if defined(DART_PRECOMPILED_RUNTIME)
690 UNREACHABLE();
691#else
692 Thread* thread = Thread::Current();
693 HANDLESCOPE(thread);
694
695 if (FLAG_trace_class_finalization) {
696 THR_Print("Finalize %s\n", cls.ToCString());
697 }
698
699#if defined(SUPPORT_TIMELINE)
700 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
701 "FinalizeClass");
702 if (tbes.enabled()) {
703 tbes.SetNumArguments(1);
704 tbes.CopyArgument(0, "class", cls.ToCString());
705 }
706#endif // defined(SUPPORT_TIMELINE)
707
708 // If loading from a kernel, make sure that the class is fully loaded.
709 ASSERT(cls.IsTopLevel() || (cls.kernel_offset() > 0));
710 if (!cls.is_loaded()) {
712 if (cls.is_finalized()) {
713 return;
714 }
715 }
716
717 // Ensure super class is finalized.
718 const Class& super = Class::Handle(cls.SuperClass());
719 if (!super.IsNull()) {
720 FinalizeClass(super);
721 if (cls.is_finalized()) {
722 return;
723 }
724 }
725 // Mark as loaded and finalized.
726 cls.Finalize();
727 if (FLAG_print_classes) {
728 PrintClassInformation(cls);
729 }
730 FinalizeMemberTypes(cls);
731
732 // The rest of finalization for non-top-level class has to be done with
733 // stopped mutators. It will be done by AllocateFinalizeClass. before new
734 // instance of a class is created in GetAllocationStubForClass.
735 if (cls.IsTopLevel()) {
737 }
738#endif // defined(DART_PRECOMPILED_RUNTIME)
739}
740
741#if !defined(DART_PRECOMPILED_RUNTIME)
742
744 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
745 ASSERT(cls.is_finalized());
747
748 Thread* thread = Thread::Current();
749 HANDLESCOPE(thread);
750
751 if (FLAG_trace_class_finalization) {
752 THR_Print("Allocate finalize %s\n", cls.ToCString());
753 }
754
755#if defined(SUPPORT_TIMELINE)
756 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
757 "AllocateFinalizeClass");
758 if (tbes.enabled()) {
759 tbes.SetNumArguments(1);
760 tbes.CopyArgument(0, "class", cls.ToCString());
761 }
762#endif // defined(SUPPORT_TIMELINE)
763
764 // Run additional checks after all types are finalized.
765 if (FLAG_use_cha_deopt && !cls.IsTopLevel()) {
766 {
770 RemoveCHAOptimizedCode(cls, cids);
771 }
772
773 Zone* zone = thread->zone();
774 ClassTable* class_table = thread->isolate_group()->class_table();
775 auto& interface_class = Class::Handle(zone);
776
777 // We scan every interface this [cls] implements and invalidate all CHA
778 // code which depends on knowing the implementors of that interface.
779 {
781 InterfaceFinder finder(zone, class_table, &cids);
782 finder.FindAllInterfaces(cls);
783 for (intptr_t j = 0; j < cids.length(); ++j) {
784 interface_class = class_table->At(cids[j]);
785 interface_class.DisableCHAImplementorUsers();
786 }
787 }
788 }
789
791 return Error::null();
792}
793
795 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
796 ASSERT(!cls.is_finalized());
797
798 LongJumpScope jump;
799 if (setjmp(*jump.Set()) == 0) {
800#if !defined(DART_PRECOMPILED_RUNTIME)
802#endif
805 return Error::null();
806 } else {
808 }
809}
810
811void ClassFinalizer::PrintClassInformation(const Class& cls) {
812 Thread* thread = Thread::Current();
813 HANDLESCOPE(thread);
814 const String& class_name = String::Handle(cls.Name());
815 THR_Print("class '%s'", class_name.ToCString());
816 const Library& library = Library::Handle(cls.library());
817 if (!library.IsNull()) {
818 THR_Print(" library '%s%s':\n", String::Handle(library.url()).ToCString(),
820 } else {
821 THR_Print(" (null library):\n");
822 }
823 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
824 if (super_type.IsNull()) {
825 THR_Print(" Super: nullptr");
826 } else {
827 const String& super_name = String::Handle(super_type.Name());
828 THR_Print(" Super: %s", super_name.ToCString());
829 }
830 const Array& interfaces_array = Array::Handle(cls.interfaces());
831 if (interfaces_array.Length() > 0) {
832 THR_Print("; interfaces: ");
833 AbstractType& interface = AbstractType::Handle();
834 intptr_t len = interfaces_array.Length();
835 for (intptr_t i = 0; i < len; i++) {
836 interface ^= interfaces_array.At(i);
837 THR_Print(" %s ", interface.ToCString());
838 }
839 }
840 THR_Print("\n");
841 const Array& functions_array = Array::Handle(cls.current_functions());
842 Function& function = Function::Handle();
843 intptr_t len = functions_array.Length();
844 for (intptr_t i = 0; i < len; i++) {
845 function ^= functions_array.At(i);
846 THR_Print(" %s\n", function.ToCString());
847 }
848 const Array& fields_array = Array::Handle(cls.fields());
849 Field& field = Field::Handle();
850 len = fields_array.Length();
851 for (intptr_t i = 0; i < len; i++) {
852 field ^= fields_array.At(i);
853 THR_Print(" %s\n", field.ToCString());
854 }
855}
856
857#endif // !defined(DART_PRECOMPILED_RUNTIME)
858
859void ClassFinalizer::ReportError(const Error& error) {
861 UNREACHABLE();
862}
863
864void ClassFinalizer::ReportError(const char* format, ...) {
865 va_list args;
867 const Script& null_script = Script::Handle();
868 Report::MessageV(Report::kError, null_script, TokenPosition::kNoSource,
870 va_end(args);
871 UNREACHABLE();
872}
873
874#if !defined(DART_PRECOMPILED_RUNTIME)
875
876void ClassFinalizer::VerifyImplicitFieldOffsets() {
877#ifdef DEBUG
878 Thread* thread = Thread::Current();
879 auto isolate_group = thread->isolate_group();
880
881 if (isolate_group->obfuscate()) {
882 // Field names are obfuscated.
883 return;
884 }
885
886 Zone* zone = thread->zone();
887 const ClassTable& class_table = *(isolate_group->class_table());
888 Class& cls = Class::Handle(zone);
889 Array& fields_array = Array::Handle(zone);
890 Field& field = Field::Handle(zone);
891 String& name = String::Handle(zone);
892 String& expected_name = String::Handle(zone);
893 Error& error = Error::Handle(zone);
894 TypeParameter& type_param = TypeParameter::Handle(zone);
895
896 // Now verify field offsets of '_ByteBuffer' class.
897 cls = class_table.At(kByteBufferCid);
898 error = cls.EnsureIsFinalized(thread);
899 ASSERT(error.IsNull());
900 fields_array ^= cls.fields();
901 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
902 field ^= fields_array.At(0);
903 ASSERT(field.HostOffset() == ByteBuffer::data_offset());
904 name ^= field.name();
905 expected_name ^= String::New("_data");
907
908 // Now verify field offsets of 'Pointer' class.
909 cls = class_table.At(kPointerCid);
910 error = cls.EnsureIsFinalized(thread);
911 ASSERT(error.IsNull());
912 ASSERT(cls.NumTypeParameters() == 1);
913 type_param = cls.TypeParameterAt(0);
914 ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
915#endif
916}
917
919 auto T = Thread::Current();
920 StackZone stack_zone(T);
921 auto Z = T->zone();
922 auto IG = T->isolate_group();
923
924 // Prevent background compiler from adding deferred classes or canonicalizing
925 // new types while classes are being sorted and type hashes are modified.
926 NoBackgroundCompilerScope no_bg_compiler(T);
927 SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
928
929 ClassTable* table = IG->class_table();
930 intptr_t num_cids = table->NumCids();
931
932 std::unique_ptr<intptr_t[]> old_to_new_cid(new intptr_t[num_cids]);
933
934 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) {
935 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids.
936 }
937 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
938 old_to_new_cid[cid] = -1;
939 }
940
941 intptr_t next_new_cid = kNumPredefinedCids;
942 GrowableArray<intptr_t> dfs_stack;
943 Class& cls = Class::Handle(Z);
945
946 // Object doesn't use its subclasses list.
947 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
948 if (!table->HasValidClassAt(cid)) {
949 continue;
950 }
951 cls = table->At(cid);
952 if (!cls.is_declaration_loaded()) {
953 continue;
954 }
955 if (cls.SuperClass() == IG->object_store()->object_class()) {
956 dfs_stack.Add(cid);
957 }
958 }
959
960 while (dfs_stack.length() > 0) {
961 intptr_t cid = dfs_stack.RemoveLast();
962 ASSERT(table->HasValidClassAt(cid));
963 cls = table->At(cid);
964 ASSERT(!cls.IsNull());
965 if (old_to_new_cid[cid] == -1) {
966 old_to_new_cid[cid] = next_new_cid++;
967 if (FLAG_trace_class_finalization) {
968 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
969 cls.ToCString(), cid);
970 }
971 }
972 subclasses = cls.direct_subclasses();
973 if (!subclasses.IsNull()) {
974 for (intptr_t i = 0; i < subclasses.Length(); i++) {
975 cls ^= subclasses.At(i);
976 ASSERT(!cls.IsNull());
977 dfs_stack.Add(cls.id());
978 }
979 }
980 }
981
982 // Top-level classes, typedefs, patch classes, etc.
983 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
984 if (old_to_new_cid[cid] == -1) {
985 old_to_new_cid[cid] = next_new_cid++;
986 if (FLAG_trace_class_finalization && table->HasValidClassAt(cid)) {
987 cls = table->At(cid);
988 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
989 cls.ToCString(), cid);
990 }
991 }
992 }
993 ASSERT(next_new_cid == num_cids);
994 RemapClassIds(old_to_new_cid.get());
995 // Types use cid's as part of their hashes.
996 RehashTypes();
997 // Const objects use cid's as part of their hashes.
998 IG->RehashConstants(nullptr);
999}
1000
1002 public:
1003 explicit CidRewriteVisitor(intptr_t* old_to_new_cids)
1004 : old_to_new_cids_(old_to_new_cids) {}
1005
1006 intptr_t Map(intptr_t cid) {
1007 ASSERT(cid != -1);
1008 return old_to_new_cids_[cid];
1009 }
1010
1011 void VisitObject(ObjectPtr obj) override {
1012 if (obj->IsClass()) {
1013 ClassPtr cls = Class::RawCast(obj);
1014 const classid_t old_cid = cls->untag()->id_;
1015 if (ClassTable::IsTopLevelCid(old_cid)) {
1016 // We don't remap cids of top level classes.
1017 return;
1018 }
1019 cls->untag()->id_ = Map(old_cid);
1020 cls->untag()->implementor_cid_ = Map(cls->untag()->implementor_cid_);
1021 } else if (obj->IsField()) {
1022 FieldPtr field = Field::RawCast(obj);
1023 field->untag()->guarded_cid_ = Map(field->untag()->guarded_cid_);
1024 field->untag()->is_nullable_ = Map(field->untag()->is_nullable_);
1025 } else if (obj->IsTypeParameter()) {
1026 TypeParameterPtr param = TypeParameter::RawCast(obj);
1028 param->untag()->flags())) {
1029 param->untag()->set_owner(
1030 Smi::New(Map(Smi::Value(Smi::RawCast(param->untag()->owner())))));
1031 }
1032 } else if (obj->IsType()) {
1033 TypePtr type = Type::RawCast(obj);
1034 type->untag()->set_type_class_id(Map(type->untag()->type_class_id()));
1035 } else {
1036 intptr_t old_cid = obj->GetClassId();
1037 intptr_t new_cid = Map(old_cid);
1038 if (old_cid != new_cid) {
1039 // Don't touch objects that are unchanged. In particular, Instructions,
1040 // which are write-protected.
1041 obj->untag()->SetClassIdUnsynchronized(new_cid);
1042 }
1043 }
1044 }
1045
1046 private:
1047 intptr_t* old_to_new_cids_;
1048};
1049
1050void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
1052 IsolateGroup* IG = T->isolate_group();
1053
1054 // Code, ICData, allocation stubs have now-invalid cids.
1055 ClearAllCode();
1056
1057 {
1058 // The [HeapIterationScope] also safepoints all threads.
1059 HeapIterationScope his(T);
1060
1061 // Update the class table. Do it before rewriting cids in headers, as
1062 // the heap walkers load an object's size *after* calling the visitor.
1063 IG->class_table()->Remap(old_to_new_cid);
1064 IG->set_remapping_cids(true);
1065
1066 // Rewrite cids in headers and cids in Classes, Fields, Types and
1067 // TypeParameters.
1068 {
1069 CidRewriteVisitor visitor(old_to_new_cid);
1070 IG->heap()->VisitObjects(&visitor);
1071 }
1072
1073 IG->set_remapping_cids(false);
1074#if defined(DEBUG)
1075 IG->class_table()->Validate();
1076#endif
1077 }
1078
1079#if defined(DEBUG)
1080 IG->heap()->Verify("RemapClassIds");
1081#endif
1082}
1083
1084// Clears the cached canonicalized hash codes for all instances which directly
1085// (or indirectly) depend on class ids.
1086//
1087// In the Dart VM heap the following instances directly use cids for the
1088// computation of canonical hash codes:
1089//
1090// * TypePtr (due to UntaggedType::type_class_id)
1091// * TypeParameterPtr (due to UntaggedTypeParameter::owner_)
1092//
1093// The following instances use cids for the computation of canonical hash codes
1094// indirectly:
1095//
1096// * TypePtr (due to type arguments)
1097// * FunctionTypePtr (due to the result and parameter types)
1098// * RecordTypePtr (due to field types)
1099// * TypeArgumentsPtr (due to type references)
1100// * InstancePtr (due to instance fields)
1101// * ArrayPtr (due to type arguments & array entries)
1102//
1103// Caching of the canonical hash codes happens for:
1104//
1105// * UntaggedAbstractType::hash_
1106// * UntaggedTypeArguments::hash_
1107// * InstancePtr (weak table)
1108// * ArrayPtr (weak table)
1109//
1110// Usages of canonical hash codes are:
1111//
1112// * ObjectStore::canonical_types()
1113// * ObjectStore::canonical_function_types()
1114// * ObjectStore::canonical_record_types()
1115// * ObjectStore::canonical_type_parameters()
1116// * ObjectStore::canonical_type_arguments()
1117// * Class::constants()
1118//
1120 public:
1122 : type_(AbstractType::Handle(zone)),
1123 type_args_(TypeArguments::Handle(zone)) {}
1124
1125 void VisitObject(ObjectPtr obj) override {
1126 if (obj->IsType() || obj->IsTypeParameter() || obj->IsFunctionType() ||
1127 obj->IsRecordType()) {
1128 type_ ^= obj;
1129 type_.SetHash(0);
1130 } else if (obj->IsTypeArguments()) {
1131 type_args_ ^= obj;
1132 type_args_.SetHash(0);
1133 }
1134 }
1135
1136 private:
1137 AbstractType& type_;
1138 TypeArguments& type_args_;
1139};
1140
1142 auto T = Thread::Current();
1143 auto Z = T->zone();
1144 auto IG = T->isolate_group();
1145
1146 // Clear all cached hash values.
1147 {
1148 HeapIterationScope his(T);
1149 ClearTypeHashVisitor visitor(Z);
1150 IG->heap()->VisitObjects(&visitor);
1151 }
1152
1153 // Rehash the canonical Types table.
1154 ObjectStore* object_store = IG->object_store();
1155 Array& types = Array::Handle(Z);
1156 Type& type = Type::Handle(Z);
1157 {
1158 CanonicalTypeSet types_table(Z, object_store->canonical_types());
1159 types = HashTables::ToArray(types_table, false);
1160 types_table.Release();
1161 }
1162
1163 intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3);
1164 CanonicalTypeSet types_table(
1165 Z, HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld));
1166 for (intptr_t i = 0; i < types.Length(); i++) {
1167 type ^= types.At(i);
1168 bool present = types_table.Insert(type);
1169 ASSERT(!present);
1170 }
1171 object_store->set_canonical_types(types_table.Release());
1172
1173 // Rehash the canonical FunctionTypes table.
1174 Array& function_types = Array::Handle(Z);
1175 FunctionType& function_type = FunctionType::Handle(Z);
1176 {
1177 CanonicalFunctionTypeSet function_types_table(
1178 Z, object_store->canonical_function_types());
1179 function_types = HashTables::ToArray(function_types_table, false);
1180 function_types_table.Release();
1181 }
1182
1183 dict_size = Utils::RoundUpToPowerOfTwo(function_types.Length() * 4 / 3);
1184 CanonicalFunctionTypeSet function_types_table(
1185 Z, HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld));
1186 for (intptr_t i = 0; i < function_types.Length(); i++) {
1187 function_type ^= function_types.At(i);
1188 bool present = function_types_table.Insert(function_type);
1189 ASSERT(!present);
1190 }
1191 object_store->set_canonical_function_types(function_types_table.Release());
1192
1193 // Rehash the canonical RecordTypes table.
1194 Array& record_types = Array::Handle(Z);
1195 RecordType& record_type = RecordType::Handle(Z);
1196 {
1197 CanonicalRecordTypeSet record_types_table(
1198 Z, object_store->canonical_record_types());
1199 record_types = HashTables::ToArray(record_types_table, false);
1200 record_types_table.Release();
1201 }
1202
1203 dict_size = Utils::RoundUpToPowerOfTwo(record_types.Length() * 4 / 3);
1204 CanonicalRecordTypeSet record_types_table(
1205 Z, HashTables::New<CanonicalRecordTypeSet>(dict_size, Heap::kOld));
1206 for (intptr_t i = 0; i < record_types.Length(); i++) {
1207 record_type ^= record_types.At(i);
1208 bool present = record_types_table.Insert(record_type);
1209 ASSERT(!present);
1210 }
1211 object_store->set_canonical_record_types(record_types_table.Release());
1212
1213 // Rehash the canonical TypeParameters table.
1214 Array& typeparams = Array::Handle(Z);
1216 {
1217 CanonicalTypeParameterSet typeparams_table(
1218 Z, object_store->canonical_type_parameters());
1219 typeparams = HashTables::ToArray(typeparams_table, false);
1220 typeparams_table.Release();
1221 }
1222
1223 dict_size = Utils::RoundUpToPowerOfTwo(typeparams.Length() * 4 / 3);
1224 CanonicalTypeParameterSet typeparams_table(
1225 Z, HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld));
1226 for (intptr_t i = 0; i < typeparams.Length(); i++) {
1227 typeparam ^= typeparams.At(i);
1228 bool present = typeparams_table.Insert(typeparam);
1229 ASSERT(!present);
1230 }
1231 object_store->set_canonical_type_parameters(typeparams_table.Release());
1232
1233 // Rehash the canonical TypeArguments table.
1234 Array& typeargs = Array::Handle(Z);
1236 {
1237 CanonicalTypeArgumentsSet typeargs_table(
1238 Z, object_store->canonical_type_arguments());
1239 typeargs = HashTables::ToArray(typeargs_table, false);
1240 typeargs_table.Release();
1241 }
1242
1243 // The canonical constant tables use canonical hashcodes which can change
1244 // due to cid-renumbering.
1245 IG->RehashConstants(nullptr);
1246
1247 dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3);
1248 CanonicalTypeArgumentsSet typeargs_table(
1249 Z, HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld));
1250 for (intptr_t i = 0; i < typeargs.Length(); i++) {
1251 typearg ^= typeargs.At(i);
1252 bool present = typeargs_table.Insert(typearg);
1253 ASSERT(!present);
1254 }
1255 object_store->set_canonical_type_arguments(typeargs_table.Release());
1256}
1257
1258void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
1259 auto const thread = Thread::Current();
1260 auto const isolate_group = thread->isolate_group();
1261 SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
1262 StackZone stack_zone(thread);
1263 auto const zone = thread->zone();
1264
1265 class ClearCodeVisitor : public FunctionVisitor {
1266 public:
1267 ClearCodeVisitor(Zone* zone, bool force)
1268 : force_(force),
1269 pool_(ObjectPool::Handle(zone)),
1270 entry_(Object::Handle(zone)) {}
1271
1272 void VisitClass(const Class& cls) {
1273 if (force_ || cls.id() >= kNumPredefinedCids) {
1275 }
1276 }
1277
1278 void VisitFunction(const Function& function) {
1279 function.ClearCode();
1280 function.ClearICDataArray();
1281 }
1282
1283 private:
1284 const bool force_;
1285 ObjectPool& pool_;
1286 Object& entry_;
1287 };
1288
1289 ClearCodeVisitor visitor(zone, including_nonchanging_cids);
1290 ProgramVisitor::WalkProgram(zone, isolate_group, &visitor);
1291}
1292
1293#endif // !defined(DART_PRECOMPILED_RUNTIME)
1294
1295} // namespace dart
SI F table(const skcms_Curve *curve, F v)
#define IG
#define UNREACHABLE()
Definition assert.h:248
#define ASSERT_EQUAL(expected, actual)
Definition assert.h:309
#define Z
virtual bool HasTypeClass() const
Definition object.h:9063
void SetHash(intptr_t value) const
Definition object.h:13360
virtual ClassPtr type_class() const
Definition object.cc:21083
static intptr_t InstanceSize()
Definition object.h:10910
ObjectPtr At(intptr_t index) const
Definition object.h:10854
intptr_t Length() const
Definition object.h:10808
void Add(const T &value)
intptr_t length() const
static constexpr T decode(S value)
Definition bitfield.h:173
static intptr_t InstanceSize()
Definition object.h:10772
static intptr_t NumberOfFields()
Definition object.h:11844
static intptr_t data_offset()
Definition object.h:11846
CidRewriteVisitor(intptr_t *old_to_new_cids)
void VisitObject(ObjectPtr obj) override
intptr_t Map(intptr_t cid)
static AbstractTypePtr FinalizeType(const AbstractType &type, FinalizationKind finalization=kCanonicalize)
static bool ProcessPendingClasses()
static void MarkClassCanBeFuture(Zone *zone, const Class &cls)
static void VerifyBootstrapClasses()
static bool AllClassesFinalized()
static void FinalizeTypesInClass(const Class &cls)
static void RegisterClassInHierarchy(Zone *zone, const Class &cls)
static ErrorPtr AllocateFinalizeClass(const Class &cls)
static void FinalizeClass(const Class &cls)
static void ClearAllCode(bool including_nonchanging_cids=false)
static void RemapClassIds(intptr_t *old_to_new_cid)
static ErrorPtr LoadClassMembers(const Class &cls)
ClassPtr At(intptr_t cid) const
static bool IsTopLevelCid(intptr_t cid)
void set_is_implemented() const
Definition object.cc:5668
intptr_t kernel_offset() const
Definition object.h:1806
LibraryPtr library() const
Definition object.h:1335
void set_is_isolate_unsendable_due_to_pragma(bool value) const
Definition object.cc:3199
void set_super_type(const Type &value) const
Definition object.cc:3734
void set_is_allocate_finalized() const
Definition object.cc:5780
void Finalize() const
Definition object.cc:4362
bool can_be_future() const
Definition object.h:2178
bool is_declaration_loaded() const
Definition object.h:1705
GrowableObjectArrayPtr direct_subclasses() const
Definition object.h:1539
TypePtr super_type() const
Definition object.h:1433
intptr_t id() const
Definition object.h:1235
intptr_t NumTypeArguments() const
Definition object.cc:3690
bool is_loaded() const
Definition object.h:1787
ArrayPtr interfaces() const
Definition object.h:1449
bool is_type_finalized() const
Definition object.h:1711
void SetUserVisibleNameInClassTable()
Definition object.cc:5438
ArrayPtr fields() const
Definition object.h:1617
void DisableAllocationStub() const
Definition object.cc:5934
bool HasInstanceFields() const
Definition object.cc:3261
void set_is_future_subtype(bool value) const
Definition object.cc:3210
intptr_t host_instance_size() const
Definition object.h:1145
void DisableCHAOptimizedCode(const Class &subclass)
Definition object.cc:4457
bool is_abstract() const
Definition object.h:1698
bool IsGeneric() const
Definition object.h:1360
StringPtr Name() const
Definition object.cc:3038
bool is_prefinalized() const
Definition object.h:1740
bool IsFutureClass() const
Definition object.cc:5962
bool is_future_subtype() const
Definition object.h:2172
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
Definition object.cc:3715
bool IsTopLevel() const
Definition object.cc:6176
bool NoteImplementor(const Class &implementor) const
Definition object.cc:5635
TypeParametersPtr type_parameters() const
Definition object.h:1340
void set_is_type_finalized() const
Definition object.cc:5693
const char * UserVisibleNameCString() const
Definition object.cc:3059
bool is_implemented() const
Definition object.h:1694
bool is_allocate_finalized() const
Definition object.h:1734
bool is_transformed_mixin_application() const
Definition object.h:1756
intptr_t NumTypeParameters(Thread *thread) const
Definition object.cc:3605
bool is_isolate_unsendable_due_to_pragma() const
Definition object.h:2159
bool is_finalized() const
Definition object.h:1725
ArrayPtr current_functions() const
Definition object.h:1643
void EnsureDeclarationLoaded() const
Definition object.cc:4968
void set_can_be_future(bool value) const
Definition object.cc:3215
void VisitObject(ObjectPtr obj) override
static intptr_t InstanceSize()
Definition object.h:10114
virtual const char * ToErrorCString() const
Definition object.cc:19830
static intptr_t InstanceSize()
Definition object.h:12986
static intptr_t InstanceSize()
Definition object.h:13055
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition object.h:11118
intptr_t Length() const
Definition object.h:11046
ObjectPtr At(intptr_t index) const
Definition object.h:11059
bool Insert(const Object &key)
Definition hash_table.h:801
static ArrayPtr ToArray(const Table &table, bool include_payload)
Definition hash_table.h:653
@ kOld
Definition heap.h:39
bool Verify(const char *msg, MarkExpectation mark_expectation=kForbidMarked)
Definition heap.cc:760
static intptr_t InstanceSize()
Definition object.h:11020
static intptr_t InstanceSize()
Definition object.h:8308
InterfaceFinder(Zone *zone, ClassTable *class_table, GrowableArray< intptr_t > *cids)
void FindAllInterfaces(const Class &klass)
Heap * heap() const
Definition isolate.h:295
ObjectStore * object_store() const
Definition isolate.h:505
SafepointRwLock * program_lock()
Definition isolate.h:532
static IsolateGroup * Current()
Definition isolate.h:534
ClassTable * class_table() const
Definition isolate.h:491
StringPtr private_key() const
Definition object.h:5070
StringPtr url() const
Definition object.h:5068
jmp_buf * Set()
Definition longjump.cc:16
static intptr_t InstanceSize()
Definition object.h:12085
static intptr_t InstanceSize()
Definition object.h:10069
static DART_NORETURN void Exit(int code)
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
UntaggedObject * untag() const
intptr_t GetClassId() const
Definition raw_object.h:864
static ObjectPtr null()
Definition object.h:433
ObjectPtr ptr() const
Definition object.h:332
virtual const char * ToCString() const
Definition object.h:366
bool IsNull() const
Definition object.h:363
static intptr_t InstanceSize()
Definition object.h:592
static Object & Handle()
Definition object.h:407
static ObjectPtr RawCast(ObjectPtr obj)
Definition object.h:325
static intptr_t InstanceSize()
Definition object.h:10543
static constexpr intptr_t kNativeTypeArgPos
Definition object.h:11880
static void WalkProgram(Zone *zone, IsolateGroup *isolate_group, ClassVisitor *visitor)
static void static void MessageV(Kind kind, const Script &script, TokenPosition token_pos, bool report_after_token, const char *format, va_list args)
Definition report.cc:135
static DART_NORETURN void LongJump(const Error &error)
Definition report.cc:86
static constexpr bool AtLocation
Definition report.h:29
static intptr_t InstanceSize()
Definition object.h:12188
static SmiPtr New(intptr_t value)
Definition object.h:9985
static intptr_t InstanceSize()
Definition object.h:9983
intptr_t Value() const
Definition object.h:9969
static StaticTypeExactnessState Uninitialized()
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition object.cc:23777
static bool EqualsIgnoringPrivateKey(const String &str1, const String &str2)
Definition object.cc:24378
Zone * zone() const
static Thread * Current()
Definition thread.h:361
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
Definition thread.cc:243
IsolateGroup * isolate_group() const
Definition thread.h:540
ErrorPtr sticky_error() const
Definition thread.cc:230
static intptr_t InstanceSize()
Definition object.h:10683
bool IsClassTypeParameter() const
Definition object.h:9796
void set_parameterized_class_id(classid_t value) const
Definition object.cc:22778
intptr_t index() const
Definition object.h:9800
void set_index(intptr_t value) const
Definition object.cc:22804
ClassPtr parameterized_class() const
Definition object.cc:22783
AbstractTypePtr bound() const
Definition object.cc:22810
void set_base(intptr_t value) const
Definition object.cc:22798
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
Definition utils.h:120
static bool IsUint(intptr_t N, T value)
Definition utils.h:313
static intptr_t InstanceSize()
Definition object.h:12906
static intptr_t InstanceSize()
Definition object.h:12932
static void FinishLoading(const Class &klass)
#define THR_Print(format,...)
Definition log.h:20
#define ASSERT(E)
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
#define DEFINE_FLAG(type, name, default_value, comment)
Definition flags.h:16
Dart_NativeFunction function
Definition fuchsia.cc:51
#define HANDLESCOPE(thread)
Definition handles.h:321
va_start(args, format)
va_end(args)
static void MarkImplemented(Zone *zone, const Class &iface)
static void CollectFinalizedSuperClasses(const Class &cls_, GrowableArray< intptr_t > *finalized_super_classes)
const char *const name
static void AddSuperType(const AbstractType &type, GrowableArray< intptr_t > *finalized_super_classes)
static bool IsPotentialExactGeneric(const AbstractType &type)
const char *const class_name
int32_t classid_t
Definition globals.h:524
@ kIllegalCid
Definition class_id.h:214
@ kNumPredefinedCids
Definition class_id.h:257
@ kVoidCid
Definition class_id.h:254
@ kByteBufferCid
Definition class_id.h:247
@ kDynamicCid
Definition class_id.h:253
const intptr_t cid
static void RemoveCHAOptimizedCode(const Class &subclass, const GrowableArray< intptr_t > &added_subclass_to_cids)
static void CollectImmediateSuperInterfaces(const Class &cls, GrowableArray< intptr_t > *cids)
#define Pd
Definition globals.h:408
#define T
Point offset
#define TIMELINE_DURATION(thread, stream, name)
Definition timeline.h:39